Break off Topology related stuff into own class
This commit is contained in:
parent
3d3a0375d2
commit
2047f25e4e
|
@ -18,7 +18,6 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Control;
|
||||||
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
||||||
using InnovEnergy.Lib.Time.Unix;
|
using InnovEnergy.Lib.Time.Unix;
|
||||||
using InnovEnergy.Lib.Units;
|
using InnovEnergy.Lib.Units;
|
||||||
using InnovEnergy.Lib.Units.Power;
|
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
|
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
|
||||||
using AcPower = InnovEnergy.Lib.Units.Composite.AcPower;
|
using AcPower = InnovEnergy.Lib.Units.Composite.AcPower;
|
||||||
|
@ -210,7 +209,7 @@ internal static class Program
|
||||||
|
|
||||||
WriteControl(record);
|
WriteControl(record);
|
||||||
|
|
||||||
CreateTopology(record).WriteLine();
|
Topology.From(record).WriteLine();
|
||||||
|
|
||||||
//await UploadCsv(record, t);
|
//await UploadCsv(record, t);
|
||||||
|
|
||||||
|
@ -224,179 +223,7 @@ internal static class Program
|
||||||
// ReSharper disable once FunctionNeverReturns
|
// 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)
|
private static async Task<T?> ResultOrNull<T>(this Task<T> task)
|
||||||
{
|
{
|
||||||
|
@ -513,5 +340,4 @@ internal static class Program
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue