From ba44fdcfa0f250c9d740bb66792960eac26dd362 Mon Sep 17 00:00:00 2001 From: atef Date: Tue, 20 Feb 2024 17:44:44 +0100 Subject: [PATCH] Fix naming,Comment debug lines, Update discharging current depends on string status instead of battery states. Update ControlPV Power --- csharp/App/SaliMax/src/Program.cs | 134 ++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 44 deletions(-) diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index 48e88f6ae..24926ae3a 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -209,22 +209,35 @@ internal static class Program var record = ReadStatus(); - /******************************************** For Debug Display *************************************/ + /******************************************** For Battery Debug *************************************/ - //foreach (var batteryNodeRecord in record.Battery.Devices) - //{ - // var strings = batteryNodeRecord.BatteryStrings; - // batteryNodeRecord.FwVersion.WriteLine(" FwVersion "); - // var stringsString1Active = strings.String1Active; - // stringsString1Active.WriteLine(" BatteryString1"); - // strings.String2Active.WriteLine(" BatteryString2"); - // strings.String3Active.WriteLine(" BatteryString3"); - // strings.String4Active.WriteLine(" BatteryString4"); - // strings.String5Active.WriteLine(" BatteryString5"); - // - // ("********************************************************").WriteLine(); - //} + // foreach (var batteryNodeRecord in record.Battery.Devices) + // { + // var ioStates = batteryNodeRecord.IoStates; + + // batteryNodeRecord.FwVersion.WriteLine(" FwVersion "); + // batteryNodeRecord.IoStatus.ConnectedToDcBus.WriteLine(" ConnectedToDcBus"); + // batteryNodeRecord.IoStatus.AlarmOutActive.WriteLine(" AlarmOutActive"); + // batteryNodeRecord.IoStatus.InternalFanActive.WriteLine(" InternalFanActive"); + // batteryNodeRecord.IoStatus.VoltMeasurementAllowed.WriteLine(" VoltMeasurementAllowed"); + // batteryNodeRecord.IoStatus.AuxRelayBus.WriteLine(" AuxRelayBus"); + // batteryNodeRecord.IoStatus.RemoteStateActive.WriteLine(" RemoteStateActive"); + // batteryNodeRecord.IoStatus.RiscActive.WriteLine(" RiscActive"); + + + // Convert.ToString(ioStates, 2).PadLeft(16, '0').WriteLine($" IoStates Battery node "); + + // batteryNodeRecord.TimeSinceTOC.WriteLine(" TOC"); + // batteryNodeRecord.Eoc.WriteLine(" EOC"); + //strings.String1Active.WriteLine(" BatteryString1"); + //strings.String2Active.WriteLine(" BatteryString2"); + //strings.String3Active.WriteLine(" BatteryString3"); + //strings.String4Active.WriteLine(" BatteryString4"); + //strings.String5Active.WriteLine(" BatteryString5"); + + // ("********************************************************").WriteLine(); + // } //record.GridMeter?.ActivePowerExportT1.WriteLine("kWh Export 5910"); //record.GridMeter?.ActivePowerImportT1.WriteLine("kWh Import 5902"); @@ -276,7 +289,7 @@ internal static class Program private static void SendSalimaxStateAlarm(StatusMessage currentSalimaxState, StatusRecord record) { var s3Bucket = Config.Load().S3?.Bucket; - var subsribedNow = false; + var subscribedNow = false; //Every 15 iterations(30 seconds), the installation sends a heartbit message to the queue _heartBitInterval++; @@ -284,13 +297,13 @@ internal static class Program //When the controller boots, it tries to subscribe to the queue if (_subscribeToQueueForTheFirstTime == false) { - subsribedNow = true; + subscribedNow = true; _subscribeToQueueForTheFirstTime = true; _subscribedToQueue = RabbitMqManager.SubscribeToQueue(currentSalimaxState, s3Bucket, VpnServerIp); } //If already subscribed to the queue and the status has been changed, update the queue - if (!subsribedNow && _subscribedToQueue && currentSalimaxState.Status != _prevSalimaxState) + if (!subscribedNow && _subscribedToQueue && currentSalimaxState.Status != _prevSalimaxState) { _prevSalimaxState = currentSalimaxState.Status; if (s3Bucket != null) @@ -416,20 +429,20 @@ internal static class Program } } - 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 + 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 + 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); @@ -461,13 +474,40 @@ internal static class Program var maxBatteryDischargingCurrentLive = 0.0; - // This adapting the max discharging current to the current connected batteries + // This adapting the max discharging current to the current connected batteries // Connected to Dc Bus is not reliable yet + // if (r.Battery != null) + // { + // var numberOfBatteries = r.Battery.Devices.Count;; + // var dischargingCurrentByBattery = configFile.MaxBatteryDischargingCurrent / numberOfBatteries; + // var numberOfConnectedBatteries = r.Battery.Devices.Where(d => d.IoStatus.ConnectedToDcBus).ToList().Count; + // maxBatteryDischargingCurrentLive = dischargingCurrentByBattery * numberOfConnectedBatteries; + // } + + // This adapting the max discharging current to the current Active Strings if (r.Battery != null) { - var numberOfBatteries = configFile.Devices.BatteryNodes.Length; - var dischargingCurrentByBattery = configFile.MaxBatteryDischargingCurrent / numberOfBatteries; - var numberOfConnectedBatteries = r.Battery.Devices.Where(d => d.IoStatus.ConnectedToDcBus).ToList().Count; - maxBatteryDischargingCurrentLive = dischargingCurrentByBattery * numberOfConnectedBatteries; + const Int32 stringsByBattery = 5; + var numberOfBatteries = r.Battery.Devices.Count; + var numberOfTotalStrings = stringsByBattery * numberOfBatteries; + var dischargingCurrentByString = (configFile.MaxBatteryDischargingCurrent / configFile.Devices.BatteryNodes.Length) / stringsByBattery; + + var boolList = new List(); + + foreach (var stringActive in r.Battery.Devices.Select(b => b.BatteryStrings).ToList()) + { + boolList.Add(stringActive.String1Active); + boolList.Add(stringActive.String2Active); + boolList.Add(stringActive.String3Active); + boolList.Add(stringActive.String4Active); + boolList.Add(stringActive.String5Active); + } + + var numberOfBatteriesStringActive = boolList.Count(_ => true); + + if (numberOfTotalStrings != 0) + { + maxBatteryDischargingCurrentLive = dischargingCurrentByString * numberOfBatteriesStringActive / numberOfTotalStrings; + } } @@ -484,7 +524,7 @@ internal static class Program 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 = maxBatteryDischargingCurrentLive == 0? configFile.MaxBatteryDischargingCurrent : maxBatteryDischargingCurrentLive); + dcDevices.ForEach(d => d.Control.CurrentControl.MaxBatteryDischargingCurrent = maxBatteryDischargingCurrentLive); dcDevices.ForEach(d => d.Control.MaxDcPower = configFile.MaxDcPower); dcDevices.ForEach(d => d.Control.VoltageLimits.MaxBatteryVoltage = configFile.MaxChargeBatteryVoltage); @@ -498,19 +538,25 @@ internal static class Program // This is will be used for provider throttling private static void ControlPvPower(this StatusRecord r, Int16 exportLimit = 100) { + + // 950 V = 0% + // 750 V = 100% + + const Int32 maxDcLinkVoltage = 950; + const Int32 minDcLinkVoltage = 850; // we may dont need this two; + const Int32 referenceDcLinkVoltage = 900; // we may dont need this two; + 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); + inverters.ForEach(d => d.Control.Dc.MaxVoltage = maxDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.MinVoltage = minDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = 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); + dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = maxDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = minDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = referenceDcLinkVoltage); } // why this is not in Controller?