parent
de6ba209d3
commit
7af05b88b9
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"todo-tree.tree.showBadges": true,
|
||||||
|
"todo-tree.tree.showCountsInTree": true
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
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<MqttPublisher> _logger;
|
||||||
|
public DateTime LastConfigAnnounce { get; private set; }
|
||||||
|
public DeviceConfigModel DeviceConfigModel { get; private set; }
|
||||||
|
public bool IsConnected
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this._mqttClient.IsConnected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttPublisher(
|
||||||
|
ILogger<MqttPublisher> 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.Device.Identifiers}/config")
|
||||||
|
.WithPayload(clearPreviousConfig ? "" : JsonSerializer.Serialize(config, options))
|
||||||
|
.WithRetainFlag()
|
||||||
|
.Build();
|
||||||
|
await this.Publish(message);
|
||||||
|
LastConfigAnnounce = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace hass_desktop_service.Communication.Util
|
||||||
|
{
|
||||||
|
public class CamelCaseJsonNamingpolicy : JsonNamingPolicy
|
||||||
|
{
|
||||||
|
public override string ConvertName(string name) => name.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace hass_desktop_service.Data
|
||||||
|
{
|
||||||
|
public class ConfiguredSensor
|
||||||
|
{
|
||||||
|
public string Type { get; set; }
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.IsolatedStorage;
|
||||||
|
using System.Text.Json;
|
||||||
|
using hass_desktop_service.Communication;
|
||||||
|
using hass_desktop_service.Domain.Sensors;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace hass_desktop_service.Data
|
||||||
|
{
|
||||||
|
public class ConfiguredSensorsService
|
||||||
|
{
|
||||||
|
public ICollection<AbstractSensor> ConfiguredSensors { get; private set; }
|
||||||
|
public IConfiguration Configuration { get; private set; }
|
||||||
|
private readonly MqttPublisher _publisher;
|
||||||
|
private readonly IsolatedStorageFile _fileStorage;
|
||||||
|
|
||||||
|
public ConfiguredSensorsService(MqttPublisher publisher)
|
||||||
|
{
|
||||||
|
this._fileStorage = IsolatedStorageFile.GetUserStoreForApplication();
|
||||||
|
|
||||||
|
ConfiguredSensors = new List<AbstractSensor>();
|
||||||
|
_publisher = publisher;
|
||||||
|
ReadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void ReadSettings()
|
||||||
|
{
|
||||||
|
IsolatedStorageFileStream stream = this._fileStorage.OpenFile("configured-sensors.json", FileMode.OpenOrCreate);
|
||||||
|
List<ConfiguredSensor> sensors = await JsonSerializer.DeserializeAsync<List<ConfiguredSensor>>(stream);
|
||||||
|
|
||||||
|
foreach (ConfiguredSensor configuredSensor in sensors)
|
||||||
|
{
|
||||||
|
AbstractSensor sensor;
|
||||||
|
#pragma warning disable IDE0066
|
||||||
|
switch (configuredSensor.Type)
|
||||||
|
{
|
||||||
|
case "UserNotificationStateSensor":
|
||||||
|
sensor = new UserNotificationStateSensor(_publisher, configuredSensor.Name, configuredSensor.Id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException("unsupported sensor type in config");
|
||||||
|
}
|
||||||
|
this.ConfiguredSensors.Add(sensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddConfiguredSensor(AbstractSensor sensor)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using hass_desktop_service.Domain.Sensors;
|
||||||
|
|
||||||
|
namespace hass_desktop_service.Domain
|
||||||
|
{
|
||||||
|
public abstract class Device
|
||||||
|
{
|
||||||
|
public Guid Id { get; private set; }
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public string Manufacturer { get; private set; }
|
||||||
|
public string Model { get; private set; }
|
||||||
|
public string Version { get; private set; }
|
||||||
|
|
||||||
|
public ICollection<AbstractSensor> Sensors { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using hass_desktop_service.Communication;
|
||||||
|
using MQTTnet;
|
||||||
|
|
||||||
|
namespace hass_desktop_service.Domain.Sensors
|
||||||
|
{
|
||||||
|
public abstract class AbstractSensor
|
||||||
|
{
|
||||||
|
public Guid Id { get; protected set; }
|
||||||
|
public string Name { get; protected set; }
|
||||||
|
public MqttPublisher Publisher { get; protected set; }
|
||||||
|
protected AutoDiscoveryConfigModel _autoDiscoveryConfigModel;
|
||||||
|
protected AutoDiscoveryConfigModel SetAutoDiscoveryConfigModel(AutoDiscoveryConfigModel config)
|
||||||
|
{
|
||||||
|
this._autoDiscoveryConfigModel = config;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract AutoDiscoveryConfigModel GetAutoDiscoveryConfig();
|
||||||
|
public abstract string GetState();
|
||||||
|
|
||||||
|
public async Task PublishStateAsync()
|
||||||
|
{
|
||||||
|
var message = new MqttApplicationMessageBuilder()
|
||||||
|
.WithTopic(this.GetAutoDiscoveryConfig().State_topic)
|
||||||
|
.WithPayload(this.GetState())
|
||||||
|
.WithExactlyOnceQoS()
|
||||||
|
.WithRetainFlag()
|
||||||
|
.Build();
|
||||||
|
await Publisher.Publish(message);
|
||||||
|
}
|
||||||
|
public async Task PublishAutoDiscoveryConfigAsync()
|
||||||
|
{
|
||||||
|
await this.Publisher.PublishAutoDiscoveryConfig(this.GetAutoDiscoveryConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue