Innovenergy_trunk/csharp/app/VenusLogger/Parsers/Battery48TL.cs

207 lines
8.5 KiB
C#

using System.Collections.Immutable;
using InnovEnergy.Lib.Utils;
using InnovEnergy.Lib.Victron.VeDBus;
using InnovEnergy.WireFormat.VictronV1;
namespace InnovEnergy.VenusLogger.Parsers;
using Props = ImmutableDictionary<String, VeProperty>;
public static class BatteryData
{
private record struct Bat(Props Props, Int32 NodeId);
public static Maybe<Device> GetBattery(this IEnumerable<ServiceProperties> services)
{
return services
.Where(VeService.IsBatteryService)
.Select(GetBatteryDevice)
.ToList()
.SingleOrDefault(Maybe<Device>.Nothing);
}
private static Maybe<Device> GetBatteryDevice(ServiceProperties serviceProps)
{
var individualBatteries = serviceProps
.Properties
.GetBatteriesData()
.Select(MakeDevice)
.ToList();
if (!individualBatteries.Any())
return null;
return individualBatteries.Combine(DeviceType.Battery48Tl200);
}
private static Device MakeDevice(BatteryStatus48TL batteryData)
{
return new Device
{
BatteryData = batteryData,
Type = DeviceType.Battery48Tl200,
Phases =
{
new Phase
{
Voltage = batteryData.BusVoltage, // TODO ?? cellsVoltage vs BusVoltage?
Current = -batteryData.CellsCurrent, // TODO ?? cellsCurrent vs BusCurrent?
Power = -batteryData.CellsVoltage * batteryData.CellsCurrent,
}
}
};
}
private static IEnumerable<BatteryStatus48TL> GetBatteriesData(this IReadOnlyList<ServiceProperties> batterySv)
{
return batterySv.Any()
? batterySv[0].Properties.GetBatteriesData()
: Enumerable.Empty<BatteryStatus48TL>();
}
private static IEnumerable<BatteryStatus48TL> GetBatteriesData(this Props props)
{
return GetNodes(props)
.Select(node => new Bat(props, node))
.TrySelect(Parse);
}
private static IEnumerable<Int32> GetNodes(Props props)
{
return props
.Keys
.Where(k => k.StartsWith("/_Battery/"))
.Select(p => p.Split("/")[2])
.Distinct()
.Select(Int32.Parse)
.OrderBy(n => n);
}
private static BatteryStatus48TL Parse(Bat bat)
{
var soc = bat.GetProperty<Single>("Soc");
var busVoltage = bat.GetProperty<Single>("BussVoltage");
var cellsCurrent = bat.GetDcValue("Current");
var cellsVoltage = bat.GetDcValue("Voltage");
var temperature = bat.GetDcValue("Temperature");
var alarms = bat.GetAlarms();
var warnings = bat.GetWarnings();
var ioStatus = bat.GetIoStatus();
var leds = bat.GetLeds();
return new BatteryStatus48TL
{
NodeId = bat.NodeId,
Soc = soc,
BusVoltage = busVoltage,
CellsVoltage = cellsVoltage,
CellsCurrent = cellsCurrent,
Temperature = temperature,
Alarms = { alarms },
Warnings = { warnings },
IoStatus = { ioStatus },
Leds = leds,
// TODO: temperatures
};
}
private static Single GetDcValue(this Bat bat, String prop)
{
return bat.GetProperty<Single>("Dc/0/" + prop);
}
private static IEnumerable<IoStatus> GetIoStatus(this Bat bat)
{
if (!bat.GetIoStatus("AlarmOutActive")) yield return IoStatus.AlarmActive; // inverted
if (bat.GetIoStatus("AuxRelay")) yield return IoStatus.AuxRelay;
if (bat.GetIoStatus("BatteryCold")) yield return IoStatus.AlarmActive;
if (bat.GetIoStatus("EocReached")) yield return IoStatus.EocReached;
if (bat.GetIoStatus("BatteryCold")) yield return IoStatus.BatteryCold;
if (bat.GetIoStatus("HeaterOn")) yield return IoStatus.HeaterActive;
if (bat.GetIoStatus("MainSwitchClosed")) yield return IoStatus.DisconnectedFromDc; // inverted
if (bat.GetIoStatus("RemoteState")) yield return IoStatus.RemoteState;
if (bat.GetIoStatus("VoltMeasurementAllowed")) yield return IoStatus.VoltMeasurementAllowed;
}
private static IEnumerable<Warnings> GetWarnings(this Bat bat)
{
if (bat.GetWarning("Ah_W")) yield return Warnings.AhWBit35;
if (bat.GetWarning("BLPW")) yield return Warnings.BlpwBit32;
if (bat.GetWarning("CELL1")) yield return Warnings.Cell1Bit46;
if (bat.GetWarning("IDM1")) yield return Warnings.Idm1Bit10;
if (bat.GetWarning("MID1")) yield return Warnings.Mid1Bit30;
if (bat.GetWarning("MPMM")) yield return Warnings.MpmmBit38;
if (bat.GetWarning("TCMM")) yield return Warnings.TcmmBit39;
if (bat.GetWarning("TCdi")) yield return Warnings.TcdiBit40;
if (bat.GetWarning("TaM1")) yield return Warnings.TaM1Bit1;
if (bat.GetWarning("TbM1")) yield return Warnings.TbM1Bit4;
if (bat.GetWarning("VBM1")) yield return Warnings.Vbm1Bit8;
if (bat.GetWarning("VBm1")) yield return Warnings.Vbm1Bit6;
if (bat.GetWarning("WMTO")) yield return Warnings.WmtoBit41;
if (bat.GetWarning("iCM1")) yield return Warnings.ICm1Bit26;
if (bat.GetWarning("iDM1")) yield return Warnings.IDm1Bit28;
if (bat.GetWarning("vsM1")) yield return Warnings.VsM1Bit24;
}
private static IEnumerable<Alarms> GetAlarms(this Bat bat)
{
if (bat.GetAlarm("AhFL")) yield return Alarms.AhFlBit34;
if (bat.GetAlarm("BRNF")) yield return Alarms.BrnfBit37;
if (bat.GetAlarm("CCBF")) yield return Alarms.CcbfBit33;
if (bat.GetAlarm("CELL2")) yield return Alarms.Cell2Bit45;
if (bat.GetAlarm("CME")) yield return Alarms.CmeBit18;
if (bat.GetAlarm("DATA")) yield return Alarms.DataBit43;
if (bat.GetAlarm("FUSE")) yield return Alarms.FuseBit14;
if (bat.GetAlarm("HTFS")) yield return Alarms.HtfsBit42;
if (bat.GetAlarm("HTRE")) yield return Alarms.HtreBit15;
if (bat.GetAlarm("HWEM")) yield return Alarms.HwemBit20;
if (bat.GetAlarm("HWFL")) yield return Alarms.HwflBit19;
if (bat.GetAlarm("IDM2")) yield return Alarms.IDm2Bit29;
if (bat.GetAlarm("ISOB")) yield return Alarms.IsobBit12;
if (bat.GetAlarm("MID2")) yield return Alarms.Mid2Bit31;
if (bat.GetAlarm("MSWE")) yield return Alarms.MsweBit13;
if (bat.GetAlarm("STRE")) yield return Alarms.StreBit17;
if (bat.GetAlarm("TCPE")) yield return Alarms.TcpeBit16;
if (bat.GetAlarm("TaM2")) yield return Alarms.TaM2Bit2;
if (bat.GetAlarm("Tam")) yield return Alarms.TamBit0;
if (bat.GetAlarm("TbCM")) yield return Alarms.TbCmBit36;
if (bat.GetAlarm("TbM2")) yield return Alarms.TbM2Bit5;
if (bat.GetAlarm("Tbm")) yield return Alarms.TbmBit3;
if (bat.GetAlarm("ThM")) yield return Alarms.ThMBit21;
if (bat.GetAlarm("VBm2")) yield return Alarms.Vbm2Bit7;
if (bat.GetAlarm("iCM2")) yield return Alarms.ICm2Bit27;
if (bat.GetAlarm("iDM2")) yield return Alarms.Idm2Bit11;
if (bat.GetAlarm("vsM2")) yield return Alarms.VsM2Bit25;
if (bat.GetAlarm("vsm1")) yield return Alarms.Vsm1Bit22;
if (bat.GetAlarm("vsm2")) yield return Alarms.Vsm2Bit23;
}
private static Boolean GetIoStatus(this Bat bat, String name) => bat.GetProperty<Boolean>("IoStatus/" + name);
private static Boolean GetAlarm (this Bat bat, String name) => bat.GetProperty<Boolean>("AlarmFlags/" + name);
private static Boolean GetWarning (this Bat bat, String name) => bat.GetProperty<Boolean>("WarningFlags/" + name);
private static Leds GetLeds(this Bat bat)
{
const String ls = "LedStatus/";
return new Leds
{
Amber = (Led) bat.GetProperty<Int16>(ls + "Amber"),
Red = (Led) bat.GetProperty<Int16>(ls + "Red"),
Blue = (Led) bat.GetProperty<Int16>(ls + "Blue"),
Green = (Led) bat.GetProperty<Int16>(ls + "Green"),
};
}
private static T GetProperty<T>(this Bat bat, String path)
{
var (props, nodeId) = bat;
return props.GetProperty<T>($"/_Battery/{nodeId}/{path}");
}
}