Introduce CombinedStatus
This commit is contained in:
parent
d564b3c3b6
commit
840643f069
|
@ -2,23 +2,23 @@
|
|||
<Import Project="../InnovEnergy.App.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../Lib/Devices/Adam6060/Adam6060.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Devices/AMPT/Ampt.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Devices/Battery48TL/Battery48TL.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Devices/EmuMeter/EmuMeter.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvert/TruConvert.csproj"/>
|
||||
<ProjectReference Include="../../Lib/StatusApi/StatusApi.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Utils/Utils.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Time/Time.csproj"/>
|
||||
<ProjectReference Include="../../Lib/Devices/Adam6060/Adam6060.csproj" />
|
||||
<ProjectReference Include="../../Lib/Devices/AMPT/Ampt.csproj" />
|
||||
<ProjectReference Include="../../Lib/Devices/Battery48TL/Battery48TL.csproj" />
|
||||
<ProjectReference Include="../../Lib/Devices/EmuMeter/EmuMeter.csproj" />
|
||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj" />
|
||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj" />
|
||||
<ProjectReference Include="../../Lib/Devices/Trumpf/TruConvert/TruConvert.csproj" />
|
||||
<ProjectReference Include="../../Lib/StatusApi/StatusApi.csproj" />
|
||||
<ProjectReference Include="../../Lib/Utils/Utils.csproj" />
|
||||
<ProjectReference Include="../../Lib/Time/Time.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliWrap" Version="3.6.0"/>
|
||||
<PackageReference Include="Flurl.Http" Version="3.2.4"/>
|
||||
<PackageReference Include="System.IO.Ports" Version="7.0.0"/>
|
||||
<PackageReference Include="DecimalMath.DecimalEx" Version="1.0.2"/>
|
||||
<PackageReference Include="CliWrap" Version="3.6.0" />
|
||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
|
||||
<PackageReference Include="DecimalMath.DecimalEx" Version="1.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
|
|
@ -1,51 +1,53 @@
|
|||
using InnovEnergy.Lib.Devices.Battery48TL;
|
||||
using InnovEnergy.Lib.StatusApi;
|
||||
using InnovEnergy.Lib.Units;
|
||||
using InnovEnergy.Lib.Units.Composite;
|
||||
using static InnovEnergy.Lib.Devices.Battery48TL.TemperatureState;
|
||||
|
||||
namespace InnovEnergy.App.SaliMax.Controller;
|
||||
|
||||
public class AvgBatteriesStatus
|
||||
public static class AvgBatteriesStatus
|
||||
{
|
||||
public Decimal Soc { get; set; }
|
||||
public Decimal Current { get; set; }
|
||||
public Decimal Voltage { get; set; }
|
||||
public Decimal Power { get; set; }
|
||||
public Decimal BusVoltage { get; set; }
|
||||
public Decimal BatteryTemperature { get; set; }
|
||||
public IReadOnlyList<String> Warnings { get; set; }
|
||||
public IReadOnlyList<String> Alarms { get; set; }
|
||||
public Boolean HeaterOn { get; set; }
|
||||
public Boolean EocReached { get; set; }
|
||||
public Boolean BatteryCold { get; set; }
|
||||
public Decimal MaxChargingPower { get; set; }
|
||||
public Decimal MaxDischargingPower { get; set; }
|
||||
|
||||
public static AvgBatteriesStatus ReadBatteriesStatus(IReadOnlyList<Battery48TLStatus> batteriesStatus)
|
||||
public static CombinedStatus<Battery48TLStatus>? Combine(this IReadOnlyList<Battery48TLStatus> stati)
|
||||
{
|
||||
var soc = batteriesStatus.Any() ? batteriesStatus.Average(b => b.Soc) : 0;
|
||||
var current = batteriesStatus.Select(b => b.Dc.Current).Aggregate(0m,(a, b) => a + b);
|
||||
var voltage = batteriesStatus.Any() ? batteriesStatus.Average(b => b.Dc.Voltage) : 0;
|
||||
var power = batteriesStatus.Select(b => b.Dc.Power).Aggregate(0m,(a, b) => a + b);
|
||||
var busVoltage = batteriesStatus.Any() ? batteriesStatus.Average(b => b.BusVoltage): 0;
|
||||
var batteryTemperature = batteriesStatus.Any() ? batteriesStatus.Average(b => b.Temperature): 0;
|
||||
var heaterOn = batteriesStatus.Any() && batteriesStatus.Select(b => b.HeaterOn).Aggregate((a, b) => a | b);
|
||||
var eocReached = batteriesStatus.All(b => b.EocReached);
|
||||
var batteryCold = batteriesStatus.Any(b => b.BatteryCold);
|
||||
var maxChargingPower = batteriesStatus.Select(b => b.MaxChargingPower).Aggregate(0m, (a, b) => a + b);
|
||||
var maxDischargingPower = batteriesStatus.Select(b => b.MaxDischargingPower).Aggregate(0m, (a, b) => a + b);
|
||||
|
||||
|
||||
return new AvgBatteriesStatus
|
||||
var combined = stati.Count == 0
|
||||
? null
|
||||
: new Battery48TLStatus
|
||||
{
|
||||
Soc = soc,
|
||||
Current = current,
|
||||
Voltage = voltage,
|
||||
Power = power,
|
||||
BusVoltage = busVoltage,
|
||||
BatteryTemperature = batteryTemperature,
|
||||
HeaterOn = heaterOn,
|
||||
EocReached = eocReached,
|
||||
BatteryCold = batteryCold,
|
||||
MaxChargingPower = maxChargingPower,
|
||||
MaxDischargingPower = maxDischargingPower
|
||||
Soc = stati.Min(b => b.Soc),
|
||||
Temperature = stati.Average(b => b.Temperature),
|
||||
Dc = new DcBus
|
||||
{
|
||||
Voltage = stati.Average(b => b.Dc.Voltage),
|
||||
Current = stati.Sum(b => b.Dc.Current),
|
||||
},
|
||||
|
||||
Alarms = stati.SelectMany(b => b.Alarms).Distinct().ToList(),
|
||||
Warnings = stati.SelectMany(b => b.Warnings).Distinct().ToList(),
|
||||
|
||||
MaxChargingPower = stati.Sum(b => b.MaxChargingPower),
|
||||
MaxDischargingPower = stati.Sum(b => b.MaxDischargingPower),
|
||||
|
||||
Heating = stati.Any(b => b.Heating),
|
||||
|
||||
AmberLed = LedState.Off, // not used for combined battery
|
||||
BlueLed = LedState.Off,
|
||||
RedLed = LedState.Off,
|
||||
GreenLed = LedState.Off,
|
||||
|
||||
CellsVoltage = stati.Average(b => b.CellsVoltage),
|
||||
ConnectedToDc = stati.Any(b => b.ConnectedToDc),
|
||||
|
||||
TemperatureState = stati.Any(b => b.TemperatureState == OperatingTemperature) // TODO: revisit when we have the overheated state
|
||||
? OperatingTemperature
|
||||
: Cold,
|
||||
|
||||
};
|
||||
|
||||
return new CombinedStatus<Battery48TLStatus>
|
||||
{
|
||||
Combined = combined!,
|
||||
Children = stati
|
||||
};
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ using InnovEnergy.Lib.Devices.Battery48TL;
|
|||
using InnovEnergy.Lib.Devices.EmuMeter;
|
||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||
using InnovEnergy.Lib.StatusApi;
|
||||
|
||||
namespace InnovEnergy.App.SaliMax.Controller;
|
||||
|
||||
|
@ -12,8 +13,8 @@ public record StatusRecord
|
|||
{
|
||||
public TruConvertAcStatus? InverterStatus { get; init; }
|
||||
public TruConvertDcStatus? DcDcStatus { get; init; }
|
||||
public Battery48TLStatus[]? BatteriesStatus { get; set; } = Array.Empty<Battery48TLStatus>(); // TODO remove static
|
||||
public AvgBatteriesStatus? AvgBatteriesStatus { get; init; }
|
||||
public CombinedStatus<Battery48TLStatus>? BatteriesStatus { get; init; }
|
||||
|
||||
public EmuMeterStatus? GridMeterStatus { get; init; }
|
||||
public SaliMaxRelayStatus? SaliMaxRelayStatus { get; init; }
|
||||
public AmptStatus? AmptStatus { get; init; }
|
||||
|
|
|
@ -13,6 +13,7 @@ using InnovEnergy.Lib.Devices.EmuMeter;
|
|||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||
using InnovEnergy.Lib.Time.Unix;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
|
||||
#pragma warning disable IL2026
|
||||
|
||||
|
@ -41,6 +42,18 @@ internal static class Program
|
|||
{
|
||||
Console.WriteLine("Starting SaliMax");
|
||||
|
||||
var batteryNodes = new Byte[] { 2, 3 };
|
||||
|
||||
var batteryTty = "/dev/ttyUSB0";
|
||||
|
||||
var relaysIp = "10.0.1.1";
|
||||
var truConvertAcIp = "10.0.2.1";
|
||||
var truConvertDcIp = "10.0.3.1";
|
||||
var gridMeterIp = "10.0.4.1";
|
||||
var internalMeter = "10.0.4.2";
|
||||
var amptIp = "10.0.5.1";
|
||||
|
||||
|
||||
var s3Config = new S3Config
|
||||
{
|
||||
Bucket = "saliomameiringen",
|
||||
|
@ -62,33 +75,33 @@ internal static class Program
|
|||
var firstBattery48TlDevice =Battery48TlDevice.Fake();;
|
||||
var salimaxConfig = new SalimaxConfig();
|
||||
#else
|
||||
#if BatteriesAllowed
|
||||
var firstBattery48TlDevice = new Battery48TlDevice("/dev/ttyUSB0", 2);
|
||||
var secondBattery48TlDevice = new Battery48TlDevice("/dev/ttyUSB0", 3);
|
||||
#endif
|
||||
var inverterDevice = new TruConvertAcDevice("192.168.1.2");
|
||||
var dcDcDevice = new TruConvertDcDevice("192.168.1.3");
|
||||
var gridMeterDevice = new EmuMeterDevice("192.168.1.241");
|
||||
var acInToAcOutMeterDevice = new EmuMeterDevice("192.168.1.241"); // TODO: use real device
|
||||
var amptDevice = new AmptCommunicationUnit("192.168.1.249");
|
||||
var saliMaxRelaysDevice = new SaliMaxRelaysDevice("192.168.1.242");
|
||||
|
||||
var batteries = batteryNodes.Select(n => new Battery48TlDevice(batteryTty, n)).ToList();
|
||||
|
||||
|
||||
var inverterDevice = new TruConvertAcDevice(truConvertAcIp);
|
||||
var dcDcDevice = new TruConvertDcDevice(truConvertDcIp);
|
||||
|
||||
var gridMeterDevice = new EmuMeterDevice(gridMeterIp);
|
||||
var acInToAcOutMeterDevice = new EmuMeterDevice(internalMeter); // TODO: use real device
|
||||
|
||||
var amptDevice = new AmptCommunicationUnit(amptIp);
|
||||
|
||||
var saliMaxRelaysDevice = new SaliMaxRelaysDevice(relaysIp);
|
||||
var salimaxConfig = new SalimaxConfig();
|
||||
#endif
|
||||
// This is will be always add manually ? or do we need to read devices automatically in a range of IP @
|
||||
#if BatteriesAllowed
|
||||
|
||||
var battery48TlDevices = new[] { firstBattery48TlDevice, secondBattery48TlDevice };
|
||||
#endif
|
||||
|
||||
var dcDcDevices = new[] { dcDcDevice };
|
||||
var inverterDevices = new[] { inverterDevice};
|
||||
|
||||
StatusRecord ReadStatus()
|
||||
{
|
||||
#if BatteriesAllowed
|
||||
var combinedBatteryStatus = batteries
|
||||
.Select(b => b.ReadStatus())
|
||||
.NotNull()
|
||||
.ToList()
|
||||
.Combine();
|
||||
|
||||
var battery48TlStatusArray = battery48TlDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||
#endif
|
||||
// var dcDcStatusArray = dcDcDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||
// var inverterStatusArray = inverterDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
|
||||
|
||||
|
@ -96,14 +109,8 @@ internal static class Program
|
|||
{
|
||||
InverterStatus = inverterDevice.ReadStatus(),
|
||||
DcDcStatus = dcDcDevice.ReadStatus(),
|
||||
#if BatteriesAllowed
|
||||
|
||||
BatteriesStatus = battery48TlStatusArray,
|
||||
AvgBatteriesStatus = AvgBatteriesStatus.ReadBatteriesStatus(battery48TlStatusArray),
|
||||
#else
|
||||
BatteriesStatus = null,
|
||||
AvgBatteriesStatus = null,
|
||||
#endif
|
||||
BatteriesStatus = combinedBatteryStatus,
|
||||
AcInToAcOutMeterStatus = acInToAcOutMeterDevice.ReadStatus(),
|
||||
GridMeterStatus = gridMeterDevice.ReadStatus(),
|
||||
SaliMaxRelayStatus = saliMaxRelaysDevice.ReadStatus(),
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
|
||||
host=ie-entwicklung@10.2.3.115
|
||||
|
||||
tunnel() {
|
||||
name=$1
|
||||
ip=$2
|
||||
rPort=$3
|
||||
lPort=$4
|
||||
|
||||
echo -n "localhost:$lPort $name "
|
||||
ssh -nNTL "$lPort:$ip:$rPort" "$host" 2> /dev/null &
|
||||
|
||||
until nc -vz 127.0.0.1 $lPort 2> /dev/null
|
||||
do
|
||||
echo -n .
|
||||
sleep 0.3
|
||||
done
|
||||
|
||||
echo "ok"
|
||||
}
|
||||
|
||||
echo ""
|
||||
|
||||
tunnel "Trumpf Inverter (http) " 10.0.2.1 80 8001
|
||||
tunnel "Trumpf DCDC (http) " 10.0.3.1 80 8002
|
||||
tunnel "Ext Emu Meter (http) " 10.0.4.1 80 8003
|
||||
tunnel "Int Emu Meter (http) " 10.0.4.2 80 8004
|
||||
tunnel "AMPT (http) " 10.0.5.1 8080 8005
|
||||
|
||||
tunnel "Trumpf Inverter (modbus)" 10.0.2.1 502 5001
|
||||
tunnel "Trumpf DCDC (modbus) " 10.0.3.1 502 5002
|
||||
tunnel "Ext Emu Meter (modbus) " 10.0.4.1 502 5003
|
||||
tunnel "Int Emu Meter " 10.0.4.2 502 5004
|
||||
tunnel "AMPT (modbus) " 10.0.5.1 502 5005
|
||||
|
||||
|
||||
|
||||
echo
|
||||
echo "press any key to close the tunnels ..."
|
||||
read -r -n 1 -s
|
||||
kill $(jobs -p)
|
||||
echo "done"
|
|
@ -1,5 +1,6 @@
|
|||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||
using static InnovEnergy.Lib.Devices.Battery48TL.Constants;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.Battery48TL;
|
||||
|
||||
|
@ -10,10 +11,10 @@ public class Battery48TlDevice
|
|||
public Battery48TlDevice(String device, Byte nodeId)
|
||||
{
|
||||
var serialConnection = new ModbusSerialConnection(device,
|
||||
Constants.BaudRate,
|
||||
Constants.Parity,
|
||||
Constants.DataBits,
|
||||
Constants.StopBits,
|
||||
BaudRate,
|
||||
Parity,
|
||||
DataBits,
|
||||
StopBits,
|
||||
Constants.Timeout);
|
||||
|
||||
Modbus = new ModbusRtuClient(serialConnection, nodeId);
|
||||
|
@ -34,7 +35,7 @@ public class Battery48TlDevice
|
|||
try
|
||||
{
|
||||
return Modbus
|
||||
.ReadInputRegisters(Constants.BaseAddress, Constants.NoOfRegisters)
|
||||
.ReadInputRegisters(BaseAddress, NoOfRegisters)
|
||||
.ParseBatteryStatus();
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
|
@ -4,5 +4,5 @@ public enum TemperatureState
|
|||
{
|
||||
Cold = 0,
|
||||
OperatingTemperature = 1,
|
||||
Overheated =2,
|
||||
Overheated = 2,
|
||||
}
|
|
@ -13,4 +13,3 @@ public record BatteryStatus : IDcConnection
|
|||
public Percent Soc { get; init; }
|
||||
public Temperature Temperature { get; init; }
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
namespace InnovEnergy.Lib.StatusApi;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
public record CombinedStatus<T>
|
||||
{
|
||||
public T Combined { get; init; }
|
||||
public IReadOnlyList<T> Children { get; init; }
|
||||
|
||||
public Boolean Available => Children.Any();
|
||||
|
||||
}
|
Loading…
Reference in New Issue