Break off Topology related stuff into own class

This commit is contained in:
ig 2023-08-16 15:41:13 +02:00
parent 3d3a0375d2
commit 2047f25e4e
2 changed files with 193 additions and 177 deletions

View File

@ -18,7 +18,6 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Control;
using InnovEnergy.Lib.Protocols.Modbus.Channels;
using InnovEnergy.Lib.Time.Unix;
using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Units.Power;
using InnovEnergy.Lib.Utils;
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
using AcPower = InnovEnergy.Lib.Units.Composite.AcPower;
@ -210,7 +209,7 @@ internal static class Program
WriteControl(record);
CreateTopology(record).WriteLine();
Topology.From(record).WriteLine();
//await UploadCsv(record, t);
@ -224,179 +223,7 @@ internal static class Program
// ReSharper disable once FunctionNeverReturns
}
private static TextBlock CreateTopology(StatusRecord s)
{
// Power Measurement Values
var gridPower = s.GridMeter is not null ? s.GridMeter!.Ac.Power.Active : 0;
var ac = s.AcDc.Ac;
var inverterPower = ac.Power.Active;
var islandLoadPower = s.LoadOnAcIsland is not null ? s.LoadOnAcIsland.Ac.Power.Active : 0;
var dcBatteryPower = s.DcDc.Dc.Battery.Power;
var dcdcPower = s.DcDc.Dc.Link.Power;
var pvOnDcPower = s.PvOnDc.Dc!.Power.Value;
// Power Calculated Values
ActivePower islandToGridBusPower = inverterPower + islandLoadPower;
var islandBusData = TextBlock.AlignLeft(ac.L1.Power.Active.ToDisplayString(),
ac.L2.Power.Active.ToDisplayString(),
ac.L3.Power.Active.ToDisplayString());
var dc48Voltage = s.DcDc.Dc.Battery.Voltage.ToDisplayString();
var islandBusPv = 0.W(); // TODO
var islandBusColumn = ColumnBox("Pv" , islandBusPv,
"Island Bus", islandBusData,
"Load" , islandLoadPower);
var dcBusLoad = 0.W(); // TODO
var dcLinkVoltage = s.DcDc.Dc.Link.Voltage.ToDisplayString();
var dcBusColumn = ColumnBox("Pv" , pvOnDcPower,
"Dc Bus", dcLinkVoltage,
"Load" , dcBusLoad);
var inverterAcPhases = s
.AcDc
.Devices
.Select(d => d.Status.Ac.Power)
.ToArray(s.AcDc.Devices.Count)
.AsReadOnlyList();
var inverterBox = TextBlock.AlignLeft(inverterAcPhases).TitleBox("AC/DC");
var dcDcBox = TextBlock.AlignLeft(dc48Voltage) .TitleBox("DC/DC");
var bat = s.Battery;
var batteryAvgBox = CreateAveragedBatteryBox(bat);
var batteryBoxes = bat
.Devices
.Select(CreateIndividualBattery)
.ToArray(bat.Devices.Count)
.AsReadOnlyList();
var individualBatteries = batteryBoxes.Any()
? TextBlock.AlignLeft(batteryBoxes)
: TextBlock.Spacer(1);
var flowIslandBusToInverter = Flow.Horizontal(inverterPower);
var flowInverterToDcBus = Flow.Horizontal(inverterPower);
var flowDcBusToDcDc = Flow.Horizontal(dcdcPower);
var flowDcDcToBattery = Flow.Horizontal(dcBatteryPower);
var islandTopology = TextBlock
.AlignCenterVertical
(
islandBusColumn,
flowIslandBusToInverter,
inverterBox,
flowInverterToDcBus,
dcBusColumn,
flowDcBusToDcDc,
dcDcBox,
flowDcDcToBattery,
batteryAvgBox,
individualBatteries
);
if (s.GridMeter is null)
return islandTopology;
var gridBox = CreateGridBox(s);
var gridToGridBus = Flow.Horizontal(gridPower);
var gridBusColumn = GridBusColumn(s);
var gridBusToIslandBus = Flow.Horizontal(islandToGridBusPower);
return TextBlock
.AlignCenterVertical
(
gridBox,
gridToGridBus,
gridBusColumn,
gridBusToIslandBus,
islandTopology
);
}
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 alarms = bat.Alarms.Count + " Alarms";
var warnings = bat.Warnings.Count + " Warnings";
return TextBlock
.AlignLeft
(
batteryVoltage,
batterySoc,
batteryCurrent,
batteryTemp,
batteryHeatingCurrent,
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
var ac = s.GridMeter!.Ac;
var gridVoltageByPhase = TextBlock.AlignLeft(ac.L1.Voltage.ToDisplayString(),
ac.L2.Voltage.ToDisplayString(),
ac.L3.Voltage.ToDisplayString());
return ColumnBox("Pv", 0, "Grid Bus", gridVoltageByPhase, "Load", gridLoadPower);
}
private static TextBlock CreateGridBox(StatusRecord s)
{
return TextBlock.AlignLeft(s.GridMeter!.Ac.L1.Power.Active.ToDisplayString(),
s.GridMeter!.Ac.L2.Power.Active.ToDisplayString(),
s.GridMeter!.Ac.L3.Power.Active.ToDisplayString())
.TitleBox("Grid");
}
private static TextBlock CreateIndividualBattery(Battery48TlRecord battery, Int32 i)
{
var batteryWarnings = battery.Warnings.Any();
var batteryAlarms = battery.Alarms.Any();
var content = TextBlock.AlignLeft(battery.Dc.Voltage.ToDisplayString(),
battery.Soc.ToDisplayString(),
battery.Dc.Current.ToDisplayString() + " C/D",
battery.Temperatures.Cells.Average.ToDisplayString(),
battery.BusCurrent.ToDisplayString() + " T",
batteryWarnings,
batteryAlarms,
battery.HeatingCurrent.ToDisplayString()+ " H");
var box = content.TitleBox($"Battery {i + 1}");
var flow = Flow.Horizontal(battery.Dc.Power);
return TextBlock.AlignCenterVertical(flow, box);
}
private static TextBlock ColumnBox(String pvTitle , ActivePower pvPower,
String busTitle , Object busData,
String loadTitle, ActivePower loadPower)
{
var pvBox = TextBlock.FromString(pvTitle).Box();
var pvToBus = Flow.Vertical(pvPower);
var busBox = TextBlock.AlignLeft(busData).TitleBox(busTitle);
var busToLoad = Flow.Vertical(loadPower);
var loadBox = TextBlock.FromString(loadTitle).Box();
return TextBlock.AlignCenterHorizontal(pvBox, pvToBus, busBox, busToLoad, loadBox);
}
private static async Task<T?> ResultOrNull<T>(this Task<T> task)
{
@ -514,4 +341,3 @@ internal static class Program
return true;
}
}

View File

@ -0,0 +1,190 @@
using System.Diagnostics.CodeAnalysis;
using InnovEnergy.App.SaliMax.Ess;
using InnovEnergy.Lib.Devices.Battery48TL;
using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Units.Power;
using InnovEnergy.Lib.Utils;
using Ac3Bus = InnovEnergy.Lib.Units.Composite.Ac3Bus;
namespace InnovEnergy.App.SaliMax;
public static class Topology
{
public static TextBlock From(this StatusRecord s)
{
// Power Measurement Values
var inverterPower = s.AcDc.Ac.Power.Active;
var islandLoadPower = s.LoadOnAcIsland is not null ? s.LoadOnAcIsland.Ac.Power.Active : 0;
var dcBatteryPower = s.DcDc.Dc.Battery.Power;
var dcdcPower = s.DcDc.Dc.Link.Power;
// Power Calculated Values
ActivePower islandToGridBusPower = inverterPower + islandLoadPower;
var islandBusPv = 0.W(); // TODO
var islandBusColumn = ColumnBox("Pv" , islandBusPv,
"Island Bus", s.AcDc.Ac.PhasePowersActive(),
"Load" , islandLoadPower);
var dcBusLoad = 0.W(); // TODO
var dcLinkVoltage = s.DcDc.Dc.Link.Voltage.ToDisplayString();
var pvOnDcPower = s.PvOnDc.Dc!.Power; // TODO !
var dcBusColumn = ColumnBox("Pv" , pvOnDcPower,
"Dc Bus", dcLinkVoltage,
"Load" , dcBusLoad);
var inverterAcPhases = s
.AcDc
.Devices
.Select(d => d.Status.Ac.Power)
.ToArray(s.AcDc.Devices.Count)
.AsReadOnlyList();
var inverterBox = TextBlock.AlignLeft(inverterAcPhases).TitleBox("AC/DC");
var dc48Voltage = s.DcDc.Dc.Battery.Voltage.ToDisplayString();
var dcDcBox = TextBlock.AlignLeft(dc48Voltage) .TitleBox("DC/DC");
var bat = s.Battery;
var batteryAvgBox = CreateAveragedBatteryBox(bat);
var batteryBoxes = bat
.Devices
.Select(CreateIndividualBattery)
.ToArray(bat.Devices.Count)
.AsReadOnlyList();
var individualBatteries = batteryBoxes.Any()
? TextBlock.AlignLeft(batteryBoxes)
: TextBlock.Empty;
var islandTopology = TextBlock
.AlignCenterVertical
(
islandBusColumn, Flow.Horizontal(inverterPower),
inverterBox , Flow.Horizontal(inverterPower),
dcBusColumn , Flow.Horizontal(dcdcPower),
dcDcBox , Flow.Horizontal(dcBatteryPower),
batteryAvgBox,
individualBatteries
);
if (s.GridMeter is null)
return islandTopology;
var gridMeterAc = s.GridMeter.Ac;
var gridBox = gridMeterAc.PhasePowersActive().TitleBox("Grid");
var gridToGridBus = Flow.Horizontal(gridMeterAc.Power.Active);
var gridBusColumn = GridBusColumn(s);
var gridBusToIslandBus = Flow.Horizontal(islandToGridBusPower);
return TextBlock
.AlignCenterVertical
(
gridBox,
gridToGridBus,
gridBusColumn,
gridBusToIslandBus,
islandTopology
);
}
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 alarms = bat.Alarms.Count + " Alarms";
var warnings = bat.Warnings.Count + " Warnings";
return TextBlock
.AlignLeft
(
batteryVoltage,
batterySoc,
batteryCurrent,
batteryTemp,
batteryHeatingCurrent,
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
(
ac.L1.Voltage.ToDisplayString(),
ac.L2.Voltage.ToDisplayString(),
ac.L3.Voltage.ToDisplayString()
);
}
private static TextBlock PhasePowersActive(this Ac3Bus ac)
{
return TextBlock.AlignLeft
(
ac.L1.Power.Active.ToDisplayString(),
ac.L2.Power.Active.ToDisplayString(),
ac.L3.Power.Active.ToDisplayString()
);
}
private static TextBlock CreateIndividualBattery(Battery48TlRecord battery, Int32 i)
{
var batteryWarnings = battery.Warnings.Any();
var batteryAlarms = battery.Alarms.Any();
var content = TextBlock.AlignLeft
(
battery.Dc.Voltage.ToDisplayString(),
battery.Soc.ToDisplayString(),
battery.Dc.Current.ToDisplayString() + " C/D",
battery.Temperatures.Cells.Average.ToDisplayString(),
battery.BusCurrent.ToDisplayString() + " T",
batteryWarnings,
batteryAlarms,
battery.HeatingCurrent.ToDisplayString() + " H"
);
var box = content.TitleBox($"Battery {i + 1}");
var flow = Flow.Horizontal(battery.Dc.Power);
return TextBlock.AlignCenterVertical(flow, box);
}
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")]
private static TextBlock ColumnBox(String pvTitle , ActivePower pvPower,
String busTitle , Object busData,
String loadTitle, ActivePower loadPower)
{
var pvBox = TextBlock.FromString(pvTitle).Box();
var pvToBus = Flow.Vertical(pvPower);
var busBox = TextBlock.AlignLeft(busData).TitleBox(busTitle);
var busToLoad = Flow.Vertical(loadPower);
var loadBox = TextBlock.FromString(loadTitle).Box();
return TextBlock.AlignCenterHorizontal(pvBox, pvToBus, busBox, busToLoad, loadBox);
}
}