using System.Reactive.Linq; using InnovEnergy.Lib.Devices.IEM3kGridMeter; using InnovEnergy.Lib.Protocols.DBus; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils.Reflection; using InnovEnergy.Lib.Victron.VeDBus; namespace InnovEnergy.App.SchneiderDriver; public static class SchneiderMeterDriver { 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 schneider = new Iem3KGridMeterDevice(hostName, port, Config.ModbusNodeId); var schneiderStatus = Observable .Interval(Config.UpdatePeriod) .Select(_ => schneider.Read()) .Where(reading => reading != null) .Publish(); var poller = schneiderStatus.Connect(); var properties = Config.DefaultProperties; var signals = Config .Signals .Select(signal => schneiderStatus .Select(reading => { var property = signal.ToVeProperty(reading); if (property == null) { Console.WriteLine($"Warning: Signal {signal} produced a null property."); } else { Console.WriteLine($"Transformed Signal to Property: {property}"); } return property; }) .Where(property => property != null)) .Merge() .Do(p => { Console.WriteLine($"Setting property: {p}"); properties.Set(p); }); // TODO: remove when possible // Apparently some VE services need to be periodically reminded that // this service is /Connected Console.WriteLine("Goes to subscribe"); schneiderStatus.Subscribe(_ => properties.Set("/Connected", 1)); Console.WriteLine("Subscribed successfully"); // Wait until status is read once to make sure all // properties are set when we go onto the bus. var dbus = schneiderStatus .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); } }