Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
bb2de9d0d4
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.App.SaliMax.Ess;
|
||||||
|
|
||||||
|
public enum LedState
|
||||||
|
{
|
||||||
|
Red,
|
||||||
|
Orange,
|
||||||
|
Green
|
||||||
|
}
|
|
@ -25,7 +25,8 @@ public record StatusRecord
|
||||||
public required RelaysRecord? Relays { get; init; }
|
public required RelaysRecord? Relays { get; init; }
|
||||||
public required AmptStatus? PvOnDc { get; init; }
|
public required AmptStatus? PvOnDc { get; init; }
|
||||||
public required Config Config { 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 EssControl EssControl { get; set; } // TODO: init only
|
||||||
public required StateMachine StateMachine { get; init; }
|
public required StateMachine StateMachine { get; init; }
|
||||||
}
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace InnovEnergy.App.SaliMax.Ess;
|
||||||
|
|
||||||
|
public record SystemLog
|
||||||
|
{
|
||||||
|
public required String? Message { get; init; }
|
||||||
|
public required LedState Led { get; init; }
|
||||||
|
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
||||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Control;
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Control;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
||||||
|
using InnovEnergy.Lib.Time.Unix;
|
||||||
using InnovEnergy.Lib.Units;
|
using InnovEnergy.Lib.Units;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
|
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
|
||||||
|
@ -113,24 +114,25 @@ internal static class Program
|
||||||
|
|
||||||
return new StatusRecord
|
return new StatusRecord
|
||||||
{
|
{
|
||||||
AcDc = acDc,
|
AcDc = acDc,
|
||||||
DcDc = dcDc,
|
DcDc = dcDc,
|
||||||
Battery = battery,
|
Battery = battery,
|
||||||
Relays = relays,
|
Relays = relays,
|
||||||
GridMeter = gridMeter,
|
GridMeter = gridMeter,
|
||||||
|
|
||||||
PvOnAcGrid = pvOnAcGrid,
|
PvOnAcGrid = pvOnAcGrid,
|
||||||
PvOnAcIsland = pvOnAcIsland,
|
PvOnAcIsland = pvOnAcIsland,
|
||||||
PvOnDc = pvOnDc,
|
PvOnDc = pvOnDc,
|
||||||
|
|
||||||
AcGridToAcIsland = gridBusToIslandBus,
|
AcGridToAcIsland = gridBusToIslandBus,
|
||||||
LoadOnAcGrid = gridBusLoad,
|
LoadOnAcGrid = gridBusLoad,
|
||||||
LoadOnAcIsland = loadOnAcIsland,
|
LoadOnAcIsland = loadOnAcIsland,
|
||||||
LoadOnDc = dcLoad,
|
LoadOnDc = dcLoad,
|
||||||
|
|
||||||
StateMachine = StateMachine.Default,
|
StateMachine = StateMachine.Default,
|
||||||
EssControl = EssControl.Default,
|
EssControl = EssControl.Default,
|
||||||
Config = Config.Load() // load from disk every iteration, so config can be changed while running
|
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;)
|
// If control Special Error return true, we must stop the system.(break;)
|
||||||
var alarmCondition = record.DetectAlarmStates();
|
var alarmCondition = record.DetectAlarmStates();
|
||||||
|
|
||||||
|
|
||||||
if (alarmCondition is not null)
|
if (alarmCondition is not null)
|
||||||
{
|
{
|
||||||
//stop the system
|
|
||||||
//return
|
|
||||||
alarmCondition.LogInfo();
|
alarmCondition.LogInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
record.ControlConstants();
|
record.ControlConstants();
|
||||||
record.ControlSystemState();
|
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();
|
var essControl = record.ControlEss().WriteLine().LogInfo();
|
||||||
|
|
||||||
|
@ -313,17 +312,20 @@ internal static class Program
|
||||||
sc.ResetAlarmsAndWarnings = true;
|
sc.ResetAlarmsAndWarnings = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<Boolean> UploadCsv(StatusRecord status, DateTime timeStamp)
|
private static async Task<Boolean> UploadCsv(StatusRecord status, UnixTime timeStamp)
|
||||||
{
|
{
|
||||||
var s3Config = status.Config.S3;
|
var s3Config = status.Config.S3;
|
||||||
|
var csv = status.ToCsv().LogInfo();
|
||||||
if (s3Config is null)
|
if (s3Config is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var csv = status.ToCsv();
|
|
||||||
var s3Path = timeStamp + ".csv";
|
var s3Path = timeStamp + ".csv";
|
||||||
var request = s3Config.CreatePutRequest(s3Path);
|
var request = s3Config.CreatePutRequest(s3Path);
|
||||||
var response = await request.PutAsync(new StringContent(csv));
|
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)
|
if (response.StatusCode != 200)
|
||||||
{
|
{
|
||||||
Console.WriteLine("ERROR: PUT");
|
Console.WriteLine("ERROR: PUT");
|
||||||
|
|
|
@ -95,7 +95,15 @@ public class Config //TODO: let IE choose from config files (Json) and connect t
|
||||||
BatteryIp = new() { Host = "localhost", Port = 5007},
|
BatteryIp = new() { Host = "localhost", Port = 5007},
|
||||||
BatteryNodes = new []{ 2, 3, 4, 5, 6 }
|
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
|
#else
|
||||||
public static Config Default => new()
|
public static Config Default => new()
|
||||||
|
|
|
@ -20,7 +20,7 @@ public partial class Battery48TlRecord
|
||||||
public Boolean Eoc => Leds is { Green: On, Amber: Off, Blue : Off };
|
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 String FwVersion => _FwVersion.ToString("X4");
|
||||||
public Strings Warnings => ParseWarnings().OrderBy(w => w).ToList();
|
public Strings Warnings => ParseWarnings().OrderBy(w => w).ToList();
|
||||||
|
@ -28,12 +28,17 @@ public partial class Battery48TlRecord
|
||||||
|
|
||||||
public Percent Soc => _Soc;
|
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
|
// 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
|
// When The battery is full charged (reached EOC) the Time Since TOC is set to 0
|
||||||
public TimeSpan TimeSinceTOC => TimeSpan.FromMinutes(_TimeSinceToc);
|
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);
|
public Boolean CalibrationChargeRequested => TimeSinceTOC > TimeSpan.FromDays(7);
|
||||||
|
|
||||||
|
@ -214,5 +219,4 @@ public partial class Battery48TlRecord
|
||||||
return Math.Min(pLimit, 0);
|
return Math.Min(pLimit, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,11 @@ public partial class Battery48TlRecord
|
||||||
[InputRegister(999, Scale = 0.01)] private Double _CellsVoltage;
|
[InputRegister(999, Scale = 0.01)] private Double _CellsVoltage;
|
||||||
[InputRegister(1001, Scale = 0.01)] private Double _BusVoltage;
|
[InputRegister(1001, Scale = 0.01)] private Double _BusVoltage;
|
||||||
[InputRegister(1000, Scale = 0.01, Offset = -10000)] private Double _CellsCurrent;
|
[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, Scale = 0.01, Offset = -10000)] private Double _BusCurrent;
|
||||||
|
[InputRegister(1062)] private UInt16 _BusCurrentHex;
|
||||||
|
|
||||||
[InputRegister(1053, Scale = 0.1)] private Double _Soc;
|
[InputRegister(1053, Scale = 0.1)] private Double _Soc;
|
||||||
[InputRegister(1052)] private UInt16 _TimeSinceToc;
|
[InputRegister(1052)] private UInt16 _TimeSinceToc;
|
||||||
|
|
|
@ -3,7 +3,8 @@ using System.Collections;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.Units.Composite;
|
namespace InnovEnergy.Lib.Units.Composite;
|
||||||
|
|
||||||
public record Ac3Bus : IReadOnlyList<AcPhase>
|
// removed to have it on S3. Find a better solution
|
||||||
|
public record Ac3Bus // : IReadOnlyList<AcPhase>
|
||||||
{
|
{
|
||||||
public required AcPhase L1 { get; init; }
|
public required AcPhase L1 { get; init; }
|
||||||
public required AcPhase L2 { get; init; }
|
public required AcPhase L2 { get; init; }
|
||||||
|
@ -20,22 +21,22 @@ public record Ac3Bus : IReadOnlyList<AcPhase>
|
||||||
L3 = AcPhase.Zero,
|
L3 = AcPhase.Zero,
|
||||||
};
|
};
|
||||||
|
|
||||||
public IEnumerator<AcPhase> GetEnumerator()
|
// public IEnumerator<AcPhase> GetEnumerator()
|
||||||
{
|
// {
|
||||||
yield return L1;
|
// yield return L1;
|
||||||
yield return L2;
|
// yield return L2;
|
||||||
yield return L3;
|
// yield return L3;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
//
|
||||||
public Int32 Count => 3;
|
// public Int32 Count => 3;
|
||||||
|
//
|
||||||
public AcPhase this[Int32 index] => index switch
|
// public AcPhase this[Int32 index] => index switch
|
||||||
{
|
// {
|
||||||
0 => L1, // it's retarded
|
// 0 => L1, // it's retarded
|
||||||
1 => L2,
|
// 1 => L2,
|
||||||
2 => L3,
|
// 2 => L3,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(index))
|
// _ => throw new ArgumentOutOfRangeException(nameof(index))
|
||||||
};
|
// };
|
||||||
}
|
}
|
Loading…
Reference in New Issue