using DecimalMath; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.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, Current1 = r.GetInt16(90) * currentFactor, Current2 = r.GetInt16(106) * currentFactor, Voltage1 = r.GetUInt32(91) * voltageFactor, Voltage2 = r.GetUInt32(107) * voltageFactor, //AvgVolatge = ReadDevicesVoltage(nbrOfDevices), //AvgCurrent = ReadDevicesCurrent(nbrOfDevices) }; 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 { DeviceId = r.GetInt16 (b) , Timestamp = r.GetUInt32((UInt16)(b + 3)), Current = r.GetUInt16((UInt16)(b + 5)) * currentFactor, Voltage = r.GetUInt32((UInt16)(b + 6)) * voltageFactor, ProductionToday = r.GetUInt32((UInt16)(b + 12))* energyFactor, Strings = new AmptStringStatus[] { new() { Voltage = r.GetUInt32((UInt16)(b + 8)) * voltageFactor, Current = r.GetUInt16((UInt16)(b + 14)) * currentFactor, }, new() { Voltage = r.GetUInt32((UInt16)(b + 9)) * voltageFactor, Current = r.GetUInt16((UInt16)(b + 15)) * currentFactor, } } }; } } }