diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index 833f2f21d..c514988b0 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -212,12 +212,12 @@ internal static class Program /******************************************** For Battery Debug *************************************/ - // foreach (var batteryNodeRecord in record.Battery.Devices) - // { - // var ioStates = batteryNodeRecord.IoStates; - - // batteryNodeRecord.FwVersion.WriteLine(" FwVersion "); - // batteryNodeRecord.IoStatus.ConnectedToDcBus.WriteLine(" ConnectedToDcBus"); + //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"); @@ -236,49 +236,49 @@ internal static class Program //strings.String4Active.WriteLine(" BatteryString4"); //strings.String5Active.WriteLine(" BatteryString5"); - // ("********************************************************").WriteLine(); - // } + // ("********************************************************").WriteLine(); + //} - //record.GridMeter?.ActivePowerExportT1.WriteLine("kWh Export 5910"); - //record.GridMeter?.ActivePowerImportT1.WriteLine("kWh Import 5902"); - //record.GridMeter?.ActivePowerExportT2.WriteLine("Wh Export 6008"); - //record.GridMeter?.ActivePowerImportT2.WriteLine("Wh Import 6028"); - //record.GridMeter?.ActivePowerExportT3.WriteLine("Kwh Import 8004"); - //record.GridMeter?.ActivePowerImportT3.WriteLine("kWh Export 8014"); - //record.GridMeter?.ActivePowerExportT4.WriteLine("port 5906"); - //record.GridMeter?.ActivePowerImportT4.WriteLine("port 5914"); + //record.GridMeter?.ActivePowerImportT1.WriteLine("kWh Export 6004"); + //record.GridMeter?.ActivePowerExportT1.WriteLine("kWh Import 6024"); + //record.GridMeter?.ActivePowerImportT2.WriteLine("Wh Import 6008"); + //record.GridMeter?.ActivePowerExportT2.WriteLine("Wh Export 6028"); + //record.GridMeter?.ActivePowerExportT3.WriteLine("KWh Export 8012"); + //record.GridMeter?.ActivePowerImportT3.WriteLine("kWh Import 8002"); + //record.GridMeter?.ActivePowerImportT4.WriteLine("Wh Import 8000"); + //record.GridMeter?.ActivePowerExportT4.WriteLine("Wh Export 8010"); - var currentSalimaxState = GetSalimaxStateAlarm(record); + var currentSalimaxState = GetSalimaxStateAlarm(record); - SendSalimaxStateAlarm(currentSalimaxState, record); + SendSalimaxStateAlarm(currentSalimaxState, record); - record.ControlConstants(); - record.ControlSystemState(); + record.ControlConstants(); + record.ControlSystemState(); - var essControl = record.ControlEss().WriteLine().LogInfo(); + var essControl = record.ControlEss().WriteLine().LogInfo(); - record.EssControl = essControl; + record.EssControl = essControl; - record.AcDc.SystemControl.ApplyAcDcDefaultSettings(); - record.DcDc.SystemControl.ApplyDcDcDefaultSettings(); + record.AcDc.SystemControl.ApplyAcDcDefaultSettings(); + record.DcDc.SystemControl.ApplyDcDcDefaultSettings(); - DistributePower(record, essControl); + DistributePower(record, essControl); - WriteControl(record); + WriteControl(record); - $"{DateTime.Now.Round(UpdateInterval).ToUnixTime()} : {record.StateMachine.State}: {record.StateMachine.Message}".WriteLine() - .LogInfo(); + $"{DateTime.Now.Round(UpdateInterval).ToUnixTime()} : {record.StateMachine.State}: {record.StateMachine.Message}".WriteLine() + .LogInfo(); - record.CreateTopologyTextBlock().WriteLine(); + 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.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.Config.Save(); + record.Config.Save(); - "===========================================".LogInfo(); + "===========================================".LogInfo(); - return record; + return record; } // ReSharper disable once FunctionNeverReturns @@ -424,8 +424,10 @@ internal static class Program CreatedBy = "Battery node" + record.Config.Devices.BatteryNodes[i], Description = alarm }); - i++; } + + i++; + } } @@ -452,33 +454,11 @@ internal static class Program }); } - if (record.Battery != null) - { - var i = 0; - 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 node" + record.Config.Devices.BatteryNodes[i], - 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() + var salimaxAlarmsState = warningList.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 + salimaxAlarmsState = alarmList.Any() ? SalimaxAlarmState.Red : salimaxAlarmsState; // this will be replaced by LedState @@ -524,8 +504,8 @@ internal static class Program if (r.Battery != null) { const Int32 stringsByBattery = 5; - var numberOfBatteries = r.Battery.Devices.Count; - var numberOfTotalStrings = stringsByBattery * numberOfBatteries; + var numberOfBatteriesConfigured = r.Config.Devices.BatteryNodes.Length; + var numberOfTotalStrings = stringsByBattery * numberOfBatteriesConfigured; var dischargingCurrentByString = configFile.MaxBatteryDischargingCurrent / numberOfTotalStrings; var boolList = new List(); @@ -539,7 +519,7 @@ internal static class Program boolList.Add(stringActive.String5Active); } - var numberOfBatteriesStringActive = boolList.Count(_ => true); + var numberOfBatteriesStringActive = boolList.Count(b => b); if (numberOfTotalStrings != 0) { @@ -552,7 +532,7 @@ internal static class Program //maxBatteryDischargingCurrentLive.WriteLine(" maxBatteryDischargingCurrentLive"); } - // TODO The discharging current is well calculated but not communicated to live. Need to think about this + // TODO The discharging current is well calculated but not communicated to live. But Written in S3 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 @@ -578,28 +558,31 @@ internal static class Program r.AcDc.ResetAlarms(); } - // This is will be used for provider throttling + // This is will be used for provider throttling, this example is only for either 100% or 0 % 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 = r.AcDc.Devices.All(d => d.Control.Ac.GridType == GridType.GridTied400V50Hz) ? configFile.GridTie : configFile.IslandMode; // TODO if any of the grid tie mode + // 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; + const Int32 minDcLinkVoltage = 850; // we may dont need this; + const Int32 referenceDcLinkVoltage = 900; // we may dont need this; - inverters.ForEach(d => d.Control.Dc.MaxVoltage = maxDcLinkVoltage); - inverters.ForEach(d => d.Control.Dc.MinVoltage = minDcLinkVoltage); - inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = referenceDcLinkVoltage); + + inverters.ForEach(d => d.Control.Dc.MaxVoltage = exportLimit == 100 ? devicesConfig.AcDc.MaxDcLinkVoltage : maxDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.MinVoltage = exportLimit == 100 ? devicesConfig.AcDc.MinDcLinkVoltage : minDcLinkVoltage); + inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = exportLimit == 100 ? devicesConfig.AcDc.ReferenceDcLinkVoltage : 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); + dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = exportLimit == 100 ? devicesConfig.DcDc.UpperDcLinkVoltage : maxDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = exportLimit == 100 ? devicesConfig.DcDc.LowerDcLinkVoltage : minDcLinkVoltage); + dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = exportLimit == 100 ? devicesConfig.DcDc.ReferenceDcLinkVoltage : referenceDcLinkVoltage); } // why this is not in Controller? @@ -687,6 +670,11 @@ internal static class Program return true; } + private static Boolean IsPowerOfTwo(Int32 n) + { + return n > 0 && (n & (n - 1)) == 0; + } + private static void ApplyConfigFile(this StatusRecord status, Configuration? config) { status.Config.MinSoc = config.MinimumSoC;