make AMPT use updated Modbus Lib
This commit is contained in:
parent
0ac7773ac0
commit
a2c0674ecb
|
@ -1,9 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<!-- <Import Project="../../InnovEnergy.Lib.props"/>-->
|
||||||
<Configurations>Debug;Release;Release-Server</Configurations>
|
|
||||||
<Platforms>AnyCPU;linux-arm</Platforms>
|
<Import Project="../../../App/InnovEnergy.App.props" />
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="../../InnovEnergy.Lib.props" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../../Protocols/Modbus/Modbus.csproj" />
|
<ProjectReference Include="../../Protocols/Modbus/Modbus.csproj" />
|
||||||
|
|
|
@ -1,118 +1,90 @@
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
// using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
// using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
// using InnovEnergy.Lib.Protocols.Modbus.Conversions;
|
||||||
using static DecimalMath.DecimalEx;
|
// using InnovEnergy.Lib.Protocols.Modbus.Slaves;
|
||||||
|
// using InnovEnergy.Lib.Units.Composite;
|
||||||
namespace InnovEnergy.Lib.Devices.AMPT;
|
//
|
||||||
|
// namespace InnovEnergy.Lib.Devices.AMPT;
|
||||||
public class AmptCommunicationUnit
|
//
|
||||||
{
|
// public class AmptCommunicationUnit : ModbusDevice<CommunicationUnitRegisters>
|
||||||
private ModbusTcpClient? Modbus { get; set; }
|
// {
|
||||||
|
//
|
||||||
private const UInt16 RegistersPerDevice = 16;
|
// private const UInt16 RegistersPerDevice = 16;
|
||||||
private const UInt16 FirstDeviceOffset = 85;
|
// private const UInt16 FirstDeviceOffset = 85;
|
||||||
|
//
|
||||||
public String Hostname { get; }
|
//
|
||||||
public UInt16 Port { get; }
|
// public AmptCommunicationUnit(String hostname, UInt16 port = 502, Byte slaveAddress = 1) : this
|
||||||
public Byte SlaveAddress { get; }
|
// (
|
||||||
|
// channel: new TcpChannel(hostname, port),
|
||||||
public AmptCommunicationUnit(String hostname, UInt16 port = 502, Byte slaveAddress = 1)
|
// slaveAddress
|
||||||
{
|
// )
|
||||||
Hostname = hostname;
|
// {}
|
||||||
Port = port;
|
//
|
||||||
SlaveAddress = slaveAddress;
|
//
|
||||||
}
|
// public AmptCommunicationUnit(Channel channel, Byte slaveAddress) : this
|
||||||
|
// (
|
||||||
public AmptCommunicationUnitStatus? ReadStatus()
|
// client: new ModbusTcpClient(channel, slaveAddress)
|
||||||
{
|
// )
|
||||||
try
|
// {}
|
||||||
{
|
//
|
||||||
OpenConnection();
|
// public AmptCommunicationUnit(ModbusClient client) : base(client)
|
||||||
return TryReadStatus();
|
// {
|
||||||
}
|
// }
|
||||||
catch
|
//
|
||||||
{
|
//
|
||||||
CloseConnection();
|
// private AmptCommunicationUnitStatus TryReadStatus()
|
||||||
return null;
|
// {
|
||||||
}
|
// var r = new ModbusRegisters(116, Modbus.ReadHoldingRegisters(1, 116).ToArray()) ; // TODO
|
||||||
}
|
//
|
||||||
|
// var currentFactor = Pow(10.0m, r.GetInt16(73));
|
||||||
private void CloseConnection()
|
// var voltageFactor = Pow(10.0m, r.GetInt16(74));
|
||||||
{
|
// var energyFactor = Pow(10.0m, r.GetInt16(76) + 3); // +3 => converted from Wh to kWh
|
||||||
try
|
// var nbrOfDevices = r.GetUInt16(78);
|
||||||
{
|
//
|
||||||
Modbus?.CloseConnection();
|
// var devices = Enumerable
|
||||||
}
|
// .Range(0, nbrOfDevices)
|
||||||
catch
|
// .Select(ReadDeviceStatus)
|
||||||
{
|
// .ToList();
|
||||||
// ignored
|
//
|
||||||
}
|
// return new AmptCommunicationUnitStatus
|
||||||
|
// {
|
||||||
Modbus = null;
|
// Sid = r.GetUInt32(1),
|
||||||
}
|
// IdSunSpec = r.GetUInt16(3),
|
||||||
|
// Manufacturer = r.GetString(5, 16),
|
||||||
private void OpenConnection()
|
// Model = r.GetString(21, 16),
|
||||||
{
|
// Version = r.GetString(45, 8),
|
||||||
if (Modbus is null)
|
// SerialNumber = r.GetString(53, 16),
|
||||||
{
|
// DeviceAddress = r.GetInt16(69),
|
||||||
var connection = new ModbusTcpConnection(Hostname, Port);
|
// IdVendor = r.GetUInt16(71),
|
||||||
Modbus = new ModbusTcpClient(connection, SlaveAddress);
|
// Devices = devices
|
||||||
}
|
// };
|
||||||
}
|
//
|
||||||
|
// AmptStatus ReadDeviceStatus(Int32 deviceNumber)
|
||||||
private AmptCommunicationUnitStatus TryReadStatus()
|
// {
|
||||||
{
|
// var baseAddress = (UInt16)(FirstDeviceOffset + deviceNumber * RegistersPerDevice); // base address
|
||||||
var r = Modbus!.ReadHoldingRegisters(1, 116);
|
//
|
||||||
|
// return new AmptStatus
|
||||||
var currentFactor = Pow(10.0m, r.GetInt16(73));
|
// {
|
||||||
var voltageFactor = Pow(10.0m, r.GetInt16(74));
|
// Dc = new DcBus
|
||||||
var energyFactor = Pow(10.0m, r.GetInt16(76) + 3); // +3 => converted from Wh to kWh
|
// {
|
||||||
var nbrOfDevices = r.GetUInt16(78);
|
// Voltage = r.GetUInt32((UInt16)(baseAddress + 6)) * voltageFactor,
|
||||||
|
// Current = r.GetUInt16((UInt16)(baseAddress + 5)) * currentFactor
|
||||||
var devices = Enumerable
|
// },
|
||||||
.Range(0, nbrOfDevices)
|
// Strings = new DcBus[]
|
||||||
.Select(ReadDeviceStatus)
|
// {
|
||||||
.ToList();
|
// new()
|
||||||
|
// {
|
||||||
return new AmptCommunicationUnitStatus
|
// Voltage = r.GetUInt32((UInt16)(baseAddress + 8)) * voltageFactor,
|
||||||
{
|
// Current = r.GetUInt16((UInt16)(baseAddress + 14)) * currentFactor
|
||||||
Sid = r.GetUInt32(1),
|
// },
|
||||||
IdSunSpec = r.GetUInt16(3),
|
// new()
|
||||||
Manufacturer = r.GetString(5, 16),
|
// {
|
||||||
Model = r.GetString(21, 16),
|
// Voltage = r.GetUInt32((UInt16)(baseAddress + 9)) * voltageFactor,
|
||||||
Version = r.GetString(45, 8),
|
// Current = r.GetUInt16((UInt16)(baseAddress + 15)) * currentFactor
|
||||||
SerialNumber = r.GetString(53, 16),
|
// }
|
||||||
DeviceAddress = r.GetInt16(69),
|
// },
|
||||||
IdVendor = r.GetUInt16(71),
|
// ProductionToday = r.GetUInt32((UInt16)(baseAddress + 12)) * energyFactor,
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace InnovEnergy.Lib.Devices.AMPT;
|
namespace InnovEnergy.Lib.Devices.AMPT;
|
||||||
|
|
||||||
public record AmptCommunicationUnitStatus
|
public class AmptCommunicationUnitStatus
|
||||||
{
|
{
|
||||||
public UInt32 Sid { get; init; } // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map
|
public UInt32 Sid { get; init; } // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map
|
||||||
public UInt16 IdSunSpec { get; init; } // A well-known value 1, uniquely identifies this as a SunSpec Common Model
|
public UInt16 IdSunSpec { get; init; } // A well-known value 1, uniquely identifies this as a SunSpec Common Model
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Slaves;
|
||||||
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.AMPT;
|
||||||
|
|
||||||
|
public class AmptDevice
|
||||||
|
{
|
||||||
|
private readonly ModbusDevice<CommunicationUnitRegisters> _CommunicationUnit;
|
||||||
|
private readonly IEnumerable<ModbusDevice<StringOptimizerRegisters>> _StringOptimizers;
|
||||||
|
|
||||||
|
public AmptDevice(ModbusClient modbusClient)
|
||||||
|
{
|
||||||
|
_CommunicationUnit = new ModbusDevice<CommunicationUnitRegisters>(modbusClient);
|
||||||
|
_StringOptimizers = StringOptimizers(modbusClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AmptStatus? Read()
|
||||||
|
{
|
||||||
|
var cuStatus = _CommunicationUnit.Read();
|
||||||
|
|
||||||
|
if (cuStatus.NumberOfStrings == 0)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
var rs = _StringOptimizers
|
||||||
|
.Take(cuStatus.NumberOfStrings)
|
||||||
|
.Select(so => so.Read())
|
||||||
|
.ToArray(cuStatus.NumberOfStrings);
|
||||||
|
|
||||||
|
var busVoltage = rs.Average(r => r.Voltage);
|
||||||
|
var busCurrent = rs.Sum(r => r.Current);
|
||||||
|
var strings = rs.SelectMany(GetStrings).ToArray(rs.Length * 2);
|
||||||
|
|
||||||
|
return new AmptStatus
|
||||||
|
(
|
||||||
|
Dc : DcBus.FromVoltageCurrent(busVoltage, busCurrent),
|
||||||
|
Strings: strings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<DcBus> GetStrings(StringOptimizerRegisters r)
|
||||||
|
{
|
||||||
|
yield return DcBus.FromVoltageCurrent(r.String1Voltage, r.String1Current);
|
||||||
|
yield return DcBus.FromVoltageCurrent(r.String2Voltage, r.String2Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static IEnumerable<ModbusDevice<StringOptimizerRegisters>> StringOptimizers(ModbusClient modbusClient)
|
||||||
|
{
|
||||||
|
var cache = new List<ModbusDevice<StringOptimizerRegisters>>();
|
||||||
|
|
||||||
|
ModbusDevice<StringOptimizerRegisters> GetOptimizer(Int32 i)
|
||||||
|
{
|
||||||
|
if (i < cache.Count)
|
||||||
|
return cache[i];
|
||||||
|
|
||||||
|
var modbusDevice = new ModbusDevice<StringOptimizerRegisters>(modbusClient, i * 16);
|
||||||
|
return modbusDevice.Apply(cache.Add);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Enumerable
|
||||||
|
.Range(0, Byte.MaxValue)
|
||||||
|
.Select(GetOptimizer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,6 @@
|
||||||
using InnovEnergy.Lib.StatusApi;
|
using InnovEnergy.Lib.StatusApi.DeviceTypes;
|
||||||
using InnovEnergy.Lib.Units;
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.AMPT;
|
namespace InnovEnergy.Lib.Devices.AMPT;
|
||||||
|
|
||||||
public record AmptStatus : MpptStatus
|
public record AmptStatus(DcBus Dc, IReadOnlyList<DcBus> Strings) : IMppt;
|
||||||
{
|
|
||||||
public Energy ProductionToday { get; init; } // converted to kW in AmptCU class
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.AMPT;
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
|
||||||
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
|
|
||||||
|
|
||||||
|
[OneBasedAddressing]
|
||||||
|
public record CommunicationUnitRegisters
|
||||||
|
{
|
||||||
|
[HoldingRegister<Int16>(73)] public Int16 CurrentScaleFactor { get; private set; }
|
||||||
|
[HoldingRegister<Int16>(74)] public Int16 VoltageScaleFactor { get; private set; }
|
||||||
|
[HoldingRegister<Int16>(76)] public Int16 EnergyScaleFactor { get; private set; }
|
||||||
|
|
||||||
|
[HoldingRegister(78)] public UInt16 NumberOfStrings { get; private set; }
|
||||||
|
}
|
|
@ -0,0 +1,412 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Modbus Map</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #565A5C;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.content {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.textblock {
|
||||||
|
text-align: left;
|
||||||
|
padding: 0;
|
||||||
|
width: 40%;
|
||||||
|
position: relative;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.main {
|
||||||
|
border: solid black 2px;
|
||||||
|
border-spacing: 0;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 6px;
|
||||||
|
border: solid black 1px;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.even {
|
||||||
|
background: #EFEFEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.odd {
|
||||||
|
background: #DDDDDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.desc {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="content">
|
||||||
|
<br><br>
|
||||||
|
<h2>Modbus Map</h2>
|
||||||
|
<div class="textblock">
|
||||||
|
<p>These Modbus maps are for your reference. The modbus service runs on port 502.</p>
|
||||||
|
<p>Important note: The Ampt ModBus register map uses big endian values.</p>
|
||||||
|
<p><a href="smdx_64050.xml">SunSpec SMDX File</a></p>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<h2> SunSpec Registers </h2>
|
||||||
|
<table class="main" style="width:70%">
|
||||||
|
<tbody>
|
||||||
|
<tr class="odd">
|
||||||
|
<td><strong>Start Offset</strong></td>
|
||||||
|
<td><strong>Size</strong></td>
|
||||||
|
<td><strong>Name</strong></td>
|
||||||
|
<td><strong>Type</strong></td>
|
||||||
|
<td><strong>R/W</strong></td>
|
||||||
|
<td><strong>Description</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>1</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>SID</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>3</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>ID</td>
|
||||||
|
<td>uint16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">A well-known value 1, uniquely identifies this as a SunSpec Common Model</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>4</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>L</td>
|
||||||
|
<td>uint16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Well-known # of 16-bit registers to follow: 66</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>5</td>
|
||||||
|
<td>16</td>
|
||||||
|
<td>Manufacturer</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">A well-known value registered with SunSpec for compliance: "Ampt"</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>21</td>
|
||||||
|
<td>16</td>
|
||||||
|
<td>Model</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Manufacturer specific value "Communication Unit"</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>37</td>
|
||||||
|
<td>8</td>
|
||||||
|
<td><em>Reserved</em></td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>45</td>
|
||||||
|
<td>8</td>
|
||||||
|
<td>Version</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Software Version</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>53</td>
|
||||||
|
<td>16</td>
|
||||||
|
<td>Serial Number</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Manufacturer specific value</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>69</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>Device Address</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R/W</td>
|
||||||
|
<td class="desc">Modbus Device ID</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>70</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td><em>Reserved</em></td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>71</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>ID</td>
|
||||||
|
<td>uint16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Ampt SunSpec Vendor Code 64050</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>72</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>L</td>
|
||||||
|
<td>uint16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Variable number of 16-bit registers to follow: 12 + N*16</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>73</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>DCA_SF</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Current scale factor</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>74</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>DCV_SF</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Voltage scale factor</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>75</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td><em>Reserved</em></td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>76</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>DCkWh_SF</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Energy Scale Factor</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>77</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td><em>Reserved</em></td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>78</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>N</td>
|
||||||
|
<td>uint16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Number of strings</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>79</td>
|
||||||
|
<td>6</td>
|
||||||
|
<td><em>Reserved</em></td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="6"><strong>1</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>85</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>String ID</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">The string number</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>86</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td><em>Reserved</em></td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>88</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>String data timestamp</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">The UTC timestamp of the measurements</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>90</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>OutDCA</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String output current in mA</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>91</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>OutDCV</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String output voltage in mV</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>93</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>In1DCV</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 1 voltage in mV</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>95</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>In2DCV</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 2 voltage in mV</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>97</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>DCWh</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Daily integrated string output energy in Wh</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>99</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>In1DCA</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 1 current in mA</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>100</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>In2DCA</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 2 current in mA</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="6"><strong>2</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>101</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>String ID</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">The string number</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>102</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td><em>Reserved</em></td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>104</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>String data timestamp</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">The UTC timestamp of the measurements</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>106</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>OutDCA</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String output current in mA</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>107</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>OutDCV</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String output voltage in mV</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>109</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>In1DCV</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 1 voltage in mV</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>111</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>In2DCV</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 2 voltage in mV</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>113</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>DCWh</td>
|
||||||
|
<td>uint32</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">Daily integrated string output energy in Wh</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>115</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>In1DCA</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 1 current in mA</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>116</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>In2DCA</td>
|
||||||
|
<td>int16</td>
|
||||||
|
<td>R</td>
|
||||||
|
<td class="desc">String input 2 current in mA</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<br><br><br>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.AMPT;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static Task Main(string[] args)
|
||||||
|
{
|
||||||
|
var ch = new TcpChannel("localhost", 5005);
|
||||||
|
var cl = new ModbusTcpClient(ch, 1);
|
||||||
|
var d = new AmptDevice(cl);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var x = d.Read();
|
||||||
|
|
||||||
|
var options = new JsonSerializerOptions{WriteIndented = true};
|
||||||
|
(x, options).Apply(JsonSerializer.Serialize).WriteLine();
|
||||||
|
|
||||||
|
//Console.WriteLine(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Console.WriteLine(x);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.AMPT;
|
||||||
|
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
|
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
|
||||||
|
|
||||||
|
[OneBasedAddressing][BigEndian]
|
||||||
|
public record StringOptimizerRegisters
|
||||||
|
{
|
||||||
|
[HoldingRegister<UInt32>(88) ] public UInt32 Timestamp { get; private set; }
|
||||||
|
|
||||||
|
[HoldingRegister<Int16> (90, Scale = .001)] public Double Current { get; private set; }
|
||||||
|
[HoldingRegister<UInt32>(91, Scale = .001)] public Double Voltage { get; private set; }
|
||||||
|
|
||||||
|
[HoldingRegister<UInt32>(93, Scale = .001)] public Double String1Voltage { get; private set; }
|
||||||
|
[HoldingRegister<UInt32>(95, Scale = .001)] public Double String2Voltage { get; private set; }
|
||||||
|
|
||||||
|
[HoldingRegister<UInt32>(97)] public Double ProductionToday { get; private set; }
|
||||||
|
|
||||||
|
[HoldingRegister<Int16>(99, Scale = .001)] public Double String1Current { get; private set; }
|
||||||
|
[HoldingRegister<Int16>(100, Scale = .001)] public Double String2Current { get; private set; }
|
||||||
|
}
|
Loading…
Reference in New Issue