2023-02-16 12:57:06 +00:00
|
|
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
|
|
|
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
2023-03-09 11:40:47 +00:00
|
|
|
using InnovEnergy.Lib.Units.Composite;
|
|
|
|
using static DecimalMath.DecimalEx;
|
2023-02-16 12:57:06 +00:00
|
|
|
|
2023-02-25 14:53:58 +00:00
|
|
|
namespace InnovEnergy.Lib.Devices.AMPT;
|
2023-02-16 12:57:06 +00:00
|
|
|
|
|
|
|
public class AmptCommunicationUnit
|
|
|
|
{
|
2023-03-09 11:40:47 +00:00
|
|
|
private ModbusTcpClient? Modbus { get; set; }
|
2023-02-16 12:57:06 +00:00
|
|
|
|
2023-03-09 11:40:47 +00:00
|
|
|
private const UInt16 RegistersPerDevice = 16;
|
|
|
|
private const UInt16 FirstDeviceOffset = 85;
|
|
|
|
|
|
|
|
public String Hostname { get; }
|
|
|
|
public UInt16 Port { get; }
|
|
|
|
public Byte SlaveAddress { get; }
|
2023-02-16 12:57:06 +00:00
|
|
|
|
|
|
|
public AmptCommunicationUnit(String hostname, UInt16 port = 502, Byte slaveAddress = 1)
|
|
|
|
{
|
2023-03-09 11:40:47 +00:00
|
|
|
Hostname = hostname;
|
|
|
|
Port = port;
|
|
|
|
SlaveAddress = slaveAddress;
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|
|
|
|
|
2023-03-09 11:40:47 +00:00
|
|
|
public AmptCommunicationUnitStatus? ReadStatus()
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2023-03-09 12:16:26 +00:00
|
|
|
OpenConnection();
|
|
|
|
return TryReadStatus();
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|
2023-03-09 12:16:26 +00:00
|
|
|
catch
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
2023-03-09 12:16:26 +00:00
|
|
|
CloseConnection();
|
2023-02-16 12:57:06 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2023-03-09 11:40:47 +00:00
|
|
|
|
2023-03-09 12:16:26 +00:00
|
|
|
private void CloseConnection()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Modbus?.CloseConnection();
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
// ignored
|
|
|
|
}
|
|
|
|
|
|
|
|
Modbus = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OpenConnection()
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
2023-03-09 11:40:47 +00:00
|
|
|
if (Modbus is null)
|
|
|
|
{
|
|
|
|
var connection = new ModbusTcpConnection(Hostname, Port);
|
|
|
|
Modbus = new ModbusTcpClient(connection, SlaveAddress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-09 12:16:26 +00:00
|
|
|
private AmptCommunicationUnitStatus TryReadStatus()
|
2023-03-09 11:40:47 +00:00
|
|
|
{
|
2023-03-09 12:16:26 +00:00
|
|
|
var r = Modbus!.ReadHoldingRegisters(1, 116);
|
2023-03-09 11:40:47 +00:00
|
|
|
|
|
|
|
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
|
2023-02-16 12:57:06 +00:00
|
|
|
var nbrOfDevices = r.GetUInt16(78);
|
|
|
|
|
|
|
|
var devices = Enumerable
|
|
|
|
.Range(0, nbrOfDevices)
|
|
|
|
.Select(ReadDeviceStatus)
|
|
|
|
.ToList();
|
|
|
|
|
2023-03-09 11:40:47 +00:00
|
|
|
return new AmptCommunicationUnitStatus
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
2023-03-09 11:40:47 +00:00
|
|
|
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
|
|
|
|
};
|
2023-02-16 12:57:06 +00:00
|
|
|
|
2023-03-09 11:40:47 +00:00
|
|
|
AmptStatus ReadDeviceStatus(Int32 deviceNumber)
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
2023-03-09 11:40:47 +00:00
|
|
|
var baseAddress = (UInt16)(FirstDeviceOffset + deviceNumber * RegistersPerDevice); // base address
|
2023-02-16 12:57:06 +00:00
|
|
|
|
2023-03-09 11:40:47 +00:00
|
|
|
return new AmptStatus
|
|
|
|
{
|
|
|
|
Dc = new DcBus
|
|
|
|
{
|
|
|
|
Voltage = r.GetUInt32((UInt16)(baseAddress + 6)) * voltageFactor,
|
|
|
|
Current = r.GetUInt16((UInt16)(baseAddress + 5)) * currentFactor
|
|
|
|
},
|
|
|
|
Strings = new DcBus[]
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
2023-03-09 11:40:47 +00:00
|
|
|
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,
|
|
|
|
};
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|