diff --git a/csharp/App/SaliMax/SaliMax.csproj b/csharp/App/SaliMax/SaliMax.csproj
index c647ee0d5..6802aca05 100644
--- a/csharp/App/SaliMax/SaliMax.csproj
+++ b/csharp/App/SaliMax/SaliMax.csproj
@@ -2,23 +2,23 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
diff --git a/csharp/App/SaliMax/src/Controller/AvgBatteriesStatus.cs b/csharp/App/SaliMax/src/Controller/AvgBatteriesStatus.cs
index b62316d85..745b18187 100644
--- a/csharp/App/SaliMax/src/Controller/AvgBatteriesStatus.cs
+++ b/csharp/App/SaliMax/src/Controller/AvgBatteriesStatus.cs
@@ -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 Warnings { get; set; }
- public IReadOnlyList 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 batteriesStatus)
+ public static CombinedStatus? Combine(this IReadOnlyList 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
+ {
+ Combined = combined!,
+ Children = stati
};
}
}
\ No newline at end of file
diff --git a/csharp/App/SaliMax/src/Controller/StatusRecord.cs b/csharp/App/SaliMax/src/Controller/StatusRecord.cs
index 53de658b8..9071f5976 100644
--- a/csharp/App/SaliMax/src/Controller/StatusRecord.cs
+++ b/csharp/App/SaliMax/src/Controller/StatusRecord.cs
@@ -5,18 +5,19 @@ 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;
public record StatusRecord
{
- public TruConvertAcStatus? InverterStatus { get; init; }
- public TruConvertDcStatus? DcDcStatus { get; init; }
- public Battery48TLStatus[]? BatteriesStatus { get; set; } = Array.Empty(); // TODO remove static
- public AvgBatteriesStatus? AvgBatteriesStatus { get; init; }
- public EmuMeterStatus? GridMeterStatus { get; init; }
- public SaliMaxRelayStatus? SaliMaxRelayStatus { get; init; }
- public AmptStatus? AmptStatus { get; init; }
- public EmuMeterStatus? AcInToAcOutMeterStatus { get; init; }
- public SalimaxConfig SalimaxConfig { get; init; } = null!;
+ public TruConvertAcStatus? InverterStatus { get; init; }
+ public TruConvertDcStatus? DcDcStatus { get; init; }
+ public CombinedStatus? BatteriesStatus { get; init; }
+
+ public EmuMeterStatus? GridMeterStatus { get; init; }
+ public SaliMaxRelayStatus? SaliMaxRelayStatus { get; init; }
+ public AmptStatus? AmptStatus { get; init; }
+ public EmuMeterStatus? AcInToAcOutMeterStatus { get; init; }
+ public SalimaxConfig SalimaxConfig { get; init; } = null!;
}
\ No newline at end of file
diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs
index 229e3f0b8..d4d080a11 100644
--- a/csharp/App/SaliMax/src/Program.cs
+++ b/csharp/App/SaliMax/src/Program.cs
@@ -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,14 +42,26 @@ 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",
- Region = "sos-ch-dk-2",
- Provider = "exo.io",
+ Bucket = "saliomameiringen",
+ Region = "sos-ch-dk-2",
+ Provider = "exo.io",
ContentType = "text/plain; charset=utf-8",
- Key = "EXO2bf0cbd97fbfa75aa36ed46f",
- Secret = "Bn1CDPqOG-XpDSbYjfIJxojcHTm391vZTc8z8l_fEPs"
+ Key = "EXO2bf0cbd97fbfa75aa36ed46f",
+ Secret = "Bn1CDPqOG-XpDSbYjfIJxojcHTm391vZTc8z8l_fEPs"
};
#if DEBUG
@@ -62,48 +75,42 @@ 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 battery48TlStatusArray = battery48TlDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
-#endif
- // var dcDcStatusArray = dcDcDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
+ var combinedBatteryStatus = batteries
+ .Select(b => b.ReadStatus())
+ .NotNull()
+ .ToList()
+ .Combine();
+
+ // var dcDcStatusArray = dcDcDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
// var inverterStatusArray = inverterDevices.Select(b => b.ReadStatus()).NotNull().ToArray();
return new StatusRecord
{
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(),
diff --git a/csharp/App/SaliMax/tunneltoProto.sh b/csharp/App/SaliMax/tunneltoProto.sh
new file mode 100644
index 000000000..215e43c1d
--- /dev/null
+++ b/csharp/App/SaliMax/tunneltoProto.sh
@@ -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"
\ No newline at end of file
diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs
index 6507ac32d..97462b720 100644
--- a/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs
+++ b/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs
@@ -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)
diff --git a/csharp/Lib/Devices/Battery48TL/TemperatureState.cs b/csharp/Lib/Devices/Battery48TL/TemperatureState.cs
index da34812e0..6bb71b4e1 100644
--- a/csharp/Lib/Devices/Battery48TL/TemperatureState.cs
+++ b/csharp/Lib/Devices/Battery48TL/TemperatureState.cs
@@ -4,5 +4,5 @@ public enum TemperatureState
{
Cold = 0,
OperatingTemperature = 1,
- Overheated =2,
+ Overheated = 2,
}
\ No newline at end of file
diff --git a/csharp/Lib/StatusApi/BatteryStatus.cs b/csharp/Lib/StatusApi/BatteryStatus.cs
index d512b931f..be2c8f0d5 100644
--- a/csharp/Lib/StatusApi/BatteryStatus.cs
+++ b/csharp/Lib/StatusApi/BatteryStatus.cs
@@ -12,5 +12,4 @@ public record BatteryStatus : IDcConnection
public DcBus Dc { get; init; }
public Percent Soc { get; init; }
public Temperature Temperature { get; init; }
-}
-
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/csharp/Lib/StatusApi/CombinedStatus.cs b/csharp/Lib/StatusApi/CombinedStatus.cs
new file mode 100644
index 000000000..132f0c573
--- /dev/null
+++ b/csharp/Lib/StatusApi/CombinedStatus.cs
@@ -0,0 +1,12 @@
+namespace InnovEnergy.Lib.StatusApi;
+
+#pragma warning disable CS8618
+
+public record CombinedStatus
+{
+ public T Combined { get; init; }
+ public IReadOnlyList Children { get; init; }
+
+ public Boolean Available => Children.Any();
+
+}
\ No newline at end of file