using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using hass_desktop_service.Communication.Util; using Microsoft.Extensions.Logging; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; namespace hass_desktop_service.Communication { public class MqttPublisher { private readonly IMqttClient _mqttClient; private readonly ILogger _logger; public DateTime LastConfigAnnounce { get; private set; } public DeviceConfigModel DeviceConfigModel { get; private set; } public bool IsConnected { get { return this._mqttClient.IsConnected; } } public MqttPublisher( ILogger logger, IMqttClientOptions options, DeviceConfigModel deviceConfigModel) { this._logger = logger; this.DeviceConfigModel = deviceConfigModel; var factory = new MqttFactory(); this._mqttClient = factory.CreateMqttClient(); // connect to the broker this._mqttClient.ConnectAsync(options); // configure what happens on disconnect this._mqttClient.UseDisconnectedHandler(async e => { _logger.LogWarning("Disconnected from server"); await Task.Delay(TimeSpan.FromSeconds(5)); try { await this._mqttClient.ConnectAsync(options, CancellationToken.None); } catch { _logger.LogError("Reconnecting failed"); } }); } public async Task Publish(MqttApplicationMessage message) { if (this._mqttClient.IsConnected) { await this._mqttClient.PublishAsync(message); } else { this._logger.LogInformation($"message dropped because mqtt not connected: {message}"); } } public async Task PublishAutoDiscoveryConfig(AutoDiscoveryConfigModel config, bool clearPreviousConfig = false) { if (this._mqttClient.IsConnected) { var options = new JsonSerializerOptions { PropertyNamingPolicy = new CamelCaseJsonNamingpolicy(), IgnoreNullValues = true, PropertyNameCaseInsensitive = true }; var message = new MqttApplicationMessageBuilder() .WithTopic($"homeassistant/sensor/{config.Name}/config") .WithPayload(clearPreviousConfig ? "" : JsonSerializer.Serialize(config, options)) .WithRetainFlag() .Build(); await this.Publish(message); LastConfigAnnounce = DateTime.UtcNow; } } } }