diff --git a/fipha/App.xaml.cs b/fipha/App.xaml.cs index 00e8c96..e62881e 100644 --- a/fipha/App.xaml.cs +++ b/fipha/App.xaml.cs @@ -95,7 +95,7 @@ private static void RunProcess(string fileName) process.Start(); process.WaitForExit(); } - + protected override void OnStartup(StartupEventArgs evtArgs) { const string appName = "fipha"; @@ -140,7 +140,7 @@ protected override void OnStartup(StartupEventArgs evtArgs) } } - catch(Exception ex) + catch (Exception ex) { Log.Error("Connecting to Home Assistant Failed", ex); } @@ -160,7 +160,7 @@ protected override void OnStartup(StartupEventArgs evtArgs) Task.Run(async () => { - + if (EntityClient != null) { var config = new TemplateServiceConfiguration @@ -175,7 +175,8 @@ protected override void OnStartup(StartupEventArgs evtArgs) "System.Collections.Generic" }*/ }; - splashScreen.Dispatcher.Invoke(() => splashScreen.ProgressText.Text = "Loading cshtml templates..."); + splashScreen.Dispatcher.Invoke(() => + splashScreen.ProgressText.Text = "Loading cshtml templates..."); Engine.Razor = RazorEngineService.Create(config); @@ -210,23 +211,24 @@ protected override void OnStartup(StartupEventArgs evtArgs) Log.Info($"{mediaPlayer}"); } } - catch(Exception ex ) + catch (Exception ex) { - Log.Error("Finding Media Players",ex ); + Log.Error("Finding Media Players", ex); } } else { - Log.Error("No Home Assistant Connection"); + Log.Error("No Home Assistant Connection for Flight Instrument Panels"); } - splashScreen.Dispatcher.Invoke(() => splashScreen.ProgressText.Text = "Getting sensor data from HWInfo..."); + splashScreen.Dispatcher.Invoke(() => + splashScreen.ProgressText.Text = "Getting sensor data from HWInfo..."); HWInfo.ReadMem("HWINFO.INC"); - + if (HWInfo.SensorData.Any()) { - Log.Info($"Writing { HWInfo.SensorData.Count} HWINFO Sensors to hwinfo.json"); + Log.Info($"Writing {HWInfo.SensorData.Count} HWINFO Sensors to hwinfo.json"); HWInfo.SaveDataToFile(@"Data\hwinfo.json"); } @@ -259,7 +261,7 @@ protected override void OnStartup(StartupEventArgs evtArgs) }); Dispatcher.Invoke(() => { splashScreen.Close(); }); - + var haMediaPlayerToken = _haMediaPlayerTokenSource.Token; @@ -350,20 +352,27 @@ protected override void OnStartup(StartupEventArgs evtArgs) if (sensor.State.Attributes.ContainsKey("unit_of_measurement")) { - sensor.Value += " " + (string)sensor.State.Attributes["unit_of_measurement"]; + sensor.Value += " " + + (string)sensor.State.Attributes[ + "unit_of_measurement"]; } - if (string.IsNullOrEmpty(sensor.Name) && sensor.State.Attributes.ContainsKey("friendly_name")) + if (string.IsNullOrEmpty(sensor.Name) && + sensor.State.Attributes.ContainsKey("friendly_name")) { sensor.Name = (string)sensor.State.Attributes["friendly_name"]; } if (HistoryClient != null && sensor.Chart) { - sensor.HistoryList = await HistoryClient.GetHistory(sensor.EntityId, - DateTime.Now.AddMinutes(-sensor.ChartMinutes), DateTime.Now); + sensor.HistoryList = await HistoryClient.GetHistory( + sensor.EntityId, + DateTime.Now.AddMinutes(-sensor.ChartMinutes), + DateTime.Now); - (sensor.Points, sensor.MinVString, sensor.MaxVString) = HistoryToChart(sensor, FipPanel.ChartImageDisplayWidth, FipPanel.ChartImageDisplayHeight); + (sensor.Points, sensor.MinVString, sensor.MaxVString) = + HistoryToChart(sensor, FipPanel.ChartImageDisplayWidth, + FipPanel.ChartImageDisplayHeight); } } @@ -373,7 +382,7 @@ protected override void OnStartup(StartupEventArgs evtArgs) { sensor.Value = "-"; } - + } } } @@ -389,83 +398,70 @@ protected override void OnStartup(StartupEventArgs evtArgs) var hwInfoToken = _hwInfoTokenSource.Token; - if (File.Exists(Path.Combine(App.ExePath, "mqtt.config")) && HWInfo.SensorData.Any()) + if (File.Exists(Path.Combine(App.ExePath, "mqtt.config")) && HWInfo.SensorData.Any()) { - HWInfoTask = Task.Run(async () => { - var result = await MQTT.Connect(); - if (!result) - { - Log.Info("Failed to connect to MQTT server"); - } - else - { - - + await MQTT.Connect(); - Log.Info("HWInfo task started"); + Log.Info("HWInfo task started"); - if (HWInfo.SensorData.Any()) + if (HWInfo.SensorData.Any()) + { + foreach (var sensor in HWInfo.SensorData) { - - foreach (var sensor in HWInfo.SensorData) + foreach (var element in sensor.Value.Elements) { - foreach (var element in sensor.Value.Elements) + var mqttValue = JsonConvert.SerializeObject(new HWInfo.MQTTDiscoveryObj { - var mqttValue = JsonConvert.SerializeObject(new HWInfo.MQTTDiscoveryObj - { - device_class = element.Value.DeviceClass, - name = element.Value.Name, - state_topic = - $"homeassistant/{element.Value.Component}/{element.Value.Node}/state", - unit_of_measurement = element.Value.Unit, - value_template = "{{ value_json.value}}", - unique_id = element.Value.Node, - state_class = "measurement" - }, new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore - }); + device_class = element.Value.DeviceClass, + name = element.Value.Name, + state_topic = + $"homeassistant/{element.Value.Component}/{element.Value.Node}/state", + unit_of_measurement = element.Value.Unit, + value_template = "{{ value_json.value}}", + unique_id = element.Value.Node, + state_class = "measurement" + }, new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore + }); - var task = Task.Run(async () => - await MQTT.Publish( - $"homeassistant/{element.Value.Component}/{element.Value.Node}/config", - mqttValue)); + await MQTT.Publish( + $"homeassistant/{element.Value.Component}/{element.Value.Node}/config", + mqttValue); - } } + } - while (true) + while (true) + { + if (hwInfoToken.IsCancellationRequested) { - if (hwInfoToken.IsCancellationRequested) - { - hwInfoToken.ThrowIfCancellationRequested(); - } + hwInfoToken.ThrowIfCancellationRequested(); + } - HWInfo.ReadMem("HWINFO.INC"); + HWInfo.ReadMem("HWINFO.INC"); - foreach (var sensor in HWInfo.SensorData) + foreach (var sensor in HWInfo.SensorData) + { + foreach (var element in sensor.Value.Elements) { - foreach (var element in sensor.Value.Elements) + var mqttValue = JsonConvert.SerializeObject(new HWInfo.MQTTStateObj { - var mqttValue = JsonConvert.SerializeObject(new HWInfo.MQTTStateObj - { - value = element.Value.NumericValue - }); - - var task = Task.Run(async () => - await MQTT.Publish( - $"homeassistant/{element.Value.Component}/{element.Value.Node}/state", - mqttValue)); - } + value = element.Value.NumericValue + }); + await MQTT.Publish( + $"homeassistant/{element.Value.Component}/{element.Value.Node}/state", + mqttValue); } - //!!!FipHandler.RefreshHWInfoPages(); - - await Task.Delay(5 * 1000, _hwInfoTokenSource.Token); // repeat every 5 seconds } + + //!!!FipHandler.RefreshHWInfoPages(); + + await Task.Delay(5 * 1000, _hwInfoTokenSource.Token); // repeat every 5 seconds } } @@ -475,7 +471,7 @@ await MQTT.Publish( }); } - + protected override void OnExit(ExitEventArgs e) { diff --git a/fipha/Mqtt.cs b/fipha/Mqtt.cs index 2d92489..2c7c93b 100644 --- a/fipha/Mqtt.cs +++ b/fipha/Mqtt.cs @@ -11,6 +11,7 @@ using System.Xml; using MQTTnet; using MQTTnet.Client; +using MQTTnet.Extensions.ManagedClient; using MQTTnet.Protocol; namespace fipha @@ -18,7 +19,7 @@ namespace fipha public static class MQTT { private static MqttFactory factory = new MqttFactory(); - private static IMqttClient mqttClient = factory.CreateMqttClient(); + private static IManagedMqttClient mqttClient = factory.CreateManagedMqttClient(); private static string ClientId = Guid.NewGuid().ToString(); private static string mqttURI; @@ -29,24 +30,41 @@ public static class MQTT public static async Task Publish(string channel, string value) { - if (mqttClient.IsConnected == false) - { - return false; - } - var message = new MqttApplicationMessageBuilder() .WithTopic(channel) .WithPayload(value) - //.WithAtMostOnceQoS() - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) - //.WithRetainFlag() + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithRetainFlag() .Build(); - var result = await mqttClient.PublishAsync(message); - - return result.ReasonCode == MqttClientPublishReasonCode.Success; + try { + await mqttClient.EnqueueAsync(message); + } + catch (Exception ex) + { + App.Log.Error($"MQTT Client : Enqueue Failed", ex); + } + + return true; + } + + private static void MqttOnConnectingFailed(ConnectingFailedEventArgs e) + { + App.Log.Error($"MQTT Client: Connection Failed", e.Exception); + } + + private static void MqttOnConnected(MqttClientConnectedEventArgs e) + { + + App.Log.Info($"MQTT Client: Connected with result: {e.ConnectResult?.ResultCode}"); } - + + private static void MqttOnDisconnected(MqttClientDisconnectedEventArgs e) + { + + App.Log.Error($"MQTT Client: Connection lost with reason: {e.Reason}."); + } + public static async Task Connect() { if (File.Exists(Path.Combine(App.ExePath, "mqtt.config"))) @@ -78,6 +96,7 @@ public static async Task Connect() else return false; var messageBuilder = new MqttClientOptionsBuilder() + //.WithProtocolVersion(MqttProtocolVersion.V500) .WithClientId(ClientId) .WithCredentials(mqttUser, mqttPassword) .WithTcpServer(mqttURI, mqttPort) @@ -90,24 +109,38 @@ public static async Task Connect() : messageBuilder .Build(); + var managedOptions = new ManagedMqttClientOptionsBuilder() + .WithAutoReconnectDelay(TimeSpan.FromSeconds(30)) + .WithClientOptions(options) + .Build(); + try { - var result = await mqttClient.ConnectAsync(options, CancellationToken.None); - - if (result.ResultCode != MqttClientConnectResultCode.Success) + mqttClient.ConnectedAsync += e => { - App.Log.Error($"MQTT CONNECT FAILED: {result.ResultCode} {result.ReasonString}"); - } + MqttOnConnected(e); + return Task.CompletedTask; + }; + mqttClient.DisconnectedAsync += e => + { + MqttOnDisconnected(e); + return Task.CompletedTask; + }; + mqttClient.ConnectingFailedAsync += e => + { + MqttOnConnectingFailed(e); + return Task.CompletedTask; + }; + + await mqttClient.StartAsync(managedOptions); - return result.ResultCode == MqttClientConnectResultCode.Success; } catch (Exception ex) { - // ignore this exception App.Log.Error($"MQTT CONNECT FAILED", ex); } - return false; + return true; } diff --git a/fipha/Properties/AssemblyInfo.cs b/fipha/Properties/AssemblyInfo.cs index 97296e9..55e9b9e 100644 --- a/fipha/Properties/AssemblyInfo.cs +++ b/fipha/Properties/AssemblyInfo.cs @@ -31,7 +31,7 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.0.0.9")] -[assembly: AssemblyFileVersion("0.0.0.9")] +[assembly: AssemblyVersion("0.0.1.0")] +[assembly: AssemblyFileVersion("0.0.1.0")] [assembly: log4net.Config.XmlConfigurator(Watch = true)] diff --git a/fipha/fipha.csproj b/fipha/fipha.csproj index 68c698d..6ced869 100644 --- a/fipha/fipha.csproj +++ b/fipha/fipha.csproj @@ -77,8 +77,11 @@ ..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll - - ..\packages\MQTTnet.4.1.0.247\lib\net461\MQTTnet.dll + + ..\packages\MQTTnet.4.1.1.318\lib\net461\MQTTnet.dll + + + ..\packages\MQTTnet.Extensions.ManagedClient.4.1.1.318\lib\net461\MQTTnet.Extensions.ManagedClient.dll ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll diff --git a/fipha/packages.config b/fipha/packages.config index fb75b06..e06c935 100644 --- a/fipha/packages.config +++ b/fipha/packages.config @@ -10,7 +10,8 @@ - + +