Add Interface for Relay record.

Add Amax library.
Add preprocessor use for Amax and Adam
This commit is contained in:
atef 2024-04-12 11:29:46 +02:00
parent 78676ce504
commit 2c087c4788
9 changed files with 211 additions and 8 deletions

View File

@ -21,6 +21,7 @@
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj" /> <ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj" />
<ProjectReference Include="../../Lib/Units/Units.csproj" /> <ProjectReference Include="../../Lib/Units/Units.csproj" />
<ProjectReference Include="../../Lib/Utils/Utils.csproj" /> <ProjectReference Include="../../Lib/Utils/Utils.csproj" />
<ProjectReference Include="../../Lib/Devices/Amax5070/Amax5070.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -23,7 +23,7 @@ public record StatusRecord
public required AcPowerDevice? AcGridToAcIsland { get; init; } public required AcPowerDevice? AcGridToAcIsland { get; init; }
public required DcPowerDevice? AcDcToDcLink { get; init; } public required DcPowerDevice? AcDcToDcLink { get; init; }
public required DcPowerDevice? LoadOnDc { get; init; } public required DcPowerDevice? LoadOnDc { get; init; }
public required RelaysRecord? Relays { get; init; } public required IRelaysRecord? Relays { get; init; }
public required AmptStatus? PvOnDc { get; init; } public required AmptStatus? PvOnDc { get; init; }
public required Config Config { get; set; } public required Config Config { get; set; }
public required SystemLog Log { get; init; } // TODO: init only public required SystemLog Log { get; init; } // TODO: init only

View File

@ -1,4 +1,4 @@
#undef Amax #define Amax
#undef GridLimit #undef GridLimit
using System.Reactive.Linq; using System.Reactive.Linq;
@ -126,7 +126,13 @@ internal static class Program
var pvOnDcDevice = new AmptDevices(PvOnDc); var pvOnDcDevice = new AmptDevices(PvOnDc);
var pvOnAcGridDevice = new AmptDevices(PvOnAcGrid); var pvOnAcGridDevice = new AmptDevices(PvOnAcGrid);
var pvOnAcIslandDevice = new AmptDevices(PvOnAcIsland); var pvOnAcIslandDevice = new AmptDevices(PvOnAcIsland);
#if Amax
var saliMaxRelaysDevice = new RelaysDeviceAmax(RelaysChannel);
#else
var saliMaxRelaysDevice = new RelaysDevice(RelaysChannel); var saliMaxRelaysDevice = new RelaysDevice(RelaysChannel);
#endif
StatusRecord ReadStatus() StatusRecord ReadStatus()
{ {
@ -183,8 +189,11 @@ internal static class Program
void WriteControl(StatusRecord r) void WriteControl(StatusRecord r)
{ {
if (r.Relays is not null) if (r.Relays is not null)
saliMaxRelaysDevice.Write(r.Relays); #if Amax
saliMaxRelaysDevice.Write((RelaysRecordAmax)r.Relays);
#else
((RelaysDevice)saliMaxRelaysDevice).Write((RelaysRecord)r.Relays);
#endif
acDcDevices.Write(r.AcDc); acDcDevices.Write(r.AcDc);
dcDcDevices.Write(r.DcDc); dcDcDevices.Write(r.DcDc);
} }

View File

@ -1,4 +1,5 @@
using InnovEnergy.Lib.Devices.Adam6360D; using InnovEnergy.Lib.Devices.Adam6360D;
using InnovEnergy.Lib.Devices.Amax5070;
using InnovEnergy.Lib.Protocols.Modbus.Channels; using InnovEnergy.Lib.Protocols.Modbus.Channels;
namespace InnovEnergy.App.SaliMax.SaliMaxRelays; namespace InnovEnergy.App.SaliMax.SaliMaxRelays;
@ -10,6 +11,7 @@ public class RelaysDevice
public RelaysDevice(String hostname) => AdamDevice = new Adam6360DDevice(hostname, 2); public RelaysDevice(String hostname) => AdamDevice = new Adam6360DDevice(hostname, 2);
public RelaysDevice(Channel channel) => AdamDevice = new Adam6360DDevice(channel, 2); public RelaysDevice(Channel channel) => AdamDevice = new Adam6360DDevice(channel, 2);
public RelaysRecord? Read() public RelaysRecord? Read()
{ {
try try
@ -37,3 +39,34 @@ public class RelaysDevice
} }
public class RelaysDeviceAmax
{
private Amax5070Device AmaxDevice { get; }
public RelaysDeviceAmax(Channel channel) => AmaxDevice = new Amax5070Device(channel);
public RelaysRecordAmax? Read()
{
try
{
return AmaxDevice.Read();
}
catch (Exception e)
{
$"Failed to read from {nameof(RelaysDeviceAmax)}\n{e}".LogError();
return null;
}
}
public void Write(RelaysRecordAmax r)
{
try
{
AmaxDevice.Write(r);
}
catch (Exception e)
{
$"Failed to write to {nameof(RelaysDeviceAmax)}\n{e}".LogError();
}
}
}

View File

@ -1,8 +1,19 @@
using InnovEnergy.Lib.Devices.Adam6360D; using InnovEnergy.Lib.Devices.Adam6360D;
using InnovEnergy.Lib.Devices.Amax5070;
namespace InnovEnergy.App.SaliMax.SaliMaxRelays; namespace InnovEnergy.App.SaliMax.SaliMaxRelays;
public class RelaysRecord public interface IRelaysRecord
{
Boolean K1GridBusIsConnectedToGrid { get; }
Boolean K2IslandBusIsConnectedToGridBus { get; }
IEnumerable<Boolean> K3InverterIsConnectedToIslandBus { get; }
Boolean FiWarning { get; }
Boolean FiError { get; }
Boolean K2ConnectIslandBusToGridBus { get; set; }
}
public class RelaysRecord : IRelaysRecord
{ {
private readonly Adam6360DRegisters _Regs; private readonly Adam6360DRegisters _Regs;
@ -36,3 +47,39 @@ public class RelaysRecord
public static implicit operator RelaysRecord(Adam6360DRegisters d) => new RelaysRecord(d); public static implicit operator RelaysRecord(Adam6360DRegisters d) => new RelaysRecord(d);
} }
public class RelaysRecordAmax : IRelaysRecord
{
private readonly Amax5070Registers _Regs;
private RelaysRecordAmax(Amax5070Registers regs) => _Regs = regs;
public Boolean K1GridBusIsConnectedToGrid => _Regs.DigitalInput22;
public Boolean K2IslandBusIsConnectedToGridBus => !_Regs.DigitalInput20;
public IEnumerable<Boolean> K3InverterIsConnectedToIslandBus
{
get
{
yield return K3Inverter1IsConnectedToIslandBus;
yield return K3Inverter2IsConnectedToIslandBus;
yield return K3Inverter3IsConnectedToIslandBus;
yield return K3Inverter4IsConnectedToIslandBus;
}
}
public Boolean K3Inverter1IsConnectedToIslandBus => !_Regs.DigitalInput16;
public Boolean K3Inverter2IsConnectedToIslandBus => !_Regs.DigitalInput17;
public Boolean K3Inverter3IsConnectedToIslandBus => !_Regs.DigitalInput18;
public Boolean K3Inverter4IsConnectedToIslandBus => !_Regs.DigitalInput19;
public Boolean FiWarning => !_Regs.DigitalInput21;
public Boolean FiError => !_Regs.DigitalInput23;
public Boolean K2ConnectIslandBusToGridBus { get => _Regs.Relay23; set => _Regs.Relay23 = value;}
public static implicit operator Amax5070Registers(RelaysRecordAmax d) => d._Regs;
public static implicit operator RelaysRecordAmax(Amax5070Registers d) => new RelaysRecordAmax(d);
}

View File

@ -704,13 +704,13 @@ public static class Controller
//s.Config.LowerDcLinkVoltageFromDc = 20; //s.Config.LowerDcLinkVoltageFromDc = 20;
} }
private static void DisconnectIslandBusFromGrid(this RelaysRecord? relays) private static void DisconnectIslandBusFromGrid(this IRelaysRecord? relays)
{ {
if (relays is not null) if (relays is not null)
relays.K2ConnectIslandBusToGridBus = false; relays.K2ConnectIslandBusToGridBus = false;
} }
private static void ConnectIslandBusToGrid(this RelaysRecord? relays) private static void ConnectIslandBusToGrid(this IRelaysRecord? relays)
{ {
if (relays is not null) if (relays is not null)
relays.K2ConnectIslandBusToGridBus = true; relays.K2ConnectIslandBusToGridBus = true;

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../InnovEnergy.Lib.props" />
<PropertyGroup>
<RootNamespace>InnovEnergy.Lib.Devices.Amax5070</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../Protocols/Modbus/Modbus.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,18 @@
using InnovEnergy.Lib.Protocols.Modbus.Channels;
using InnovEnergy.Lib.Protocols.Modbus.Clients;
using InnovEnergy.Lib.Protocols.Modbus.Slaves;
namespace InnovEnergy.Lib.Devices.Amax5070;
public class Amax5070Device : ModbusDevice<Amax5070Registers>
{
// Amax5070 have slave ID = 0
public Amax5070Device(String hostname, Byte slaveId = 0, UInt16 port = 502) :
this(new TcpChannel(hostname, port), slaveId)
{
}
public Amax5070Device(Channel channel, Byte slaveId = 0) : base(new ModbusTcpClient(channel, slaveId))
{
}
}

View File

@ -0,0 +1,77 @@
using System.Diagnostics.CodeAnalysis;
using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes;
namespace InnovEnergy.Lib.Devices.Amax5070
{
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
[SuppressMessage("ReSharper", "UnusedMember.Global")]
[AddressOffset(-1)]
public class Amax5070Registers
{
[Coil(1)] public Boolean DigitalOutput0 { get; private set; }
[Coil(2)] public Boolean DigitalOutput1 { get; private set; }
[Coil(3)] public Boolean DigitalOutput2 { get; private set; }
[Coil(4)] public Boolean DigitalOutput3 { get; private set; }
[Coil(5)] public Boolean DigitalOutput4 { get; private set; }
[Coil(6)] public Boolean DigitalOutput5 { get; private set; }
[Coil(7)] public Boolean DigitalOutput6 { get; private set; }
[Coil(8)] public Boolean DigitalOutput7 { get; private set; }
[Coil(9)] public Boolean DigitalOutput8 { get; private set; }
[Coil(10)] public Boolean DigitalOutput9 { get; private set; }
[Coil(11)] public Boolean DigitalOutput10 { get; private set; }
[Coil(12)] public Boolean DigitalOutput11 { get; private set; }
[Coil(13)] public Boolean DigitalOutput12 { get; private set; }
[Coil(14)] public Boolean DigitalOutput13 { get; private set; }
[Coil(15)] public Boolean DigitalOutput14 { get; private set; }
[Coil(16)] public Boolean DigitalOutput15 { get; private set; }
[Coil(17)] public Boolean Relay10 { get; set; } // Relay5060 1
[Coil(18)] public Boolean Relay11 { get; set; } // Relay5060 1
[Coil(19)] public Boolean Relay12 { get; set; } // Relay5060 1
[Coil(20)] public Boolean Relay13 { get; set; } // Relay5060 1
[Coil(25)] public Boolean Relay20 { get; set; } // Relay5060 2
[Coil(26)] public Boolean Relay21 { get; set; } // Relay5060 2
[Coil(27)] public Boolean Relay22 { get; set; } // Relay5060 2
[Coil(28)] public Boolean Relay23 { get; set; } // Relay5060 2
[Coil(33)] public Boolean Relay30 { get; set; } // Relay5060 3
[Coil(34)] public Boolean Relay31 { get; set; } // Relay5060 3
[Coil(35)] public Boolean Relay32 { get; set; } // Relay5060 3
[Coil(36)] public Boolean Relay33 { get; set; } // Relay5060 3
[Coil(41)] public Boolean Relay40 { get; set; } // Relay5060 4
[Coil(42)] public Boolean Relay41 { get; set; } // Relay5060 4
[Coil(43)] public Boolean Relay42 { get; set; } // Relay5060 4
[Coil(44)] public Boolean Relay43 { get; set; } // Relay5060 4
[DiscreteInput(49)] public Boolean DigitalInput0 { get; private set; }
[DiscreteInput(50)] public Boolean DigitalInput1 { get; private set; }
[DiscreteInput(51)] public Boolean DigitalInput2 { get; private set; }
[DiscreteInput(52)] public Boolean DigitalInput3 { get; private set; }
[DiscreteInput(53)] public Boolean DigitalInput4 { get; private set; }
[DiscreteInput(54)] public Boolean DigitalInput5 { get; private set; }
[DiscreteInput(55)] public Boolean DigitalInput6 { get; private set; }
[DiscreteInput(56)] public Boolean DigitalInput7 { get; private set; }
[DiscreteInput(57)] public Boolean DigitalInput8 { get; private set; }
[DiscreteInput(58)] public Boolean DigitalInput9 { get; private set; }
[DiscreteInput(59)] public Boolean DigitalInput10 { get; private set; }
[DiscreteInput(60)] public Boolean DigitalInput11 { get; private set; }
[DiscreteInput(61)] public Boolean DigitalInput12 { get; private set; }
[DiscreteInput(62)] public Boolean DigitalInput13 { get; private set; }
[DiscreteInput(63)] public Boolean DigitalInput14 { get; private set; }
[DiscreteInput(64)] public Boolean DigitalInput15 { get; private set; }
[DiscreteInput(65)] public Boolean DigitalInput16 { get; private set; } // Relay5060 1
[DiscreteInput(66)] public Boolean DigitalInput17 { get; private set; } // Relay5060 1
[DiscreteInput(73)] public Boolean DigitalInput18 { get; private set; } // Relay5060 2
[DiscreteInput(74)] public Boolean DigitalInput19 { get; private set; } // Relay5060 2
[DiscreteInput(81)] public Boolean DigitalInput20 { get; private set; } // Relay5060 3
[DiscreteInput(82)] public Boolean DigitalInput21 { get; private set; } // Relay5060 3
[DiscreteInput(89)] public Boolean DigitalInput22 { get; private set; } // Relay5060 4
[DiscreteInput(90)] public Boolean DigitalInput23 { get; private set; } // Relay5060 4
}
}