From 91da191874675278e5fff24282aa248d430e5db9 Mon Sep 17 00:00:00 2001 From: atef Date: Mon, 18 Dec 2023 16:53:19 +0100 Subject: [PATCH] Add ControlPvPower function. --- csharp/App/SaliMax/src/Program.cs | 513 ++++++++++++++++-------------- 1 file changed, 273 insertions(+), 240 deletions(-) diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index 763390bbb..5151ba247 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -1,3 +1,6 @@ +#undef Amax +#undef GridLimit + using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using Flurl.Http; @@ -21,6 +24,8 @@ using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Utils; using InnovEnergy.App.SaliMax.AggregationService; using InnovEnergy.App.SaliMax.DataTypes; +using static InnovEnergy.App.SaliMax.AggregationService.Aggregator; +using static InnovEnergy.App.SaliMax.MiddlewareClasses.MiddlewareAgent; using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig; using DeviceState = InnovEnergy.App.SaliMax.Devices.DeviceState; @@ -45,44 +50,51 @@ internal static class Program private static readonly Channel RelaysChannel; private static readonly Channel BatteriesChannel; - private const String VpnServerIp = "10.2.0.11"; - private static Boolean _subscribedToQueue = false; - private static Boolean _subscribeToQueueForTheFirstTime = false; - private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green; - private static Int32 _heartBitInterval = 0; - + private const String VpnServerIp = "10.2.0.11"; + private static Boolean _subscribedToQueue = false; + private static Boolean _subscribeToQueueForTheFirstTime = false; + private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green; + private static Int32 _heartBitInterval = 0; + static Program() { var config = Config.Load(); var d = config.Devices; - Channel CreateChannel(SalimaxDevice device) => device.DeviceState == DeviceState.Disabled - ? new NullChannel() - : new TcpChannel(device); + Channel CreateChannel(SalimaxDevice device) => device.DeviceState == DeviceState.Disabled + ? new NullChannel() + : new TcpChannel(device); - TruConvertAcChannel = CreateChannel(d.TruConvertAcIp); - TruConvertDcChannel = CreateChannel(d.TruConvertDcIp); - GridMeterChannel = CreateChannel(d.GridMeterIp); + TruConvertAcChannel = CreateChannel(d.TruConvertAcIp); + TruConvertDcChannel = CreateChannel(d.TruConvertDcIp); + GridMeterChannel = CreateChannel(d.GridMeterIp); IslandBusLoadChannel = CreateChannel(d.IslandBusLoadMeterIp); - PvOnDc = CreateChannel(d.PvOnDc); - PvOnAcGrid = CreateChannel(d.PvOnAcGrid); - PvOnAcIsland = CreateChannel(d.PvOnAcIsland); - RelaysChannel = CreateChannel(d.RelaysIp); - BatteriesChannel = CreateChannel(d.BatteryIp); - - BatteryNodes = config - .Devices - .BatteryNodes - .Select(n => n.ConvertTo()) - .ToArray(config.Devices.BatteryNodes.Length); + PvOnDc = CreateChannel(d.PvOnDc); + PvOnAcGrid = CreateChannel(d.PvOnAcGrid); + PvOnAcIsland = CreateChannel(d.PvOnAcIsland); + RelaysChannel = CreateChannel(d.RelaysIp); + BatteriesChannel = CreateChannel(d.BatteryIp); + + BatteryNodes = config + .Devices + .BatteryNodes + .Select(n => n.ConvertTo()) + .ToArray(config.Devices.BatteryNodes.Length); } public static async Task Main(String[] args) { //Do not await - Aggregator.HourlyDataAggregationManager().ContinueWith(t => t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning(); - Aggregator.DailyDataAggregationManager().ContinueWith(t => t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning(); - MiddlewareAgent.InitializeCommunicationToMiddleware(); + HourlyDataAggregationManager() + .ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted) + .SupressAwaitWarning(); + + DailyDataAggregationManager() + .ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted) + .SupressAwaitWarning(); + + InitializeCommunicationToMiddleware(); + while (true) { try @@ -92,7 +104,7 @@ internal static class Program catch (Exception e) { e.LogError(); - } + } } } @@ -104,68 +116,68 @@ internal static class Program Watchdog.NotifyReady(); var battery48TlDevices = BatteryNodes - .Select(n => new Battery48TlDevice(BatteriesChannel, n)) - .ToList(); - - var batteryDevices = new Battery48TlDevices(battery48TlDevices); - var acDcDevices = new TruConvertAcDcDevices(TruConvertAcChannel); - var dcDcDevices = new TruConvertDcDcDevices(TruConvertDcChannel); - var gridMeterDevice = new EmuMeterDevice(GridMeterChannel); - var acIslandLoadMeter = new EmuMeterDevice(IslandBusLoadChannel); - var pvOnDcDevice = new AmptDevices(PvOnDc); - var pvOnAcGridDevice = new AmptDevices(PvOnAcGrid); - var pvOnAcIslandDevice = new AmptDevices(PvOnAcIsland); + .Select(n => new Battery48TlDevice(BatteriesChannel, n)) + .ToList(); + + var batteryDevices = new Battery48TlDevices(battery48TlDevices); + var acDcDevices = new TruConvertAcDcDevices(TruConvertAcChannel); + var dcDcDevices = new TruConvertDcDcDevices(TruConvertDcChannel); + var gridMeterDevice = new EmuMeterDevice(GridMeterChannel); + var acIslandLoadMeter = new EmuMeterDevice(IslandBusLoadChannel); + var pvOnDcDevice = new AmptDevices(PvOnDc); + var pvOnAcGridDevice = new AmptDevices(PvOnAcGrid); + var pvOnAcIslandDevice = new AmptDevices(PvOnAcIsland); var saliMaxRelaysDevice = new RelaysDevice(RelaysChannel); StatusRecord ReadStatus() { - var config = Config.Load(); - var devices = config.Devices; - var acDc = acDcDevices.Read(); - var dcDc = dcDcDevices.Read(); - var relays = saliMaxRelaysDevice.Read(); - var loadOnAcIsland = acIslandLoadMeter.Read(); - var gridMeter = gridMeterDevice.Read(); - var pvOnDc = pvOnDcDevice.Read(); - var battery = batteryDevices.Read(); + var config = Config.Load(); + var devices = config.Devices; + var acDc = acDcDevices.Read(); + var dcDc = dcDcDevices.Read(); + var relays = saliMaxRelaysDevice.Read(); + var loadOnAcIsland = acIslandLoadMeter.Read(); + var gridMeter = gridMeterDevice.Read(); + var pvOnDc = pvOnDcDevice.Read(); + var battery = batteryDevices.Read(); - var pvOnAcGrid = pvOnAcGridDevice.Read(); - var pvOnAcIsland = pvOnAcIslandDevice.Read(); + var pvOnAcGrid = pvOnAcGridDevice.Read(); + var pvOnAcIsland = pvOnAcIslandDevice.Read(); var gridBusToIslandBus = Topology.CalculateGridBusToIslandBusPower(pvOnAcIsland, loadOnAcIsland, acDc); var gridBusLoad = devices.LoadOnAcGrid.DeviceState == DeviceState.Disabled - ? new AcPowerDevice { Power = 0 } - : Topology.CalculateGridBusLoad(gridMeter, pvOnAcGrid, gridBusToIslandBus); + ? new AcPowerDevice { Power = 0 } + : Topology.CalculateGridBusLoad(gridMeter, pvOnAcGrid, gridBusToIslandBus); var dcLoad = devices.LoadOnDc.DeviceState == DeviceState.Disabled - ? new DcPowerDevice { Power = 0 } - : Topology.CalculateDcLoad(acDc, pvOnDc, dcDc); + ? new DcPowerDevice { Power = 0 } + : Topology.CalculateDcLoad(acDc, pvOnDc, dcDc); - var acDcToDcLink = devices.LoadOnDc.DeviceState == DeviceState.Disabled - ? Topology.CalculateAcDcToDcLink(pvOnDc, dcDc, acDc) - : new DcPowerDevice { Power = acDc.Dc.Power }; + var acDcToDcLink = devices.LoadOnDc.DeviceState == DeviceState.Disabled ? + Topology.CalculateAcDcToDcLink(pvOnDc, dcDc, acDc) + : new DcPowerDevice{ Power = acDc.Dc.Power}; return new StatusRecord { - AcDc = acDc, - DcDc = dcDc, - Battery = battery, - Relays = relays, - GridMeter = gridMeter, - PvOnAcGrid = pvOnAcGrid, - PvOnAcIsland = pvOnAcIsland, - PvOnDc = pvOnDc, + AcDc = acDc, + DcDc = dcDc, + Battery = battery, + Relays = relays, + GridMeter = gridMeter, + PvOnAcGrid = pvOnAcGrid, + PvOnAcIsland = pvOnAcIsland, + PvOnDc = pvOnDc, AcGridToAcIsland = gridBusToIslandBus, - AcDcToDcLink = acDcToDcLink, - LoadOnAcGrid = gridBusLoad, - LoadOnAcIsland = loadOnAcIsland, - LoadOnDc = dcLoad, + AcDcToDcLink = acDcToDcLink, + LoadOnAcGrid = gridBusLoad, + LoadOnAcIsland = loadOnAcIsland, + LoadOnDc = dcLoad, - StateMachine = StateMachine.Default, - EssControl = EssControl.Default, - Log = new SystemLog { SalimaxAlarmState = SalimaxAlarmState.Green, Message = null }, //TODO: Put real stuff - Config = config // load from disk every iteration, so config can be changed while running + StateMachine = StateMachine.Default, + EssControl = EssControl.Default, + Log = new SystemLog { SalimaxAlarmState = SalimaxAlarmState.Green, Message = null }, //TODO: Put real stuff + Config = config // load from disk every iteration, so config can be changed while running }; } @@ -183,11 +195,11 @@ internal static class Program while (true) { await Observable - .Interval(UpdateInterval) - .Select(_ => RunIteration()) - .SelectMany(r => UploadCsv(r, DateTime.Now.Round(UpdateInterval))) - .SelectError() - .ToTask(); + .Interval(UpdateInterval) + .Select(_ => RunIteration()) + .SelectMany(r => UploadCsv(r, DateTime.Now.Round(UpdateInterval))) + .SelectError() + .ToTask(); } @@ -221,7 +233,7 @@ internal static class Program record.CreateTopologyTextBlock().WriteLine(); (record.Relays is null ? "No relay Data available" : record.Relays.FiWarning ? "Alert: Fi Warning Detected" : "No Fi Warning Detected").WriteLine(); - (record.Relays is null ? "No relay Data available" : record.Relays.FiError ? "Alert: Fi Error Detected" : "No Fi Error Detected").WriteLine(); + (record.Relays is null ? "No relay Data available" : record.Relays.FiError ? "Alert: Fi Error Detected" : "No Fi Error Detected") .WriteLine(); //record.ApplyConfigFile(minSoc:22, gridSetPoint:1); @@ -235,7 +247,7 @@ internal static class Program // ReSharper disable once FunctionNeverReturns } - public static void SendSalimaxStateAlarm(StatusMessage currentSalimaxState, StatusRecord record) + private static void SendSalimaxStateAlarm(StatusMessage currentSalimaxState, StatusRecord record) { var s3Bucket = Config.Load().S3?.Bucket; @@ -268,7 +280,7 @@ internal static class Program } //If there is an available message from the RabbitMQ Broker, apply the configuration file - Configuration? config = MiddlewareAgent.SetConfigurationFile(); + Configuration? config = SetConfigurationFile(); if (config != null) { record.ApplyConfigFile(config); @@ -278,10 +290,10 @@ internal static class Program private static StatusMessage GetSalimaxStateAlarm(StatusRecord record) { var alarmCondition = record.DetectAlarmStates(); - var s3Bucket = Config.Load().S3?.Bucket; + var s3Bucket = Config.Load().S3?.Bucket; - var alarmList = new List(); - var warningList = new List(); + var alarmList = new List(); + var warningList = new List(); if (alarmCondition is not null) { @@ -295,162 +307,180 @@ internal static class Program Description = alarmCondition }); } + + foreach (var alarm in record.AcDc.Alarms) + { + alarmList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "AcDc", + Description = alarm.ToString() + }); + } + + foreach (var alarm in record.DcDc.Alarms) + { + alarmList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "DcDc", + Description = alarm.ToString() + }); + } - foreach (var alarm in record.AcDc.Alarms) - { - alarmList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "AcDc", - Description = alarm.ToString() - }); - } + if (record.Battery != null) + { + var i = 0; + + foreach (var battery in record.Battery.Devices) + { + foreach (var alarm in battery.Alarms) + { + alarmList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "Battery node" + record.Config.Devices.BatteryNodes[i], + Description = alarm + }); + i++; + } + } + + } + + foreach (var warning in record.AcDc.Warnings) + { + warningList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "AcDc", + Description = warning.ToString() + }); + } + + foreach (var warning in record.DcDc.Warnings) + { + warningList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "DcDc", + Description = warning.ToString() + }); + } - foreach (var alarm in record.DcDc.Alarms) - { - alarmList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "DcDc", - Description = alarm.ToString() - }); - } + if (record.Battery != null) + { + foreach (var warning in record.Battery.Warnings) + { + warningList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "Battery", + Description = warning + }); + } + } - if (record.Battery != null) - { - var i = 0; + var salimaxAlarmsState = (record.Battery is not null && record.Battery.Warnings.Any()) + | record.AcDc.Warnings.Any() + | record.AcDc.SystemControl.Warnings.Any() + | record.DcDc.Warnings.Any() + ? SalimaxAlarmState.Orange + : SalimaxAlarmState.Green; // this will be replaced by LedState - foreach (var battery in record.Battery.Devices) - { - i++; - foreach (var alarm in battery.Alarms) - { - alarmList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "Battery" + i, - Description = alarm - }); - } - } - } + salimaxAlarmsState = (record.Battery is not null && record.Battery.Alarms.Any()) + | record.AcDc.Alarms.Any() + | record.AcDc.SystemControl.Alarms.Any() + | record.DcDc.Alarms.Any() + | alarmCondition is not null + ? SalimaxAlarmState.Red + : salimaxAlarmsState; // this will be replaced by LedState - foreach (var warning in record.AcDc.Warnings) - { - warningList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "AcDc", - Description = warning.ToString() - }); - } + int.TryParse(s3Bucket?.Split("-")[0], out var installationId); - foreach (var warning in record.DcDc.Warnings) - { - warningList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "DcDc", - Description = warning.ToString() - }); - } + var returnedStatus = new StatusMessage + { + InstallationId = installationId, + Status = salimaxAlarmsState, + Type = MessageType.AlarmOrWarning, + Alarms = alarmList, + Warnings = warningList + }; - if (record.Battery != null) - { - foreach (var warning in record.Battery.Warnings) - { - warningList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "Battery", - Description = warning - }); - } - } - - var salimaxAlarmsState = (record.Battery is not null && record.Battery.Warnings.Any()) - | record.AcDc.Warnings.Any() - | record.AcDc.SystemControl.Warnings.Any() - | record.DcDc.Warnings.Any() - ? SalimaxAlarmState.Orange - : SalimaxAlarmState.Green; // this will be replaced by LedState - - salimaxAlarmsState = (record.Battery is not null && record.Battery.Alarms.Any()) - | record.AcDc.Alarms.Any() - | record.AcDc.SystemControl.Alarms.Any() - | record.DcDc.Alarms.Any() - | alarmCondition is not null - ? SalimaxAlarmState.Red - : salimaxAlarmsState; // this will be replaced by LedState - - int.TryParse(s3Bucket?.Split("-")[0], out var installationId); - - var returnedStatus = new StatusMessage - { - InstallationId = installationId, - Status = salimaxAlarmsState, - Type = MessageType.AlarmOrWarning, - Alarms = alarmList, - Warnings = warningList - }; - - return returnedStatus; + return returnedStatus; } private static String? DetectAlarmStates(this StatusRecord r) => r.Relays switch { { K2ConnectIslandBusToGridBus: false, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: R0 is opening the K2 but the K2 is still close ", { K1GridBusIsConnectedToGrid : false, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: K1 is open but the K2 is still close ", - { FiError: true, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: Fi error occured but the K2 is still close ", - _ => null + { FiError: true, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: Fi error occured but the K2 is still close ", + _ => null }; private static void ControlConstants(this StatusRecord r) { - var inverters = r.AcDc.Devices; - var dcDevices = r.DcDc.Devices; - var configFile = r.Config; + var inverters = r.AcDc.Devices; + var dcDevices = r.DcDc.Devices; + var configFile = r.Config; var devicesConfig = r.AcDc.Devices.All(d => d.Control.Ac.GridType == GridType.GridTied400V50Hz) ? configFile.GridTie : configFile.IslandMode; // TODO if any of the grid tie mode - - inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage); - inverters.ForEach(d => d.Control.Dc.MinVoltage = devicesConfig.AcDc.MinDcLinkVoltage); - inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = devicesConfig.AcDc.ReferenceDcLinkVoltage); - - inverters.ForEach(d => d.Control.Dc.PrechargeConfig = DcPrechargeConfig.PrechargeDcWithInternal); - - dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = devicesConfig.DcDc.UpperDcLinkVoltage); - dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = devicesConfig.DcDc.LowerDcLinkVoltage); - dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = devicesConfig.DcDc.ReferenceDcLinkVoltage); - - dcDevices.ForEach(d => d.Control.CurrentControl.MaxBatteryChargingCurrent = configFile.MaxBatteryChargingCurrent); + + inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.MinVoltage = devicesConfig.AcDc.MinDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = devicesConfig.AcDc.ReferenceDcLinkVoltage); + + inverters.ForEach(d => d.Control.Dc.PrechargeConfig = DcPrechargeConfig.PrechargeDcWithInternal); + + dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = devicesConfig.DcDc.UpperDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = devicesConfig.DcDc.LowerDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = devicesConfig.DcDc.ReferenceDcLinkVoltage); + + dcDevices.ForEach(d => d.Control.CurrentControl.MaxBatteryChargingCurrent = configFile.MaxBatteryChargingCurrent); dcDevices.ForEach(d => d.Control.CurrentControl.MaxBatteryDischargingCurrent = configFile.MaxBatteryDischargingCurrent); - dcDevices.ForEach(d => d.Control.MaxDcPower = configFile.MaxDcPower); + dcDevices.ForEach(d => d.Control.MaxDcPower = configFile.MaxDcPower); - dcDevices.ForEach(d => d.Control.VoltageLimits.MaxBatteryVoltage = configFile.MaxChargeBatteryVoltage); - dcDevices.ForEach(d => d.Control.VoltageLimits.MinBatteryVoltage = configFile.MinDischargeBatteryVoltage); - dcDevices.ForEach(d => d.Control.ControlMode = DcControlMode.VoltageDroop); + dcDevices.ForEach(d => d.Control.VoltageLimits.MaxBatteryVoltage = configFile.MaxChargeBatteryVoltage); + dcDevices.ForEach(d => d.Control.VoltageLimits.MinBatteryVoltage = configFile.MinDischargeBatteryVoltage); + dcDevices.ForEach(d => d.Control.ControlMode = DcControlMode.VoltageDroop); r.DcDc.ResetAlarms(); r.AcDc.ResetAlarms(); } + // This is will be used for + private static void ControlPvPower(this StatusRecord r, Int16 exportLimit = 100) + { + var inverters = r.AcDc.Devices; + var dcDevices = r.DcDc.Devices; + var configFile = r.Config; + + var devicesConfig = configFile.GridTie; + + inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.MinVoltage = devicesConfig.AcDc.MinDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = devicesConfig.AcDc.ReferenceDcLinkVoltage); + + dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = devicesConfig.DcDc.UpperDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = devicesConfig.DcDc.LowerDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = devicesConfig.DcDc.ReferenceDcLinkVoltage); + } // why this is not in Controller? private static void DistributePower(StatusRecord record, EssControl essControl) { var nInverters = record.AcDc.Devices.Count; - + var powerPerInverterPhase = nInverters > 0 - ? essControl.PowerSetpoint / nInverters / 3 - : 0; - + ? essControl.PowerSetpoint / nInverters / 3 + : 0; + record.AcDc.Devices.ForEach(d => { d.Control.Ac.PhaseControl = PhaseControl.Asymmetric; @@ -464,71 +494,74 @@ internal static class Program { if (sc is null) return; + + sc.ReferenceFrame = ReferenceFrame.Consumer; + sc.SystemConfig = AcDcAndDcDc; - sc.ReferenceFrame = ReferenceFrame.Consumer; - sc.SystemConfig = AcDcAndDcDc; - -#if DEBUG - sc.CommunicationTimeout = TimeSpan.FromMinutes(2); -#else - sc.CommunicationTimeout = TimeSpan.FromSeconds(20); -#endif - + #if DEBUG + sc.CommunicationTimeout = TimeSpan.FromMinutes(2); + #else + sc.CommunicationTimeout = TimeSpan.FromSeconds(20); + #endif + sc.PowerSetPointActivation = PowerSetPointActivation.Immediate; sc.UseSlaveIdForAddressing = true; - sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed; - sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off; - - sc.ResetAlarmsAndWarnings = true; + sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed; + sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off; + + sc.ResetAlarmsAndWarnings = true; } - + private static void ApplyDcDcDefaultSettings(this SystemControlRegisters? sc) { + if (sc is null) return; - - sc.SystemConfig = DcDcOnly; -#if DEBUG - sc.CommunicationTimeout = TimeSpan.FromMinutes(2); -#else - sc.CommunicationTimeout = TimeSpan.FromSeconds(20); -#endif - + + sc.SystemConfig = DcDcOnly; + #if DEBUG + sc.CommunicationTimeout = TimeSpan.FromMinutes(2); + #else + sc.CommunicationTimeout = TimeSpan.FromSeconds(20); + #endif + sc.PowerSetPointActivation = PowerSetPointActivation.Immediate; sc.UseSlaveIdForAddressing = true; - sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed; - sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off; - sc.ResetAlarmsAndWarnings = true; + sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed; + sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off; + + sc.ResetAlarmsAndWarnings = true; } private static async Task UploadCsv(StatusRecord status, DateTime timeStamp) { var s3Config = status.Config.S3; - var csv = status.ToCsv().LogInfo(); + var csv = status.ToCsv().LogInfo(); if (s3Config is null) return false; - var s3Path = timeStamp.ToUnixTime() + ".csv"; - var request = s3Config.CreatePutRequest(s3Path); + var s3Path = timeStamp.ToUnixTime() + ".csv"; + var request = s3Config.CreatePutRequest(s3Path); var response = await request.PutAsync(new StringContent(csv)); // This is temporary for Wittman //await File.WriteAllTextAsync("/var/www/html/status.csv", csv.SplitLines().Where(l => !l.Contains("Secret")).JoinLines()); - + if (response.StatusCode != 200) { Console.WriteLine("ERROR: PUT"); var error = await response.GetStringAsync(); Console.WriteLine(error); } - - return true; + + return true; } private static void ApplyConfigFile(this StatusRecord status, Configuration? config) { - status.Config.MinSoc = config.MinimumSoC; - status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W + status.Config.MinSoc = config.MinimumSoC; + status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W status.Config.ForceCalibrationCharge = config.ForceCalibrationCharge; } + } \ No newline at end of file