using MQTTnet; using MQTTnet.Client; using NModbus; using System.Net.Sockets; namespace TestApp { internal class Program { private static IMqttClient _MqttClient; private static Dictionary _CurrentValues = new Dictionary(); static async Task Main(string[] args) { await ConnectMQTT(); while (true) { try { ConnectToModBus(); } catch (Exception ex) { Console.WriteLine($"Error connecting to ModBus slave: {ex.Message}"); Thread.Sleep(5000); } } } private static void ConnectToModBus() { var factory = new ModbusFactory(); var tcpClient = new TcpClient("192.168.188.21", 502); var master = factory.CreateMaster(tcpClient); Console.WriteLine("ModBus TCP Connection established!"); while (tcpClient.Connected) { try { var currentWirkleistung = _CurrentValues.GetValueOrDefault(1099528667391UL) / 1000; ushort input = master.ReadHoldingRegisters(1, 1000, 1)[0]; ushort output = (ushort)(input + currentWirkleistung); master.WriteMultipleRegisters(1, 1100, new ushort[] { output }); Thread.Sleep(100); } catch (Exception e) { Console.WriteLine($"Error updating ModBus registers: {e.Message}"); Thread.Sleep(1000); } } } private static async Task ConnectMQTT() { var factory = new MqttFactory(); _MqttClient = factory.CreateMqttClient(); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost") .Build(); Console.WriteLine("Connecting to local MQTT ..."); await _MqttClient.ConnectAsync(clientOptions); Console.WriteLine("Connected to local MQTT!"); _MqttClient.ApplicationMessageReceivedAsync += Client_ApplicationMessageReceivedAsync; var subscribeOptions = factory.CreateSubscribeOptionsBuilder() .WithTopicFilter( f => { f.WithTopic("gdr/local/values/smart-meter"); } ) .Build(); Console.WriteLine("Subscribing to smart-meter values ..."); var response = await _MqttClient.SubscribeAsync(subscribeOptions); Console.WriteLine("Subscribed to smart-meter values!"); } private static Task Client_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg) { switch (arg.ApplicationMessage.Topic) { case "gdr/local/values/smart-meter": ParseGDRs(arg.ApplicationMessage.Payload); break; } return Task.CompletedTask; } private static void ParseGDRs(byte[] payload) { var gdrs = GDRs.Parser.ParseFrom(payload); if (!gdrs.GDRs_.TryGetValue("smart-meter", out GDR smartMeterGDR)) { return; } foreach (var value in smartMeterGDR.Values) { _CurrentValues[value.Key] = value.Value; } } } }