diff --git a/csharp/App/GrowattCommunication/Program.cs b/csharp/App/GrowattCommunication/Program.cs index c9c7f6214..2b6692711 100644 --- a/csharp/App/GrowattCommunication/Program.cs +++ b/csharp/App/GrowattCommunication/Program.cs @@ -1,26 +1,32 @@ -using System.IO.Compression; -using InnovEnergy.Lib.Devices.WITGrowatt4_15K; +using System.Diagnostics; +using System.IO.Compression; using System.IO.Ports; using System.Text; using System.Text.Json; -using System.Xml; + using Flurl.Http; + +using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; + +using InnovEnergy.Lib.Devices.WITGrowatt4_15K; using InnovEnergy.App.GrowattCommunication.DataLogging; using InnovEnergy.App.GrowattCommunication.ESS; using InnovEnergy.App.GrowattCommunication.MiddlewareClasses; using InnovEnergy.App.GrowattCommunication.SystemConfig; using InnovEnergy.Lib.Protocols.Modbus.Channels; +using InnovEnergy.App.GrowattCommunication.DataTypes; + using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Utils; + using Newtonsoft.Json; using Formatting = Newtonsoft.Json.Formatting; using JsonSerializer = System.Text.Json.JsonSerializer; -using System.Diagnostics.CodeAnalysis; -using System.Reactive.Linq; -using System.Reactive.Threading.Tasks; -using InnovEnergy.App.GrowattCommunication.DataTypes; using InnovEnergy.Lib.Devices.WITGrowatt4_15K.DataType; using static InnovEnergy.App.GrowattCommunication.MiddlewareClasses.MiddlewareAgent; +using System.Diagnostics.CodeAnalysis; +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. namespace InnovEnergy.App.GrowattCommunication; @@ -69,7 +75,7 @@ public static class Program e.LogError(); } } - + // ReSharper disable once FunctionNeverReturns } [RequiresUnreferencedCode("Calls InnovEnergy.App.GrowattCommunication.Program.SaveModbusTcpFile(StatusRecord)")] @@ -124,16 +130,18 @@ public static class Program SendSalimaxStateAlarm(GetSodiHomeStateAlarm(statusrecord),statusrecord); //await DataLogging(statusrecord, timestamp); // save a csv file locally - //await SaveModbusTcpFile(statusrecord); // save the json file for modbuscTCP - + //await SaveModbusTcpFile(statusrecord); // save the JSON file for modbuscTCP + + Debug.Assert(statusrecord != null, nameof(statusrecord) + " != null"); statusrecord.AcDcGrowatt.RemotePowerControl.WriteLine(" = RemotePowerControl"); + statusrecord.AcDcGrowatt.EnableEmsCommunicationFailureTime.WriteLine(" = EnableEmsCommunicationFailureTime"); statusrecord.AcDcGrowatt.EnableCommand.WriteLine(" = EnableCommand"); - statusrecord.AcDcGrowatt.ControlPermession.WriteLine(" ControlPermession"); + statusrecord.AcDcGrowatt.ControlPermession.WriteLine(" = ControlPermession"); statusrecord.AcDcGrowatt.MeterPower.WriteLine(" MeterPower"); - statusrecord.AcDcGrowatt.GridMeterPower.WriteLine(" GridMeterPower"); - var x = CalculateActivePower(statusrecord); - x.WriteLine(" Calculated Grid Power"); + statusrecord.AcDcGrowatt.ConsumptionPower.WriteLine(" ConsumptionPower"); + statusrecord.AcDcGrowatt.ExportedPowerToGridMeter.WriteLine(" ExportedPowerToGrid"); + statusrecord.AcDcGrowatt.ImportedPowerFromGrid.WriteLine(" ImportedPowerFromGrid"); statusrecord.AcDcGrowatt.InverterActivePower.WriteLine(" InverterActivePower"); statusrecord.AcDcGrowatt.BatteryChargeCutoffVoltage.WriteLine(" BatteryChargeCutoffVoltage "); //30409 we set power here statusrecord.AcDcGrowatt.BatteryDischargeCutoffVoltage.WriteLine(" BatteryDishargeCutoffVoltage "); //30409 we set power here @@ -144,7 +152,11 @@ public static class Program statusrecord.AcDcGrowatt.Batteries[0].Voltage.WriteLine(" Battery Voltage"); statusrecord.AcDcGrowatt.BatteryMaxChargeCurrent.WriteLine(" BatteryMaxChargeCurrent "); //30409 we set power here statusrecord.AcDcGrowatt.BatteryMaxdischargeCurrent.WriteLine(" BatteryMaxDischargeCurrent "); //30409 we set power here - + statusrecord.AcDcGrowatt.DischargeCutoffSoc.WriteLine(" DischargeCutoffSoc "); //30409 we set power here + statusrecord.AcDcGrowatt.ChargeCutoffSoc.WriteLine(" ChargeCutoffSoc "); //30409 we set power here + + statusrecord.AcDcGrowatt.TotalPvPower.WriteLine(" Pv Power "); //30409 we set power here + statusrecord.AcDcGrowatt.SystemOperatingMode.WriteLine(" = SystemOperatingMode"); statusrecord.AcDcGrowatt.BatteryOperatingMode.WriteLine(" = BatteryOperatingMode"); statusrecord.AcDcGrowatt.OperatingPriority.WriteLine(" = OperatingPriority"); // 30408 this the duration @@ -171,38 +183,12 @@ public static class Program { // Handle exception and print the error Console.WriteLine(e ); - // await Task.Delay(2000); // Delay in milliseconds (2000ms = 2 seconds) return null; } } } - public static double CalculateActivePower(this StatusRecord? status) - { - // Convert raw registers to engineering units - double Vab = status.AcDcGrowatt.GridAbLineVoltage * 0.1; - double Vbc = status.AcDcGrowatt.GridBcLineVoltage * 0.1; - double Vca = status.AcDcGrowatt.GridCaLineVoltage * 0.1; - double Ia = status.AcDcGrowatt.PhaseACurrent * 0.1; - double Ib = status.AcDcGrowatt.PhaseBCurrent * 0.1; - double Ic = status.AcDcGrowatt.PhaseCCurrent * 0.1; - - // Average line-to-line voltage - double Vll = (Vab + Vbc + Vca) / 3.0; - - // Average line current (absolute values, in case of signed currents) - double Il = (Math.Abs(Ia) + Math.Abs(Ib) + Math.Abs(Ic)) / 3.0; - - // Apparent power (kVA) - double S_kVA = Math.Sqrt(3) * Vll * Il / 1000.0; - - // Active power (kW) - double P_kW = S_kVA * 1; - - return P_kW; - } - private static void ApplyConfigFile(this StatusRecord? status, Configuration? config) { if (config == null) return; @@ -212,7 +198,8 @@ public static class Program status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W status.Config.MaximumChargingCurrent = config.MaximumChargingCurrent; status.Config.MaximumDischargingCurrent = config.MaximumDischargingCurrent; - status.Config.OperatingPriority = config.OperatingPriority; + status.Config.OperatingPriority = config.OperatingPriority; + status.Config.BatteriesCount = config.BatteriesCount; } private static String EssModeControl(StatusRecord? statusrecord) @@ -347,11 +334,11 @@ public static class Program st.AcDcGrowatt.BatteryMaxdischargeCurrent = st.Config.MaximumDischargingCurrent ; st.AcDcGrowatt.DischargeCutoffSoc = st.Config.MinSoc; st.AcDcGrowatt.EmsCommunicationFailureTime = 20; // 20 sec - st.AcDcGrowatt.EnableEmsCommunicationFailureTime = true; + st.AcDcGrowatt.EnableEmsCommunicationFailureTime = false; st.AcDcGrowatt.EnableCommand = true; st.AcDcGrowatt.ControlPermession = true; st.AcDcGrowatt.BatteryChargeCutoffVoltage = 60; //st.Config.BatteryChargeCutoffVoltage; - st.AcDcGrowatt.BatteryDischargeCutoffVoltage = 20; //st.Config.BatteryDischargeCutoffVoltage; + st.AcDcGrowatt.BatteryDischargeCutoffVoltage = 25; //st.Config.BatteryDischargeCutoffVoltage; } private static Dictionary ConvertToModbusRegisters(Object value, String outputType, Int32 startingAddress) @@ -392,12 +379,9 @@ public static class Program private static async Task SaveModbusTcpFile(StatusRecord status) { var modbusData = new Dictionary(); - const Double protcolNumber = 1.1; // to be communicated by yinyin maybe add this to config file - var pv1Power = status.AcDcGrowatt.Pv1Current * status.AcDcGrowatt.Pv1Voltage; - var pv2Power = status.AcDcGrowatt.Pv2Current * status.AcDcGrowatt.Pv2Voltage; - + // SYSTEM DATA - var result1 = ConvertToModbusRegisters((protcolNumber * 10), "UInt16", 30001); // this to be updated to modbusTCP version + var result1 = ConvertToModbusRegisters((status.Config.ModbusProtcolNumber * 10), "UInt16", 30001); // this to be updated to modbusTCP version var result2 = ConvertToModbusRegisters(status.AcDcGrowatt.SystemDateTime.ToUnixTime(), "UInt32", 30002); var result3 = ConvertToModbusRegisters(status.AcDcGrowatt.SystemOperatingMode, "UInt16", 30004); var result17 = ConvertToModbusRegisters(status.AcDcGrowatt.OperatingPriority, "UInt16", 30005); @@ -405,33 +389,30 @@ public static class Program // BATTERY SUMMARY (assuming single battery [0]) // this to be improved var battery = status.AcDcGrowatt.BatteriesRecords!.Batteries[0]; - var result4 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteriesRecords!.Batteries.Count ), "UInt16", 30099); - var result5 = ConvertToModbusRegisters((battery.Power.Value * 10), "Int32", 31001); - var result6 = ConvertToModbusRegisters((battery.DailyChargeEnergy.Value * 10), "UInt32", 31003); - var result7 = ConvertToModbusRegisters((battery.AccumulatedChargeEnergy.Value * 10), "UInt32", 31005); - var result8 = ConvertToModbusRegisters((battery.DailyDischargeEnergy.Value * 10), "UInt32", 31007); - var result9 = ConvertToModbusRegisters((battery.AccumulatedDischargeEnergy.Value * 10), "UInt32", 31009); - var result10 = ConvertToModbusRegisters((battery.MaxAllowableDischargePower.Value * 10), "UInt32", 31011); - var result11 = ConvertToModbusRegisters((battery.MaxAllowableDischargePower.Value * 10), "UInt32", 31013); + var result4 = ConvertToModbusRegisters((status.Config.BatteriesCount ), "UInt16", 31000); + var result8 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteryOperatingMode), "UInt16", 31001); + var result12 = ConvertToModbusRegisters((battery.Voltage.Value * 10), "Int16", 31002); + var result13 = ConvertToModbusRegisters((battery.Current.Value * 10), "Int32", 31003); + var result14 = ConvertToModbusRegisters((battery.Soc.Value * 100), "UInt16", 31005); + var result5 = ConvertToModbusRegisters((battery.Power.Value * 10), "Int32", 31006); - var result12 = ConvertToModbusRegisters((battery.Voltage.Value * 10), "Int16", 31016); - var result13 = ConvertToModbusRegisters((battery.Current.Value * 10), "Int32", 31017); - var result14 = ConvertToModbusRegisters((battery.Soc.Value * 100), "UInt16", 31019); - var result15 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteriesRecords!.AverageSoh * 100), "UInt16", 31022); - var result16 = ConvertToModbusRegisters((battery.BatteryAmbientTemperature.Value * 100), "UInt16", 31023); - var result18 = ConvertToModbusRegisters(((pv1Power + pv2Power) * 10), "UInt32", 31999); - var result19 = ConvertToModbusRegisters((status.AcDcGrowatt.GridMeterPower.Value * 10), "Int32", 32999); - var result20 = ConvertToModbusRegisters((status.AcDcGrowatt.DischargeCutoffSoc * 100), "UInt16", 31020); - var result21 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteryMaxChargeCurrent * 10), "UInt16", 31024); - var result22 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteryMaxdischargeCurrent * 10), "UInt16", 31025); - var result23 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteryChargeCutoffVoltage * 10), "UInt16", 31026); - + var result7 = ConvertToModbusRegisters((status.AcDcGrowatt.DischargeCutoffSoc * 100), "UInt16", 31008); + var result20 = ConvertToModbusRegisters((status.AcDcGrowatt.ChargeCutoffSoc * 100), "UInt16", 31009); + var result15 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteriesRecords!.AverageSoh * 100), "UInt16", 310010); + var result16 = ConvertToModbusRegisters((battery.BatteryAmbientTemperature.Value * 100), "UInt16", 31011); + var result21 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteryMaxChargeCurrent * 10), "UInt16", 31012); + var result22 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteryMaxdischargeCurrent * 10), "UInt16", 31013); + var result23 = ConvertToModbusRegisters((status.AcDcGrowatt.BatteryChargeCutoffVoltage * 10), "UInt16", 31014); + + var result18 = ConvertToModbusRegisters((status.AcDcGrowatt.TotalPvPower.Value * 10), "UInt32", 32000); + var result19 = ConvertToModbusRegisters((status.AcDcGrowatt.MeterPower * 10), "Int32", 33000); + // Merge all results into one dictionary var allResults = new[] { - result1,result2, result3, result17, result4, result5, result6, result7, result8, - result9, result10, result11, result12, result13, result14, result15, result16, result18, result19,result20, + result1,result2, result3, result17, result4, result5, result7, result8, + result12, result13, result14, result15, result16, result18, result19,result20, result21, result22, result23 }; @@ -523,6 +504,7 @@ public static class Program } } } + private static async Task SavingLocalCsvFile(Int64 timestamp, String csv) { const String directoryPath = "/home/inesco/SodiStoreHome/csvFile"; @@ -626,7 +608,7 @@ public static class Program } private static void Heartbit() - { /* + { var s3Bucket = Config.Load().S3?.Bucket; var tryParse = int.TryParse(s3Bucket?.Split("-")[0], out var installationId); @@ -641,10 +623,10 @@ public static class Program }; if (s3Bucket != null) RabbitMqManager.InformMiddleware(returnedStatus); - }*/ + } } - private static async Task SaveToLocalCompressedFallback(Byte[] compressedData, String fileNameWithoutExtension) + private static async Task SaveToLocalCompressedFallback(Byte[] compressedData, String fileNameWithoutExtension) { try {