diff --git a/csharp/Lib/Devices/EmuMeter/Conversions.cs b/csharp/Lib/Devices/EmuMeter/Conversions.cs deleted file mode 100644 index 9844875eb..000000000 --- a/csharp/Lib/Devices/EmuMeter/Conversions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using InnovEnergy.Lib.Protocols.Modbus.Conversions; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.Devices.EmuMeter; - -public static class Conversions -{ - - // TODO: integrate into ModbusRegisters - - public static IReadOnlyList ToSingles(this ModbusRegisters regs) - { - return regs - .Chunk(2) - .Select(c => c.Reverse().SelectMany(BitConverter.GetBytes).ToArray()) - .Select(d => BitConverter.ToSingle(d)) - .ToList(); - } - - public static IReadOnlyList ToDecimals(this ModbusRegisters regs) - { - return regs - .Chunk(2) - .Select(c => c.Reverse().SelectMany(BitConverter.GetBytes).ToArray()) - .Select(d => BitConverter.ToSingle(d)) - .Select(d => d.ConvertTo()) - .ToList(); - } - - // ReSharper disable once InconsistentNaming - public static IReadOnlyList ToUInt64s(this ModbusRegisters regs) - { - return regs - .SelectMany(d => BitConverter.GetBytes(d).Reverse()) - .Chunk(8) - .Select(c => c.Reverse().ToArray()) - .Select(d => BitConverter.ToUInt64(d)) - .ToList(); - } - -} \ No newline at end of file diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeter.csproj b/csharp/Lib/Devices/EmuMeter/EmuMeter.csproj index 92dd034ad..379b280a0 100644 --- a/csharp/Lib/Devices/EmuMeter/EmuMeter.csproj +++ b/csharp/Lib/Devices/EmuMeter/EmuMeter.csproj @@ -1,9 +1,7 @@ - - Debug;Release;Release-Server - AnyCPU;linux-arm - - + + + diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs index f26117c3f..7ca06419d 100644 --- a/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs +++ b/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs @@ -1,97 +1,21 @@ +using InnovEnergy.Lib.Protocols.Modbus.Channels; using InnovEnergy.Lib.Protocols.Modbus.Clients; -using InnovEnergy.Lib.Protocols.Modbus.Connections; -using InnovEnergy.Lib.Units.Composite; -using static DecimalMath.DecimalEx; +using InnovEnergy.Lib.Protocols.Modbus.Slaves; namespace InnovEnergy.Lib.Devices.EmuMeter; -public class EmuMeterDevice +public class EmuMeterDevice: ModbusDevice { - private ModbusTcpClient Modbus { get; } - - public EmuMeterDevice(String hostname, UInt16 port = 502, Byte slaveId = 1) + public EmuMeterDevice(String hostname, UInt16 port = 502, Byte slaveId = 1) : this(new TcpChannel(hostname, port), slaveId) { - var connection = new ModbusTcpConnection(hostname, port); - Modbus = new ModbusTcpClient(connection, slaveId); - } - - public EmuMeterStatus? ReadStatus() - { - try - { - return TryReadStatus(); - } - catch (Exception) - { - Modbus.CloseConnection(); - return null; - } } - - //private static Decimal GetPhi(Decimal cosPhi) => cosPhi.Clamp(-1m, 1m).Apply(ACos); - - private EmuMeterStatus TryReadStatus() + public EmuMeterDevice(Channel channel, Byte slaveId = 1) : base(new ModbusTcpClient(channel, slaveId)) + { + } + + public EmuMeterDevice(ModbusClient client) : base(client) { - // Console.WriteLine("Reading Emu Meter Data"); - - - // TODO: get SerialNb, depends on Little/Big Endian support in Modbus Lib - // var registers = Modbus.ReadHoldingRegisters(5001, 4); - // var id = registers.GetInt32(5001); - - var powerCurrent = Modbus.ReadHoldingRegisters(9000, 108).ToDecimals(); // TODO "ModbusRegisters" - var voltageFreq = Modbus.ReadHoldingRegisters(9200, 112).ToDecimals(); // To check with Ivo - - // var energyPhases = Modbus.ReadHoldingRegisters(6100, 104).ToUInt64s(); - - var activePowerL1 = powerCurrent[1]; - var activePowerL2 = powerCurrent[2]; - var activePowerL3 = powerCurrent[3]; - var reactivePowerL1 = powerCurrent[6]; - var reactivePowerL2 = powerCurrent[7]; - var reactivePowerL3 = powerCurrent[8]; - - var currentL1 = powerCurrent[51]; - var currentL2 = powerCurrent[52]; - var currentL3 = powerCurrent[53]; - - var voltageL1N = voltageFreq[0]; - var voltageL2N = voltageFreq[1]; - var voltageL3N = voltageFreq[2]; - var frequency = voltageFreq[55]; - - - var l1 = new AcPhase - { - Current = currentL1, - Voltage = voltageL1N, - Phi = ATan2(reactivePowerL1, activePowerL1) // TODO: check that this works - }; - var l2 = new AcPhase - { - Current = currentL2, - Voltage = voltageL2N, - Phi = ATan2(reactivePowerL2, activePowerL2) - }; - var l3 = new AcPhase - { - Current = currentL3, - Voltage = voltageL3N, - Phi = ATan2(reactivePowerL3, activePowerL3) - }; - - return new EmuMeterStatus - { - Ac = new Ac3Bus - { - Frequency = frequency, - L1 = l1, - L2 = l2, - L3 = l3 - } - }; - } } \ No newline at end of file diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeterRegisters.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterRegisters.cs new file mode 100644 index 000000000..2b9839892 --- /dev/null +++ b/csharp/Lib/Devices/EmuMeter/EmuMeterRegisters.cs @@ -0,0 +1,68 @@ +using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes; +using InnovEnergy.Lib.StatusApi.DeviceTypes; +using InnovEnergy.Lib.Units.Composite; + +#pragma warning disable CS0649 + +namespace InnovEnergy.Lib.Devices.EmuMeter; + +using Float32 = Single; + + +[AddressOffset(-2)] // why? +public record EmuMeterRegisters : IAc3Meter +{ + [HoldingRegister(9002)] private Float32 _ActivePowerL1; + [HoldingRegister(9004)] private Float32 _ActivePowerL2; + [HoldingRegister(9006)] private Float32 _ActivePowerL3; + + [HoldingRegister(9012)] private Float32 _ReactivePowerL1; + [HoldingRegister(9014)] private Float32 _ReactivePowerL2; + [HoldingRegister(9016)] private Float32 _ReactivePowerL3; + + [HoldingRegister(9022)] private Float32 _ApparentPowerL1; + [HoldingRegister(9024)] private Float32 _ApparentPowerL2; + [HoldingRegister(9026)] private Float32 _ApparentPowerL3; + + [HoldingRegister(9102)] private Float32 _CurrentL1; + [HoldingRegister(9104)] private Float32 _CurrentL2; + [HoldingRegister(9106)] private Float32 _CurrentL3; + + [HoldingRegister(9200)] private Float32 _VoltageL1N; + [HoldingRegister(9202)] private Float32 _VoltageL2N; + [HoldingRegister(9204)] private Float32 _VoltageL3N; + + [HoldingRegister(9310)] private Float32 _Frequency; + + public Ac3Bus Ac => Ac3Bus.FromPhasesAndFrequency + ( + l1: AcPhase.FromVoltageCurrentActiveReactiveApparent + ( + _VoltageL1N, + _CurrentL1, + _ActivePowerL1, + _ReactivePowerL1, + _ApparentPowerL1 + ), + l2: AcPhase.FromVoltageCurrentActiveReactiveApparent + ( + _VoltageL2N, + _CurrentL2, + _ActivePowerL2, + _ReactivePowerL2, + _ApparentPowerL2 + ), + l3: AcPhase.FromVoltageCurrentActiveReactiveApparent + ( + _VoltageL3N, + _CurrentL3, + _ActivePowerL3, + _ReactivePowerL3, + _ApparentPowerL3 + ), + frequency: _Frequency + ); +} + + + diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs deleted file mode 100644 index 1290843af..000000000 --- a/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs +++ /dev/null @@ -1,10 +0,0 @@ -using InnovEnergy.Lib.StatusApi; - -namespace InnovEnergy.Lib.Devices.EmuMeter; - -public record EmuMeterStatus : PowerMeterStatus -{ - // TODO: additional Measurements, device id -} - - diff --git a/csharp/Lib/Devices/EmuMeter/Program.cs b/csharp/Lib/Devices/EmuMeter/Program.cs new file mode 100644 index 000000000..5eb94aa52 --- /dev/null +++ b/csharp/Lib/Devices/EmuMeter/Program.cs @@ -0,0 +1,28 @@ +using System.Text.Json; +using InnovEnergy.Lib.Protocols.Modbus.Channels; +using InnovEnergy.Lib.Protocols.Modbus.Clients; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.Devices.EmuMeter; + +public static class Program +{ + public static Task Main(string[] args) + { + var ch = new TcpChannel("localhost", 5003); + var cl = new ModbusTcpClient(ch, 1); + var d = new EmuMeterDevice(cl); + + while (true) + { + var x = d.Read(); + + //x.WriteLine(); + var options = new JsonSerializerOptions { WriteIndented = true }; + (x, options).Apply(JsonSerializer.Serialize).WriteLine(); + + } + + + } +} \ No newline at end of file