using System.Globalization; using InnovEnergy.App.KacoCommunication.Devices; using InnovEnergy.App.KacoCommunication.ESS; using InnovEnergy.Lib.Devices.BatteryDeligreen; using InnovEnergy.Lib.Units.Power; using InnovEnergy.Lib.Utils; namespace InnovEnergy.App.KacoCommunication; // // ┌────┐ // │ Pv │ // └────┘ // V // V // (i) 13.2 kW ┌────────────┐ ┌────────────┐ ┌────────────┐ // V │ Battery K1│ │ Battery K2│ │ Battery K3│ // ┌─────────┐ ┌─────────┐ V ├────────────┤ ├────────────┤ ├────────────┤ // │ Grid │ │ AC/DC │ ┌────────┐ ┌───────┐ │ 52.3 V │ │ 52.3 V │ │ 52.3 V │ // ├─────────┤ -10.3 kW├─────────┤ -11.7 kW │ Dc Bus │ 1008 W │ DC/DC │ 1008 W │ 99.1 % │ │ 99.1 % │ │ 99.1 % │ // │ -3205 W │<<<<<<<<<│ -6646 W │<<<<<<<<<<├────────┤>>>>>>>>>>├───────┤>>>>>>>>>>│ 490 mA │ │ 490 mA │ │ 490 mA │ // │ -3507 W │ (a) │ -5071 W │ (h) │ 776 V │ (k) │ 56 V │ (l) │ 250 °C │ │ 250 °C │ │ 250 °C │ // │ -3605 W │ └─────────┘ └────────┘ └───────┘ │ 445 A │ │ 445 A │ │ 445 A │ // └─────────┘ V │ │ │ │ │ │ // V │ │ │ │ │ │ // (j) 0 W └────────────┘ └────────────┘ └────────────┘ // V // V // ┌──────┐ // │ Load │ // └──────┘ // public static class SimpleTopology { public static TextBlock CreateSimpleTopologyTextBlock(this StatusRecord status) { // Keep the same variable letters as your diagrams (where possible) var a = status.GridMeterRecord?.ActivePowerTotal; // and "h" is a separate link (AcDcToDcLink?.Power.Value). var h = status.InverterRecord?.ActivePowerW; var i = 0; var j = 0; var k = status.DcDc?.Dc.Battery.Power.Value; // You mentioned this changed: l is now equal total battery power var l = status.ListOfBatteriesRecord?.Sum(r => r.Power); var grid = status.CreateGridColumn(a); var acdc = status.CreateAcDcColumn(h); var dcBus = status.CreateDcBusColumn(i, j, k); var dcdc = status.CreateDcDcColumn(l); var batteries = status.CreateBatteriesRow(); return TextBlock.AlignCenterVertical( grid, acdc, dcBus, dcdc, batteries ); } private static TextBlock CreateGridColumn(this StatusRecord status, ActivePower? a) { // ┌─────────┐ // │ Grid │ // ├─────────┤ // │ L1 P │ // │ L2 P │ // │ L3 P │ // └─────────┘ (a) flow to AC/DC var gridMeterAc = status.GridMeterRecord; var gridBox = TextBlock .AlignLeft( gridMeterAc?.ActivePowerL1.Value.ToString(CultureInfo.InvariantCulture) ?? "???", gridMeterAc?.ActivePowerL2.Value.ToString(CultureInfo.InvariantCulture) ?? "???", gridMeterAc?.ActivePowerL3.Value.ToString(CultureInfo.InvariantCulture) ?? "???" ) .TitleBox("Grid"); // Flow from Grid to AC/DC in the picture is horizontal (left -> right), using <<<<<< for export/import. // Your Flow.Horizontal(power) already handles arrow direction by sign (based on your existing outputs). var flow = Flow.Horizontal(a); return TextBlock.AlignCenterVertical(gridBox, flow); } private static TextBlock CreateAcDcColumn(this StatusRecord status, ActivePower? h) { // ┌─────────┐ // │ AC/DC │ // ├─────────┤ // │ dev1 P │ // │ dev2 P │ // └─────────┘ (h) flow to DC Bus var acdcBox = TextBlock .AlignLeft(status.InverterRecord?.ActivePowerW.ToString() ?? "???") .TitleBox("AC/DC"); var flowToDcBus = Flow.Horizontal(h); return TextBlock.AlignCenterVertical(acdcBox, flowToDcBus); } private static TextBlock CreateDcBusColumn( this StatusRecord status, ActivePower? i, ActivePower? j, ActivePower? k) { // ┌────┐ // │ PV │ // └────┘ // V // (i) 13.2 kW // V // ┌────────┐ (k) >>>>>>>>> to DC/DC // │ Dc Bus │>>>>>>>>>>>>>>>>>>> // ├────────┤ // │ 776 V │ // └────────┘ // V // (j) 0 W // V // ┌──────┐ // │ Load │ // └──────┘ // PV box + vertical flow var pvBox = TextBlock.FromString("PV").Box(); var pvToBus = Flow.Vertical(i); // DC bus box (voltage from your DcDc record matches your existing code) var dcBusVoltage = status.DcDc.Dc.Link.Voltage.Value; var dcBusBox = dcBusVoltage .ToString(CultureInfo.InvariantCulture) .Apply(TextBlock.FromString) .TitleBox("Dc Bus"); // Horizontal flow from DC Bus to DC/DC var busToDcDc = Flow.Horizontal(k); // Load box + vertical flow var busToLoad = Flow.Vertical(j); var loadBox = TextBlock.FromString("Load").Box(); // Assemble: put PV above DC Bus, Load below DC Bus, and the (k) flow beside the bus. return TextBlock.AlignCenterVertical( TextBlock.AlignCenterHorizontal(pvBox, pvToBus, dcBusBox, busToLoad, loadBox), busToDcDc ); } private static TextBlock CreateDcDcColumn(this StatusRecord status, ActivePower? l) { // ┌───────┐ // │ DC/DC │ // ├───────┤ // │ 56 V │ // └───────┘ (l) flow to batteries var dc48Voltage = status.DcDc?.Dc.Battery.Voltage; var dcdcBox = TextBlock .AlignLeft(dc48Voltage) .TitleBox("DC/DC"); var flowToBattery = Flow.Horizontal(l); return TextBlock.AlignCenterVertical(dcdcBox, flowToBattery); } private static TextBlock CreateBatteriesRow(this StatusRecord status) { // Battery K1 | Battery K2 | Battery K3 (side-by-side) // Each box: voltage, soc, current, temp, etc. (you can tailor) var bat = status.ListOfBatteriesRecord; if (bat is null) return TextBlock.AlignLeft("no battery").Box(); // If you actually have relay names K1/K2/K3 per battery, wire them here. // For now we label by index as "Battery K{n}" to match your picture. var boxes = bat .Select((b, idx) => CreateBatteryKBox(b, idx)) .ToReadOnlyList(); // Align horizontally to match the diagram return boxes.Any() ? TextBlock.AlignTop(boxes) : TextBlock.AlignLeft("no battery devices").Box(); } private static TextBlock CreateBatteryKBox(BatteryDeligreenRecords battery, int idx) { // Some of your sample screen values look like: // 52.3 V, 99.1 %, 490 mA, 250 °C, 445 A // Map these to whatever fields you trust in your record. var voltage = battery.Voltage.ToDisplayString(); var soc = battery.Soc.ToDisplayString(); var current = battery.Current.ToDisplayString(); var count = battery.Devices.Count; return TextBlock .AlignLeft( voltage, soc, current, count ) .TitleBox($"Battery K{idx + 1}"); } }