using MQTTnet; using MQTTnet.Client; 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; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Mqtt.Client.AspNetCore.Services { public class MqttClientService : IMqttClientService { private static IMqttClient mqttClient; private IMqttClientOptions options; public static List devices = new List(); public static string userId; static DeviceDatabaseService _deviceDatabaseService; static ProviderDatabaseService _providerDatabaseService; static LocationDatabaseService _locationDatabaseService; static AutomationDatabaseService _automationDatabaseService; static ActionService _actionService; public MqttClientService(IMqttClientOptions options) { this.options = options; this.options = new MqttClientOptionsBuilder() .WithClientId("ApiServiceTest") // prod = ApiService .WithTcpServer("192.168.31.140") // TODO replace by localhost .WithCredentials("mqtt", "mqtt") .WithCleanSession() .Build(); mqttClient = new MqttFactory().CreateMqttClient(); ConfigureMqttClient(); } private void ConfigureMqttClient() { mqttClient.ConnectedHandler = this; mqttClient.DisconnectedHandler = this; mqttClient.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; if (_actionService != null) { ActionService.HandleActionFromMQTTAsync(topic, payload, _deviceDatabaseService, _providerDatabaseService, _locationDatabaseService, _automationDatabaseService, userId); } //if () { } //List Devices = _DeviceDatabaseService.GetByProviderId(topic); switch (topic) { case "zigbee2mqtt/bridge/config/devices": try { var test = JsonConvert.DeserializeObject>(payload); devices = test; // TODO Update in DB, current devices state } catch (Exception ex) { Console.WriteLine($"Error during retrieving devices ! Exception: {ex}"); } break; } //return new Task(null); // TODO check what to do //await PublishMessage("test", "teeest"); return null; } public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs) { 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) { if (!mqttClient.IsConnected) { await mqttClient.ReconnectAsync(); } //throw new System.NotImplementedException(); } public async Task StartAsync(CancellationToken cancellationToken) { await mqttClient.ConnectAsync(options); if (!mqttClient.IsConnected) { await mqttClient.ReconnectAsync(); } } public async Task StopAsync(CancellationToken cancellationToken) { if(cancellationToken.IsCancellationRequested) { var disconnectOption = new MqttClientDisconnectOptions { ReasonCode = MqttClientDisconnectReason.NormalDisconnection, ReasonString = "NormalDiconnection" }; await mqttClient.DisconnectAsync(disconnectOption, cancellationToken); } await mqttClient.DisconnectAsync(); } public static async Task PublishMessage(string topic, string message) { var mqttMessage = new MqttApplicationMessageBuilder() .WithTopic(topic) .WithPayload(message) .WithExactlyOnceQoS() .WithRetainFlag() .Build(); if (mqttClient.IsConnected) await mqttClient.PublishAsync(mqttMessage); } public static List GetDevices() { return devices; } public static void SetServices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, ActionService _ActionService, AutomationDatabaseService _AutomationDatabaseService, string UserId) { _deviceDatabaseService = _DeviceDatabaseService; _providerDatabaseService = _ProviderDatabaseService; _locationDatabaseService = _LocationDatabaseService; _automationDatabaseService = _AutomationDatabaseService; _actionService = _ActionService; userId = UserId; } public static async Task> AskDevicesAsync() { await PublishMessage("zigbee2mqtt/bridge/config/devices/get", ""); // WARNING BAD CODE BELOW while (devices.Count <= 0) { // wait } return devices; } } }