mirror of
https://bitbucket.org/myhomie/mycorerepository.git
synced 2025-12-06 01:31:19 +00:00
Add meross mqtt client histed service + action service meross and yeelight tests
This commit is contained in:
parent
4191e6137b
commit
d1edc6710a
15
MyCore.Interfaces/Models/MyControlPanel/SupportedDevice.cs
Normal file
15
MyCore.Interfaces/Models/MyControlPanel/SupportedDevice.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using MyCore.Interfaces.DTO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace MyCore.Interfaces.Models.MyControlPanel
|
||||
{
|
||||
public class SupportedDevice
|
||||
{
|
||||
public string Manufacturer { get; set; }
|
||||
public string Model { get; set; }
|
||||
public string Description { get; set; }
|
||||
public DeviceType DeviceType { get; set; }
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,10 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Mqtt.Client.AspNetCore.Services;
|
||||
using MyCore.Services.MyControlPanel;
|
||||
using MyCore.Services;
|
||||
using MyCore.Services.Devices;
|
||||
|
||||
namespace MyCore.Service.Controllers
|
||||
{
|
||||
@ -24,16 +28,25 @@ namespace MyCore.Service.Controllers
|
||||
{
|
||||
private readonly ILogger<AuthenticationController> _logger;
|
||||
private readonly TokensService _tokensService;
|
||||
private readonly DeviceDatabaseService _DeviceDatabaseService;
|
||||
private readonly ProviderDatabaseService _ProviderDatabaseService;
|
||||
private readonly LocationDatabaseService _LocationDatabaseService;
|
||||
private readonly UserDatabaseService _UserDatabaseService;
|
||||
private readonly ActionService _ActionService;
|
||||
private readonly IMqttClientService _mqttClientService;
|
||||
private readonly IMqttOnlineClientService _mqttOnlineClientService;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="logger">Logger</param>
|
||||
/// <param name="tokensService">Tokens service</param>
|
||||
public AuthenticationController(ILogger<AuthenticationController> logger, TokensService tokensService)
|
||||
public AuthenticationController(ILogger<AuthenticationController> logger, TokensService tokensService, DeviceDatabaseService DeviceDatabaseService, ProviderDatabaseService ProviderDatabaseService, LocationDatabaseService LocationDatabaseService, UserDatabaseService UserDatabaseService, ActionService ActionService, MqttClientServiceProvider provider, MqttClientOnlineServiceProvider onlineProvider)
|
||||
{
|
||||
_logger = logger;
|
||||
_tokensService = tokensService;
|
||||
_DeviceDatabaseService = DeviceDatabaseService;
|
||||
_ProviderDatabaseService = ProviderDatabaseService;
|
||||
_LocationDatabaseService = LocationDatabaseService;
|
||||
_UserDatabaseService = UserDatabaseService;
|
||||
_ActionService = ActionService;
|
||||
_mqttClientService = provider.MqttClientService;
|
||||
_mqttOnlineClientService = onlineProvider.MqttOnlineClientService;
|
||||
}
|
||||
|
||||
private ActionResult<LoginDTO> Authenticate(string email, string password)
|
||||
@ -41,7 +54,7 @@ namespace MyCore.Service.Controllers
|
||||
try
|
||||
{
|
||||
var token = _tokensService.Authenticate(email.ToLower(), password);
|
||||
|
||||
MqttClientService.SetServices(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, _ActionService, "5fef55bae30e1016d4776bfe"); // TODO Get userId when connected !!
|
||||
return Ok(token);
|
||||
}
|
||||
/*catch (UnauthorizedAccessException ex)
|
||||
|
||||
@ -138,11 +138,11 @@ namespace MyCore.Controllers
|
||||
|
||||
Provider provider = ProviderService.GetProviderById(this._ProviderDatabaseService, userId, providerId);
|
||||
if (provider == null)
|
||||
throw new KeyNotFoundException("Provider id is null");
|
||||
throw new KeyNotFoundException("Provider not found");
|
||||
|
||||
List<DeviceDetailDTO> devicesCreated = await DeviceService.CreateFromProvider(this._DeviceDatabaseService, this._ProviderDatabaseService, this._LocationDatabaseService, userId, provider);
|
||||
Dictionary<string, List<DeviceDetailDTO>> devices = await DeviceService.CreateFromProvider(this._DeviceDatabaseService, this._ProviderDatabaseService, this._LocationDatabaseService, userId, provider);
|
||||
|
||||
return new OkObjectResult(devicesCreated);
|
||||
return new OkObjectResult(devices);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
|
||||
@ -11,4 +11,10 @@
|
||||
public static BrokerOnlineHostSettings BrokerHostOnlineSettings;
|
||||
public static ClientOnlineSettings ClientOnlineSettings;
|
||||
}
|
||||
|
||||
public class AppSettingsMerossProvider
|
||||
{
|
||||
public static BrokerMerossHostSettings BrokerHostMerossSettings;
|
||||
public static ClientMerossSettings ClientMerossSettings;
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,4 +22,14 @@ namespace Mqtt.Client.AspNetCore.Options
|
||||
ServiceOnlineProvider = serviceProvider;
|
||||
}
|
||||
}
|
||||
|
||||
public class AspCoreMerossClientOptionBuilder : MqttClientOptionsBuilder
|
||||
{
|
||||
public IServiceProvider ServiceMerossProvider { get; }
|
||||
|
||||
public AspCoreMerossClientOptionBuilder(IServiceProvider serviceProvider)
|
||||
{
|
||||
ServiceMerossProvider = serviceProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,4 +11,10 @@
|
||||
public string Host { set; get; }
|
||||
public int Port { set; get; }
|
||||
}
|
||||
|
||||
public class BrokerMerossHostSettings
|
||||
{
|
||||
public string Host { set; get; }
|
||||
public int Port { set; get; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,4 +13,11 @@
|
||||
public string UserName { set; get; }
|
||||
public string Password { set; get; }
|
||||
}
|
||||
|
||||
public class ClientMerossSettings
|
||||
{
|
||||
public string Id { set; get; }
|
||||
public string UserName { set; get; }
|
||||
public string Password { set; get; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,4 +18,11 @@ namespace Mqtt.Client.AspNetCore.Services
|
||||
IMqttApplicationMessageReceivedHandler
|
||||
{
|
||||
}
|
||||
|
||||
public interface IMqttMerossClientService : IHostedService,
|
||||
IMqttClientConnectedHandler,
|
||||
IMqttClientDisconnectedHandler,
|
||||
IMqttApplicationMessageReceivedHandler
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
520
MyCore/Extensions/MqttClientMerossService.cs
Normal file
520
MyCore/Extensions/MqttClientMerossService.cs
Normal file
@ -0,0 +1,520 @@
|
||||
using MQTTnet;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Formatter;
|
||||
using MyCore.Interfaces.Models;
|
||||
using MyCore.Services.Devices;
|
||||
using MyCore.Services.MyControlPanel;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Authentication;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static MyCore.Interfaces.Models.DeviceAbilities;
|
||||
|
||||
namespace Mqtt.Client.AspNetCore.Services
|
||||
{
|
||||
public class MqttClientMerossService : IMqttMerossClientService
|
||||
{
|
||||
// API HTTP
|
||||
private const string _merossUrl = "https://iot.meross.com";
|
||||
private static string _secret = "23x17ahWarFH6w29";
|
||||
private string _loginUrl = $"{_merossUrl}/v1/Auth/Login";
|
||||
private string _logUrl = $"{_merossUrl}/v1/log/user";
|
||||
private string _devList = $"{_merossUrl}/v1/Device/devList";
|
||||
|
||||
private static string username = "thomas.fransolet@hotmail.be";
|
||||
private static string password = "Coconuts07";
|
||||
|
||||
private static ResultToken resultToken;
|
||||
|
||||
private List<MerossDevice> allDevices;
|
||||
|
||||
// API MQTT
|
||||
private const int port = 2001;
|
||||
private const string domain = "iot.meross.com";
|
||||
|
||||
private static IMqttClient client;
|
||||
private IMqttClientOptions options;
|
||||
private string _userMQTT;
|
||||
private string _passwordMQTT;
|
||||
|
||||
public string clientId = "";
|
||||
public static string appId = "";
|
||||
|
||||
public class Credential
|
||||
{
|
||||
public string email;
|
||||
public string password;
|
||||
}
|
||||
|
||||
public class ResultToken
|
||||
{
|
||||
public string userid;
|
||||
public string email;
|
||||
public string token;
|
||||
public string key;
|
||||
}
|
||||
|
||||
public enum RequestType
|
||||
{
|
||||
Login,
|
||||
Log,
|
||||
DeviceList
|
||||
}
|
||||
|
||||
|
||||
public MqttClientMerossService(IMqttClientOptions _options)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO
|
||||
/*this.username = username;
|
||||
this.password = password;*/
|
||||
|
||||
// LOGIN
|
||||
var loginTask = Task.Run(() => PostURI(new Uri(_loginUrl), RequestType.Login));
|
||||
loginTask.Wait();
|
||||
|
||||
if (loginTask.Result != "")
|
||||
{
|
||||
//RESULT TOKEN
|
||||
var data = ((JObject)JsonConvert.DeserializeObject(loginTask.Result))["data"];
|
||||
resultToken = JsonConvert.DeserializeObject<ResultToken>(data.ToString());
|
||||
|
||||
allDevices = GetMerossDevices();
|
||||
|
||||
// RETRIEVE LOG TODO Create a GetLogs method
|
||||
/*var logTask = Task.Run(() => PostURI(new Uri(_logUrl), RequestType.Log));
|
||||
logTask.Wait();
|
||||
|
||||
if (logTask.Result != "")
|
||||
{
|
||||
data = ((JObject)JsonConvert.DeserializeObject(logTask.Result))["data"];
|
||||
}*/
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
resultToken = null;
|
||||
throw new AuthenticationException("Bad service username or password");
|
||||
}
|
||||
|
||||
string stringForMD5 = resultToken.userid + resultToken.key;
|
||||
string hashed_password = CreateMD5(stringForMD5).ToLower();
|
||||
|
||||
// Check if we can hardcode it -> seems ok 20/01/2020
|
||||
var uuid = "01df8092-d790-4377-8481-5b73aef045c6";
|
||||
|
||||
GenerateClientAndAppId(uuid);
|
||||
|
||||
options = new MqttClientOptionsBuilder()
|
||||
.WithClientId(clientId)
|
||||
.WithTcpServer(domain, port)
|
||||
.WithCredentials(resultToken.userid, hashed_password)
|
||||
.WithCleanSession()
|
||||
.WithTls()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V311)
|
||||
.Build();
|
||||
|
||||
client = new MqttFactory().CreateMqttClient();
|
||||
|
||||
ConfigureMqttClient();
|
||||
}
|
||||
|
||||
private void ConfigureMqttClient()
|
||||
{
|
||||
client.ConnectedHandler = this;
|
||||
client.DisconnectedHandler = this;
|
||||
client.ApplicationMessageReceivedHandler = this;
|
||||
}
|
||||
|
||||
public Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs e)
|
||||
{
|
||||
Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
|
||||
Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
|
||||
var payload = "";
|
||||
if (e.ApplicationMessage.Payload != null)
|
||||
{
|
||||
Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
|
||||
payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
||||
}
|
||||
|
||||
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
|
||||
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
|
||||
Console.WriteLine();
|
||||
|
||||
var topic = e.ApplicationMessage.Topic;
|
||||
|
||||
/* Example :
|
||||
*
|
||||
*
|
||||
* Toggle channel 0 multiprise
|
||||
* topic = /appliance/1909206725106690802148e1e95243fd/subscribe
|
||||
*
|
||||
* payload =
|
||||
* {"header": {"from": "/app/174744-2c2c67eab37f04625d60dc678e5a2349/subscribe",
|
||||
* "messageId": "5e2ac8700552ef089da05f8543993319",
|
||||
* "method": "SET",
|
||||
* "namespace": "Appliance.Control.ToggleX",
|
||||
* "payloadVersion": 1,
|
||||
* "sign": "18469fb032695f3144f060e65f3fad26",
|
||||
* "timestamp": 1579540738},
|
||||
* "payload":
|
||||
* {"togglex":
|
||||
* {"onoff": 1, "channel": 0}
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs)
|
||||
{
|
||||
System.Console.WriteLine("connected meross");
|
||||
|
||||
var topic = $"/app/{resultToken.userid}-{appId.ToLower()}/subscribe";
|
||||
|
||||
await client.SubscribeAsync(topic);
|
||||
//await client.SubscribeAsync("#");
|
||||
|
||||
//await client.SubscribeAsync(new TopicFilterBuilder().WithTopic(topic).Build());
|
||||
|
||||
/*MerossDevice multisocket = allDevices.Where(d => d.onlineStatus == 1 && d.deviceType == "mss425f").FirstOrDefault();
|
||||
|
||||
ExecuteCommand(multisocket.uuid, Method.GET, CommandMqtt.ABILITY);
|
||||
|
||||
foreach (var device in allDevices.Where(d => d.deviceType == "mss310" && d.onlineStatus == 1).ToList())
|
||||
{
|
||||
ExecuteCommand(device.uuid, Method.GET, CommandMqtt.ABILITY);
|
||||
ExecuteCommand(device.uuid, Method.GET, CommandMqtt.ELECTRICITY);
|
||||
}
|
||||
|
||||
Console.WriteLine("### SUBSCRIBED ###");*/
|
||||
}
|
||||
|
||||
public static void ExecuteCommand(string uuid, Method method, CommandMqtt command, string payload = null, string callback = null, ToggleStatus toggleStatus = 0, int channelChosen = 0)
|
||||
{
|
||||
var topic = $"/appliance/{uuid}/subscribe";
|
||||
var namespaceVar = "";
|
||||
var payloadVar = payload;
|
||||
bool multisocket = false;
|
||||
|
||||
// TODO Check device type.. and add switch case
|
||||
switch (command)
|
||||
{
|
||||
case CommandMqtt.ABILITY:
|
||||
namespaceVar = Common.ABILITY;
|
||||
break;
|
||||
case CommandMqtt.CONSUMPTIONX:
|
||||
namespaceVar = PlugsAndBulbs.TOGGLEX;
|
||||
break;
|
||||
case CommandMqtt.TOGGLE:
|
||||
namespaceVar = PlugsAndBulbs.TOGGLE;
|
||||
break;
|
||||
case CommandMqtt.TOGGLEX:
|
||||
multisocket = true;
|
||||
namespaceVar = PlugsAndBulbs.TOGGLEX;
|
||||
break;
|
||||
case CommandMqtt.ELECTRICITY:
|
||||
namespaceVar = PlugsAndBulbs.ELECTRICITY;
|
||||
break;
|
||||
}
|
||||
|
||||
// if a plug
|
||||
// and if a toggleX ability
|
||||
if (method == Method.SET && multisocket)
|
||||
{
|
||||
PayLoadToggleX payLoadToggleX = new PayLoadToggleX();
|
||||
ToggleX toggleX = new ToggleX();
|
||||
toggleX.onoff = toggleStatus.GetHashCode();
|
||||
toggleX.channel = channelChosen;
|
||||
payLoadToggleX.togglex = toggleX;
|
||||
|
||||
payloadVar = JsonConvert.SerializeObject(payLoadToggleX);
|
||||
}
|
||||
|
||||
// if a plug
|
||||
// and if hasn't toggleX ability
|
||||
if (method == Method.SET && !multisocket)
|
||||
{
|
||||
PayLoadToggle payLoadToggle = new PayLoadToggle();
|
||||
Toggle toggle = new Toggle();
|
||||
toggle.onoff = toggleStatus.GetHashCode();
|
||||
payLoadToggle.toggle = toggle;
|
||||
|
||||
payloadVar = JsonConvert.SerializeObject(payLoadToggle);
|
||||
}
|
||||
|
||||
var message = BuildMQTTMessage(method, namespaceVar, payloadVar);
|
||||
|
||||
PublishMessage(topic, message);
|
||||
}
|
||||
|
||||
private static string BuildMQTTMessage(Method method, string namespaceVar, string payloadVar)
|
||||
{
|
||||
HeaderMqtt headerMqtt = new HeaderMqtt();
|
||||
|
||||
headerMqtt.from = $"/app/{resultToken.userid}-{appId.ToLower()}/subscribe";
|
||||
headerMqtt.messageId = CreateMD5(GenerateNonce(16).ToUpper()).ToLower();
|
||||
headerMqtt.method = method.ToString();
|
||||
headerMqtt.Namespace = namespaceVar;
|
||||
headerMqtt.payloadVersion = 1;
|
||||
headerMqtt.timestamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
|
||||
headerMqtt.sign = CreateMD5($"{headerMqtt.messageId}{resultToken.key}{(headerMqtt.timestamp).ToString()}").ToLower();
|
||||
|
||||
|
||||
RequestMQTT requestMQTT = new RequestMQTT();
|
||||
requestMQTT.header = headerMqtt;
|
||||
if (payloadVar != null)
|
||||
requestMQTT.payload = JsonConvert.DeserializeObject(payloadVar);
|
||||
else
|
||||
requestMQTT.payload = new Object();
|
||||
|
||||
var data = JsonConvert.SerializeObject(requestMQTT);
|
||||
|
||||
// Change Namespace to namespace
|
||||
data = data.Replace("Namespace", "namespace");
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public async Task HandleDisconnectedAsync(MqttClientDisconnectedEventArgs eventArgs)
|
||||
{
|
||||
if (!client.IsConnected)
|
||||
{
|
||||
await client.ReconnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await client.ConnectAsync(options);
|
||||
if (!client.IsConnected)
|
||||
{
|
||||
await client.ReconnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var disconnectOption = new MqttClientDisconnectOptions
|
||||
{
|
||||
ReasonCode = MqttClientDisconnectReason.NormalDisconnection,
|
||||
ReasonString = "NormalDiconnection"
|
||||
};
|
||||
await client.DisconnectAsync(disconnectOption, cancellationToken);
|
||||
}
|
||||
await client.DisconnectAsync();
|
||||
}
|
||||
|
||||
public static async Task PublishMessage(string topic, string message)
|
||||
{
|
||||
var mqttMessage = new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topic)
|
||||
.WithPayload(message)
|
||||
.WithExactlyOnceQoS()
|
||||
.WithRetainFlag()
|
||||
.Build();
|
||||
|
||||
if (client.IsConnected)
|
||||
await client.PublishAsync(mqttMessage).ContinueWith(res => {
|
||||
if (res.Status == TaskStatus.RanToCompletion)
|
||||
{
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static string CreateMD5(string input)
|
||||
{
|
||||
// Use input string to calculate MD5 hash
|
||||
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
|
||||
{
|
||||
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
|
||||
byte[] hashBytes = md5.ComputeHash(inputBytes);
|
||||
|
||||
// Convert the byte array to hexadecimal string
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < hashBytes.Length; i++)
|
||||
{
|
||||
sb.Append(hashBytes[i].ToString("X2"));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> PostURI(Uri u, RequestType requestType)
|
||||
{
|
||||
var response = string.Empty;
|
||||
var requestParam = "";
|
||||
string nonce = GenerateNonce(16).ToUpper();
|
||||
var timeStamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
|
||||
|
||||
switch (requestType)
|
||||
{
|
||||
case RequestType.Login:
|
||||
requestParam = Base64Encode(JsonConvert.SerializeObject(new Credential { email = username, password = password }).ToString());
|
||||
break;
|
||||
case RequestType.Log:
|
||||
requestParam = Base64Encode("{'extra': { }, 'model': 'Android,Android SDK built for x86_64', 'system': 'Android','uuid': '493dd9174941ed58waitForOpenWifi', 'vendor': 'Meross', 'version': '6.0'}");
|
||||
break;
|
||||
case RequestType.DeviceList:
|
||||
requestParam = "e30=";
|
||||
break;
|
||||
}
|
||||
|
||||
string stringForMD5 = stringForMD5 = _secret + timeStamp.ToString() + nonce + requestParam;
|
||||
string md5 = CreateMD5(stringForMD5);
|
||||
|
||||
var payloadLogin = "{ \"params\":\"" + requestParam + "\",\"sign\":\"" + md5.ToLower() + "\",\"timestamp\":" + timeStamp + ",\"nonce\":\"" + nonce + "\"}";
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
HttpContent c = new StringContent(payloadLogin, Encoding.UTF8, "application/json");
|
||||
if (resultToken != null)
|
||||
{
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", resultToken.token);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic");
|
||||
}
|
||||
|
||||
client.DefaultRequestHeaders.Add("vender", "Meross");
|
||||
client.DefaultRequestHeaders.Add("AppVersion", "1.3.0");
|
||||
client.DefaultRequestHeaders.Add("AppLanguage", "EN");
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "okhttp/3.6.0");
|
||||
|
||||
HttpResponseMessage result = await client.PostAsync(u, c);
|
||||
if (result.IsSuccessStatusCode)
|
||||
{
|
||||
response = await result.Content.ReadAsStringAsync();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private void GenerateClientAndAppId(string uuid)
|
||||
{
|
||||
var md5Result = CreateMD5($"API{uuid}");
|
||||
appId = md5Result;
|
||||
clientId = $"app:{md5Result}";
|
||||
}
|
||||
|
||||
private static string validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
private static Random random = new Random();
|
||||
|
||||
private static string GenerateNonce(int length)
|
||||
{
|
||||
var nonceString = new StringBuilder();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
nonceString.Append(validChars[random.Next(0, validChars.Length - 1)]);
|
||||
}
|
||||
|
||||
return nonceString.ToString();
|
||||
}
|
||||
|
||||
public static string Base64Encode(string plainText)
|
||||
{
|
||||
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
|
||||
return System.Convert.ToBase64String(plainTextBytes);
|
||||
}
|
||||
|
||||
public static List<MerossDevice> GetMerossDevices()
|
||||
{
|
||||
// GET DEVICE LIST
|
||||
var deviceTask = Task.Run(() => PostURI(new Uri(_devList), RequestType.DeviceList));
|
||||
deviceTask.Wait();
|
||||
|
||||
if (deviceTask.Result != "")
|
||||
{
|
||||
var data = ((JObject)JsonConvert.DeserializeObject(deviceTask.Result))["data"];
|
||||
// RETRIEVE ALL DEVICES
|
||||
allDevices = JsonConvert.DeserializeObject<List<MerossDevice>>(data.ToString());
|
||||
}
|
||||
else
|
||||
throw new HttpRequestException("Error retrieving meross devices");
|
||||
|
||||
return allDevices;
|
||||
}
|
||||
|
||||
#region MQTT
|
||||
|
||||
public class RequestMQTT
|
||||
{
|
||||
public HeaderMqtt header;
|
||||
public Object payload;
|
||||
}
|
||||
|
||||
public class HeaderMqtt
|
||||
{
|
||||
public string from;
|
||||
public string messageId;
|
||||
public string method;
|
||||
public string Namespace;
|
||||
public int payloadVersion;
|
||||
public string sign;
|
||||
public long timestamp;
|
||||
}
|
||||
|
||||
public class PayLoadToggle
|
||||
{
|
||||
// as it's not a multi-socket
|
||||
public int channel = 0;
|
||||
public Toggle toggle;
|
||||
}
|
||||
|
||||
public class Toggle
|
||||
{
|
||||
// 1 = on or 0 = off
|
||||
public int onoff;
|
||||
}
|
||||
|
||||
public class PayLoadToggleX
|
||||
{
|
||||
public ToggleX togglex;
|
||||
}
|
||||
|
||||
public class ToggleX
|
||||
{
|
||||
// 1 = on or 0 = off
|
||||
public int onoff;
|
||||
// number of the socket of the multi-socket
|
||||
public int channel;
|
||||
}
|
||||
|
||||
// TODO Create ability class related to device
|
||||
public enum CommandMqtt
|
||||
{
|
||||
ABILITY,
|
||||
CONSUMPTIONX,
|
||||
ELECTRICITY,
|
||||
TOGGLE,
|
||||
TOGGLEX
|
||||
}
|
||||
|
||||
public enum Method
|
||||
{
|
||||
GET,
|
||||
SET
|
||||
}
|
||||
|
||||
public enum ToggleStatus
|
||||
{
|
||||
OFF,
|
||||
ON
|
||||
}
|
||||
#endregion MQTT
|
||||
}
|
||||
|
||||
}
|
||||
12
MyCore/Extensions/MqttClientMerossServiceProvider.cs
Normal file
12
MyCore/Extensions/MqttClientMerossServiceProvider.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Mqtt.Client.AspNetCore.Services
|
||||
{
|
||||
public class MqttClientMerossServiceProvider
|
||||
{
|
||||
public readonly IMqttMerossClientService MqttMerossClientService;
|
||||
|
||||
public MqttClientMerossServiceProvider(IMqttMerossClientService mqttMerossClientService)
|
||||
{
|
||||
MqttMerossClientService = mqttMerossClientService;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,14 @@ namespace Mqtt.Client.AspNetCore.Services
|
||||
public MqttClientOnlineService(IMqttClientOptions options)
|
||||
{
|
||||
this.onlineOptions = options;
|
||||
|
||||
this.onlineOptions = new MqttClientOptionsBuilder()
|
||||
.WithClientId("ApiService")
|
||||
.WithTcpServer("myhomie.be") // TODO replace by localhost
|
||||
.WithCredentials("thomas", "MyCore,1")
|
||||
.WithCleanSession()
|
||||
.Build();
|
||||
|
||||
mqttClient = new MqttFactory().CreateMqttClient();
|
||||
ConfigureMqttClient();
|
||||
}
|
||||
@ -79,7 +87,6 @@ namespace Mqtt.Client.AspNetCore.Services
|
||||
System.Console.WriteLine("connected");
|
||||
//await mqttClient.SubscribeAsync("hello/world");
|
||||
await mqttClient.SubscribeAsync("#");
|
||||
await PublishMessage("zigbee2mqtt/bridge/config/devices/get", "");
|
||||
}
|
||||
|
||||
public async Task HandleDisconnectedAsync(MqttClientDisconnectedEventArgs eventArgs)
|
||||
@ -88,7 +95,6 @@ namespace Mqtt.Client.AspNetCore.Services
|
||||
{
|
||||
await mqttClient.ReconnectAsync();
|
||||
}
|
||||
//throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
|
||||
@ -4,6 +4,8 @@ using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MyCore.Interfaces.Models;
|
||||
using MyCore.Services.Devices;
|
||||
using MyCore.Services.MyControlPanel;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -18,7 +20,11 @@ namespace Mqtt.Client.AspNetCore.Services
|
||||
private static IMqttClient mqttClient;
|
||||
private IMqttClientOptions options;
|
||||
public static List<Zigbee2MqttDevice> devices = new List<Zigbee2MqttDevice>();
|
||||
|
||||
public static string userId;
|
||||
static DeviceDatabaseService _deviceDatabaseService;
|
||||
static ProviderDatabaseService _providerDatabaseService;
|
||||
static LocationDatabaseService _locationDatabaseService;
|
||||
static ActionService _actionService;
|
||||
|
||||
public MqttClientService(IMqttClientOptions options)
|
||||
{
|
||||
@ -51,13 +57,19 @@ namespace Mqtt.Client.AspNetCore.Services
|
||||
payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
|
||||
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
|
||||
Console.WriteLine();
|
||||
|
||||
var topic = e.ApplicationMessage.Topic;
|
||||
|
||||
if (_actionService != null) {
|
||||
ActionService.HandleActionFromMQTTAsync(topic, payload, _deviceDatabaseService, _providerDatabaseService, _locationDatabaseService, userId);
|
||||
}
|
||||
|
||||
//if () { }
|
||||
//List<Device> Devices = _DeviceDatabaseService.GetByProviderId(topic);
|
||||
|
||||
switch (topic)
|
||||
{
|
||||
case "zigbee2mqtt/bridge/config/devices":
|
||||
@ -139,6 +151,15 @@ namespace Mqtt.Client.AspNetCore.Services
|
||||
return devices;
|
||||
}
|
||||
|
||||
public static void SetServices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, ActionService _ActionService, string UserId)
|
||||
{
|
||||
_deviceDatabaseService = _DeviceDatabaseService;
|
||||
_providerDatabaseService = _ProviderDatabaseService;
|
||||
_locationDatabaseService = _LocationDatabaseService;
|
||||
_actionService = _ActionService;
|
||||
userId = UserId;
|
||||
}
|
||||
|
||||
public static async Task<List<Zigbee2MqttDevice>> AskDevicesAsync()
|
||||
{
|
||||
await PublishMessage("zigbee2mqtt/bridge/config/devices/get", "");
|
||||
|
||||
@ -4,6 +4,7 @@ using Mqtt.Client.AspNetCore.Options;
|
||||
using Mqtt.Client.AspNetCore.Services;
|
||||
using Mqtt.Client.AspNetCore.Settings;
|
||||
using MQTTnet.Client.Options;
|
||||
using MyCore.Services;
|
||||
using System;
|
||||
|
||||
namespace MyCore.Service.Extensions
|
||||
@ -41,7 +42,21 @@ namespace MyCore.Service.Extensions
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
public static IServiceCollection AddMerossClientHostedService(this IServiceCollection services)
|
||||
{
|
||||
services.AddMerossClientServiceWithConfig(aspOnlineOptionBuilder =>
|
||||
{
|
||||
/*var clientSettings = AppSettingsMerossProvider.ClientMerossSettings;
|
||||
var brokerHostSettings = AppSettingsMerossProvider.BrokerHostMerossSettings;
|
||||
|
||||
aspOnlineOptionBuilder
|
||||
.WithCredentials(clientSettings.UserName, clientSettings.Password)
|
||||
.WithClientId(clientSettings.Id)
|
||||
.WithTcpServer(brokerHostSettings.Host, brokerHostSettings.Port);*/
|
||||
});
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
private static IServiceCollection AddMqttClientServiceWithConfig(this IServiceCollection services, Action<AspCoreMqttClientOptionBuilder> configure)
|
||||
{
|
||||
@ -88,5 +103,27 @@ namespace MyCore.Service.Extensions
|
||||
return services;
|
||||
}
|
||||
|
||||
private static IServiceCollection AddMerossClientServiceWithConfig(this IServiceCollection services, Action<AspCoreMerossClientOptionBuilder> configure)
|
||||
{
|
||||
/*services.AddSingleton<IMqttClientOptions>(serviceMerossProvider =>
|
||||
{
|
||||
var optionBuilder = new AspCoreMerossClientOptionBuilder(serviceMerossProvider);
|
||||
configure(optionBuilder);
|
||||
return optionBuilder.Build();
|
||||
});*/
|
||||
services.AddSingleton<MqttClientMerossService>();
|
||||
services.AddSingleton<IHostedService>(serviceProvider =>
|
||||
{
|
||||
return serviceProvider.GetService<MqttClientMerossService>();
|
||||
});
|
||||
services.AddSingleton<MqttClientMerossServiceProvider>(serviceProvider =>
|
||||
{
|
||||
var merossClientService = serviceProvider.GetService<MqttClientMerossService>();
|
||||
var merossServiceProvider = new MqttClientMerossServiceProvider(merossClientService);
|
||||
return merossServiceProvider;
|
||||
});
|
||||
return services;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,89 @@
|
||||
using System;
|
||||
using Mqtt.Client.AspNetCore.Services;
|
||||
using MyCore.Interfaces.Models;
|
||||
using MyCore.Services.MyControlPanel;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Mqtt.Client.AspNetCore.Services.MqttClientMerossService;
|
||||
|
||||
namespace MyCore.Services.Devices
|
||||
{
|
||||
public class ActionService
|
||||
{
|
||||
public static bool isOpen = false;
|
||||
public static long lastActionTime;
|
||||
// TODO it's here that action are thrown.. Call from Mqtt Or other service like controller if from RpiServices
|
||||
public async static Task HandleActionFromMQTTAsync(string topic, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId)
|
||||
{
|
||||
// TODO Check if last action is not too close for each action
|
||||
var actionTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
var providers = _ProviderDatabaseService.GetAll(userId);
|
||||
string[] topicSplit = topic.Split('/');
|
||||
switch (topicSplit[0]) {
|
||||
case "zigbee2mqtt":
|
||||
// switch case according to device type (topic !)
|
||||
if (topicSplit[1].Contains("MagicCube0"))
|
||||
{
|
||||
var test = JsonConvert.DeserializeObject<AqaraCube>(message);
|
||||
if (test.Action == "shake")
|
||||
{
|
||||
if (YeelightService.devices.Count <= 0) {
|
||||
await YeelightService.GetDevices();
|
||||
}
|
||||
var labLamp = YeelightService.devices.Where(d => d.Hostname == "192.168.31.74").FirstOrDefault();
|
||||
if (labLamp != null) {
|
||||
Task.Run(async () => { await YeelightService.Toggle(labLamp); });
|
||||
}
|
||||
}
|
||||
if (test.Action == "tap")
|
||||
{
|
||||
var provider = providers.Where(p => p.Type == "meross").FirstOrDefault();
|
||||
var merossDevices = _DeviceDatabaseService.GetByProviderId(provider.Id);
|
||||
|
||||
var multiprise = merossDevices.Where(md => md.Name == "Multiprise bureau").FirstOrDefault();
|
||||
//var prise = merossDevices.Where(md => md.Name == "Imprimante 3D").FirstOrDefault();
|
||||
|
||||
if (multiprise != null)
|
||||
{
|
||||
//As multisocket channel 0 is all the sockets, skip 0
|
||||
var tests = actionTime - lastActionTime;
|
||||
if (tests >= 1000) {
|
||||
isOpen = !isOpen;
|
||||
if (isOpen)
|
||||
{
|
||||
/*foreach (var channel in multiprise.channels)
|
||||
{
|
||||
if (i != 0)
|
||||
MerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, i);
|
||||
i++;
|
||||
}*/
|
||||
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 1);
|
||||
//MqttClientMerossService.ExecuteCommand(prise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 1);
|
||||
//MqttClientMerossService.ExecuteCommand(prise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 0);
|
||||
}
|
||||
}
|
||||
|
||||
lastActionTime = actionTime;
|
||||
|
||||
}
|
||||
/*if (lightStateIkeaBulb == LightState.Undefined || lightStateIkeaBulb == LightState.Off)
|
||||
PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"ON\"}");
|
||||
else
|
||||
PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"OFF\"}");*/
|
||||
}
|
||||
//await MqttClientOnlineService.PublishMessage("Notification", "Hey magic cube 0 !");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using Mqtt.Client.AspNetCore.Services;
|
||||
using MyCore.Interfaces.DTO;
|
||||
using MyCore.Interfaces.Models;
|
||||
using MyCore.Interfaces.Models.MyControlPanel;
|
||||
using MyCore.Services.MyControlPanel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -14,6 +15,25 @@ namespace MyCore.Services.Devices
|
||||
{
|
||||
public class DeviceService
|
||||
{
|
||||
static List<SupportedDevice> supportedDevices = new List<SupportedDevice>() {
|
||||
new SupportedDevice { Manufacturer = "Aqara", Model = "RTCGQ11LM", Description = "Aqara human body movement and illuminance sensor", DeviceType = DeviceType.Motion },
|
||||
new SupportedDevice { Manufacturer = "Aqara", Model = "DJT11LM", Description = "Aqara vibration sensor", DeviceType = DeviceType.Environment },
|
||||
new SupportedDevice { Manufacturer = "Aqara", Model = "SJCGQ11LM", Description = "Aqara water leak sensor", DeviceType = DeviceType.Environment },
|
||||
new SupportedDevice { Manufacturer = "Aqara", Model = "WSDCGQ11LM", Description = "Aqara temperature, humidity and pressure sensor", DeviceType = DeviceType.Environment },
|
||||
|
||||
new SupportedDevice { Manufacturer = "Xiaomi", Model = "WXKG01LM", Description = "MiJia wireless switch", DeviceType = DeviceType.Switch },
|
||||
new SupportedDevice { Manufacturer = "Xiaomi", Model = "MFKZQ01LM", Description = "Mi/Aqara smart home cube", DeviceType = DeviceType.Switch },
|
||||
new SupportedDevice { Manufacturer = "Xiaomi", Model = "MCCGQ01LM", Description = "MiJia door & window contact sensor", DeviceType = DeviceType.Door },
|
||||
new SupportedDevice { Manufacturer = "Xiaomi", Model = "JTYJ-GD-01LM/BW", Description = "MiJia Honeywell smoke detector", DeviceType = DeviceType.Environment },
|
||||
new SupportedDevice { Manufacturer = "Xiaomi", Model = "ZNCZ04LM", Description = "Mi power plug ZigBee EU", DeviceType = DeviceType.Plug },
|
||||
|
||||
new SupportedDevice { Manufacturer = "Ikea", Model = "E1744", Description = "SYMFONISK Sound Controller", DeviceType = DeviceType.Switch },
|
||||
new SupportedDevice { Manufacturer = "Ikea", Model = "LED1836G9", Description = "TRADFRI LED bulb E26/E27 806 lumen, dimmable, warm white", DeviceType = DeviceType.Light },
|
||||
new SupportedDevice { Manufacturer = "Ikea", Model = "LED1842G3", Description = "TRADFRI LED bulb E27 WW clear 250 lumen, dimmable", DeviceType = DeviceType.Light },
|
||||
new SupportedDevice { Manufacturer = "Ikea", Model = "LED1837R5", Description = "TRADFRI LED bulb GU10 400 lumen, dimmable", DeviceType = DeviceType.Light },
|
||||
new SupportedDevice { Manufacturer = "Ikea", Model = "E1743", Description = "TRADFRI ON/OFF switch", DeviceType = DeviceType.Switch },
|
||||
new SupportedDevice { Manufacturer = "Ikea", Model = "E1524/E1810", Description = "TRADFRI remote control", DeviceType = DeviceType.Switch },
|
||||
};
|
||||
|
||||
public static DeviceDetailDTO CreateOrUpdate(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, DeviceDetailDTO deviceDetailDTO, bool create)
|
||||
{
|
||||
@ -32,6 +52,8 @@ namespace MyCore.Services.Devices
|
||||
|
||||
device.UserId = userId;
|
||||
device.Name = deviceDetailDTO.Name;
|
||||
device.Description = deviceDetailDTO.Description;
|
||||
device.ManufacturerName = deviceDetailDTO.ManufacturerName;
|
||||
|
||||
if (_ProviderDatabaseService.IsExist(deviceDetailDTO.ProviderId))
|
||||
device.ProviderId = deviceDetailDTO.ProviderId;
|
||||
@ -47,6 +69,7 @@ namespace MyCore.Services.Devices
|
||||
device.Model = deviceDetailDTO.Model;
|
||||
device.Type = deviceDetailDTO.Type;
|
||||
device.FirmwareVersion = deviceDetailDTO.FirmwareVersion;
|
||||
device.HardwareVersion = deviceDetailDTO.HardwareVersion;
|
||||
device.Status = deviceDetailDTO.Status;
|
||||
if (create)
|
||||
device.ConnectionStatus = ConnectionStatus.Unknown;
|
||||
@ -74,31 +97,31 @@ namespace MyCore.Services.Devices
|
||||
return _DeviceDatabaseService.Update(device.Id, device).ToDTO();
|
||||
}
|
||||
|
||||
public async static Task<List<DeviceDetailDTO>> CreateFromProvider(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, Provider provider)
|
||||
public async static Task<Dictionary<string, List<DeviceDetailDTO>>> CreateFromProvider(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, Provider provider)
|
||||
{
|
||||
if (!ProviderService.IsProviderSupported(provider.Type))
|
||||
throw new KeyNotFoundException("Provider is not yet supported");
|
||||
|
||||
List<DeviceDetailDTO> createdDevice = new List<DeviceDetailDTO>();
|
||||
Dictionary<string, List<DeviceDetailDTO>> devices = new Dictionary<string, List<DeviceDetailDTO>>();
|
||||
|
||||
try {
|
||||
switch (provider.Type)
|
||||
{
|
||||
case "arlo":
|
||||
List<ArloDevice> arloDevices = new ArloService(provider.Username, provider.Password).GetAllDevices();
|
||||
createdDevice = CreateArloDevices(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, arloDevices, provider);
|
||||
devices = CreateArloDevices(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, arloDevices, provider);
|
||||
break;
|
||||
case "meross":
|
||||
List<MerossDevice> merossDevices = new MerossService(provider.Username, provider.Password).GetMerossDevices();
|
||||
createdDevice = CreateMerossDevices(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, merossDevices, provider);
|
||||
List<MerossDevice> merossDevices = MqttClientMerossService.GetMerossDevices(); // TO TEST IF IT WORKS
|
||||
devices = CreateMerossDevices(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, merossDevices, provider);
|
||||
break;
|
||||
case "yeelight":
|
||||
List<YeelightAPI.Device> yeelightDevices = await new YeelightService().GetDevices();
|
||||
createdDevice = CreateYeelightDevices(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, yeelightDevices, provider);
|
||||
List<YeelightAPI.Device> yeelightDevices = await YeelightService.GetDevices();
|
||||
devices = CreateYeelightDevices(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, yeelightDevices, provider);
|
||||
break;
|
||||
case "zigbee2mqtt":
|
||||
List<Zigbee2MqttDevice> zigbee2MqttDevices = MqttClientService.devices;
|
||||
createdDevice = await CreateFromZigbeeAsync(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, zigbee2MqttDevices, provider);
|
||||
devices = await CreateFromZigbeeAsync(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, zigbee2MqttDevices, provider);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -111,14 +134,15 @@ namespace MyCore.Services.Devices
|
||||
catch (Exception ex) {
|
||||
|
||||
}
|
||||
return createdDevice;
|
||||
return devices;
|
||||
}
|
||||
|
||||
public static async Task<List<DeviceDetailDTO>> CreateFromZigbeeAsync(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<Zigbee2MqttDevice> zigbee2MqttDevices, Provider provider)
|
||||
public static async Task<Dictionary<string, List<DeviceDetailDTO>>> CreateFromZigbeeAsync(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<Zigbee2MqttDevice> zigbee2MqttDevices, Provider provider)
|
||||
{
|
||||
List<DeviceDetailDTO> createdZigbeeDevices = new List<DeviceDetailDTO>();
|
||||
List<DeviceDetailDTO> notSupportedZigbeeDevices = new List<DeviceDetailDTO>();
|
||||
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByprovider(provider.Id);
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id);
|
||||
|
||||
if (zigbee2MqttDevices.Count <= 0)
|
||||
{
|
||||
@ -136,25 +160,12 @@ namespace MyCore.Services.Devices
|
||||
deviceDetailDTO.ProviderId = provider.Id;
|
||||
deviceDetailDTO.ProviderName = provider.Name;
|
||||
|
||||
deviceDetailDTO.Model = zigbee2MqttDevice.model; // Will be the base to understand incoming messages !
|
||||
deviceDetailDTO.FirmwareVersion = zigbee2MqttDevice.softwareBuildID;
|
||||
deviceDetailDTO.Model = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.model; // Is the base to understand incoming messages !
|
||||
deviceDetailDTO.FirmwareVersion = zigbee2MqttDevice.softwareBuildID;
|
||||
deviceDetailDTO.HardwareVersion = zigbee2MqttDevice.hardwareVersion.ToString();
|
||||
|
||||
|
||||
deviceDetailDTO.Type = DeviceType.Unknown;
|
||||
|
||||
// TODO ! => switch case en fonction du model pour gestion des appareils compatibles
|
||||
if (zigbee2MqttDevice.type == "Coordinator") deviceDetailDTO.Type = DeviceType.Gateway;
|
||||
if (zigbee2MqttDevice.modelID.Contains("plug")) deviceDetailDTO.Type = DeviceType.Plug;
|
||||
if (zigbee2MqttDevice.modelID.Contains("bulb")) deviceDetailDTO.Type = DeviceType.Light;
|
||||
if (zigbee2MqttDevice.modelID.Contains("remote") || zigbee2MqttDevice.modelID.Contains("switch") || zigbee2MqttDevice.modelID.Contains("cube") || zigbee2MqttDevice.modelID.Contains("Sound Controller")) deviceDetailDTO.Type = DeviceType.Switch;
|
||||
if (zigbee2MqttDevice.modelID.Contains("magnet")) deviceDetailDTO.Type = DeviceType.Door;
|
||||
if (zigbee2MqttDevice.modelID.Contains("motion")) deviceDetailDTO.Type = DeviceType.Motion;
|
||||
if (zigbee2MqttDevice.modelID.Contains("weather") || zigbee2MqttDevice.modelID.Contains("smoke") || zigbee2MqttDevice.modelID.Contains("wleak") || zigbee2MqttDevice.modelID.Contains("vibration")) deviceDetailDTO.Type = DeviceType.Environment;
|
||||
|
||||
|
||||
deviceDetailDTO.Battery = zigbee2MqttDevice.powerSource.Contains("Battery");
|
||||
deviceDetailDTO.ManufacturerName = zigbee2MqttDevice.vendor;
|
||||
deviceDetailDTO.Battery = zigbee2MqttDevice.powerSource == null ? false : zigbee2MqttDevice.powerSource.Contains("Battery");
|
||||
deviceDetailDTO.ManufacturerName = zigbee2MqttDevice.vendor == null ? provider.Type : zigbee2MqttDevice.vendor.ToLower();
|
||||
deviceDetailDTO.MeansOfCommunications = new List<MeansOfCommunication>();
|
||||
deviceDetailDTO.MeansOfCommunications.Add(MeansOfCommunication.Zigbee);
|
||||
|
||||
@ -162,25 +173,48 @@ namespace MyCore.Services.Devices
|
||||
deviceDetailDTO.UpdatedDate = DateTime.Now;
|
||||
deviceDetailDTO.LastStateDate = new DateTime(zigbee2MqttDevice.lastSeen);
|
||||
|
||||
createdZigbeeDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, deviceDetailDTO, true));
|
||||
deviceDetailDTO.Type = zigbee2MqttDevice.type == "Coordinator" ? DeviceType.Gateway : GetDeviceTypeFromZigbeeModel(zigbee2MqttDevice.model);
|
||||
|
||||
if (deviceDetailDTO.Type != DeviceType.Unknown)
|
||||
{
|
||||
// Supoorted device !
|
||||
createdZigbeeDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, deviceDetailDTO, true));
|
||||
}
|
||||
else {
|
||||
// Not yet supported !
|
||||
notSupportedZigbeeDevices.Add(deviceDetailDTO);
|
||||
}
|
||||
}
|
||||
|
||||
return createdZigbeeDevices;
|
||||
|
||||
return new Dictionary<string, List<DeviceDetailDTO>>() {
|
||||
{ "createdDevices", createdZigbeeDevices },
|
||||
{ "notSupportedDevices", notSupportedZigbeeDevices }
|
||||
};
|
||||
}
|
||||
|
||||
public static List<DeviceDetailDTO> CreateArloDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<ArloDevice> arloDevices, Provider provider)
|
||||
private static DeviceType GetDeviceTypeFromZigbeeModel(string zigbeeModel)
|
||||
{
|
||||
return supportedDevices.Any(sd => sd.Model == zigbeeModel) ?
|
||||
// It's supported !
|
||||
supportedDevices.Where(sd => sd.Model == zigbeeModel).FirstOrDefault().DeviceType :
|
||||
// Not yet supported
|
||||
DeviceType.Unknown;
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<DeviceDetailDTO>> CreateArloDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<ArloDevice> arloDevices, Provider provider)
|
||||
{
|
||||
List<DeviceDetailDTO> createdArloDevices = new List<DeviceDetailDTO>();
|
||||
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByprovider(provider.Id);
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id);
|
||||
|
||||
arloDevices = arloDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.deviceId)).ToList();
|
||||
|
||||
foreach (var arlo in arloDevices)
|
||||
{
|
||||
DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO();
|
||||
deviceDetailDTO.ManufacturerName = provider.Type;
|
||||
deviceDetailDTO.Name = arlo.deviceName;
|
||||
deviceDetailDTO.Description = arlo.deviceName; // As description not exist, put name in description
|
||||
deviceDetailDTO.ServiceIdentification = arlo.deviceId;
|
||||
deviceDetailDTO.ProviderId = provider.Id;
|
||||
deviceDetailDTO.ProviderName = provider.Name;
|
||||
@ -221,21 +255,24 @@ namespace MyCore.Services.Devices
|
||||
createdArloDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, deviceDetailDTO, true));
|
||||
}
|
||||
|
||||
return createdArloDevices;
|
||||
return new Dictionary<string, List<DeviceDetailDTO>>() { { "createdDevices", createdArloDevices } }; // TODO Check if exist not supported devices
|
||||
}
|
||||
|
||||
public static List<DeviceDetailDTO> CreateMerossDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<MerossDevice> merossDevices, Provider provider)
|
||||
public static Dictionary<string, List<DeviceDetailDTO>> CreateMerossDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<MerossDevice> merossDevices, Provider provider)
|
||||
{
|
||||
List<DeviceDetailDTO> createdMerossDevices = new List<DeviceDetailDTO>();
|
||||
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByprovider(provider.Id);
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id);
|
||||
|
||||
merossDevices = merossDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.uuid)).ToList();
|
||||
|
||||
foreach (var meross in merossDevices)
|
||||
{
|
||||
DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO();
|
||||
deviceDetailDTO.ManufacturerName = provider.Type;
|
||||
deviceDetailDTO.HardwareVersion = meross.hdwareVersion;
|
||||
deviceDetailDTO.Name = meross.devName;
|
||||
deviceDetailDTO.Description = meross.devName; // As description not exist, put name in description
|
||||
deviceDetailDTO.ServiceIdentification = meross.uuid;
|
||||
deviceDetailDTO.ProviderId = provider.Id;
|
||||
deviceDetailDTO.ProviderName = provider.Name;
|
||||
@ -273,21 +310,23 @@ namespace MyCore.Services.Devices
|
||||
createdMerossDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, deviceDetailDTO, true));
|
||||
}
|
||||
|
||||
return createdMerossDevices;
|
||||
return new Dictionary<string, List<DeviceDetailDTO>>() { { "createdDevices", createdMerossDevices } }; // TODO Check if exist not supported devices
|
||||
}
|
||||
|
||||
public static List<DeviceDetailDTO> CreateYeelightDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<YeelightAPI.Device> yeelightDevices, Provider provider)
|
||||
public static Dictionary<string, List<DeviceDetailDTO>> CreateYeelightDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string userId, List<YeelightAPI.Device> yeelightDevices, Provider provider)
|
||||
{
|
||||
List<DeviceDetailDTO> createdYeelightDevices = new List<DeviceDetailDTO>();
|
||||
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByprovider(provider.Id);
|
||||
List<Device> existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id);
|
||||
|
||||
yeelightDevices = yeelightDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.Id)).ToList();
|
||||
|
||||
foreach (var light in yeelightDevices)
|
||||
{
|
||||
DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO();
|
||||
deviceDetailDTO.ManufacturerName = provider.Type;
|
||||
deviceDetailDTO.Name = light.Name;
|
||||
deviceDetailDTO.Description = light.Name; // As description not exist, put name in description
|
||||
deviceDetailDTO.IpAddress = light.Hostname;
|
||||
deviceDetailDTO.ServiceIdentification = light.Id;
|
||||
deviceDetailDTO.ProviderId = provider.Id;
|
||||
@ -317,7 +356,7 @@ namespace MyCore.Services.Devices
|
||||
createdYeelightDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, userId, deviceDetailDTO, true));
|
||||
}
|
||||
|
||||
return createdYeelightDevices;
|
||||
return new Dictionary<string, List<DeviceDetailDTO>>() { { "createdDevices", createdYeelightDevices } }; // TODO Check if exist not supported devices
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,8 +146,8 @@ namespace MyCore.Services
|
||||
var test = JsonConvert.DeserializeObject<AqaraCube>(payload);
|
||||
if (test.Action == "shake")
|
||||
{
|
||||
var labLamp = yeelightService.devices.Where(d => d.Hostname == "192.168.31.74").FirstOrDefault();
|
||||
Task.Run(async () => { await yeelightService.Toggle(labLamp); });
|
||||
/*var labLamp = yeelightService.devices.Where(d => d.Hostname == "192.168.31.74").FirstOrDefault();
|
||||
Task.Run(async () => { await yeelightService.Toggle(labLamp); });*/
|
||||
}
|
||||
if (test.Action == "slide")
|
||||
{
|
||||
@ -184,10 +184,10 @@ namespace MyCore.Services
|
||||
|
||||
if (aqaraSwitch.Click == "single") {
|
||||
YeelightService yeelighService = new YeelightService();
|
||||
var devicesYeelight = yeelighService.GetDevices().Result;
|
||||
var labLamp = devicesYeelight.Where(light => light.Hostname == "192.168.31.74").FirstOrDefault();
|
||||
if (labLamp != null)
|
||||
yeelightService.Toggle(labLamp);
|
||||
// var devicesYeelight = yeelighService.GetDevices().Result;
|
||||
// var labLamp = devicesYeelight.Where(light => light.Hostname == "192.168.31.74").FirstOrDefault();
|
||||
//if (labLamp != null) { }
|
||||
// yeelightService.Toggle(labLamp);
|
||||
}
|
||||
|
||||
if (aqaraSwitch.Click == "double")
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
using MQTTnet;
|
||||
using Mqtt.Client.AspNetCore.Services;
|
||||
using MQTTnet;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Implementations;
|
||||
@ -19,7 +21,7 @@ using static MyCore.Interfaces.Models.DeviceAbilities;
|
||||
|
||||
namespace MyCore.Services
|
||||
{
|
||||
public class MerossService
|
||||
public class MerossService
|
||||
{
|
||||
// API HTTP
|
||||
private const string _merossUrl = "https://iot.meross.com";
|
||||
@ -39,7 +41,7 @@ namespace MyCore.Services
|
||||
private const int port = 2001;
|
||||
private const string domain = "iot.meross.com";
|
||||
|
||||
private IMqttClient _client;
|
||||
private static IMqttClient _client;
|
||||
private IMqttClientOptions _options;
|
||||
private string _userMQTT;
|
||||
private string _passwordMQTT;
|
||||
@ -67,7 +69,7 @@ namespace MyCore.Services
|
||||
|
||||
public MerossService(string username, string password)
|
||||
{
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// TODO
|
||||
@ -94,7 +96,7 @@ namespace MyCore.Services
|
||||
}*/
|
||||
|
||||
//MQTT CONNEXION TODO Create a Connexion To MQTT method
|
||||
// ConnexionToMqtt();
|
||||
ConnexionToMqtt();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -104,6 +106,30 @@ namespace MyCore.Services
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _client.ConnectAsync(_options);
|
||||
if (!_client.IsConnected)
|
||||
{
|
||||
await _client.ReconnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var disconnectOption = new MqttClientDisconnectOptions
|
||||
{
|
||||
ReasonCode = MqttClientDisconnectReason.NormalDisconnection,
|
||||
ReasonString = "NormalDiconnection"
|
||||
};
|
||||
await _client.DisconnectAsync(disconnectOption, cancellationToken);
|
||||
}
|
||||
await _client.DisconnectAsync();
|
||||
}
|
||||
|
||||
|
||||
public List<MerossDevice> GetMerossDevices() {
|
||||
// GET DEVICE LIST
|
||||
var deviceTask = Task.Run(() => PostURI(new Uri(_devList), RequestType.DeviceList));
|
||||
@ -278,7 +304,7 @@ namespace MyCore.Services
|
||||
}
|
||||
|
||||
public string clientId = "";
|
||||
public string appId = "";
|
||||
public static string appId = "";
|
||||
|
||||
private void ConnexionToMqtt()
|
||||
{
|
||||
@ -304,9 +330,11 @@ namespace MyCore.Services
|
||||
.WithProtocolVersion(MqttProtocolVersion.V311)
|
||||
.Build();
|
||||
|
||||
_client.ConnectAsync(_options, CancellationToken.None).ContinueWith(res => {
|
||||
_client.ConnectAsync(_options, CancellationToken.None).ContinueWith(res =>
|
||||
{
|
||||
if (res.Status == TaskStatus.RanToCompletion)
|
||||
{
|
||||
ExecuteCommand("1912209125699190807048e1e9144656", Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 1);
|
||||
Console.WriteLine("It's connected");
|
||||
}
|
||||
else
|
||||
@ -417,7 +445,7 @@ namespace MyCore.Services
|
||||
clientId = $"app:{md5Result}";
|
||||
}
|
||||
|
||||
private void ExecuteCommand(string uuid, Method method, CommandMqtt command, string payload = null, string callback = null, ToggleStatus toggleStatus = 0,int channelChosen = 0)
|
||||
public void ExecuteCommand(string uuid, Method method, CommandMqtt command, string payload = null, string callback = null, ToggleStatus toggleStatus = 0,int channelChosen = 0)
|
||||
{
|
||||
var topic = $"/appliance/{uuid}/subscribe";
|
||||
var namespaceVar = "";
|
||||
@ -475,7 +503,7 @@ namespace MyCore.Services
|
||||
PublishMessage(topic, message);
|
||||
}
|
||||
|
||||
private string BuildMQTTMessage(Method method, string namespaceVar, string payloadVar)
|
||||
private static string BuildMQTTMessage(Method method, string namespaceVar, string payloadVar)
|
||||
{
|
||||
HeaderMqtt headerMqtt = new HeaderMqtt();
|
||||
|
||||
@ -503,7 +531,7 @@ namespace MyCore.Services
|
||||
return data;
|
||||
}
|
||||
|
||||
public void PublishMessage(string topic, string message)
|
||||
public static void PublishMessage(string topic, string message)
|
||||
{
|
||||
var mqttMessage = new MqttApplicationMessageBuilder()
|
||||
.WithTopic(topic)
|
||||
@ -8,15 +8,15 @@ namespace MyCore.Services
|
||||
{
|
||||
public class YeelightService
|
||||
{
|
||||
public List<Device> devices = new List<Device>();
|
||||
public static List<Device> devices = new List<Device>();
|
||||
|
||||
public async Task<List<YeelightAPI.Device>> GetDevices()
|
||||
public static async Task<List<YeelightAPI.Device>> GetDevices()
|
||||
{
|
||||
devices = await DeviceLocator.Discover();
|
||||
return devices;
|
||||
}
|
||||
|
||||
public async Task<bool> Toggle(Device device)
|
||||
public static async Task<bool> Toggle(Device device)
|
||||
{
|
||||
await device.Connect();
|
||||
return await device.Toggle();
|
||||
|
||||
@ -28,7 +28,7 @@ namespace MyCore.Services.MyControlPanel
|
||||
return _Devices.Find<Device>(d => d.Id == id).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<Device> GetByprovider(string providerId)
|
||||
public List<Device> GetByProviderId(string providerId)
|
||||
{
|
||||
return _Devices.Find(d => d.ProviderId == providerId).ToList();
|
||||
}
|
||||
|
||||
@ -38,6 +38,11 @@ namespace MyCore.Services.MyControlPanel
|
||||
return _Providers.Find<Provider>(p => p.Name == name).FirstOrDefault();
|
||||
}
|
||||
|
||||
public Provider GetByType(string type)
|
||||
{
|
||||
return _Providers.Find<Provider>(p => p.Type == type).FirstOrDefault();
|
||||
}
|
||||
|
||||
public bool IsExist(string id)
|
||||
{
|
||||
return _Providers.Find<Provider>(p => p.Id == id).FirstOrDefault() != null ? true : false;
|
||||
|
||||
@ -35,6 +35,7 @@ using MQTTnet.AspNetCore.Extensions;
|
||||
using MyCore.Service.Extensions;
|
||||
using Mqtt.Client.AspNetCore.Services;
|
||||
using Mqtt.Client.AspNetCore.Settings;
|
||||
using MyCore.Services.Devices;
|
||||
|
||||
namespace MyCore
|
||||
{
|
||||
@ -44,17 +45,7 @@ namespace MyCore
|
||||
{
|
||||
Configuration = configuration;
|
||||
|
||||
//MQTTService mQTTService = new MQTTService();
|
||||
|
||||
//MerossService merossService = new MerossService();
|
||||
|
||||
//ArloService arloService = new ArloService();
|
||||
|
||||
/*YeelightService yeelighService = new YeelightService();
|
||||
yeelighService.GetDevices();*/
|
||||
|
||||
MapConfiguration();
|
||||
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
@ -193,6 +184,13 @@ namespace MyCore
|
||||
};
|
||||
});
|
||||
|
||||
services.AddMqttClientHostedService(); // Todo client files (a lot are useless)
|
||||
services.AddMqttClientOnlineHostedService();
|
||||
|
||||
services.AddMerossClientHostedService(); // Todo client files (a lot are useless)
|
||||
|
||||
services.AddScoped<YeelightService>(); // To clarify if needed.. ?
|
||||
|
||||
services.AddScoped<TokensService>();
|
||||
services.AddScoped(typeof(ProfileLogic));
|
||||
|
||||
@ -202,10 +200,8 @@ namespace MyCore
|
||||
services.AddScoped<ProviderDatabaseService>();
|
||||
services.AddScoped<DeviceDatabaseService>();
|
||||
services.AddScoped<LocationDatabaseService>();
|
||||
services.AddScoped<ActionService>();
|
||||
services.AddScoped<RoomDatabaseService>();
|
||||
|
||||
services.AddMqttClientHostedService(); // Todo client files (a lot are useless)
|
||||
services.AddMqttClientOnlineHostedService();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
|
||||
@ -45,5 +45,16 @@
|
||||
"Id": "5eb020f043ba8930506acbaa",
|
||||
"UserName": "thomas",
|
||||
"Password": "MyCore,1"
|
||||
},
|
||||
|
||||
"BrokerMerossHostSettings": {
|
||||
"Host": "iot.meross.com",
|
||||
"Port": 2001
|
||||
},
|
||||
|
||||
"ClientMerossSettings": {
|
||||
"Id": "5eb020f043ba8930506acbbb",
|
||||
"UserName": "thomas",
|
||||
"Password": "MyCore,1"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user