266 lines
12 KiB
C#
266 lines
12 KiB
C#
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 │
|
||
// └──────┘
|
||
//
|
||
|
||
// New (simplified) topology:
|
||
//
|
||
// ┌────┐
|
||
// │ PV │
|
||
// └────┘
|
||
// V
|
||
// V
|
||
// (i) 13.2 kW
|
||
// V
|
||
// V
|
||
// ┌─────────┐ ┌─────────┐ (h) ┌────────┐ (k) ┌───────┐ (l) ┌────────────┐ ┌────────────┐ ┌────────────┐
|
||
// │ Grid │<<<│ AC/DC │<<<<<<<<<<<<<│ Dc Bus │>>>>>>>>│ DC/DC │>>>>>>>>│ Battery K1 │ │ Battery K2 │ │ Battery K3 │
|
||
// ├─────────┤ ├─────────┤ ├────────┤ ├───────┤ ├────────────┤ ├────────────┤ ├────────────┤
|
||
// │ -3205 W │ │ -6646 W │ │ 776 V │ │ 56 V │ │ 52.3 V ... │ │ 52.3 V ... │ │ 52.3 V ... │
|
||
// │ -3507 W │ │ -5071 W │ └────────┘ └───────┘ └────────────┘ └────────────┘ └────────────┘
|
||
// │ -3605 W │
|
||
// └─────────┘
|
||
//
|
||
// V
|
||
// V
|
||
// (j) 0 W
|
||
// V
|
||
// V
|
||
// ┌──────┐
|
||
// │ Load │
|
||
// └──────┘
|
||
//
|
||
// Notes:
|
||
// - (a) is grid power (to/from grid)
|
||
// - (h) is AC/DC -> DC link power (or your chosen link variable)
|
||
// - (i) PV -> DC bus
|
||
// - (j) DC load
|
||
// - (k) DC bus -> DC/DC link
|
||
// - (l) DC/DC -> battery power (or total battery power)
|
||
|
||
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;
|
||
|
||
// In your existing code, "AC/DC column" shows per-device AC power;
|
||
// and "h" is a separate link (AcDcToDcLink?.Power.Value).
|
||
var h = 0;
|
||
|
||
var i = 0;
|
||
var j = 0;
|
||
|
||
var k = 0;
|
||
|
||
// You mentioned this changed: l is now equal total battery power
|
||
var l = status.BatteryKabinet1.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?.ActivePowerSetPercent.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 = 0.0;
|
||
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 =0.0;
|
||
|
||
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.BatteryKabinet1;
|
||
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.Devices
|
||
.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(BatteryDeligreenRecord battery, int idx)
|
||
{
|
||
// Minimal “K-style” battery box matching your diagram fields
|
||
var data = battery.BatteryDeligreenDataRecord;
|
||
|
||
// 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 = data.BusVoltage.ToDisplayString();
|
||
var soc = data.Soc.ToDisplayString();
|
||
var current = data.BusCurrent.ToDisplayString();
|
||
var temp = data.TemperaturesList.PowerTemperature.ToDisplayString();
|
||
|
||
// If you have a better “pack current” field, replace this line.
|
||
// Keeping it as a separate line to mimic the picture’s extra current-like line.
|
||
var extraCurrent = data.BusCurrent.ToDisplayString();
|
||
|
||
return TextBlock
|
||
.AlignLeft(
|
||
voltage,
|
||
soc,
|
||
current,
|
||
temp,
|
||
extraCurrent
|
||
)
|
||
.TitleBox($"Battery K{idx + 1}");
|
||
}
|
||
}
|