diff --git a/csharp/App/SaliMax/src/AsciiArt.cs b/csharp/App/SaliMax/src/AsciiArt.cs index cff4dea90..9e0b47545 100644 --- a/csharp/App/SaliMax/src/AsciiArt.cs +++ b/csharp/App/SaliMax/src/AsciiArt.cs @@ -69,39 +69,6 @@ public static class AsciiArt ); } - public static String CreateVerticalPad(String value, Int32 contentVerticalWidth, Boolean direction, String name) - { - var v = value.PadLeft(contentVerticalWidth); - var n = name.PadLeft(contentVerticalWidth); - - if (direction) // up - { - var horizontal = "".PadLeft(contentVerticalWidth - 4, ' ').V(); - - return StringUtils.JoinLines( - n, - horizontal, - horizontal, - v, - horizontal, - horizontal - ); - } - else // down - { - var horizontal = "".PadLeft(contentVerticalWidth - 4, ' ').V(); - - return StringUtils.JoinLines( - horizontal, - horizontal, - v, - horizontal, - horizontal, - n - ); - } - } - public static String CreateVerticalArrow(Decimal power, Int32 width = 0) { var flow = "V".NewLine() + "V".NewLine() + power.W().NewLine() + "V".NewLine() + "V"; diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index d4d080a11..84245bb28 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -4,7 +4,6 @@ using System.Text.Json.Nodes; using System.Text.Json.Serialization; using Flurl.Http; using InnovEnergy.App.SaliMax.Controller; -using InnovEnergy.App.SaliMax.Log; using InnovEnergy.App.SaliMax.SaliMaxRelays; using InnovEnergy.App.SaliMax.SystemConfig; using InnovEnergy.Lib.Devices.AMPT; @@ -109,7 +108,6 @@ internal static class Program { InverterStatus = inverterDevice.ReadStatus(), DcDcStatus = dcDcDevice.ReadStatus(), - BatteriesStatus = combinedBatteryStatus, AcInToAcOutMeterStatus = acInToAcOutMeterDevice.ReadStatus(), GridMeterStatus = gridMeterDevice.ReadStatus(), @@ -123,10 +121,6 @@ internal static class Program var startTime = UnixTime.Now; const Int32 delayTime = 10; - - await UploadTopology(s3Config, Salimax.TopologyToLog(startTime), startTime); - DebugWriteTopology(startTime); - Console.WriteLine("press ctrl-C to stop"); @@ -167,21 +161,6 @@ internal static class Program // WriteToFile(jsonLog, "/home/debian/DataSaliMax/" + timestamp); // this is was for beaglebone TODO } - // [Conditional("RELEASE")] - private static JsonObject ReleaseWriteTopology(UnixTime timestamp) - { - var topologyJson = Salimax.TopologyToLog(timestamp); - - // WriteToFile(topologyJson, "/home/debian/DataSaliMax/topology" + timestamp); // this is was for beaglebone - return topologyJson; - } - - [Conditional("DEBUG")] - private static void DebugWriteTopology(UnixTime timestamp) - { - var topologyJson = Salimax.TopologyToLog(timestamp); - WriteToFile(topologyJson, "/home/atef/JsonData/topology" + timestamp); - } [Conditional("DEBUG")] private static void DebugWriteLog(JsonObject jsonLog, UnixTime timestamp) diff --git a/csharp/App/SaliMax/src/Topology.cs b/csharp/App/SaliMax/src/Topology.cs index defb0f570..9966be228 100644 --- a/csharp/App/SaliMax/src/Topology.cs +++ b/csharp/App/SaliMax/src/Topology.cs @@ -1,4 +1,4 @@ -#undef BatteriesAllowed +#define BatteriesAllowed using InnovEnergy.App.SaliMax.Controller; using InnovEnergy.Lib.Utils; @@ -9,32 +9,56 @@ namespace InnovEnergy.App.SaliMax; public static class Topology { - public static void Print(StatusRecord s) + 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 pwr = s.InverterStatus!.Ac.ActivePower; - var pvPower = (s.AmptStatus!.Strings[0].Voltage * s.AmptStatus.Strings[0].Current + s.AmptStatus!.Strings[1].Voltage * s.AmptStatus.Strings[1].Current); // TODO using one Ampt - var loadPower = Utils.Round3((s.GridMeterStatus!.Ac.ActivePower + pwr)); // it's a + because the pwr is inverted - - var gridSeparator = s.GridMeterStatus!.Ac.ActivePower > 0 ? chargingSeparator : dischargingSeparator; - var inverterSeparator = -pwr > 0 ? chargingSeparator : dischargingSeparator; - var dcSeparator = -s.DcDcStatus!.Right.Power > 0 ? chargingSeparator : dischargingSeparator; -#if BatteriesAllowed - var battery1Separator = s.BatteriesStatus[0]!.Power > 0 ? chargingSeparator : dischargingSeparator; - var battery2Separator = s.BatteriesStatus[1]!.Power > 0 ? chargingSeparator : dischargingSeparator; + 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.V(), - s.GridMeterStatus.Ac.L2.Voltage.V(), - s.GridMeterStatus.Ac.L3.Voltage.V() + 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) @@ -45,9 +69,9 @@ public static class Topology var boxAcBus = AsciiArt.CreateBox ( "AC Bus", - s.InverterStatus.Ac.L1.Voltage.V(), - s.InverterStatus.Ac.L2.Voltage.V(), - s.InverterStatus.Ac.L3.Voltage.V() + 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 @@ -57,9 +81,9 @@ public static class Topology "" ); - var loadRect = StringUtils.AlignBottom(CreateRect(boxAcBus, boxLoad, loadPower), height); + var loadRect = StringUtils.AlignBottom(CreateRect(boxAcBus, boxLoad, gridLoadPower), height); - var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr, inverterSeparator) + var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(measuredActivePwr, inverterSeparator) .AlignCenterVertical(height); //////////////////// Inverter ///////////////////////// @@ -70,7 +94,7 @@ public static class Topology "" ).AlignCenterVertical(height); - var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr, inverterSeparator) + var inverterArrow = AsciiArt.CreateHorizontalArrow(measuredActivePwr, inverterSeparator) .AlignCenterVertical(height); @@ -78,90 +102,113 @@ public static class Topology var dcBusBox = AsciiArt.CreateBox ( "DC Bus", - (s.InverterStatus.ActualDcLinkVoltageLowerHalfExt + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt).V(), + (s.InverterStatus.ActualDcLinkVoltageLowerHalfExt.Value + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt.Value).V(), "" ); var pvBox = AsciiArt.CreateBox ( "MPPT", - ((s.AmptStatus!.Strings[0].Voltage + s.AmptStatus!.Strings[1].Voltage) / 2).V(), + ((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!.Dc.Power, dcSeparator) + var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Left.Power, dcSeparator) .AlignCenterVertical(height); - //////////////////// Dc/Dc ///////////////////////// - var dcBox = AsciiArt.CreateBox - ( - "Dc/Dc", - s.DcDcStatus.BatteryVoltage.V(), - "" - ).AlignCenterVertical(height); -#if BatteriesAllowed - var dcArrow1 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[0]!.Power, battery1Separator); - var dcArrow2 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[1]!.Power, battery2Separator); -#else - var dcArrow1 =""; - var dcArrow2 = ""; - var dcArrowRect = StringUtils.AlignCenterVertical(CreateRect(dcArrow1, dcArrow2), height); -#endif - - -#if BatteriesAllowed + //////////////////// Dc/Dc ///////////////////////// - //////////////////// Batteries ///////////////////////// - var battery1Box = AsciiArt.CreateBox - ( - "Battery 1", - s.BatteriesStatus[0].Voltage.V(), - s.BatteriesStatus[0].Soc.Percent(), - s.BatteriesStatus[0].Temperature.Celsius() - ); - - var battery2Box = AsciiArt.CreateBox - ( - "Battery 2", - s.BatteriesStatus[1].Voltage.V(), - s.BatteriesStatus[1].Soc.Percent(), - s.BatteriesStatus[1].Temperature.Celsius() - ); + var dcBox = AsciiArt.CreateBox( "Dc/Dc", s.DcDcStatus.Right.Voltage.Value.V(), "").AlignCenterVertical(height); - var batteryRect = CreateRect(battery1Box, battery2Box).AlignCenterVertical(height); + var topology = ""; + + if (s.BatteriesStatus != null) + { + var numBatteries = s.BatteriesStatus.Children.Count; - var avgBatteryBox = AsciiArt.CreateBox - ( - "Batteries", - s.AvgBatteriesStatus!.Voltage.V(), - s.AvgBatteriesStatus.Soc.Percent(), - s.AvgBatteriesStatus.Temperature.Celsius() - ).AlignCenterVertical(height); + // 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"; + } - var 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 - var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") - .SideBySideWith(loadRect, "") - .SideBySideWith(acBusInvertArrow, "") - .SideBySideWith(inverterBox, "") - .SideBySideWith(inverterArrow, "") - .SideBySideWith(pvRect, "") - .SideBySideWith(dcBusArrow, "") - .SideBySideWith(dcBox, "")+ "\n"; -#endif Console.WriteLine(topology); } @@ -183,5 +230,12 @@ public static class Topology 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; + } } \ No newline at end of file