From 932f8bdac43924821861060d65c37f511e02ce89 Mon Sep 17 00:00:00 2001 From: ig Date: Thu, 9 Mar 2023 12:40:47 +0100 Subject: [PATCH] lift AMPT to new StatusApi --- .../Lib/Devices/AMPT/AmptCommunicationUnit.cs | 167 ++++++++---------- .../AMPT/AmptCommunicationUnitStatus.cs | 16 ++ csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs | 15 -- csharp/Lib/Devices/AMPT/AmptStatus.cs | 27 +-- csharp/Lib/Devices/AMPT/AmptStringStatus.cs | 7 - 5 files changed, 93 insertions(+), 139 deletions(-) create mode 100644 csharp/Lib/Devices/AMPT/AmptCommunicationUnitStatus.cs delete mode 100644 csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs delete mode 100644 csharp/Lib/Devices/AMPT/AmptStringStatus.cs diff --git a/csharp/Lib/Devices/AMPT/AmptCommunicationUnit.cs b/csharp/Lib/Devices/AMPT/AmptCommunicationUnit.cs index e701c8463..4238877ac 100644 --- a/csharp/Lib/Devices/AMPT/AmptCommunicationUnit.cs +++ b/csharp/Lib/Devices/AMPT/AmptCommunicationUnit.cs @@ -1,46 +1,60 @@ -using DecimalMath; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; -using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; +using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Devices.AMPT; public class AmptCommunicationUnit { - private ModbusTcpClient Modbus { get; } + private ModbusTcpClient? Modbus { get; set; } - private const Int32 RegistersPerDevice = 16; - private const Int32 FirstDeviceOffset = 85; + private const UInt16 RegistersPerDevice = 16; + private const UInt16 FirstDeviceOffset = 85; + + public String Hostname { get; } + public UInt16 Port { get; } + public Byte SlaveAddress { get; } - public AmptCommunicationUnit(String hostname, UInt16 port = 502, Byte slaveAddress = 1) { - var connection = new ModbusTcpConnection(hostname, port); - Modbus = new ModbusTcpClient(connection, slaveAddress); + Hostname = hostname; + Port = port; + SlaveAddress = slaveAddress; } - public AmptStatus? ReadStatus() + public AmptCommunicationUnitStatus? ReadStatus() { try { - return TryReadStatus(); + var modbus = OpenConnection(); + return TryReadStatus(modbus); } - catch (Exception) + catch { - Modbus.CloseConnection(); + Modbus?.CloseConnection(); return null; } } - - private AmptStatus TryReadStatus() - { - // Console.WriteLine("Reading Ampt Device"); - - var r = Modbus.ReadHoldingRegisters(1, 116); - var currentFactor = DecimalEx.Pow(10.0m, r.GetInt16(73)); - var voltageFactor = DecimalEx.Pow(10.0m, r.GetInt16(74)); - var energyFactor = DecimalEx.Pow(10.0m, r.GetInt16(76) + 3); // +3 => converted from Wh to kWh + private ModbusTcpClient OpenConnection() + { + if (Modbus is null) + { + var connection = new ModbusTcpConnection(Hostname, Port); + Modbus = new ModbusTcpClient(connection, SlaveAddress); + } + + return Modbus; + } + + private static AmptCommunicationUnitStatus TryReadStatus(ModbusTcpClient modbus) + { + var r = modbus.ReadHoldingRegisters(1, 116); + + var currentFactor = Pow(10.0m, r.GetInt16(73)); + var voltageFactor = Pow(10.0m, r.GetInt16(74)); + var energyFactor = Pow(10.0m, r.GetInt16(76) + 3); // +3 => converted from Wh to kWh var nbrOfDevices = r.GetUInt16(78); var devices = Enumerable @@ -48,84 +62,45 @@ public class AmptCommunicationUnit .Select(ReadDeviceStatus) .ToList(); - var amptSt = new AmptStatus - ( - Sid : r.GetUInt32(1), - IdSunSpec : r.GetUInt16(3), - Manufacturer : r.GetString(5, 16), - Model : r.GetString(21, 16), - Version : r.GetString(45, 8), - SerialNumber : r.GetString(53, 16), - DeviceAddress : r.GetInt16(69), - IdVendor : r.GetUInt16(71), - Devices : devices - // devices.d Current1 = r.GetInt16(90) * currentFactor, - // Current2 = r.GetInt16(106) * currentFactor, - // Voltage1 = r.GetUInt32(91) * voltageFactor, - // Voltage2 = r.GetUInt32(107) * voltageFactor - - ); - - - return amptSt; - - Decimal ReadDevicesVoltage(Int32 numberOfDevice) + return new AmptCommunicationUnitStatus { - var avgVoltage = 0.0m; - - for (var i = 0; i < numberOfDevice; i++) + Sid = r.GetUInt32(1), + IdSunSpec = r.GetUInt16(3), + Manufacturer = r.GetString(5, 16), + Model = r.GetString(21, 16), + Version = r.GetString(45, 8), + SerialNumber = r.GetString(53, 16), + DeviceAddress = r.GetInt16(69), + IdVendor = r.GetUInt16(71), + Devices = devices + }; + + AmptStatus ReadDeviceStatus(Int32 deviceNumber) + { + var baseAddress = (UInt16)(FirstDeviceOffset + deviceNumber * RegistersPerDevice); // base address + + return new AmptStatus { - var b = (UInt16)(FirstDeviceOffset + i * RegistersPerDevice); // base address - - avgVoltage+= r.GetUInt32((UInt16)(b + 6)) * voltageFactor; - } - - return avgVoltage / numberOfDevice; - } - - Decimal ReadDevicesCurrent(Int32 numberOfDevice) - { - Decimal avgCurrent = 0; - - for (var i = 0; i < numberOfDevice; i++) - { - var b = (UInt16)(FirstDeviceOffset + i * RegistersPerDevice); // base address - - avgCurrent+= r!.GetUInt32((UInt16)(b + 5)) * voltageFactor; - } - - return avgCurrent / numberOfDevice; - } - - AmptDeviceStatus ReadDeviceStatus(Int32 deviceNumber) - { - var b = (UInt16)(FirstDeviceOffset + deviceNumber * RegistersPerDevice); // base address - - return new AmptDeviceStatus - ( - Dc : new DcConnection - ( - Voltage:r.GetUInt32((UInt16)(b + 6)) * voltageFactor, - Current:r.GetUInt16((UInt16)(b + 5)) * currentFactor - ), - DeviceId : r.GetInt16 (b) , - Timestamp : r.GetUInt32((UInt16)(b + 3)), - ProductionToday : r.GetUInt32((UInt16)(b + 12))* energyFactor, - - Strings : new [] + Dc = new DcBus { - new DcConnection - ( - Voltage : r.GetUInt32((UInt16)(b + 8)) * voltageFactor, - Current : r.GetUInt16((UInt16)(b + 14)) * currentFactor - ), - new DcConnection - ( - Voltage : r.GetUInt32((UInt16)(b + 9)) * voltageFactor, - Current : r.GetUInt16((UInt16)(b + 15)) * currentFactor - ) - } - ); + Voltage = r.GetUInt32((UInt16)(baseAddress + 6)) * voltageFactor, + Current = r.GetUInt16((UInt16)(baseAddress + 5)) * currentFactor + }, + Strings = new DcBus[] + { + new() + { + Voltage = r.GetUInt32((UInt16)(baseAddress + 8)) * voltageFactor, + Current = r.GetUInt16((UInt16)(baseAddress + 14)) * currentFactor + }, + new() + { + Voltage = r.GetUInt32((UInt16)(baseAddress + 9)) * voltageFactor, + Current = r.GetUInt16((UInt16)(baseAddress + 15)) * currentFactor + } + }, + ProductionToday = r.GetUInt32((UInt16)(baseAddress + 12)) * energyFactor, + }; } } } \ No newline at end of file diff --git a/csharp/Lib/Devices/AMPT/AmptCommunicationUnitStatus.cs b/csharp/Lib/Devices/AMPT/AmptCommunicationUnitStatus.cs new file mode 100644 index 000000000..757d3592f --- /dev/null +++ b/csharp/Lib/Devices/AMPT/AmptCommunicationUnitStatus.cs @@ -0,0 +1,16 @@ +namespace InnovEnergy.Lib.Devices.AMPT; + +public record AmptCommunicationUnitStatus +{ + public UInt32 Sid { get; init; } // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map + public UInt16 IdSunSpec { get; init; } // A well-known value 1, uniquely identifies this as a SunSpec Common Model + + public String Manufacturer { get; init; } = "undefined"; // A well-known value registered with SunSpec for compliance: "Ampt" + public String Model { get; init; } = "undefined"; // Manufacturer specific value "Communication Unit" + public String Version { get; init; } = "undefined"; // Software Version + public String SerialNumber { get; init; } = "undefined"; // Manufacturer specific value + public Int16 DeviceAddress { get; init; } // Modbus Device ID + public UInt16 IdVendor { get; init; } // Ampt SunSpec Vendor Code 64050 + + public IReadOnlyList Devices { get; init; } = Array.Empty(); +} \ No newline at end of file diff --git a/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs b/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs deleted file mode 100644 index 8ee809b72..000000000 --- a/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs +++ /dev/null @@ -1,15 +0,0 @@ -using InnovEnergy.Lib.StatusApi; -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.Devices.AMPT; - -public record AmptDeviceStatus -( - DcConnection Dc, - // UInt16 NbrOfStrings, - Int16 DeviceId, // The string number - UInt32 Timestamp, // The UTC timestamp of the measurements - Decimal ProductionToday, // converted to kW in AmptCU class - IReadOnlyList Strings -): MpptStatus(Dc, Strings) -{} \ No newline at end of file diff --git a/csharp/Lib/Devices/AMPT/AmptStatus.cs b/csharp/Lib/Devices/AMPT/AmptStatus.cs index 45ff33662..8e2140bdc 100644 --- a/csharp/Lib/Devices/AMPT/AmptStatus.cs +++ b/csharp/Lib/Devices/AMPT/AmptStatus.cs @@ -1,24 +1,9 @@ +using InnovEnergy.Lib.StatusApi; +using InnovEnergy.Lib.Units; + namespace InnovEnergy.Lib.Devices.AMPT; -public record AmptStatus -( - UInt32 Sid, // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map - UInt16 IdSunSpec, // A well-known value 1, uniquely identifies this as a SunSpec Common Model - // UInt16 L, // Well-known # of 16-bit registers to follow : 66 - String? Manufacturer, // A well-known value registered with SunSpec for compliance: "Ampt" - String? Model, // Manufacturer specific value "Communication Unit" - String? Version, // Software Version - String? SerialNumber, // Manufacturer specific value - Int16 DeviceAddress, // Modbus Device ID - UInt16 IdVendor, // Ampt SunSpec Vendor Code 64050 - // Decimal Current1, - // Decimal Current2, - // Decimal Voltage1, - // Decimal Voltage2, - IReadOnlyList Devices - //internal const UInt16 StartRegister = 1; - //internal const UInt16 TotalNbOfRegister = 116; -) +public record AmptStatus : MpptStatus { - -} \ No newline at end of file + public Energy ProductionToday { get; init; } // converted to kW in AmptCU class +} diff --git a/csharp/Lib/Devices/AMPT/AmptStringStatus.cs b/csharp/Lib/Devices/AMPT/AmptStringStatus.cs deleted file mode 100644 index bd3b2c5e0..000000000 --- a/csharp/Lib/Devices/AMPT/AmptStringStatus.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace InnovEnergy.Lib.Devices.AMPT; - -public record AmptStringStatus -{ - public Decimal Voltage { get; init; } - public Decimal Current { get; init; } -} \ No newline at end of file