129 lines
4.3 KiB
C#
129 lines
4.3 KiB
C#
|
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,
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
}
|