#define BatteriesAllowed using InnovEnergy.App.SaliMax.Controller; using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Units; namespace InnovEnergy.App.SaliMax; public static class Topology { private static String Separator(Decimal power) { const String chargingSeparator = ">>>>>>>>>>"; const String dischargingSeparator = "<<<<<<<<<"; return power > 0 ? chargingSeparator : dischargingSeparator; } public static Decimal Round3(this Decimal d) { return d.RoundToSignificantDigits(3); } public static void Print(StatusRecord s) { const Int32 height = 25; var calculatedActivePwr = - s.InverterStatus!.Ac.ActivePower; var measuredActivePwr = (s.InverterStatus.SumActivePowerL1 + s.InverterStatus.SumActivePowerL2 + s.InverterStatus.SumActivePowerL3) * -1; measuredActivePwr.WriteLine(" : measured Sum of Active Pwr "); var setValueCosPhi = s.InverterStatus.CosPhiSetValue; var setValueApparentPower = s.InverterStatus.ApparentPowerSetValue; #if AmptAvailable var pvPower = (s.AmptStatus!.Devices[0].Dc.Voltage * s.AmptStatus.Devices[0].Dc.Current + s.AmptStatus!.Devices[1].Dc.Voltage * s.AmptStatus.Devices[1].Dc.Current).Round0(); // TODO using one Ampt #else var pvPower = 0; #endif var criticalLoadPower = (s.AcInToAcOutMeterStatus!.Ac.ActivePower.Value).Round3(); var dcTotalPower = -s.DcDcStatus!.TotalDcPower; var gridSeparator = Separator(s.GridMeterStatus!.Ac.ActivePower); var inverterSeparator = Separator(measuredActivePwr); var dcSeparator = Separator(dcTotalPower); var something = measuredActivePwr + criticalLoadPower; var gridLoadPower = (s.GridMeterStatus!.Ac.ActivePower - something).Value.Round3(); ////////////////// Grid ////////////////////// var boxGrid = AsciiArt.CreateBox ( "Grid", s.GridMeterStatus.Ac.L1.Voltage.Value.V(), s.GridMeterStatus.Ac.L2.Voltage.Value.V(), s.GridMeterStatus.Ac.L3.Voltage.Value.V() ).AlignCenterVertical(height); var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.Ac.ActivePower, gridSeparator) .AlignCenterVertical(height); ////////////////// Ac Bus ////////////////////// var boxAcBus = AsciiArt.CreateBox ( "AC Bus", s.InverterStatus.Ac.L1.Voltage.Value.V(), s.InverterStatus.Ac.L2.Voltage.Value.V(), s.InverterStatus.Ac.L3.Voltage.Value.V() ); var boxLoad = AsciiArt.CreateBox ( "", "LOAD", "" ); var loadRect = StringUtils.AlignBottom(CreateRect(boxAcBus, boxLoad, gridLoadPower), height); var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(measuredActivePwr, inverterSeparator) .AlignCenterVertical(height); //////////////////// Inverter ///////////////////////// var inverterBox = AsciiArt.CreateBox ( "", "Inverter", "" ).AlignCenterVertical(height); var inverterArrow = AsciiArt.CreateHorizontalArrow(measuredActivePwr, inverterSeparator) .AlignCenterVertical(height); //////////////////// DC Bus ///////////////////////// var dcBusBox = AsciiArt.CreateBox ( "DC Bus", (s.InverterStatus.ActualDcLinkVoltageLowerHalfExt.Value + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt.Value).V(), "" ); var pvBox = AsciiArt.CreateBox ( "MPPT", ((s.AmptStatus!.Devices[0].Strings[0].Voltage.Value + s.AmptStatus!.Devices[0].Strings[1].Voltage.Value) / 2).V(), "" ); var pvRect = StringUtils.AlignTop(CreateRect(pvBox, dcBusBox, pvPower), height); var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Left.Power, dcSeparator) .AlignCenterVertical(height); //////////////////// Dc/Dc ///////////////////////// var dcBox = AsciiArt.CreateBox( "Dc/Dc", s.DcDcStatus.Right.Voltage.Value.V(), "").AlignCenterVertical(height); var topology = ""; if (s.BatteriesStatus != null) { var numBatteries = s.BatteriesStatus.Children.Count; // Create an array of battery arrows using LINQ var dcArrows = s .BatteriesStatus.Children .Select(b => AsciiArt.CreateHorizontalArrow(b.Dc.Power, Separator(b.Dc.Power))) .ToArray(); // Create a rectangle from the array of arrows and align it vertically var dcArrowRect = CreateRect(dcArrows).AlignCenterVertical(height); //////////////////// Batteries ///////////////////////// var batteryBox = new String[numBatteries]; for (var i = 0; i < numBatteries; i++) { if (s.BatteriesStatus.Children[i] != null) { batteryBox[i] = AsciiArt.CreateBox ( "Battery " + (i+1), s.BatteriesStatus.Children[i].Dc.Voltage .Value.V(), s.BatteriesStatus.Children[i].Soc .Value.Percent(), s.BatteriesStatus.Children[i].Temperature .Value.Celsius(), s.BatteriesStatus.Children[i].Dc.Current .Value.A(), s.BatteriesStatus.Children[i].TotalCurrent.Value.A() ); } else { batteryBox[i] = AsciiArt.CreateBox ( "Battery " + (i+1), "not detected" ); } } var batteryRect = CreateRect(batteryBox).AlignCenterVertical(height); var avgBatteryBox = ""; if (s.BatteriesStatus.Combined != null) { avgBatteryBox = AsciiArt.CreateBox ( "Batteries", s.BatteriesStatus.Combined.CellsVoltage, s.BatteriesStatus.Combined.Soc, s.BatteriesStatus.Combined.Temperature, s.BatteriesStatus.Combined.Dc.Current, s.BatteriesStatus.Combined.Alarms.Count > 0 ? String.Join(Environment.NewLine, s.BatteriesStatus.Combined.Alarms) : "No Alarm" ).AlignCenterVertical(height); } topology = boxGrid.SideBySideWith(gridAcBusArrow, "") .SideBySideWith(loadRect, "") .SideBySideWith(acBusInvertArrow, "") .SideBySideWith(inverterBox, "") .SideBySideWith(inverterArrow, "") .SideBySideWith(pvRect, "") .SideBySideWith(dcBusArrow, "") .SideBySideWith(dcBox, "") .SideBySideWith(dcArrowRect, "") .SideBySideWith(batteryRect, "") .SideBySideWith(avgBatteryBox, "")+ "\n"; } else { topology = boxGrid.SideBySideWith(gridAcBusArrow, "") .SideBySideWith(loadRect, "") .SideBySideWith(acBusInvertArrow, "") .SideBySideWith(inverterBox, "") .SideBySideWith(inverterArrow, "") .SideBySideWith(pvRect, "") .SideBySideWith(dcBusArrow, "") .SideBySideWith(dcBox, "") + "\n"; } Console.WriteLine(topology); } private static String CreateRect(String boxTop, String boxBottom, Decimal power) { var powerArrow = AsciiArt.CreateVerticalArrow(power); var boxes = new[] { boxTop, powerArrow, boxBottom }; var maxWidth = boxes.Max(l => l.Width()); var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); return rect; } private static String CreateRect(String boxTop, String boxBottom) { var boxes = new[] { boxTop, boxBottom }; var maxWidth = boxes.Max(l => l.Width()); var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); return rect; } private static String CreateRect(String[] boxes) { var maxWidth = boxes.Max(l => l.Width()); var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); return rect; } }