using DecimalMath; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.StatusApi.Connections; namespace InnovEnergy.Lib.Devices.AMPT; public class AmptCommunicationUnit { private ModbusTcpClient Modbus { get; } private const Int32 RegistersPerDevice = 16; private const Int32 FirstDeviceOffset = 85; public AmptCommunicationUnit(String hostname, UInt16 port = 502, Byte slaveAddress = 1) { var connection = new ModbusTcpConnection(hostname, port); Modbus = new ModbusTcpClient(connection, slaveAddress); } public AmptStatus? ReadStatus() { try { return TryReadStatus(); } catch (Exception) { 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 var nbrOfDevices = r.GetUInt16(78); var devices = Enumerable .Range(0, nbrOfDevices) .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) { var avgVoltage = 0.0m; for (var i = 0; i < numberOfDevice; i++) { 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 [] { 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 ) } ); } } }