diff --git a/csharp/App/SaliMax/HostList.sh b/csharp/App/SaliMax/HostList.txt similarity index 100% rename from csharp/App/SaliMax/HostList.sh rename to csharp/App/SaliMax/HostList.txt diff --git a/csharp/App/SaliMax/src/Ess/LedState.cs b/csharp/App/SaliMax/src/Ess/LedState.cs new file mode 100644 index 000000000..4de421c37 --- /dev/null +++ b/csharp/App/SaliMax/src/Ess/LedState.cs @@ -0,0 +1,8 @@ +namespace InnovEnergy.App.SaliMax.Ess; + +public enum LedState +{ + Red, + Orange, + Green +} \ No newline at end of file diff --git a/csharp/App/SaliMax/src/Ess/StatusRecord.cs b/csharp/App/SaliMax/src/Ess/StatusRecord.cs index fde5998e1..0d0a1da63 100644 --- a/csharp/App/SaliMax/src/Ess/StatusRecord.cs +++ b/csharp/App/SaliMax/src/Ess/StatusRecord.cs @@ -25,7 +25,8 @@ public record StatusRecord public required RelaysRecord? Relays { get; init; } public required AmptStatus? PvOnDc { get; init; } public required Config Config { get; init; } + public required SystemLog Log { get; set; } // TODO: init only public required EssControl EssControl { get; set; } // TODO: init only public required StateMachine StateMachine { get; init; } -} +} \ No newline at end of file diff --git a/csharp/App/SaliMax/src/Ess/SystemLog.cs b/csharp/App/SaliMax/src/Ess/SystemLog.cs new file mode 100644 index 000000000..ea4ca0763 --- /dev/null +++ b/csharp/App/SaliMax/src/Ess/SystemLog.cs @@ -0,0 +1,8 @@ +namespace InnovEnergy.App.SaliMax.Ess; + +public record SystemLog +{ + public required String? Message { get; init; } + public required LedState Led { get; init; } + +} \ No newline at end of file diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index 78c2eeb6d..e768cb80c 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -16,6 +16,7 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Control; using InnovEnergy.Lib.Protocols.Modbus.Channels; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Utils; using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig; @@ -113,24 +114,25 @@ internal static class Program return new StatusRecord { - AcDc = acDc, - DcDc = dcDc, - Battery = battery, - Relays = relays, - GridMeter = gridMeter, + AcDc = acDc, + DcDc = dcDc, + Battery = battery, + Relays = relays, + GridMeter = gridMeter, - PvOnAcGrid = pvOnAcGrid, - PvOnAcIsland = pvOnAcIsland, - PvOnDc = pvOnDc, + PvOnAcGrid = pvOnAcGrid, + PvOnAcIsland = pvOnAcIsland, + PvOnDc = pvOnDc, AcGridToAcIsland = gridBusToIslandBus, LoadOnAcGrid = gridBusLoad, LoadOnAcIsland = loadOnAcIsland, LoadOnDc = dcLoad, - StateMachine = StateMachine.Default, - EssControl = EssControl.Default, - Config = Config.Load() // load from disk every iteration, so config can be changed while running + StateMachine = StateMachine.Default, + EssControl = EssControl.Default, + Log = new SystemLog{Led = LedState.Green, Message = null}, //TODO: Put real stuff + Config = Config.Load() // load from disk every iteration, so config can be changed while running }; } @@ -174,18 +176,15 @@ internal static class Program // If control Special Error return true, we must stop the system.(break;) var alarmCondition = record.DetectAlarmStates(); - if (alarmCondition is not null) { - //stop the system - //return alarmCondition.LogInfo(); } record.ControlConstants(); record.ControlSystemState(); - $"{record.StateMachine.State}: {record.StateMachine.Message}".LogInfo(); + $"{UnixTime.Now} : {record.StateMachine.State}: {record.StateMachine.Message}".WriteLine().LogInfo(); var essControl = record.ControlEss().WriteLine().LogInfo(); @@ -313,17 +312,20 @@ internal static class Program sc.ResetAlarmsAndWarnings = true; } - private static async Task UploadCsv(StatusRecord status, DateTime timeStamp) + private static async Task UploadCsv(StatusRecord status, UnixTime timeStamp) { var s3Config = status.Config.S3; + var csv = status.ToCsv().LogInfo(); if (s3Config is null) return false; - var csv = status.ToCsv(); var s3Path = timeStamp + ".csv"; var request = s3Config.CreatePutRequest(s3Path); var response = await request.PutAsync(new StringContent(csv)); + // This is temporary for Wittman + //await File.WriteAllTextAsync("/var/www/html/status.csv", csv.SplitLines().Where(l => !l.Contains("Secret")).JoinLines()); + if (response.StatusCode != 200) { Console.WriteLine("ERROR: PUT"); diff --git a/csharp/App/SaliMax/src/SystemConfig/Config.cs b/csharp/App/SaliMax/src/SystemConfig/Config.cs index fcbd5f869..32468ee0d 100644 --- a/csharp/App/SaliMax/src/SystemConfig/Config.cs +++ b/csharp/App/SaliMax/src/SystemConfig/Config.cs @@ -95,7 +95,15 @@ public class Config //TODO: let IE choose from config files (Json) and connect t BatteryIp = new() { Host = "localhost", Port = 5007}, BatteryNodes = new []{ 2, 3, 4, 5, 6 } }, - S3 = null + S3 = new() + { + Bucket = "1-3e5b3069-214a-43ee-8d85-57d72000c19d", + Region = "sos-ch-dk-2", + Provider = "exo.io", + ContentType = "text/plain; charset=utf-8", + Key = "EXO4ec5faf1a7650b79b5722fb5", + Secret = "LUxu1PGEA-POEIckoEyq6bYyz0RnenW6tmqccMKgkHQ" + }, }; #else public static Config Default => new() diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Api.cs b/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Api.cs index c5908b95d..29a35e283 100644 --- a/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Api.cs +++ b/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Api.cs @@ -20,7 +20,7 @@ public partial class Battery48TlRecord public Boolean Eoc => Leds is { Green: On, Amber: Off, Blue : Off }; - public String SerialNumber => $"{_SerialNum1:X4} {_SerialNum2:X4} {_SerialNum3:X4} {_SerialNum4:X4}".TrimStart('0'); + public String SerialNumber => $"{_SerialNum1:X4}{_SerialNum2:X4}{_SerialNum3:X4}{_SerialNum4:X4}".TrimEnd('0'); public String FwVersion => _FwVersion.ToString("X4"); public Strings Warnings => ParseWarnings().OrderBy(w => w).ToList(); @@ -28,12 +28,17 @@ public partial class Battery48TlRecord public Percent Soc => _Soc; + public Current BusCurrent => _BusCurrent; + public UInt16 BusCurrentHex => _BusCurrentHex; + + public UInt16 CellsCurrentHex => _CellsCurrentHex; + + public Current HeatingCurrent => _BusCurrent - _CellsCurrent; + public DcPower HeatingPower => HeatingCurrent * Dc.Voltage; + // Time since TOC is a counter from the last moment when the battery reached EOC // When The battery is full charged (reached EOC) the Time Since TOC is set to 0 public TimeSpan TimeSinceTOC => TimeSpan.FromMinutes(_TimeSinceToc); - public Current BusCurrent => _BusCurrent; - public Current HeatingCurrent => _BusCurrent - _CellsCurrent; - public DcPower HeatingPower => HeatingCurrent * Dc.Voltage; public Boolean CalibrationChargeRequested => TimeSinceTOC > TimeSpan.FromDays(7); @@ -214,5 +219,4 @@ public partial class Battery48TlRecord return Math.Min(pLimit, 0); } } -} - +} \ No newline at end of file diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Modbus.cs b/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Modbus.cs index 312017c89..8d7882710 100644 --- a/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Modbus.cs +++ b/csharp/Lib/Devices/Battery48TL/Battery48TlRecord.Modbus.cs @@ -20,7 +20,11 @@ public partial class Battery48TlRecord [InputRegister(999, Scale = 0.01)] private Double _CellsVoltage; [InputRegister(1001, Scale = 0.01)] private Double _BusVoltage; [InputRegister(1000, Scale = 0.01, Offset = -10000)] private Double _CellsCurrent; + [InputRegister(1000)] private UInt16 _CellsCurrentHex; + + [InputRegister(1062, Scale = 0.01, Offset = -10000)] private Double _BusCurrent; + [InputRegister(1062)] private UInt16 _BusCurrentHex; [InputRegister(1053, Scale = 0.1)] private Double _Soc; [InputRegister(1052)] private UInt16 _TimeSinceToc; diff --git a/csharp/Lib/Units/Composite/Ac3Bus.cs b/csharp/Lib/Units/Composite/Ac3Bus.cs index 2301c1d97..917e98f67 100644 --- a/csharp/Lib/Units/Composite/Ac3Bus.cs +++ b/csharp/Lib/Units/Composite/Ac3Bus.cs @@ -3,7 +3,8 @@ using System.Collections; namespace InnovEnergy.Lib.Units.Composite; -public record Ac3Bus : IReadOnlyList +// removed to have it on S3. Find a better solution +public record Ac3Bus // : IReadOnlyList { public required AcPhase L1 { get; init; } public required AcPhase L2 { get; init; } @@ -20,22 +21,22 @@ public record Ac3Bus : IReadOnlyList L3 = AcPhase.Zero, }; - public IEnumerator GetEnumerator() - { - yield return L1; - yield return L2; - yield return L3; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public Int32 Count => 3; - - public AcPhase this[Int32 index] => index switch - { - 0 => L1, // it's retarded - 1 => L2, - 2 => L3, - _ => throw new ArgumentOutOfRangeException(nameof(index)) - }; + // public IEnumerator GetEnumerator() + // { + // yield return L1; + // yield return L2; + // yield return L3; + // } + // + // IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + // + // public Int32 Count => 3; + // + // public AcPhase this[Int32 index] => index switch + // { + // 0 => L1, // it's retarded + // 1 => L2, + // 2 => L3, + // _ => throw new ArgumentOutOfRangeException(nameof(index)) + // }; } \ No newline at end of file