using System.Reactive.Linq; using InnovEnergy.Lib.Devices.EmuMeter; using InnovEnergy.Lib.Protocols.DBus; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Victron.VeDBus; namespace InnovEnergy.EmuMeter; public static class EmuMeterDriver { public static Task Run(String hostName, Bus dbusAddress) { return Run(hostName, ModbusTcpClient.DefaultPort, dbusAddress); } public static async Task Run(String hostName, UInt16 port, Bus dbusAddress) { // var ep = new UnixDomainSocketEndPoint("/home/eef/graber_dbus.sock"); // var auth = AuthenticationMethod.ExternalAsRoot(); // dbusAddress = new Bus(ep, auth); var emuMeter = new EmuMeterDevice(hostName, port, Config.ModbusNodeId); var meterStatus = Observable .Interval(Config.UpdatePeriod) .Select(_ => emuMeter.ReadStatus()) .Publish(); var poller = meterStatus.Connect(); var properties = Config.DefaultProperties; var signals = Config .Signals .Select(signal => meterStatus.Select(signal.ToVeProperty)) .Merge() .Do(p => properties.Set(p)); // TODO: remove when possible // Apparently some VE services need to be periodically reminded that // this service is /Connected meterStatus.Subscribe(_ => properties.Set("/Connected", 1)); // Wait until status is read once to make sure all // properties are set when we go onto the bus. var dbus = meterStatus .Skip(1) .Take(1) .SelectMany(_ => PublishPropertiesOnDBus(properties, dbusAddress)); return await signals .MergeErrors(dbus) .Finally(poller.Dispose) .SelectErrors(); } private static Task PublishPropertiesOnDBus(VeProperties properties, Bus bus) { Console.WriteLine($"Connecting to DBus {bus}"); return properties.PublishOnDBus(bus, Config.BusName); } }