Add Calibration charge mode and clean code

This commit is contained in:
atef 2025-05-05 11:59:20 +02:00
parent bf37840d0d
commit bbca604ce9
2 changed files with 120 additions and 169 deletions

View File

@ -11,12 +11,16 @@ public static class Controller
private static readonly Double MaxDischargePower = -8000; // By battery TODO: move to config private static readonly Double MaxDischargePower = -8000; // By battery TODO: move to config
private static readonly Double MaxChargePower = 6000; // By battery TODO: move to config private static readonly Double MaxChargePower = 6000; // By battery TODO: move to config
private static Boolean _hasRepetitiveCalibrationChargeChecked = false;
private static DateTime _nextDayAt10Am = DateTime.Now;
public static EssMode SelectControlMode(this StatusRecord s) public static EssMode SelectControlMode(this StatusRecord s)
{ {
//return EssMode.OptimizeSelfConsumption; //return EssMode.OptimizeSelfConsumption;
return s.StateMachine.State != 23 ? EssMode.Off return s.StateMachine.State != 23 ? EssMode.Off
: s.MustReachMinSoc() ? EssMode.ReachMinSoc : s.MustReachMinSoc() ? EssMode.ReachMinSoc
: s.MustDoCalibrationCharge() ? EssMode.CalibrationCharge
: s.GridMeter is null ? EssMode.NoGridMeter : s.GridMeter is null ? EssMode.NoGridMeter
: EssMode.OptimizeSelfConsumption; : EssMode.OptimizeSelfConsumption;
} }
@ -147,26 +151,15 @@ public static class Controller
EssMode.Off => 0, EssMode.Off => 0,
EssMode.OffGrid => 0, EssMode.OffGrid => 0,
EssMode.NoGridMeter => 0, EssMode.NoGridMeter => 0,
EssMode.CalibrationCharge => s.ControlInverterPower(chargePower),
_ => throw new ArgumentException(null, nameof(mode)) _ => throw new ArgumentException(null, nameof(mode))
}; };
} }
// private static Boolean MustHeatBatteries(this StatusRecord s)
// {
// var batteries = s.GetBatteries();
//
// if (batteries.Count <= 0)
// return true; // batteries might be there but BMS is without power
//
// return batteries
// .Select(b => b.Temperatures.State)
// .Contains(TemperatureState.Cold);
// }
private static Double MaxBatteryChargePower(this StatusRecord s) private static Double MaxBatteryChargePower(this StatusRecord s)
{ {
// This introduces a limit when we don't have communication with batteries // This introduces a limit when we don't have communication with batteries,
// Otherwise the limit will be 0 and the batteries will be not heated // Otherwise the limit will be 0, and the batteries will be not heated
var batteries = s.GetBatteries(); var batteries = s.GetBatteries();
@ -206,6 +199,54 @@ public static class Controller
return s.Battery?.Devices ?? Array.Empty<BatteryDeligreenRecord>(); return s.Battery?.Devices ?? Array.Empty<BatteryDeligreenRecord>();
} }
private static Boolean MustDoCalibrationCharge(this StatusRecord statusRecord)
{
var calibrationChargeForced = statusRecord.Config.ForceCalibrationChargeState;
var additionalCalibrationRequired = AdditionalCalibrationDateHasBeenPassed(statusRecord.Config.DayAndTimeForAdditionalCalibration);
var repetitiveCalibrationRequired = RepetitiveCalibrationDateHasBeenPassed(statusRecord.Config.DayAndTimeForRepetitiveCalibration);
var mustDoCalibrationCharge = calibrationChargeForced == CalibrationChargeType.ChargePermanently ||
(calibrationChargeForced == CalibrationChargeType.AdditionallyOnce && additionalCalibrationRequired) ||
(calibrationChargeForced == CalibrationChargeType.RepetitivelyEvery && repetitiveCalibrationRequired);
Console.WriteLine("Next Repetitive calibration charge date is "+ statusRecord.Config.DayAndTimeForRepetitiveCalibration);
Console.WriteLine("Next Additional calibration charge date is "+ statusRecord.Config.DayAndTimeForAdditionalCalibration);
if (statusRecord.Battery is not null)
{
if (calibrationChargeForced == CalibrationChargeType.AdditionallyOnce && statusRecord.Battery.Eoc )
{
statusRecord.Config.ForceCalibrationChargeState = CalibrationChargeType.RepetitivelyEvery;
}
else if (calibrationChargeForced == CalibrationChargeType.RepetitivelyEvery && statusRecord.Battery.Eoc && _hasRepetitiveCalibrationChargeChecked)
{
statusRecord.Config.DayAndTimeForRepetitiveCalibration = statusRecord.Config.DayAndTimeForRepetitiveCalibration.AddDays(7);
_hasRepetitiveCalibrationChargeChecked = false;
}
}
return mustDoCalibrationCharge;
}
private static Boolean RepetitiveCalibrationDateHasBeenPassed(DateTime calibrationChargeDate)
{
if (DateTime.Now >= calibrationChargeDate )
{
_hasRepetitiveCalibrationChargeChecked = true;
return true;
}
return false;
}
private static Boolean AdditionalCalibrationDateHasBeenPassed(DateTime calibrationChargeDate)
{
if (DateTime.Now >= calibrationChargeDate )
{
return true;
}
return false;
}
private static Double ControlGridPower(this StatusRecord status, Double targetPower) private static Double ControlGridPower(this StatusRecord status, Double targetPower)
{ {
return ControlPower return ControlPower

View File

@ -68,8 +68,7 @@ internal static class Program
private const UInt16 NbrOfFileToConcatenate = 30; // add this to config file private const UInt16 NbrOfFileToConcatenate = 30; // add this to config file
private static UInt16 _fileCounter = 0; private static UInt16 _fileCounter = 0;
private static SalimaxAlarmState _salimaxAlarmState = SalimaxAlarmState.Green; private static SalimaxAlarmState _salimaxAlarmState = SalimaxAlarmState.Green;
private const String Port = "/dev/ttyUSB0"; private const String Port = "/dev/ttyUSB0"; // move to a config file
private static Boolean _oneTimeFlag = false;
static Program() static Program()
{ {
@ -314,108 +313,28 @@ internal static class Program
var bAlarmList = new List<String>(); var bAlarmList = new List<String>();
var bWarningList = new List<String>(); var bWarningList = new List<String>();
if (record.Battery != null) if (record.Battery is { MonomerHighVoltageAlarm: true })
{ {
//_oneTimeFlag.WriteLine(" onetime flag"); warningList.Add(new AlarmOrWarning
if (record.Battery?.MonomerHighVoltageAlarm == true /*&& !_oneTimeFlag*/) //this should be checked: the number 0 {
{ Date = DateTime.Now.ToString("yyyy-MM-dd"),
//_oneTimeFlag = true; Time = DateTime.Now.ToString("HH:mm:ss"),
warningList.Add(new AlarmOrWarning CreatedBy = "Charging Battery System",
{ Description = "dynCCL Active: Max Battery Charging is 10 * N"
Date = DateTime.Now.ToString("yyyy-MM-dd"), });
Time = DateTime.Now.ToString("HH:mm:ss"), }
CreatedBy = "Charging Battery System", if (record.Battery is { MonomerLowVoltageAlarm: true })
Description = "dynCCL Active: Max Battery Charging is 10 * N" {
}); warningList.Add(new AlarmOrWarning
} {
Date = DateTime.Now.ToString("yyyy-MM-dd"),
/* if (record.Battery?.MonomerLowVoltageAlarm == true && !_oneTimeFlag) //this should be checked: the number 10 Time = DateTime.Now.ToString("HH:mm:ss"),
{ CreatedBy = "Battery System",
_oneTimeFlag = true; Description = "dynDCL Active: Max Battery Discharging is 10 * N"
warningList.Add(new AlarmOrWarning });
{
Date = DateTime.Now.ToString("yyyy-MM-dd"),
Time = DateTime.Now.ToString("HH:mm:ss"),
CreatedBy = "Battery System",
Description = "dynDCL Active: Max Battery Discharging is 10 * N"
});
}
else
{
_oneTimeFlag = false;
}*/
} }
/*
if (record.Battery != null)
{
var i = 0;
foreach (var battery in record.Battery.Devices)
{
var devicesBatteryNode = record.Config.Devices.BatteryNodes[i];
if (battery.LimpBitMap == 0)
{
// "All String are Active".WriteLine();
}
else if (IsPowerOfTwo(battery.LimpBitMap))
{
"1 String is disabled".WriteLine();
Console.WriteLine(" ****************** ");
warningList.Add(new AlarmOrWarning if (alarmCondition is not null)
{
Date = DateTime.Now.ToString("yyyy-MM-dd"),
Time = DateTime.Now.ToString("HH:mm:ss"),
CreatedBy = "Battery node" + devicesBatteryNode,
Description = "1 String is disabled"
});
bWarningList.Add("/"+i+1 + "/1 String is disabled"); // battery id instead ( i +1 ) of node id: requested from the frontend
}
else
{
"2 or more string are disabled".WriteLine();
Console.WriteLine(" ****************** ");
alarmList.Add(new AlarmOrWarning
{
Date = DateTime.Now.ToString("yyyy-MM-dd"),
Time = DateTime.Now.ToString("HH:mm:ss"),
CreatedBy = "Battery node" + devicesBatteryNode,
Description = "2 or more string are disabled"
});
bAlarmList.Add(i +";2 or more string are disabled");
}
foreach (var warning in record.Battery.Warnings)
{
warningList.Add(new AlarmOrWarning
{
Date = DateTime.Now.ToString("yyyy-MM-dd"),
Time = DateTime.Now.ToString("HH:mm:ss"),
CreatedBy = "Battery node" + devicesBatteryNode,
Description = warning
});
bWarningList.Add(i +";" + warning);
}
foreach (var alarm in battery.Alarms)
{
alarmList.Add(new AlarmOrWarning
{
Date = DateTime.Now.ToString("yyyy-MM-dd"),
Time = DateTime.Now.ToString("HH:mm:ss"),
CreatedBy = "Battery node" + devicesBatteryNode,
Description = alarm
});
bWarningList.Add(i +";" + alarm);
}
i++;
}
}*/
if (alarmCondition is not null)
{ {
alarmCondition.WriteLine(); alarmCondition.WriteLine();
@ -428,49 +347,33 @@ internal static class Program
}); });
} }
foreach (var alarm in record.AcDc.Alarms) alarmList.AddRange(record.AcDc.Alarms
{ .Select(alarm => new AlarmOrWarning
alarmList.Add(new AlarmOrWarning { Date = DateTime.Now.ToString("yyyy-MM-dd"),
{ Time = DateTime.Now.ToString("HH:mm:ss"),
Date = DateTime.Now.ToString("yyyy-MM-dd"), CreatedBy = "AcDc",
Time = DateTime.Now.ToString("HH:mm:ss"), Description = alarm.ToString() }));
CreatedBy = "AcDc",
Description = alarm.ToString()
});
}
foreach (var alarm in record.DcDc.Alarms) alarmList.AddRange(record.DcDc.Alarms
{ .Select(alarm => new AlarmOrWarning
alarmList.Add(new AlarmOrWarning { Date = DateTime.Now.ToString("yyyy-MM-dd"),
{ Time = DateTime.Now.ToString("HH:mm:ss"),
Date = DateTime.Now.ToString("yyyy-MM-dd"), CreatedBy = "DcDc",
Time = DateTime.Now.ToString("HH:mm:ss"), Description = alarm.ToString() }));
CreatedBy = "DcDc",
Description = alarm.ToString()
});
}
foreach (var warning in record.AcDc.Warnings) warningList.AddRange(record.AcDc.Warnings
{ .Select(warning => new AlarmOrWarning
warningList.Add(new AlarmOrWarning { Date = DateTime.Now.ToString("yyyy-MM-dd"),
{ Time = DateTime.Now.ToString("HH:mm:ss"),
Date = DateTime.Now.ToString("yyyy-MM-dd"), CreatedBy = "AcDc",
Time = DateTime.Now.ToString("HH:mm:ss"), Description = warning.ToString() }));
CreatedBy = "AcDc",
Description = warning.ToString()
});
}
foreach (var warning in record.DcDc.Warnings) warningList.AddRange(record.DcDc.Warnings
{ .Select(warning => new AlarmOrWarning
warningList.Add(new AlarmOrWarning { Date = DateTime.Now.ToString("yyyy-MM-dd"),
{ Time = DateTime.Now.ToString("HH:mm:ss"),
Date = DateTime.Now.ToString("yyyy-MM-dd"), CreatedBy = "DcDc",
Time = DateTime.Now.ToString("HH:mm:ss"), Description = warning.ToString() }));
CreatedBy = "DcDc",
Description = warning.ToString()
});
}
_salimaxAlarmState = warningList.Any() _salimaxAlarmState = warningList.Any()
? SalimaxAlarmState.Orange ? SalimaxAlarmState.Orange
@ -480,7 +383,7 @@ internal static class Program
? SalimaxAlarmState.Red ? SalimaxAlarmState.Red
: _salimaxAlarmState; // this will be replaced by LedState : _salimaxAlarmState; // this will be replaced by LedState
TryParse(s3Bucket?.Split("-")[0], out var installationId); var installationId = GetInstallationId(s3Bucket ?? string.Empty);
var returnedStatus = new StatusMessage var returnedStatus = new StatusMessage
{ {
@ -494,7 +397,13 @@ internal static class Program
return returnedStatus; return returnedStatus;
} }
private static Int32 GetInstallationId(String s3Bucket)
{
var part = s3Bucket.Split('-').FirstOrDefault();
return TryParse(part, out var id) ? id : 0; // is 0 a default safe value? check with Marios
}
private static String? DetectAlarmStates(this StatusRecord r) => r.Relays switch private static String? DetectAlarmStates(this StatusRecord r) => r.Relays switch
{ {
{ K2ConnectIslandBusToGridBus: false, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: R0 is opening the K2 but the K2 is still close ", { K2ConnectIslandBusToGridBus: false, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: R0 is opening the K2 but the K2 is still close ",
@ -553,7 +462,7 @@ internal static class Program
} }
else else
{ {
maxBatteryChargingCurrentLiveByDcDc = 0; maxBatteryChargingCurrentLiveByDcDc = 0;
maxBatteryDischargingCurrentLivebyDcDc = 0; maxBatteryDischargingCurrentLivebyDcDc = 0;
} }
inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage); inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage);
@ -1001,15 +910,16 @@ internal static class Program
status.Config.MinSoc = config.MinimumSoC; status.Config.MinSoc = config.MinimumSoC;
status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W
// status.Config.ForceCalibrationChargeState = config.CalibrationChargeState;
// status.Config.ForceCalibrationChargeState = config.CalibrationChargeState;
// if (config.CalibrationChargeState == CalibrationChargeType.RepetitivelyEvery)
// { if (config.CalibrationChargeState == CalibrationChargeType.RepetitivelyEvery)
// status.Config.DayAndTimeForRepetitiveCalibration = config.CalibrationChargeDate; {
// } status.Config.DayAndTimeForRepetitiveCalibration = config.CalibrationChargeDate;
// else if (config.CalibrationChargeState == CalibrationChargeType.AdditionallyOnce) }
// { else if (config.CalibrationChargeState == CalibrationChargeType.AdditionallyOnce)
// status.Config.DayAndTimeForAdditionalCalibration = config.CalibrationChargeDate; {
// } status.Config.DayAndTimeForAdditionalCalibration = config.CalibrationChargeDate;
}
} }
} }