Innovenergy_trunk/csharp/Lib/Devices/AMPT/AmptCommunicationUnit.cs

118 lines
3.5 KiB
C#

using InnovEnergy.Lib.Protocols.Modbus.Clients;
using InnovEnergy.Lib.Protocols.Modbus.Connections;
using InnovEnergy.Lib.Units.Composite;
using static DecimalMath.DecimalEx;
namespace InnovEnergy.Lib.Devices.AMPT;
public class AmptCommunicationUnit
{
private ModbusTcpClient? Modbus { get; set; }
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)
{
Hostname = hostname;
Port = port;
SlaveAddress = slaveAddress;
}
public AmptCommunicationUnitStatus? ReadStatus()
{
try
{
OpenConnection();
return TryReadStatus();
}
catch
{
CloseConnection();
return null;
}
}
private void CloseConnection()
{
try
{
Modbus?.CloseConnection();
}
catch
{
// ignored
}
Modbus = null;
}
private void OpenConnection()
{
if (Modbus is null)
{
var connection = new ModbusTcpConnection(Hostname, Port);
Modbus = new ModbusTcpClient(connection, SlaveAddress);
}
}
private AmptCommunicationUnitStatus TryReadStatus()
{
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
.Range(0, nbrOfDevices)
.Select(ReadDeviceStatus)
.ToList();
return new AmptCommunicationUnitStatus
{
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
{
Dc = new DcBus
{
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,
};
}
}
}