diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index cd91a3eb3..67387a7e0 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -205,7 +205,7 @@ internal static class Program WriteControl(record); - Topology.From(record).WriteLine(); + record.CreateTopology().WriteLine(); //record.ToCsv().WriteLine(); diff --git a/csharp/App/SaliMax/src/Topology.cs b/csharp/App/SaliMax/src/Topology.cs index 00345a4ff..8a768ea41 100644 --- a/csharp/App/SaliMax/src/Topology.cs +++ b/csharp/App/SaliMax/src/Topology.cs @@ -1,6 +1,8 @@ +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using InnovEnergy.App.SaliMax.Ess; using InnovEnergy.Lib.Devices.Battery48TL; +using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Units.Power; using InnovEnergy.Lib.Utils; @@ -10,61 +12,68 @@ namespace InnovEnergy.App.SaliMax; public static class Topology { - public static TextBlock From(this StatusRecord s) + public static TextBlock CreateTopology(this StatusRecord status) { // Topology is built up from right to left - - // Power Measurement Values + var islandTopology = status.CreateIslandTopology(); - var inverterPower = s.AcDc.Ac.Power.Active; - var islandLoadPower = s.LoadOnAcIsland is not null - ? s.LoadOnAcIsland.Ac.Power.Active - : 0; // TODO + // TODO: check ACDCs if AC is available and synced to find out if grid meter OR grid is unavailable - var islandTopology = CreateIslandTopology(s, islandLoadPower, inverterPower); - - if (s.GridMeter is null) // no grid meter? + if (status.GridMeter is null) // no grid meter? return islandTopology; // we're done - var gridBusColumn = GridBusColumn(s); - var gridBox = CreateGridBox(s); + var gridTopology = status.CreateGridTopology(); + + return status.ConnectGridToIslandTopology(gridTopology, islandTopology); + } + + private static TextBlock ConnectGridToIslandTopology(this StatusRecord status, TextBlock gridTopology, TextBlock islandTopology) + { + var inverterPower = status.AcDc.Ac.Power.Active; + var islandLoadPower = status.LoadOnAcIsland is not null + ? status.LoadOnAcIsland.Ac.Power.Active + : 0; // TODO ActivePower islandToGridBusPower = inverterPower + islandLoadPower; - - // return TextBlock - // .AlignCenterVertical - // ( - // gridBox , Flow.Horizontal(s.GridMeter.Ac.Power.Active), - // gridBusColumn, Flow.Horizontal(islandToGridBusPower), - // islandTopology - // ); - - var gridTopology = TextBlock - .AlignCenterVertical - ( - gridBox, - Flow.Horizontal(s.GridMeter.Ac.Power.Active), - gridBusColumn - ); return TextBlock.AlignCenterVertical ( gridTopology, Flow.Horizontal(islandToGridBusPower), islandTopology - ); + ); } - private static TextBlock CreateIslandTopology(StatusRecord s, ActivePower islandLoadPower, ActivePower inverterPower) + private static TextBlock CreateGridTopology(this StatusRecord status) { - var dcBatteryPower = s.DcDc.Dc.Battery.Power; - var dcdcPower = s.DcDc.Dc.Link.Power; + Debug.Assert(status.GridMeter is not null); + + var gridBusColumn = status.CreateGridBusColumn(); + var gridBox = status.GridMeter.CreateGridBox(); - var batteries = CreateBatteryColumn(s); - var dcBusColumn = CreateDcBusColumn(s); - var islandBusColumn = CreateIslandBusColumn(s, islandLoadPower); - var inverterBox = CreateInverterBox(s); - var dcDcBox = CreateDcDcBox(s); + return TextBlock + .AlignCenterVertical + ( + gridBox, + Flow.Horizontal(status.GridMeter.Ac.Power.Active), + gridBusColumn + ); + } + + private static TextBlock CreateIslandTopology(this StatusRecord status) + { + var dcBatteryPower = status.DcDc.Dc.Battery.Power; + var dcdcPower = status.DcDc.Dc.Link.Power; + var inverterPower = status.AcDc.Ac.Power.Active; + var islandLoadPower = status.LoadOnAcIsland is not null + ? status.LoadOnAcIsland.Ac.Power.Active + : 0; // TODO + + var batteries = status.CreateBatteryColumn(); + var dcBusColumn = status.CreateDcBusColumn(); + var islandBusColumn = status.CreateIslandBusColumn(islandLoadPower); + var inverterBox = status.CreateInverterBox(); + var dcDcBox = status.CreateDcDcBox(); return TextBlock .AlignCenterVertical @@ -77,27 +86,26 @@ public static class Topology ); } - private static TextBlock CreateGridBox(StatusRecord statusRecord) + private static TextBlock CreateGridBox(this IAc3Connection gridMeter) { - return statusRecord - .GridMeter! + return gridMeter .Ac .PhasePowersActive() .TitleBox("Grid"); } - private static TextBlock CreateDcDcBox(StatusRecord s) + private static TextBlock CreateDcDcBox(this StatusRecord status) { - var dc48Voltage = s.DcDc.Dc.Battery.Voltage.ToDisplayString(); + var dc48Voltage = status.DcDc.Dc.Battery.Voltage.ToDisplayString(); return TextBlock .AlignLeft(dc48Voltage) .TitleBox("DC/DC"); } - private static TextBlock CreateInverterBox(StatusRecord s) + private static TextBlock CreateInverterBox(this StatusRecord status) { - var inverterAcPhases = s + var inverterAcPhases = status .AcDc .Devices .Select(d => d.Status.Ac.Power) @@ -107,41 +115,57 @@ public static class Topology .AlignLeft(inverterAcPhases) .TitleBox("AC/DC"); } + + private static TextBlock CreateGridBusColumn(this StatusRecord status) + { + Debug.Assert(status.GridMeter is not null); - private static TextBlock CreateIslandBusColumn(StatusRecord s, ActivePower islandLoadPower) + var gridLoadPower = status.LoadOnAcGrid is not null + ? status.LoadOnAcGrid.Power.Active + : 0; // TODO: show that LoadOnAcGrid is actually not available and not 0 + + return CreateTopologyColumn + ( + "PV" , 0, + "Grid Bus", status.GridMeter.Ac.PhaseVoltages(), + "Load" , gridLoadPower + ); + } + + private static TextBlock CreateIslandBusColumn(this StatusRecord status, ActivePower islandLoadPower) { var islandBusPv = 0.W(); // TODO - return ColumnBox + return CreateTopologyColumn ( - "Pv", islandBusPv, - "Island Bus", s.AcDc.Ac.PhasePowersActive(), - "Load", islandLoadPower + "PV" , islandBusPv, + "Island Bus", status.AcDc.Ac.PhaseVoltages(), + "Load" , islandLoadPower ); } - private static TextBlock CreateDcBusColumn(StatusRecord s) + private static TextBlock CreateDcBusColumn(this StatusRecord status) { var dcBusLoad = 0.W(); // TODO - var pvOnDcPower = s.PvOnDc.Dc!.Power; // TODO ! - var dcLinkVoltage = s.DcDc.Dc.Link.Voltage.ToDisplayString(); + var pvOnDcPower = status.PvOnDc.Dc!.Power; // TODO ! + var dcLinkVoltage = status.DcDc.Dc.Link.Voltage.ToDisplayString(); - return ColumnBox + return CreateTopologyColumn ( - "Pv" , pvOnDcPower, - "Dc Bus", dcLinkVoltage, - "Load" , dcBusLoad + "PV" , pvOnDcPower, + "DC Bus" , dcLinkVoltage, + "DC Load", dcBusLoad ); } - private static TextBlock CreateBatteryColumn(StatusRecord s) + private static TextBlock CreateBatteryColumn(this StatusRecord status) { - var bat = s.Battery; + var bat = status.Battery; var batteryAvgBox = CreateAveragedBatteryBox(bat); var batteryBoxes = bat .Devices - .Select(CreateIndividualBattery) + .Select(CreateBatteryBox) .ToReadOnlyList(); var individualBatteries = batteryBoxes.Any() @@ -158,42 +182,28 @@ public static class Topology private static TextBlock CreateAveragedBatteryBox(Battery48TlRecords bat) { - var batteryVoltage = bat.Dc.Voltage.ToDisplayString(); - var batterySoc = bat.Devices.Any() ? bat.Devices.Average(b => b.Soc).Percent().ToDisplayString() : "0"; - var batteryCurrent = bat.Dc.Current.ToDisplayString(); - var batteryTemp = bat.Temperature.ToDisplayString(); - var batteryHeatingCurrent = bat.HeatingCurrent.ToDisplayString(); + var voltage = bat.Dc.Voltage.ToDisplayString(); + var soc = bat.Devices.Any() ? bat.Devices.Average(b => b.Soc).Percent().ToDisplayString() : "0"; + var current = bat.Dc.Current.ToDisplayString(); + var temp = bat.Temperature.ToDisplayString(); + var heatingCurrent = bat.HeatingCurrent.ToDisplayString(); var alarms = bat.Alarms.Count + " Alarms"; var warnings = bat.Warnings.Count + " Warnings"; return TextBlock .AlignLeft ( - batteryVoltage, - batterySoc, - batteryCurrent, - batteryTemp, - batteryHeatingCurrent, + voltage, + soc, + current, + temp, + heatingCurrent, warnings, alarms ) .TitleBox("Battery"); } - private static TextBlock GridBusColumn(StatusRecord s) - { - var gridLoadPower = s.LoadOnAcGrid is not null - ? s.LoadOnAcGrid.Power.Active - : 0; // TODO: show that LoadOnAcGrid is actually not available and not 0 - - return ColumnBox - ( - "Pv", 0, - "Grid Bus", s.GridMeter!.Ac.PhaseVoltages(), - "Load", gridLoadPower - ); - } - private static TextBlock PhaseVoltages(this Ac3Bus ac) { return TextBlock.AlignLeft @@ -214,7 +224,7 @@ public static class Topology ); } - private static TextBlock CreateIndividualBattery(Battery48TlRecord battery, Int32 i) + private static TextBlock CreateBatteryBox(Battery48TlRecord battery, Int32 i) { var batteryWarnings = battery.Warnings.Any(); var batteryAlarms = battery.Alarms.Any(); @@ -238,10 +248,9 @@ public static class Topology } [SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")] - - private static TextBlock ColumnBox(String pvTitle , ActivePower pvPower, - String busTitle , Object busData, - String loadTitle, ActivePower loadPower) + private static TextBlock CreateTopologyColumn(String pvTitle , ActivePower pvPower, + String busTitle , Object busData, + String loadTitle, ActivePower loadPower) { var pvBox = TextBlock.FromString(pvTitle).Box(); var pvToBus = Flow.Vertical(pvPower); @@ -251,4 +260,4 @@ public static class Topology return TextBlock.AlignCenterHorizontal(pvBox, pvToBus, busBox, busToLoad, loadBox); } -} \ No newline at end of file +}