From a5110557d99faacd7afd5a180fc584b7f8ff15d9 Mon Sep 17 00:00:00 2001 From: Cam Soper Date: Tue, 5 Aug 2025 16:44:17 -0500 Subject: [PATCH] Externalize configuration settings --- Inferno.Cli/Inferno.Cli.csproj | 9 ++++ Inferno.Cli/Program.cs | 14 ++++-- Inferno.Cli/appsettings.json | 5 ++ Inferno.Common/Services/SmokerProxy.cs | 8 +-- Inferno.Mqtt/Inferno.Mqtt.csproj | 10 +++- Inferno.Mqtt/MqttSettings.cs | 20 ++++++++ Inferno.Mqtt/Program.cs | 18 +++++-- Inferno.Mqtt/Services/SmokerBridge.cs | 70 +++++++++++--------------- Inferno.Mqtt/appsettings.json | 22 ++++++++ 9 files changed, 125 insertions(+), 51 deletions(-) create mode 100644 Inferno.Cli/appsettings.json create mode 100644 Inferno.Mqtt/MqttSettings.cs create mode 100644 Inferno.Mqtt/appsettings.json diff --git a/Inferno.Cli/Inferno.Cli.csproj b/Inferno.Cli/Inferno.Cli.csproj index 41a17d1..3bac661 100644 --- a/Inferno.Cli/Inferno.Cli.csproj +++ b/Inferno.Cli/Inferno.Cli.csproj @@ -10,5 +10,14 @@ + + + + + + + PreserveNewest + + diff --git a/Inferno.Cli/Program.cs b/Inferno.Cli/Program.cs index 072759a..2be2f1f 100644 --- a/Inferno.Cli/Program.cs +++ b/Inferno.Cli/Program.cs @@ -1,5 +1,6 @@ -using Inferno.Common.Models; +using Inferno.Common.Models; using Inferno.Common.Proxies; +using Microsoft.Extensions.Configuration; using System; using System.Net.Http; using System.Threading.Tasks; @@ -8,10 +9,17 @@ namespace Inferno.Cli { class Program { - static SmokerProxy _smokerProxy = new SmokerProxy(); - + static SmokerProxy _smokerProxy = null!; + static async Task Main(string[] args) { + var configuration = new ConfigurationBuilder() + .AddJsonFile("appsettings.json", optional: false) + .AddEnvironmentVariables() + .Build(); + var apiBaseUrl = configuration["Api:BaseUrl"] ?? "http://127.0.0.1:5000"; + _smokerProxy = new SmokerProxy(apiBaseUrl); + if(args == null || args.Length < 1) { PrintHelp(); diff --git a/Inferno.Cli/appsettings.json b/Inferno.Cli/appsettings.json new file mode 100644 index 0000000..e4d1155 --- /dev/null +++ b/Inferno.Cli/appsettings.json @@ -0,0 +1,5 @@ +{ + "Api": { + "BaseUrl": "http://127.0.0.1:5000" + } +} diff --git a/Inferno.Common/Services/SmokerProxy.cs b/Inferno.Common/Services/SmokerProxy.cs index bec45d4..5a7c628 100644 --- a/Inferno.Common/Services/SmokerProxy.cs +++ b/Inferno.Common/Services/SmokerProxy.cs @@ -11,11 +11,13 @@ namespace Inferno.Common.Proxies public class SmokerProxy : IDisposable { - private HttpClient _client; + private readonly HttpClient _client; + private readonly string _baseUrl; - public SmokerProxy() + public SmokerProxy(string baseUrl) { _client = new HttpClient(); + _baseUrl = baseUrl.TrimEnd('/'); } private bool disposedValue; @@ -49,7 +51,7 @@ public async Task SetModeAsync(SmokerMode smokerMode) private async Task InfernoApiRequestAsync(SmokerEndpoint endpoint, string content = "") { - Uri requestUri = new Uri($"http://127.0.0.1:5000/api/{endpoint}"); + Uri requestUri = new Uri($"{_baseUrl}/api/{endpoint}"); HttpResponseMessage result; if (string.IsNullOrEmpty(content)) diff --git a/Inferno.Mqtt/Inferno.Mqtt.csproj b/Inferno.Mqtt/Inferno.Mqtt.csproj index 5b4db63..f561e8b 100644 --- a/Inferno.Mqtt/Inferno.Mqtt.csproj +++ b/Inferno.Mqtt/Inferno.Mqtt.csproj @@ -13,6 +13,14 @@ + + + + + + + + PreserveNewest + - diff --git a/Inferno.Mqtt/MqttSettings.cs b/Inferno.Mqtt/MqttSettings.cs new file mode 100644 index 0000000..1f0141c --- /dev/null +++ b/Inferno.Mqtt/MqttSettings.cs @@ -0,0 +1,20 @@ +namespace Inferno.Mqtt; + +public class MqttSettings +{ + public string BrokerAddress { get; set; } = "localhost"; + public string BrokerUsername { get; set; } = ""; + public string BrokerPassword { get; set; } = ""; + public string TopicRoot { get; set; } = "inferno"; + public string TopicCommand { get; set; } = "command"; + public string TopicState { get; set; } = "state"; + public string TopicMode { get; set; } = "mode"; + public string TopicSetPoint { get; set; } = "setpoint"; + public string TopicPValue { get; set; } = "pvalue"; + public string TopicGrillTemp { get; set; } = "grill"; + public string TopicProbeTemp { get; set; } = "probe"; + public string TopicAuger { get; set; } = "auger"; + public string TopicBlower { get; set; } = "blower"; + public string TopicIgniter { get; set; } = "igniter"; + public string TopicFireHealthy { get; set; } = "firehealthy"; +} diff --git a/Inferno.Mqtt/Program.cs b/Inferno.Mqtt/Program.cs index c95313b..44ad28d 100644 --- a/Inferno.Mqtt/Program.cs +++ b/Inferno.Mqtt/Program.cs @@ -1,16 +1,26 @@ -using Inferno.Mqtt.Services; +using Inferno.Mqtt; +using Inferno.Mqtt.Services; +using Microsoft.Extensions.Configuration; + +var configuration = new ConfigurationBuilder() + .AddJsonFile("appsettings.json", optional: false) + .AddEnvironmentVariables() + .Build(); + +var mqttSettings = configuration.GetSection("Mqtt").Get() ?? new MqttSettings(); +var apiBaseUrl = configuration["Api:BaseUrl"] ?? "http://127.0.0.1:5000"; while (true) { try { Console.WriteLine($"{DateTime.Now} Starting SmokerBridge"); - using var smokerBridge = await SmokerBridge.CreateAsync(); + using var smokerBridge = await SmokerBridge.CreateAsync(mqttSettings, apiBaseUrl); Thread.Sleep(Timeout.InfiniteTimeSpan); } - catch(Exception ex) + catch (Exception ex) { Console.WriteLine($"{DateTime.Now} WTF: {ex.Message}"); Thread.Sleep(5000); } -} \ No newline at end of file +} diff --git a/Inferno.Mqtt/Services/SmokerBridge.cs b/Inferno.Mqtt/Services/SmokerBridge.cs index a0c4cda..6007266 100644 --- a/Inferno.Mqtt/Services/SmokerBridge.cs +++ b/Inferno.Mqtt/Services/SmokerBridge.cs @@ -10,19 +10,7 @@ namespace Inferno.Mqtt.Services public sealed class SmokerBridge : IDisposable { - private const string TOPIC_ROOT = "inferno"; - private const string TOPIC_COMMAND = "command"; - private const string TOPIC_STATE = "state"; - private const string TOPIC_MODE = "mode"; - private const string TOPIC_SETPOINT = "setpoint"; - private const string TOPIC_PVALUE = "pvalue"; - private const string TOPIC_GRILLTEMP = "grill"; - private const string TOPIC_PROBETEMP = "probe"; - private const string TOPIC_AUGER = "auger"; - private const string TOPIC_BLOWER = "blower"; - private const string TOPIC_IGNITER = "igniter"; - private const string TOPIC_FIREHEALTHY = "firehealthy"; - + private readonly MqttSettings _settings; private readonly string _brokerAddress; private readonly string _brokerUsername; @@ -37,23 +25,25 @@ public sealed class SmokerBridge : IDisposable private readonly SmokerProxy _proxy; private bool disposedValue; - - public SmokerBridge() + + public SmokerBridge(MqttSettings settings, string apiBaseUrl) { - _brokerAddress = Environment.GetEnvironmentVariable("MQTT_BROKER_ADDRESS") ?? "localhost"; - _brokerUsername = Environment.GetEnvironmentVariable("MQTT_USERNAME") ?? ""; - _brokerPassword = Environment.GetEnvironmentVariable("MQTT_PASSWORD") ?? ""; + _settings = settings; + + _brokerAddress = settings.BrokerAddress; + _brokerUsername = settings.BrokerUsername; + _brokerPassword = settings.BrokerPassword; Console.WriteLine($"Broker Address: {_brokerAddress}"); Console.WriteLine($"Broker Username: {_brokerUsername}"); - _proxy = new SmokerProxy(); + _proxy = new SmokerProxy(apiBaseUrl); } - public static async Task CreateAsync() + public static async Task CreateAsync(MqttSettings settings, string apiBaseUrl) { - var smokerBridge = new SmokerBridge(); + var smokerBridge = new SmokerBridge(settings, apiBaseUrl); await smokerBridge.InitializeAsync(); return smokerBridge; } @@ -80,17 +70,17 @@ private async Task InitializeAsync() .WithTopicFilter( f => { - f.WithTopic(GetCommandTopic(TOPIC_MODE)); + f.WithTopic(GetCommandTopic(_settings.TopicMode)); }) .WithTopicFilter( f => { - f.WithTopic(GetCommandTopic(TOPIC_SETPOINT)); + f.WithTopic(GetCommandTopic(_settings.TopicSetPoint)); }) .WithTopicFilter( f => { - f.WithTopic(GetCommandTopic(TOPIC_PVALUE)); + f.WithTopic(GetCommandTopic(_settings.TopicPValue)); }) .Build(); @@ -107,21 +97,21 @@ private async Task ProcessCommand(MqttApplicationMessageReceivedEventArgs args) var payload = Encoding.UTF8.GetString(args.ApplicationMessage.Payload); Console.WriteLine($"{DateTime.Now} Received on {topic}: {payload}"); - if (topic == SmokerBridge.GetCommandTopic(TOPIC_MODE)) + if (topic == GetCommandTopic(_settings.TopicMode)) { if (Enum.TryParse(payload, true, out SmokerMode mode)) { await _proxy.SetModeAsync(mode); } } - else if (topic == SmokerBridge.GetCommandTopic(TOPIC_SETPOINT)) + else if (topic == GetCommandTopic(_settings.TopicSetPoint)) { if (int.TryParse(payload, out var setPoint)) { await _proxy.SetSetPointAsync(setPoint); } } - else if (topic == SmokerBridge.GetCommandTopic(TOPIC_PVALUE)) + else if (topic == GetCommandTopic(_settings.TopicPValue)) { if (int.TryParse(payload, out var pValue)) { @@ -130,14 +120,14 @@ private async Task ProcessCommand(MqttApplicationMessageReceivedEventArgs args) } } - private static string GetCommandTopic(string topic) + private string GetCommandTopic(string topic) { - return $"{TOPIC_ROOT}/{topic}/{TOPIC_COMMAND}"; + return $"{_settings.TopicRoot}/{topic}/{_settings.TopicCommand}"; } - private static string GetStateTopic(string topic) + private string GetStateTopic(string topic) { - return $"{TOPIC_ROOT}/{topic}/{TOPIC_STATE}"; + return $"{_settings.TopicRoot}/{topic}/{_settings.TopicState}"; } private async Task StateLoop() @@ -160,37 +150,37 @@ private async Task StateLoop() await SendUpdateMessage(status.AugerOn.ToString(), _lastStatus.AugerOn.ToString(), - TOPIC_AUGER, + _settings.TopicAuger, forceUpdate); await SendUpdateMessage(status.BlowerOn.ToString(), _lastStatus.BlowerOn.ToString(), - TOPIC_BLOWER, + _settings.TopicBlower, forceUpdate); await SendUpdateMessage(status.IgniterOn.ToString(), _lastStatus.IgniterOn.ToString(), - TOPIC_IGNITER, + _settings.TopicIgniter, forceUpdate); await SendUpdateMessage(status.FireHealthy.ToString(), _lastStatus.FireHealthy.ToString(), - TOPIC_FIREHEALTHY, + _settings.TopicFireHealthy, forceUpdate); await SendUpdateMessage(status.Mode, _lastStatus.Mode, - TOPIC_MODE, + _settings.TopicMode, forceUpdate); await SendUpdateMessage(status.SetPoint.ToString(), _lastStatus.SetPoint.ToString(), - TOPIC_SETPOINT, + _settings.TopicSetPoint, forceUpdate); await SendUpdateMessage(status.PValue.ToString(), _lastStatus.PValue.ToString(), - TOPIC_PVALUE, + _settings.TopicPValue, forceUpdate); // Only update the grill/probe temps every 5 iterations @@ -201,7 +191,7 @@ await SendUpdateMessage(status.PValue.ToString(), double grillTemp = status.Temps?.GrillTemp ?? -1; await SendUpdateMessage(grillTemp.ToString(), _lastGrillTemp.ToString(), - TOPIC_GRILLTEMP, + _settings.TopicGrillTemp, forceUpdate); _lastGrillTemp = grillTemp; } @@ -211,7 +201,7 @@ await SendUpdateMessage(grillTemp.ToString(), double probeTemp = status.Temps?.ProbeTemp ?? -1; await SendUpdateMessage(probeTemp.ToString(), _lastProbeTemp.ToString(), - TOPIC_PROBETEMP, + _settings.TopicProbeTemp, forceUpdate); _lastProbeTemp = probeTemp; } diff --git a/Inferno.Mqtt/appsettings.json b/Inferno.Mqtt/appsettings.json new file mode 100644 index 0000000..ae15cf6 --- /dev/null +++ b/Inferno.Mqtt/appsettings.json @@ -0,0 +1,22 @@ +{ + "Mqtt": { + "BrokerAddress": "localhost", + "BrokerUsername": "", + "BrokerPassword": "", + "TopicRoot": "inferno", + "TopicCommand": "command", + "TopicState": "state", + "TopicMode": "mode", + "TopicSetPoint": "setpoint", + "TopicPValue": "pvalue", + "TopicGrillTemp": "grill", + "TopicProbeTemp": "probe", + "TopicAuger": "auger", + "TopicBlower": "blower", + "TopicIgniter": "igniter", + "TopicFireHealthy": "firehealthy" + }, + "Api": { + "BaseUrl": "http://127.0.0.1:5000" + } +}