From 4bf9deffac921dac6a8dab9c357869379aa4c1d1 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 10:41:13 +0100 Subject: [PATCH] lift Battery48TL to new StatusApi --- .../Devices/Battery48TL/Battery48TLDevice.cs | 103 +------ .../Battery48TL/Battery48TLStatusRecord.cs | 71 +++-- .../Devices/Battery48TL/BatteryDataParser.cs | 167 ----------- .../Lib/Devices/Battery48TL/ModbusParser.cs | 272 ++++++++++++++++++ 4 files changed, 316 insertions(+), 297 deletions(-) delete mode 100644 csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs create mode 100644 csharp/Lib/Devices/Battery48TL/ModbusParser.cs diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs index 979eafaf7..6507ac32d 100644 --- a/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs +++ b/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs @@ -1,7 +1,5 @@ using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; -using InnovEnergy.Lib.Protocols.Modbus.Conversions; -using InnovEnergy.Lib.StatusApi.Connections; namespace InnovEnergy.Lib.Devices.Battery48TL; @@ -33,18 +31,11 @@ public class Battery48TlDevice public Battery48TLStatus? ReadStatus() //Already try catch is implemented { - if (Modbus is null) // TODO : remove fake - { - Console.WriteLine("Battery is null"); - return null; - } - - // Console.WriteLine("Reading Battery Data"); - try { - var registers = Modbus.ReadInputRegisters(Constants.BaseAddress, Constants.NoOfRegisters); - return TryReadStatus(registers); + return Modbus + .ReadInputRegisters(Constants.BaseAddress, Constants.NoOfRegisters) + .ParseBatteryStatus(); } catch (Exception e) { @@ -53,92 +44,4 @@ public class Battery48TlDevice return null; } } - - private Battery48TLStatus? TryReadStatus(ModbusRegisters data) - { - var soc = data.ParseDecimal(register: 1054, scaleFactor: 0.1m); - var eocReached = data.ParseEocReached(); - - var warnings = new List(); - - if (data.ParseBool(1006, 1)) warnings.Add("TaM1: BMS temperature high"); - if (data.ParseBool(1006, 4)) warnings.Add("TbM1: Battery temperature high"); - if (data.ParseBool(1006, 6)) warnings.Add("VBm1: Bus voltage low"); - if (data.ParseBool(1006, 8)) warnings.Add("VBM1: Bus voltage high"); - if (data.ParseBool(1006, 10)) warnings.Add("IDM1: Discharge current high"); - if (data.ParseBool(1006, 24)) warnings.Add("vsM1: String voltage high"); - if (data.ParseBool(1006, 26)) warnings.Add("iCM1: Charge current high"); - if (data.ParseBool(1006, 28)) warnings.Add("iDM1: Discharge current high"); - if (data.ParseBool(1006, 30)) warnings.Add("MID1: String voltages unbalanced"); - if (data.ParseBool(1006, 32)) warnings.Add("BLPW: Not enough charging power on bus"); - if (data.ParseBool(1006, 35)) warnings.Add("Ah_W: String SOC low"); - if (data.ParseBool(1006, 38)) warnings.Add("MPMM: Midpoint wiring problem"); - if (data.ParseBool(1006, 39)) warnings.Add("TCMM:"); - if (data.ParseBool(1006, 40)) warnings.Add("TCdi: Temperature difference between strings high"); - if (data.ParseBool(1006, 41)) warnings.Add("WMTO:"); - if (data.ParseBool(1006, 44)) warnings.Add("bit44:"); - if (data.ParseBool(1006, 46)) warnings.Add("CELL1:"); - - var alarms = new List(); - - if (data.ParseBool(1010, 0)) alarms.Add("Tam : BMS temperature too low"); - if (data.ParseBool(1010, 2)) alarms.Add("TaM2 : BMS temperature too high"); - if (data.ParseBool(1010, 3)) alarms.Add("Tbm : Battery temperature too low"); - if (data.ParseBool(1010, 5)) alarms.Add("TbM2 : Battery temperature too high"); - if (data.ParseBool(1010, 7)) alarms.Add("VBm2 : Bus voltage too low"); - if (data.ParseBool(1010, 9)) alarms.Add("VBM2 : Bus voltage too high"); - if (data.ParseBool(1010, 11)) alarms.Add("IDM2 : Discharge current too high"); - if (data.ParseBool(1010, 12)) alarms.Add("ISOB : Electrical insulation failure"); - if (data.ParseBool(1010, 13)) alarms.Add("MSWE : Main switch failure"); - if (data.ParseBool(1010, 14)) alarms.Add("FUSE : Main fuse blown"); - if (data.ParseBool(1010, 15)) alarms.Add("HTRE : Battery failed to warm up"); - if (data.ParseBool(1010, 16)) alarms.Add("TCPE : Temperature sensor failure"); - if (data.ParseBool(1010, 17)) alarms.Add("STRE :"); - if (data.ParseBool(1010, 18)) alarms.Add("CME : Current sensor failure"); - if (data.ParseBool(1010, 19)) alarms.Add("HWFL : BMS hardware failure"); - if (data.ParseBool(1010, 20)) alarms.Add("HWEM : Hardware protection tripped"); - if (data.ParseBool(1010, 21)) alarms.Add("ThM : Heatsink temperature too high"); - if (data.ParseBool(1010, 22)) alarms.Add("vsm1 : String voltage too low"); - if (data.ParseBool(1010, 23)) alarms.Add("vsm2 : Low string voltage failure"); - if (data.ParseBool(1010, 25)) alarms.Add("vsM2 : String voltage too high"); - if (data.ParseBool(1010, 27)) alarms.Add("iCM2 : Charge current too high"); - if (data.ParseBool(1010, 29)) alarms.Add("iDM2 : Discharge current too high"); - if (data.ParseBool(1010, 31)) alarms.Add("MID2 : String voltage unbalance too high"); - if (data.ParseBool(1010, 33)) alarms.Add("CCBF : Internal charger hardware failure"); - if (data.ParseBool(1010, 34)) alarms.Add("AhFL :"); - if (data.ParseBool(1010, 36)) alarms.Add("TbCM :"); - if (data.ParseBool(1010, 37)) alarms.Add("BRNF :"); - if (data.ParseBool(1010, 42)) alarms.Add("HTFS : If Heaters Fuse Blown"); - if (data.ParseBool(1010, 43)) alarms.Add("DATA : Parameters out of range"); - if (data.ParseBool(1010, 45)) alarms.Add("CELL2:"); - - -return new Battery48TLStatus( - Dc: new DcConnection - ( - Voltage : data.ReadVoltage(), - Current : data.ReadCurrent()), - - Soc : !eocReached && soc >= 100m ? 99.9m : soc, - Temperature : data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400), - BusVoltage : data.ParseDecimal(register: 1002, scaleFactor: 0.01m), - GreenLed : data.ParseLedState(register: 1005, led: LedColor.Green), - AmberLed : data.ParseLedState(register: 1006, led: LedColor.Amber), - BlueLed : data.ParseLedState(register: 1005, led: LedColor.Blue), - RedLed : data.ParseLedState(register: 1005, led: LedColor.Red), - Warnings : warnings, - Alarms : alarms, - MainSwitchClosed : data.ParseBool(baseRegister: 1014, bit: 0), - AlarmOutActive : data.ParseBool(baseRegister: 1014, bit: 1), - InternalFanActive : data.ParseBool(baseRegister: 1014, bit: 2), - VoltMeasurementAllowed: data.ParseBool(baseRegister: 1014, bit: 3), - AuxRelay : data.ParseBool(baseRegister: 1014, bit: 4), - RemoteState : data.ParseBool(baseRegister: 1014, bit: 5), - HeaterOn : data.ParseBool(baseRegister: 1014, bit: 6), - EocReached : eocReached, - BatteryCold : data.ParseBatteryCold(), - MaxChargingPower : data.CalcMaxChargePower(), - MaxDischargingPower : data.CalcMaxDischargePower() - ); - } } \ No newline at end of file diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs index 0871f0645..79bc1c7df 100644 --- a/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs +++ b/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs @@ -1,39 +1,50 @@ using System.Diagnostics.CodeAnalysis; -using InnovEnergy.Lib.Protocols.Modbus.Conversions; -using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Devices; +using InnovEnergy.Lib.StatusApi; +using InnovEnergy.Lib.Units; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Devices.Battery48TL; +using T = Battery48TLStatus; + [SuppressMessage("ReSharper", "InconsistentNaming")] -public record Battery48TLStatus -( - DcConnection Dc, - Decimal Soc, - Decimal Temperature, - //Decimal Current, - //Decimal Voltage, - Decimal BusVoltage, - LedState GreenLed, - LedState AmberLed, - LedState BlueLed, - LedState RedLed, - IReadOnlyList Warnings, - IReadOnlyList Alarms, - Boolean MainSwitchClosed, - Boolean AlarmOutActive, - Boolean InternalFanActive, - Boolean VoltMeasurementAllowed, - Boolean AuxRelay, - Boolean RemoteState, - Boolean HeaterOn, - Boolean EocReached, - Boolean BatteryCold, - Decimal MaxChargingPower, - Decimal MaxDischargingPower -) -: Battery(Dc, Soc, Temperature) +public record Battery48TLStatus : BatteryStatus { + public required Voltage CellsVoltage { get; init; } + + public required Power MaxChargingPower { get; init; } + public required Power MaxDischargingPower { get; init; } + + public required State GreenLed { get; init; } + public required State AmberLed { get; init; } + public required State BlueLed { get; init; } + public required State RedLed { get; init; } + + public required State Warnings { get; init; } + public required State Alarms { get; init; } + + public required State MainSwitchState { get; init; } // connected to bus | disconnected from bus + public required State HeaterState { get; init; } // heating | not heating + public required State EocState { get; init; } // EOC reached | EOC not reached + public required State TemperatureState { get; init; } // cold | operating temperature | overheated + + + public static T operator |(T left, T right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + + + + // TODO: strings + // TODO + // public State LimitedBy { get; init; } + + // TODO + // public Boolean AlarmOutActive { get; init; } + // public Boolean InternalFanActive { get; init; } + // public Boolean VoltMeasurementAllowed { get; init; } + // public Boolean AuxRelay { get; init; } + // public Boolean RemoteState { get; init; } + } diff --git a/csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs b/csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs deleted file mode 100644 index 916c8989c..000000000 --- a/csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs +++ /dev/null @@ -1,167 +0,0 @@ -using InnovEnergy.Lib.Protocols.Modbus.Conversions; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.Devices.Battery48TL; - -public static class BatteryDataParser -{ - public static Decimal ParseDecimal(this ModbusRegisters data, Int32 register, Decimal scaleFactor = 1.0m, Double offset = 0.0) - { - var value = data[register].ConvertTo(); // widen to 32bit signed - - if (value >= 0x8000) - value -= 0x10000; // Fiamm stores their integers signed AND with sign-offset @#%^&! - - return (Decimal)(value + offset) * scaleFactor; - } - - internal static Decimal ReadCurrent(this ModbusRegisters data) - { - return ParseDecimal(data, register: 1001, scaleFactor: 0.01m, offset: -10000); - } - - internal static Decimal ReadVoltage(this ModbusRegisters data) - { - return ParseDecimal(data, register: 1000, scaleFactor: 0.01m); - } - - internal static Boolean ParseBool(this ModbusRegisters data, Int32 baseRegister, Int16 bit) - { - var x = bit / 16; - var y = bit % 16; - - var value = (UInt32)data[baseRegister + x]; - - return (value & (1 << y)) > 0; - } - - internal static LedState ParseLedState(this ModbusRegisters data, Int32 register, LedColor led) - { - var lo = ParseBool(data, register, (led.ConvertTo() * 2).ConvertTo()); - var hi = ParseBool(data, register, (led.ConvertTo() * 2 + 1).ConvertTo()); - - if (hi) - { - if (lo) - { - return LedState.BlinkingFast; - } - else - { - return LedState.BlinkingSlow; - } - } - else - { - if (lo) - { - return LedState.On; - } - else - { - return LedState.Off; - } - } - - } - - internal static String ParseRegisters(this ModbusRegisters data, Int32 register, Int16 count) - { - var container = ""; - - var start = register; - var end = register + count; - - for (var i = start; i < end; i++) - { - var binary = Convert.ToString(data[register], 2); - container += binary.PadLeft(16, '0'); - } - return container; - } - - internal static Boolean ParseEocReached(this ModbusRegisters data) - { - return ParseLedState(data, 1005, LedColor.Green) == LedState.On && - ParseLedState(data, 1005, LedColor.Amber) == LedState.Off && - ParseLedState(data, 1005, LedColor.Blue) == LedState.Off; - } - - internal static Boolean ParseBatteryCold(this ModbusRegisters data) - { - return ParseLedState(data, 1005, LedColor.Green) >= LedState.BlinkingSlow && - ParseLedState(data, 1005, LedColor.Blue) >= LedState.BlinkingSlow; - } - - private static Decimal CalcPowerLimitImposedByVoltageLimit(Decimal v,Decimal i,Decimal vLimit,Decimal rInt) - { - var dv = vLimit - v; - var di = dv / rInt; - var pLimit = vLimit * (i + di); - - return pLimit; - } - - private static Decimal CalcPowerLimitImposedByCurrentLimit(Decimal v, Decimal i, Decimal iLimit, Decimal rInt) - { - var di = iLimit - i; - var dv = di * rInt; - var pLimit = iLimit * (v + dv); - - return pLimit; - } - - - private static Decimal CalcPowerLimitImposedByTempLimit(Decimal t, Decimal maxAllowedTemp, Decimal power , Decimal setpoint) - { - // const Int32 holdZone = 300; - // const Int32 maxAllowedTemp = 315; - - var kp = 0.05m; - var error = setpoint - power; - var controlOutput = (kp * error) *(1 - Math.Abs((t-307.5m)/7.5m)); - - return controlOutput; - - // var a = holdZone - maxAllowedTemp; - // var b = -a * maxAllowedTemp; - } - - internal static Decimal CalcMaxChargePower(this ModbusRegisters data) - { - var v = ReadVoltage(data); - var i = ReadCurrent(data); - - var pLimits = new[] - { - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMin), - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMax), - CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMin), - CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMax) - }; - - var pLimit = pLimits.Min(); - - return Math.Max(pLimit, 0); - } - - internal static Decimal CalcMaxDischargePower(this ModbusRegisters data) - { - var v = ReadVoltage(data); - var i = ReadCurrent(data); - var t = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400); - - var pLimits = new[] - { - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMin), - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMax), - CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMin), - CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMax), - // CalcPowerLimitImposedByTempLimit(t,315,300) - }; - - var pLimit = pLimits.Max(); - - return Math.Min(pLimit, 0); - } -} \ No newline at end of file diff --git a/csharp/Lib/Devices/Battery48TL/ModbusParser.cs b/csharp/Lib/Devices/Battery48TL/ModbusParser.cs new file mode 100644 index 000000000..dbc15a3e4 --- /dev/null +++ b/csharp/Lib/Devices/Battery48TL/ModbusParser.cs @@ -0,0 +1,272 @@ +using System.Diagnostics.CodeAnalysis; +using InnovEnergy.Lib.Protocols.Modbus.Conversions; +using InnovEnergy.Lib.Units; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.Devices.Battery48TL; + +public static class ModbusParser +{ + internal static Battery48TLStatus ParseBatteryStatus(this ModbusRegisters data) + { + return new Battery48TLStatus + { + Dc = data.ParseDcBus(), + Alarms = data.ParseAlarms().ToList(), + Warnings = data.ParseWarnings().ToList(), + Soc = data.ParseSoc(), + Temperature = data.ParseTemperature(), + GreenLed = data.ParseGreenLed(), + AmberLed = data.ParseAmberLed(), + BlueLed = data.ParseBlueLed(), + RedLed = data.ParseRedLed(), + MainSwitchState = data.ParseMainSwitchState(), + HeaterState = data.ParseHeaterState(), + EocState = data.ParseEocState(), + TemperatureState = data.ParseTemperatureState(), + MaxChargingPower = data.CalcMaxChargePower(), + MaxDischargingPower = data.CalcMaxDischargePower(), + CellsVoltage = data.ParseCellsVoltage(), + }; + } + + + public static Decimal ParseDecimal(this ModbusRegisters data, Int32 register, Decimal scaleFactor = 1.0m, Double offset = 0.0) + { + var value = data[register].ConvertTo(); // widen to 32bit signed + + if (value >= 0x8000) + value -= 0x10000; // Fiamm stores their integers signed AND with sign-offset @#%^&! + + return (Decimal)(value + offset) * scaleFactor; + } + + internal static Decimal ParseCurrent(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1001, scaleFactor: 0.01m, offset: -10000); + } + + internal static Decimal ParseCellsVoltage(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1000, scaleFactor: 0.01m); + } + + internal static Decimal ParseBusVoltage(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1002, scaleFactor: 0.01m); + } + + internal static Boolean ParseBool(this ModbusRegisters data, Int32 baseRegister, Int16 bit) + { + var x = bit / 16; + var y = bit % 16; + + var value = (UInt32)data[baseRegister + x]; + + return (value & (1 << y)) > 0; + } + + internal static LedState ParseLedState(this ModbusRegisters data, Int32 register, LedColor led) + { + var lo = data.ParseBool(register, (led.ConvertTo() * 2 ).ConvertTo()); + var hi = data.ParseBool(register, (led.ConvertTo() * 2 + 1).ConvertTo()); + + return (hi, lo) switch + { + (false, false) => LedState.Off, + (false, true) => LedState.On, + (true, false) => LedState.BlinkingSlow, + (true, true) => LedState.BlinkingFast, + }; + } + + + private static Boolean ParseEocReached(this ModbusRegisters data) + { + return ParseLedState(data, 1005, LedColor.Green) == LedState.On && + ParseLedState(data, 1005, LedColor.Amber) == LedState.Off && + ParseLedState(data, 1005, LedColor.Blue) == LedState.Off; + } + + internal static State ParseTemperatureState(this ModbusRegisters data) + { + return data.ParseBatteryCold() ? "cold" : "operating temperature"; // TODO: overheated, + } + + internal static Decimal ParseTemperature(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400); + } + + internal static Decimal ParseSoc(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1054, scaleFactor: 0.1m); + } + + internal static State ParseEocState(this ModbusRegisters data) + { + return data.ParseEocReached() ? "EOC reached" : "EOC not reached"; + } + + internal static State ParseHeaterState(this ModbusRegisters data) + { + return data.ParseBool(baseRegister: 1014, bit: 6) ? "heating" : "not heating"; + } + + internal static State ParseMainSwitchState(this ModbusRegisters data) + { + return data.ParseBool(baseRegister: 1014, bit: 0) ? "connected to bus" : "disconnected from bus"; + } + + internal static Boolean ParseBatteryCold(this ModbusRegisters data) + { + return ParseLedState(data, 1005, LedColor.Green) >= LedState.BlinkingSlow && + ParseLedState(data, 1005, LedColor.Blue) >= LedState.BlinkingSlow; + } + + private static Decimal CalcPowerLimitImposedByVoltageLimit(Decimal v,Decimal i,Decimal vLimit,Decimal rInt) + { + var dv = vLimit - v; + var di = dv / rInt; + var pLimit = vLimit * (i + di); + + return pLimit; + } + + private static Decimal CalcPowerLimitImposedByCurrentLimit(Decimal v, Decimal i, Decimal iLimit, Decimal rInt) + { + var di = iLimit - i; + var dv = di * rInt; + var pLimit = iLimit * (v + dv); + + return pLimit; + } + + + private static Decimal CalcPowerLimitImposedByTempLimit(Decimal t, Decimal maxAllowedTemp, Decimal power , Decimal setpoint) + { + // const Int32 holdZone = 300; + // const Int32 maxAllowedTemp = 315; + + var kp = 0.05m; + var error = setpoint - power; + var controlOutput = (kp * error) *(1 - Math.Abs((t-307.5m)/7.5m)); + + return controlOutput; + + // var a = holdZone - maxAllowedTemp; + // var b = -a * maxAllowedTemp; + } + + internal static Decimal CalcMaxChargePower(this ModbusRegisters data) + { + var v = ParseCellsVoltage(data); + var i = ParseCurrent(data); + + var pLimits = new[] + { + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMin), + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMax), + CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMin), + CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMax) + }; + + var pLimit = pLimits.Min(); + + return Math.Max(pLimit, 0); + } + + internal static DcPhase ParseDcBus(this ModbusRegisters data) + { + return new() + { + Current = data.ParseCurrent(), + Voltage = data.ParseBusVoltage(), + }; + } + + internal static Decimal CalcMaxDischargePower(this ModbusRegisters data) + { + var v = ParseCellsVoltage(data); + var i = ParseCurrent(data); + var t = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400); + + var pLimits = new[] + { + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMin), + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMax), + CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMin), + CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMax), + // CalcPowerLimitImposedByTempLimit(t,315,300) + }; + + var pLimit = pLimits.Max(); + + return Math.Min(pLimit, 0); + } + + + internal static LedState ParseGreenLed(this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Green); + internal static LedState ParseAmberLed(this ModbusRegisters data) => data.ParseLedState(register: 1006, led: LedColor.Amber); + internal static LedState ParseBlueLed (this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Blue); + internal static LedState ParseRedLed (this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Red); + + + [SuppressMessage("ReSharper", "StringLiteralTypo")] + internal static IEnumerable ParseAlarms(this ModbusRegisters data) + { + if (data.ParseBool(1010, 0)) yield return "Tam : BMS temperature too low"; + if (data.ParseBool(1010, 2)) yield return "TaM2 : BMS temperature too high"; + if (data.ParseBool(1010, 3)) yield return "Tbm : Battery temperature too low"; + if (data.ParseBool(1010, 5)) yield return "TbM2 : Battery temperature too high"; + if (data.ParseBool(1010, 7)) yield return "VBm2 : Bus voltage too low"; + if (data.ParseBool(1010, 9)) yield return "VBM2 : Bus voltage too high"; + if (data.ParseBool(1010, 11)) yield return "IDM2 : Discharge current too high"; + if (data.ParseBool(1010, 12)) yield return "ISOB : Electrical insulation failure"; + if (data.ParseBool(1010, 13)) yield return "MSWE : Main switch failure"; + if (data.ParseBool(1010, 14)) yield return "FUSE : Main fuse blown"; + if (data.ParseBool(1010, 15)) yield return "HTRE : Battery failed to warm up"; + if (data.ParseBool(1010, 16)) yield return "TCPE : Temperature sensor failure"; + if (data.ParseBool(1010, 17)) yield return "STRE :"; + if (data.ParseBool(1010, 18)) yield return "CME : Current sensor failure"; + if (data.ParseBool(1010, 19)) yield return "HWFL : BMS hardware failure"; + if (data.ParseBool(1010, 20)) yield return "HWEM : Hardware protection tripped"; + if (data.ParseBool(1010, 21)) yield return "ThM : Heatsink temperature too high"; + if (data.ParseBool(1010, 22)) yield return "vsm1 : String voltage too low"; + if (data.ParseBool(1010, 23)) yield return "vsm2 : Low string voltage failure"; + if (data.ParseBool(1010, 25)) yield return "vsM2 : String voltage too high"; + if (data.ParseBool(1010, 27)) yield return "iCM2 : Charge current too high"; + if (data.ParseBool(1010, 29)) yield return "iDM2 : Discharge current too high"; + if (data.ParseBool(1010, 31)) yield return "MID2 : String voltage unbalance too high"; + if (data.ParseBool(1010, 33)) yield return "CCBF : Internal charger hardware failure"; + if (data.ParseBool(1010, 34)) yield return "AhFL :"; + if (data.ParseBool(1010, 36)) yield return "TbCM :"; + if (data.ParseBool(1010, 37)) yield return "BRNF :"; + if (data.ParseBool(1010, 42)) yield return "HTFS : If Heaters Fuse Blown"; + if (data.ParseBool(1010, 43)) yield return "DATA : Parameters out of range"; + if (data.ParseBool(1010, 45)) yield return "CELL2:"; + } + + [SuppressMessage("ReSharper", "StringLiteralTypo")] + internal static IEnumerable ParseWarnings(this ModbusRegisters data) + { + if (data.ParseBool(1006, 1)) yield return "TaM1: BMS temperature high"; + if (data.ParseBool(1006, 4)) yield return "TbM1: Battery temperature high"; + if (data.ParseBool(1006, 6)) yield return "VBm1: Bus voltage low"; + if (data.ParseBool(1006, 8)) yield return "VBM1: Bus voltage high"; + if (data.ParseBool(1006, 10)) yield return "IDM1: Discharge current high"; + if (data.ParseBool(1006, 24)) yield return "vsM1: String voltage high"; + if (data.ParseBool(1006, 26)) yield return "iCM1: Charge current high"; + if (data.ParseBool(1006, 28)) yield return "iDM1: Discharge current high"; + if (data.ParseBool(1006, 30)) yield return "MID1: String voltages unbalanced"; + if (data.ParseBool(1006, 32)) yield return "BLPW: Not enough charging power on bus"; + if (data.ParseBool(1006, 35)) yield return "Ah_W: String SOC low"; + if (data.ParseBool(1006, 38)) yield return "MPMM: Midpoint wiring problem"; + if (data.ParseBool(1006, 39)) yield return "TCMM:"; + if (data.ParseBool(1006, 40)) yield return "TCdi: Temperature difference between strings high"; + if (data.ParseBool(1006, 41)) yield return "WMTO:"; + if (data.ParseBool(1006, 44)) yield return "bit44:"; + if (data.ParseBool(1006, 46)) yield return "CELL1:"; + } +} \ No newline at end of file