diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index 46e0f05d8..fe654c6db 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -16,6 +16,7 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; 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; @@ -146,83 +147,6 @@ internal static class Program Config = Config.Load() // load from disk every iteration, so config can be changed while running }; } - - // async Task ReadStatus() - // { - // var acDcTask = Task.Run(() => acDcDevices.Read()); - // var dcDcTask = Task.Run(() => dcDcDevices.Read()); - // var batteryTask = Task.Run(() => batteryDevices.Read()); - // var relaysTask = Task.Run(() => saliMaxRelaysDevice.Read()); - // var loadOnAcIslandTask = Task.Run(() => acIslandLoadMeter.Read()); - // var gridMeterTask = Task.Run(() => gridMeterDevice.Read()); - // var pvOnDcTask = Task.Run(() => amptDevice.Read()); - // - // - // var timeout = Task.Delay(TimeSpan.FromSeconds(4)); - // var whenAll = Task - // .WhenAll - // ( - // acDcTask, - // dcDcTask, - // batteryTask, - // relaysTask, - // loadOnAcIslandTask, - // gridMeterTask, - // pvOnDcTask - // ); - // - // - // await Task.WhenAny(whenAll, timeout); - // - // var acDc = await acDcTask.ResultOrNull() ; - // var dcDc = await dcDcTask.ResultOrNull(); - // var battery = await batteryTask.ResultOrNull(); - // var relays = await relaysTask.ResultOrNull(); - // var loadOnAcIsland = await loadOnAcIslandTask.ResultOrNull(); - // var gridMeter = await gridMeterTask.ResultOrNull(); - // var pvOnDc = await pvOnDcTask.ResultOrNull(); - // - // - // var pvOnAcGrid = AcDevicePower.Null; - // var pvOnAcIsland = AcDevicePower.Null; - // var loadOnAcGrid = pvOnAcGrid.Power + - // pvOnAcIsland.Power + - // (gridMeter is null ? AcPower.Null : gridMeter.Ac.Power) + - // (loadOnAcIsland is null ? AcPower.Null : loadOnAcIsland.Ac.Power); - // - // - // var dcPowers = new[] - // { - // acDc?.Dc.Power.Value, - // pvOnDc?.Dc?.Power.Value, - // dcDc?.Dc.Link.Power.Value - // }; - // - // var loadOnDc = dcPowers.Any(p => p is null) - // ? null - // : new DcDevicePower { Power = dcPowers.Sum(p => p)!} ; - // - // - // return new StatusRecord - // { - // AcDc = acDc ?? AcDcDevicesRecord.Null, - // DcDc = dcDc ?? DcDcDevicesRecord.Null, - // Battery = battery ?? Battery48TlRecords.Null, - // Relays = relays, - // GridMeter = gridMeter, - // - // PvOnAcGrid = pvOnAcGrid, - // PvOnAcIsland = pvOnAcIsland, - // PvOnDc = pvOnDc ?? AmptStatus.Null, - // - // LoadOnAcGrid = new AcDevicePower { Power = -loadOnAcGrid }, - // LoadOnAcIsland = loadOnAcIsland, - // LoadOnDc = loadOnDc, - // - // Config = Config.Load() // load from disk every iteration, so config can be changed while running - // }; - // } - void WriteControl(StatusRecord r) { @@ -246,28 +170,24 @@ internal static class Program var record = ReadStatus(); - var emuMeterRegisters = record.GridMeter; - if (emuMeterRegisters is not null) - { - emuMeterRegisters.Ac.Power.Active.WriteLine("Grid Active"); - emuMeterRegisters.Ac.Power.Reactive.WriteLine("Grid Reactive"); - } - - record.AcDc.ResetAlarms(); - record.DcDc.ResetAlarms(); + PrintTopology(record); + if (record.Relays is not null) + record.Relays.ToCsv().WriteLine(); + + record.ControlConstants(); record.ControlSystemState(); Console.WriteLine($"{record.StateMachine.State}: {record.StateMachine.Message}"); - var essControl = record.ControlEss(); + var essControl = record.ControlEss().WriteLine(); record.EssControl = essControl; - record.AcDc.SystemControl.ApplyDefaultSettings(); - record.DcDc.SystemControl.ApplyDefaultSettings(); + record.AcDc.SystemControl.ApplyDefaultSettingsAc(); + record.DcDc.SystemControl.ApplyDefaultSettingsDc(); DistributePower(record, essControl); @@ -282,6 +202,88 @@ internal static class Program // ReSharper disable once FunctionNeverReturns } + private static void PrintTopology(StatusRecord s) + { + // Power Measurement Values + var gridPower = s.GridMeter!.Ac.Power.Active; + var inverterPower = s.AcDc.Ac.Power.Active; + var islandLoadPower = s.LoadOnAcIsland is null ? 0 : s.LoadOnAcIsland.Ac.Power.Active; + var dcBatteryPower = s.DcDc.Dc.Battery.Power; + var dcdcPower = s.DcDc.Dc.Link.Power; + var pvOnDcPower = s.PvOnDc.Dc!.Power.Value; + + // Power Calculated Values + var islandToGridBusPower = inverterPower + islandLoadPower; + var gridLoadPower = gridPower - islandToGridBusPower; + + var gridPowerByPhase = s.GridMeter.Ac.L1.Power.Active.ToString()+ "," + s.GridMeter.Ac.L2.Power.Active + s.GridMeter.Ac.L3.Power.Active; + //var inverterPowerByPhase = new ActivePower[(Int32)s.AcDc.Ac.L1.Power.Active, (Int32)s.AcDc.Ac.L2.Power.Active, (Int32)s.AcDc.Ac.L3.Power.Active]; + + // Voltage Measurement Values + //var inverterVoltage = new Voltage [(Int32)s.AcDc.Ac.L1.Voltage, (Int32)s.AcDc.Ac.L2.Voltage, (Int32)s.AcDc.Ac.L3.Voltage]; + //var dcLinkVoltage = s.DcDc.Dc.Link.Voltage; + var dc48Voltage = s.DcDc.Dc.Battery.Voltage; + var batteryVoltage = s.Battery.Dc.Voltage; + var batterySoc = s.Battery.Soc; + var batteryCurrent = s.Battery.Dc.Current; + var batteryTemp = s.Battery.Temperature; + + gridPowerByPhase.Split(","); + var gridBusColumn = ColumnBox("Pv", "Grid Bus", "Load" , "Voltage", gridLoadPower); + var islandBusColumn = ColumnBox("Pv", "Island Bus", "Load" , "Voltage", islandLoadPower); + var dcBusColumn = ColumnBox("Pv", "Dc Bus", "Load" , "DC Link V", 0, pvOnDcPower); + var gridBusFlow = Flow.Horizontal(gridPower); + var flowGridBusToIslandBus = Flow.Horizontal((ActivePower)islandToGridBusPower); + var flowIslandBusToInverter = Flow.Horizontal(inverterPower); + var flowInverterToDcBus = Flow.Horizontal(inverterPower); + var flowDcBusToDcDc = Flow.Horizontal(-dcdcPower); + var flowDcDcToBattery = Flow.Horizontal(-dcBatteryPower); + + var gridBox = TextBlock.AlignLeft("none","none", "none").TitleBox("Grid"); + var inverterBox = TextBlock.AlignLeft("none","none", "none").TitleBox("Inverter"); + var dcDcBox = TextBlock.AlignLeft(dc48Voltage).TitleBox("DC/DC"); + var batteryBox = TextBlock.AlignLeft(batteryVoltage, batterySoc, batteryCurrent, batteryTemp).TitleBox("Battery"); + + + + var totalBoxes = TextBlock.CenterVertical(gridBox, + gridBusFlow, + gridBusColumn, + flowGridBusToIslandBus, + islandBusColumn, + flowIslandBusToInverter, + inverterBox, + flowInverterToDcBus, + dcBusColumn, + flowDcBusToDcDc, + dcDcBox, + flowDcDcToBattery, + batteryBox); + + totalBoxes.WriteLine(); + } + + private static TextBlock ColumnBox(String pvTitle, String busTitle, String loadTitle, String dataBox) + { + return ColumnBox(pvTitle, busTitle, loadTitle, dataBox, 0); + } + + private static TextBlock ColumnBox(String pvTitle, String busTitle, String loadTitle, String dataBox, ActivePower loadPower) + { + return ColumnBox(pvTitle, busTitle, loadTitle, dataBox, loadPower, 0); + } + + private static TextBlock ColumnBox(String pvTitle, String busTitle, String loadTitle, String dataBox, ActivePower loadPower, ActivePower pvPower) + { + var pvBox = TextBlock.AlignLeft("").TitleBox(pvTitle); + var pvToBus = Flow.Vertical(pvPower); + var busBox = TextBlock.AlignLeft(dataBox).TitleBox(busTitle); + var busToLoad = Flow.Vertical(loadPower); + var loadBox = TextBlock.AlignLeft("").TitleBox(loadTitle); + + return TextBlock.CenterHorizontal(pvBox, pvToBus, busBox, busToLoad, loadBox); + } + private static async Task ResultOrNull(this Task task) { if (task.Status == TaskStatus.RanToCompletion) @@ -294,12 +296,13 @@ internal static class Program { var inverters = r.AcDc.Devices; - inverters.ForEach(d => d.Control.Dc.MaxVoltage = r.Config.MaxDcBusVoltage); - inverters.ForEach(d => d.Control.Dc.MinVoltage = r.Config.MinDcBusVoltage); + inverters.ForEach(d => d.Control.Dc.MaxVoltage = r.Config.MaxDcBusVoltage); + inverters.ForEach(d => d.Control.Dc.MinVoltage = r.Config.MinDcBusVoltage); inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = r.Config.ReferenceDcBusVoltage); } + // why this is not in Controller? private static void DistributePower(StatusRecord record, EssControl essControl) { var nInverters = record.AcDc.Devices.Count;