Skip to content

Commit

Permalink
Added MQTT auto reconnect and added retained flag and QOS1 to MQTT items
Browse files Browse the repository at this point in the history
  • Loading branch information
mhwlng committed Oct 8, 2022
1 parent c0084b4 commit 4ad1984
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 100 deletions.
144 changes: 70 additions & 74 deletions fipha/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private static void RunProcess(string fileName)
process.Start();
process.WaitForExit();
}

protected override void OnStartup(StartupEventArgs evtArgs)
{
const string appName = "fipha";
Expand Down Expand Up @@ -140,7 +140,7 @@ protected override void OnStartup(StartupEventArgs evtArgs)
}

}
catch(Exception ex)
catch (Exception ex)
{
Log.Error("Connecting to Home Assistant Failed", ex);
}
Expand All @@ -160,7 +160,7 @@ protected override void OnStartup(StartupEventArgs evtArgs)

Task.Run(async () =>
{

if (EntityClient != null)
{
var config = new TemplateServiceConfiguration
Expand All @@ -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);

Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -259,7 +261,7 @@ protected override void OnStartup(StartupEventArgs evtArgs)
});

Dispatcher.Invoke(() => { splashScreen.Close(); });

var haMediaPlayerToken = _haMediaPlayerTokenSource.Token;


Expand Down Expand Up @@ -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);

}
}
Expand All @@ -373,7 +382,7 @@ protected override void OnStartup(StartupEventArgs evtArgs)
{
sensor.Value = "-";
}

}
}
}
Expand All @@ -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<bool>(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<bool>(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
}
}

Expand All @@ -475,7 +471,7 @@ await MQTT.Publish(
});

}


protected override void OnExit(ExitEventArgs e)
{
Expand Down
75 changes: 54 additions & 21 deletions fipha/Mqtt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
using System.Xml;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Extensions.ManagedClient;
using MQTTnet.Protocol;

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;
Expand All @@ -29,24 +30,41 @@ public static class MQTT

public static async Task<bool> 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<bool> Connect()
{
if (File.Exists(Path.Combine(App.ExePath, "mqtt.config")))
Expand Down Expand Up @@ -78,6 +96,7 @@ public static async Task<bool> Connect()
else return false;

var messageBuilder = new MqttClientOptionsBuilder()
//.WithProtocolVersion(MqttProtocolVersion.V500)
.WithClientId(ClientId)
.WithCredentials(mqttUser, mqttPassword)
.WithTcpServer(mqttURI, mqttPort)
Expand All @@ -90,24 +109,38 @@ public static async Task<bool> 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;

}

Expand Down
4 changes: 2 additions & 2 deletions fipha/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Loading

0 comments on commit 4ad1984

Please sign in to comment.