make EmuMeter use updated Modbus Lib
This commit is contained in:
parent
a2c0674ecb
commit
faa1dd2af8
|
@ -1,41 +0,0 @@
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Conversions;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.EmuMeter;
|
|
||||||
|
|
||||||
public static class Conversions
|
|
||||||
{
|
|
||||||
|
|
||||||
// TODO: integrate into ModbusRegisters
|
|
||||||
|
|
||||||
public static IReadOnlyList<Single> ToSingles(this ModbusRegisters regs)
|
|
||||||
{
|
|
||||||
return regs
|
|
||||||
.Chunk(2)
|
|
||||||
.Select(c => c.Reverse().SelectMany(BitConverter.GetBytes).ToArray())
|
|
||||||
.Select(d => BitConverter.ToSingle(d))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IReadOnlyList<Decimal> ToDecimals(this ModbusRegisters regs)
|
|
||||||
{
|
|
||||||
return regs
|
|
||||||
.Chunk(2)
|
|
||||||
.Select(c => c.Reverse().SelectMany(BitConverter.GetBytes).ToArray())
|
|
||||||
.Select(d => BitConverter.ToSingle(d))
|
|
||||||
.Select(d => d.ConvertTo<Decimal>())
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReSharper disable once InconsistentNaming
|
|
||||||
public static IReadOnlyList<UInt64> ToUInt64s(this ModbusRegisters regs)
|
|
||||||
{
|
|
||||||
return regs
|
|
||||||
.SelectMany(d => BitConverter.GetBytes(d).Reverse())
|
|
||||||
.Chunk(8)
|
|
||||||
.Select(c => c.Reverse().ToArray())
|
|
||||||
.Select(d => BitConverter.ToUInt64(d))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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="../../Utils/Utils.csproj" />
|
<ProjectReference Include="../../Utils/Utils.csproj" />
|
||||||
|
|
|
@ -1,97 +1,21 @@
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
using InnovEnergy.Lib.Protocols.Modbus.Slaves;
|
||||||
using InnovEnergy.Lib.Units.Composite;
|
|
||||||
using static DecimalMath.DecimalEx;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.EmuMeter;
|
namespace InnovEnergy.Lib.Devices.EmuMeter;
|
||||||
|
|
||||||
public class EmuMeterDevice
|
public class EmuMeterDevice: ModbusDevice<EmuMeterRegisters>
|
||||||
{
|
{
|
||||||
private ModbusTcpClient Modbus { get; }
|
public EmuMeterDevice(String hostname, UInt16 port = 502, Byte slaveId = 1) : this(new TcpChannel(hostname, port), slaveId)
|
||||||
|
|
||||||
public EmuMeterDevice(String hostname, UInt16 port = 502, Byte slaveId = 1)
|
|
||||||
{
|
{
|
||||||
var connection = new ModbusTcpConnection(hostname, port);
|
|
||||||
Modbus = new ModbusTcpClient(connection, slaveId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmuMeterStatus? ReadStatus()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return TryReadStatus();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
Modbus.CloseConnection();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EmuMeterDevice(Channel channel, Byte slaveId = 1) : base(new ModbusTcpClient(channel, slaveId))
|
||||||
//private static Decimal GetPhi(Decimal cosPhi) => cosPhi.Clamp(-1m, 1m).Apply(ACos);
|
{
|
||||||
|
}
|
||||||
private EmuMeterStatus TryReadStatus()
|
|
||||||
|
public EmuMeterDevice(ModbusClient client) : base(client)
|
||||||
{
|
{
|
||||||
// Console.WriteLine("Reading Emu Meter Data");
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: get SerialNb, depends on Little/Big Endian support in Modbus Lib
|
|
||||||
// var registers = Modbus.ReadHoldingRegisters(5001, 4);
|
|
||||||
// var id = registers.GetInt32(5001);
|
|
||||||
|
|
||||||
var powerCurrent = Modbus.ReadHoldingRegisters(9000, 108).ToDecimals(); // TODO "ModbusRegisters"
|
|
||||||
var voltageFreq = Modbus.ReadHoldingRegisters(9200, 112).ToDecimals(); // To check with Ivo
|
|
||||||
|
|
||||||
// var energyPhases = Modbus.ReadHoldingRegisters(6100, 104).ToUInt64s();
|
|
||||||
|
|
||||||
var activePowerL1 = powerCurrent[1];
|
|
||||||
var activePowerL2 = powerCurrent[2];
|
|
||||||
var activePowerL3 = powerCurrent[3];
|
|
||||||
var reactivePowerL1 = powerCurrent[6];
|
|
||||||
var reactivePowerL2 = powerCurrent[7];
|
|
||||||
var reactivePowerL3 = powerCurrent[8];
|
|
||||||
|
|
||||||
var currentL1 = powerCurrent[51];
|
|
||||||
var currentL2 = powerCurrent[52];
|
|
||||||
var currentL3 = powerCurrent[53];
|
|
||||||
|
|
||||||
var voltageL1N = voltageFreq[0];
|
|
||||||
var voltageL2N = voltageFreq[1];
|
|
||||||
var voltageL3N = voltageFreq[2];
|
|
||||||
var frequency = voltageFreq[55];
|
|
||||||
|
|
||||||
|
|
||||||
var l1 = new AcPhase
|
|
||||||
{
|
|
||||||
Current = currentL1,
|
|
||||||
Voltage = voltageL1N,
|
|
||||||
Phi = ATan2(reactivePowerL1, activePowerL1) // TODO: check that this works
|
|
||||||
};
|
|
||||||
var l2 = new AcPhase
|
|
||||||
{
|
|
||||||
Current = currentL2,
|
|
||||||
Voltage = voltageL2N,
|
|
||||||
Phi = ATan2(reactivePowerL2, activePowerL2)
|
|
||||||
};
|
|
||||||
var l3 = new AcPhase
|
|
||||||
{
|
|
||||||
Current = currentL3,
|
|
||||||
Voltage = voltageL3N,
|
|
||||||
Phi = ATan2(reactivePowerL3, activePowerL3)
|
|
||||||
};
|
|
||||||
|
|
||||||
return new EmuMeterStatus
|
|
||||||
{
|
|
||||||
Ac = new Ac3Bus
|
|
||||||
{
|
|
||||||
Frequency = frequency,
|
|
||||||
L1 = l1,
|
|
||||||
L2 = l2,
|
|
||||||
L3 = l3
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes;
|
||||||
|
using InnovEnergy.Lib.StatusApi.DeviceTypes;
|
||||||
|
using InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.EmuMeter;
|
||||||
|
|
||||||
|
using Float32 = Single;
|
||||||
|
|
||||||
|
|
||||||
|
[AddressOffset(-2)] // why?
|
||||||
|
public record EmuMeterRegisters : IAc3Meter
|
||||||
|
{
|
||||||
|
[HoldingRegister<Float32>(9002)] private Float32 _ActivePowerL1;
|
||||||
|
[HoldingRegister<Float32>(9004)] private Float32 _ActivePowerL2;
|
||||||
|
[HoldingRegister<Float32>(9006)] private Float32 _ActivePowerL3;
|
||||||
|
|
||||||
|
[HoldingRegister<Float32>(9012)] private Float32 _ReactivePowerL1;
|
||||||
|
[HoldingRegister<Float32>(9014)] private Float32 _ReactivePowerL2;
|
||||||
|
[HoldingRegister<Float32>(9016)] private Float32 _ReactivePowerL3;
|
||||||
|
|
||||||
|
[HoldingRegister<Float32>(9022)] private Float32 _ApparentPowerL1;
|
||||||
|
[HoldingRegister<Float32>(9024)] private Float32 _ApparentPowerL2;
|
||||||
|
[HoldingRegister<Float32>(9026)] private Float32 _ApparentPowerL3;
|
||||||
|
|
||||||
|
[HoldingRegister<Float32>(9102)] private Float32 _CurrentL1;
|
||||||
|
[HoldingRegister<Float32>(9104)] private Float32 _CurrentL2;
|
||||||
|
[HoldingRegister<Float32>(9106)] private Float32 _CurrentL3;
|
||||||
|
|
||||||
|
[HoldingRegister<Float32>(9200)] private Float32 _VoltageL1N;
|
||||||
|
[HoldingRegister<Float32>(9202)] private Float32 _VoltageL2N;
|
||||||
|
[HoldingRegister<Float32>(9204)] private Float32 _VoltageL3N;
|
||||||
|
|
||||||
|
[HoldingRegister<Float32>(9310)] private Float32 _Frequency;
|
||||||
|
|
||||||
|
public Ac3Bus Ac => Ac3Bus.FromPhasesAndFrequency
|
||||||
|
(
|
||||||
|
l1: AcPhase.FromVoltageCurrentActiveReactiveApparent
|
||||||
|
(
|
||||||
|
_VoltageL1N,
|
||||||
|
_CurrentL1,
|
||||||
|
_ActivePowerL1,
|
||||||
|
_ReactivePowerL1,
|
||||||
|
_ApparentPowerL1
|
||||||
|
),
|
||||||
|
l2: AcPhase.FromVoltageCurrentActiveReactiveApparent
|
||||||
|
(
|
||||||
|
_VoltageL2N,
|
||||||
|
_CurrentL2,
|
||||||
|
_ActivePowerL2,
|
||||||
|
_ReactivePowerL2,
|
||||||
|
_ApparentPowerL2
|
||||||
|
),
|
||||||
|
l3: AcPhase.FromVoltageCurrentActiveReactiveApparent
|
||||||
|
(
|
||||||
|
_VoltageL3N,
|
||||||
|
_CurrentL3,
|
||||||
|
_ActivePowerL3,
|
||||||
|
_ReactivePowerL3,
|
||||||
|
_ApparentPowerL3
|
||||||
|
),
|
||||||
|
frequency: _Frequency
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
using InnovEnergy.Lib.StatusApi;
|
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Devices.EmuMeter;
|
|
||||||
|
|
||||||
public record EmuMeterStatus : PowerMeterStatus
|
|
||||||
{
|
|
||||||
// TODO: additional Measurements, device id
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
||||||
|
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
|
namespace InnovEnergy.Lib.Devices.EmuMeter;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static Task Main(string[] args)
|
||||||
|
{
|
||||||
|
var ch = new TcpChannel("localhost", 5003);
|
||||||
|
var cl = new ModbusTcpClient(ch, 1);
|
||||||
|
var d = new EmuMeterDevice(cl);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var x = d.Read();
|
||||||
|
|
||||||
|
//x.WriteLine();
|
||||||
|
var options = new JsonSerializerOptions { WriteIndented = true };
|
||||||
|
(x, options).Apply(JsonSerializer.Serialize).WriteLine();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue