diff --git a/csharp/App/GrowattCommunication/Program.cs b/csharp/App/GrowattCommunication/Program.cs index 2b6692711..7292eb38d 100644 --- a/csharp/App/GrowattCommunication/Program.cs +++ b/csharp/App/GrowattCommunication/Program.cs @@ -96,8 +96,8 @@ public static class Program return new StatusRecord { - AcDcGrowatt = growattRecord, - Config = config // load from disk every iteration, so config can be changed while running + InverterRecord = growattRecord, + Config = config // load from disk every iteration, so config can be changed while running }; } @@ -133,38 +133,38 @@ public static class Program //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.InverterRecord.RemotePowerControl.WriteLine(" = RemotePowerControl"); + statusrecord.InverterRecord.EnableEmsCommunicationFailureTime.WriteLine(" = EnableEmsCommunicationFailureTime"); - statusrecord.AcDcGrowatt.EnableCommand.WriteLine(" = EnableCommand"); - statusrecord.AcDcGrowatt.ControlPermession.WriteLine(" = ControlPermession"); - statusrecord.AcDcGrowatt.MeterPower.WriteLine(" MeterPower"); - 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 - statusrecord.AcDcGrowatt.PowerFactor.WriteLine(" = PowerFactor"); - statusrecord.AcDcGrowatt.Batteries[0].Soc.WriteLine(" SOC"); - statusrecord.AcDcGrowatt.Batteries[0].Power.WriteLine(" Battery Power"); - statusrecord.AcDcGrowatt.Batteries[0].Current.WriteLine(" Battery Current"); - 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.InverterRecord.EnableCommand.WriteLine(" = EnableCommand"); + statusrecord.InverterRecord.ControlPermession.WriteLine(" = ControlPermession"); + statusrecord.InverterRecord.GridPower.WriteLine(" MeterPower"); + statusrecord.InverterRecord.ConsumptionPower.WriteLine(" ConsumptionPower"); + statusrecord.InverterRecord.ExportedPowerToGridMeter.WriteLine(" ExportedPowerToGrid"); + statusrecord.InverterRecord.ImportedPowerFromGrid.WriteLine(" ImportedPowerFromGrid"); + statusrecord.InverterRecord.InverterActivePower.WriteLine(" InverterActivePower"); + statusrecord.InverterRecord.MaxSoc.WriteLine(" BatteryChargeCutoffVoltage "); //30409 we set power here + statusrecord.InverterRecord.MinSoc.WriteLine(" BatteryDishargeCutoffVoltage "); //30409 we set power here + statusrecord.InverterRecord.PowerFactor.WriteLine(" = PowerFactor"); + statusrecord.InverterRecord.Battery1Soc.WriteLine(" SOC"); + statusrecord.InverterRecord.Battery1Power.WriteLine(" Battery Power"); + statusrecord.InverterRecord.Battery1Current.WriteLine(" Battery Current"); + statusrecord.InverterRecord.Battery1Voltage.WriteLine(" Battery Voltage"); + statusrecord.InverterRecord.BatteryMaxChargingCurrent.WriteLine(" BatteryMaxChargeCurrent "); //30409 we set power here + statusrecord.InverterRecord.BatteryMaxDischargingCurrent.WriteLine(" BatteryMaxDischargeCurrent "); //30409 we set power here + statusrecord.InverterRecord.MinSoc.WriteLine(" MinSoc "); //30409 we set power here + statusrecord.InverterRecord.ChargeCutoffSocVoltage.WriteLine(" ChargeCutoffSoc "); //30409 we set power here - statusrecord.AcDcGrowatt.TotalPvPower.WriteLine(" Pv Power "); //30409 we set power here + statusrecord.InverterRecord.PvPower.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 + statusrecord.InverterRecord.SystemOperatingMode.WriteLine(" = SystemOperatingMode"); + statusrecord.InverterRecord.BatteryOperatingMode.WriteLine(" = BatteryOperatingMode"); + statusrecord.InverterRecord.OperatingMode.WriteLine(" = OperatingPriority"); // 30408 this the duration - statusrecord.AcDcGrowatt.FaultMainCode.WriteLine(" = FaultMainCode"); // 30408 this the duration - statusrecord.AcDcGrowatt.FaultSubCode.WriteLine(" = FaultSubCode"); // 30408 this the duration - statusrecord.AcDcGrowatt.WarningMainCode.WriteLine(" = WarningMainCode"); // 30408 this the duration - statusrecord.AcDcGrowatt.WarningSubCode.WriteLine(" = WarningSubCode"); // 30408 this the duration + statusrecord.InverterRecord.FaultMainCode.WriteLine(" = FaultMainCode"); // 30408 this the duration + statusrecord.InverterRecord.FaultSubCode.WriteLine(" = FaultSubCode"); // 30408 this the duration + statusrecord.InverterRecord.WarningMainCode.WriteLine(" = WarningMainCode"); // 30408 this the duration + statusrecord.InverterRecord.WarningSubCode.WriteLine(" = WarningSubCode"); // 30408 this the duration @@ -173,10 +173,13 @@ public static class Program statusrecord.ApplyDefaultSettings(); Console.WriteLine( " ************************************ We are writing ************************************"); - statusrecord.Config.Save(); // save the config file - growattDeviceT415K.Write(statusrecord.AcDcGrowatt); - var stopTime = DateTime.Now; - Console.WriteLine(stopTime.ToString("HH:mm:ss.fff")); + if (statusrecord != null) + { + statusrecord.Config.Save(); // save the config file + growattDeviceT415K.Write(statusrecord.InverterRecord); + Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff")); + + } return statusrecord; } catch (Exception e) @@ -185,7 +188,6 @@ public static class Program Console.WriteLine(e ); return null; } - } } @@ -195,7 +197,6 @@ public static class Program if (status == null) return; status.Config.MinSoc = config.MinimumSoC; - 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; @@ -211,23 +212,23 @@ public static class Program case EssMode.Off: return "no mode"; case EssMode.GridPriority: - statusrecord.AcDcGrowatt.RemotePowerControl = true; - statusrecord.AcDcGrowatt.RemotePowerControlChargeDuration = 0; // 30408 this the duration + statusrecord.InverterRecord.RemotePowerControl = true; + statusrecord.InverterRecord.RemotePowerControlChargeDuration = 0; // 30408 this the duration //statusrecord.AcDcGrowatt.ActivePowerPercent = 50; // 30408 this the duration //statusrecord.AcDcGrowatt.ActivePowerPercentDerating = 50; // 30408 this the duration - statusrecord.AcDcGrowatt.RemoteChargDischargePower = - 100; //30409 we set power here // for grid priority from 0 to -100 - statusrecord.AcDcGrowatt.ActualChargeDischargePowerControlValue.WriteLine(" register 30474");; // this to check what was set + statusrecord.InverterRecord.RemoteChargDischargePower = - 100; //30409 we set power here // for grid priority from 0 to -100 + statusrecord.InverterRecord.ActualChargeDischargePowerControlValue.WriteLine(" register 30474");; // this to check what was set return "Grid priority mode active"; case EssMode.BatteryPriority: - statusrecord.AcDcGrowatt.RemotePowerControl = true; - statusrecord.AcDcGrowatt.RemotePowerControlChargeDuration = 0; // 30408 this the duration + statusrecord.InverterRecord.RemotePowerControl = true; + statusrecord.InverterRecord.RemotePowerControlChargeDuration = 0; // 30408 this the duration - statusrecord.AcDcGrowatt.RemoteChargDischargePower = 100; //30409 we set power here // for battery priority from 0 to 100 - statusrecord.AcDcGrowatt.ActualChargeDischargePowerControlValue.WriteLine(" register 30474");; // this to check what was set + statusrecord.InverterRecord.RemoteChargDischargePower = 100; //30409 we set power here // for battery priority from 0 to 100 + statusrecord.InverterRecord.ActualChargeDischargePowerControlValue.WriteLine(" register 30474");; // this to check what was set return "Battery priority mode active"; case EssMode.LoadPriority: - statusrecord.AcDcGrowatt.RemotePowerControl = false; + statusrecord.InverterRecord.RemotePowerControl = false; return "Load priority mode active"; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); @@ -236,41 +237,41 @@ public static class Program private static StatusMessage GetSodiHomeStateAlarm(StatusRecord? record) { - 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 (record.AcDcGrowatt.SystemOperatingMode == GrowattSystemStatus.Fault) - { - if (record.AcDcGrowatt.FaultMainCode != 0) - { - alarmList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "Growatt Inverter", - Description = record.AcDcGrowatt.WarningMainCode.ToString(), // to add the sub code - }); - } + if (record.InverterRecord.SystemOperatingMode == GrowattSystemStatus.Fault) + { + if (record.InverterRecord.FaultMainCode != 0) + { + alarmList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "Growatt Inverter", + Description = record.InverterRecord.WarningMainCode.ToString(), // to add the sub code + }); + } - if (record.AcDcGrowatt.WarningMainCode != 0) - { - warningList.Add(new AlarmOrWarning - { - Date = DateTime.Now.ToString("yyyy-MM-dd"), - Time = DateTime.Now.ToString("HH:mm:ss"), - CreatedBy = "Growatt inverter", - Description = record.AcDcGrowatt.FaultMainCode.ToString(), //to add the sub code - }); - } - } - - _sodiohomeAlarmState = warningList.Any() + if (record.InverterRecord.WarningMainCode != 0) + { + warningList.Add(new AlarmOrWarning + { + Date = DateTime.Now.ToString("yyyy-MM-dd"), + Time = DateTime.Now.ToString("HH:mm:ss"), + CreatedBy = "Growatt inverter", + Description = record.InverterRecord.FaultMainCode.ToString(), //to add the sub code + }); + } + } + + _sodiohomeAlarmState = warningList.Any() ? SodistoreAlarmState.Orange : SodistoreAlarmState.Green; // this will be replaced by LedState - _sodiohomeAlarmState = alarmList.Any() + _sodiohomeAlarmState = alarmList.Any() ? SodistoreAlarmState.Red : _sodiohomeAlarmState; // this will be replaced by LedState @@ -329,22 +330,23 @@ public static class Program { if (st is null) return; - - st.AcDcGrowatt.BatteryMaxChargeCurrent = st.Config.MaximumChargingCurrent; - st.AcDcGrowatt.BatteryMaxdischargeCurrent = st.Config.MaximumDischargingCurrent ; - st.AcDcGrowatt.DischargeCutoffSoc = st.Config.MinSoc; - st.AcDcGrowatt.EmsCommunicationFailureTime = 20; // 20 sec - st.AcDcGrowatt.EnableEmsCommunicationFailureTime = false; - st.AcDcGrowatt.EnableCommand = true; - st.AcDcGrowatt.ControlPermession = true; - st.AcDcGrowatt.BatteryChargeCutoffVoltage = 60; //st.Config.BatteryChargeCutoffVoltage; - st.AcDcGrowatt.BatteryDischargeCutoffVoltage = 25; //st.Config.BatteryDischargeCutoffVoltage; - } - - private static Dictionary ConvertToModbusRegisters(Object value, String outputType, Int32 startingAddress) + + st.InverterRecord.BatteryMaxChargingCurrent = st.Config.MaximumChargingCurrent; + st.InverterRecord.BatteryMaxDischargingCurrent = st.Config.MaximumDischargingCurrent; + st.InverterRecord.MinSoc = (UInt16)st.Config.MinSoc; + st.InverterRecord.EmsCommunicationFailureTime = 20; // 20 sec + st.InverterRecord.EnableEmsCommunicationFailureTime = false; + st.InverterRecord.EnableCommand = true; + st.InverterRecord.ControlPermession = true; + st.InverterRecord.MaxSoc = 60; //st.Config.BatteryChargeCutoffVoltage; + st.InverterRecord.MinSoc = 25; //st.Config.BatteryDischargeCutoffVoltage; + } + + private static Dictionary ConvertToModbusRegisters(Object value, String outputType, + Int32 startingAddress) { var registers = new Dictionary(); - + switch (outputType) { case "UInt16": @@ -379,43 +381,45 @@ public static class Program private static async Task SaveModbusTcpFile(StatusRecord status) { var modbusData = new Dictionary(); - - // SYSTEM DATA - 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); + + // SYSTEM DATA + var result1 = + ConvertToModbusRegisters((status.Config.ModbusProtcolNumber * 10), "UInt16", + 30001); // this to be updated to modbusTCP version + var result2 = ConvertToModbusRegisters(status.InverterRecord.SystemDateTime.ToUnixTime(), "UInt32", 30002); + var result3 = ConvertToModbusRegisters(status.InverterRecord.SystemOperatingMode, "UInt16", 30004); + var result17 = ConvertToModbusRegisters(status.InverterRecord.OperatingMode, "UInt16", 30005); // BATTERY SUMMARY (assuming single battery [0]) // this to be improved - var battery = status.AcDcGrowatt.BatteriesRecords!.Batteries[0]; - 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 result4 = ConvertToModbusRegisters((status.Config.BatteriesCount), "UInt16", 31000); + var result8 = ConvertToModbusRegisters((status.InverterRecord.BatteryOperatingMode), "UInt16", 31001); + var result12 = ConvertToModbusRegisters((status.InverterRecord.Battery1Voltage.Value * 10), "Int16", 31002); + var result13 = ConvertToModbusRegisters((status.InverterRecord.Battery1Current.Value * 10), "Int32", 31003); + var result14 = ConvertToModbusRegisters((status.InverterRecord.Battery1Soc.Value * 100), "UInt16", 31005); + var result5 = ConvertToModbusRegisters((status.InverterRecord.Battery1Power.Value * 10), "Int32", 31006); - 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 result7 = ConvertToModbusRegisters((status.InverterRecord.MinSoc * 100), "UInt16", 31008); + var result20 = ConvertToModbusRegisters((status.InverterRecord.ChargeCutoffSocVoltage * 100), "UInt16", 31009); + var result15 = + ConvertToModbusRegisters((status.InverterRecord.Battery1Soh * 100), "UInt16", 310010); + var result16 = ConvertToModbusRegisters((status.InverterRecord.Battery1AmbientTemperature.Value * 100), "UInt16", 31011); + var result21 = ConvertToModbusRegisters((status.InverterRecord.BatteryMaxChargingCurrent * 10), "UInt16", 31012); + var result22 = ConvertToModbusRegisters((status.InverterRecord.BatteryMaxDischargingCurrent * 10), "UInt16", 31013); + var result23 = ConvertToModbusRegisters((status.InverterRecord.MaxSoc * 10), "UInt16", 31014); + + var result18 = ConvertToModbusRegisters((status.InverterRecord.PvPower.Value * 10), "UInt32", 32000); + var result19 = ConvertToModbusRegisters((status.InverterRecord.GridPower * 10), "Int32", 33000); - 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, result7, result8, - 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 }; - + foreach (var result in allResults) { foreach (var entry in result) @@ -548,67 +552,68 @@ public static class Program private static async Task ConcatinatingAndCompressingFiles(Int64 timeStamp, S3Config s3Config) { - if (_fileCounter >= NbrOfFileToConcatenate) - { - _fileCounter = 0; + if (_fileCounter >= NbrOfFileToConcatenate) + { + _fileCounter = 0; - var logFileConcatenator = new LogFileConcatenator(); - var jsontoSend = logFileConcatenator.ConcatenateFiles(NbrOfFileToConcatenate); + var logFileConcatenator = new LogFileConcatenator(); + var jsontoSend = logFileConcatenator.ConcatenateFiles(NbrOfFileToConcatenate); - var fileNameWithoutExtension = timeStamp.ToString(); // used for both S3 and local - var s3Path = fileNameWithoutExtension + ".json"; + var fileNameWithoutExtension = timeStamp.ToString(); // used for both S3 and local + var s3Path = fileNameWithoutExtension + ".json"; - var request = s3Config.CreatePutRequest(s3Path); + var request = s3Config.CreatePutRequest(s3Path); - var compressedBytes = CompresseBytes(jsontoSend); - var base64String = Convert.ToBase64String(compressedBytes); - var stringContent = new StringContent(base64String, Encoding.UTF8, "application/base64"); + var compressedBytes = CompresseBytes(jsontoSend); + var base64String = Convert.ToBase64String(compressedBytes); + var stringContent = new StringContent(base64String, Encoding.UTF8, "application/base64"); - var uploadSucceeded = false; + var uploadSucceeded = false; - try - { - var response = await request.PutAsync(stringContent); + try + { + var response = await request.PutAsync(stringContent); - if (response.StatusCode != 200) - { - Console.WriteLine("ERROR: PUT"); - var error = await response.GetStringAsync(); - Console.WriteLine(error); + if (response.StatusCode != 200) + { + Console.WriteLine("ERROR: PUT"); + var error = await response.GetStringAsync(); + Console.WriteLine(error); - await SaveToLocalCompressedFallback(compressedBytes, fileNameWithoutExtension); - Heartbit(); - return false; - } + await SaveToLocalCompressedFallback(compressedBytes, fileNameWithoutExtension); + Heartbit(); + return false; + } - uploadSucceeded = true; - Console.WriteLine("✅ File uploaded to S3 successfully."); + uploadSucceeded = true; + Console.WriteLine("✅ File uploaded to S3 successfully."); - Console.WriteLine("---------------------------------------- Resending FailedUploadedFiles----------------------------------------"); - Heartbit(); + Console.WriteLine( + "---------------------------------------- Resending FailedUploadedFiles----------------------------------------"); + Heartbit(); - await ResendLocalFailedFilesAsync(s3Config); // retry any pending failed files - } - catch (Exception ex) - { - Console.WriteLine("Upload exception: " + ex.Message); + await ResendLocalFailedFilesAsync(s3Config); // retry any pending failed files + } + catch (Exception ex) + { + Console.WriteLine("Upload exception: " + ex.Message); - if (!uploadSucceeded) - { - await SaveToLocalCompressedFallback(compressedBytes, fileNameWithoutExtension); - } + if (!uploadSucceeded) + { + await SaveToLocalCompressedFallback(compressedBytes, fileNameWithoutExtension); + } - Heartbit(); - return false; - } - } + Heartbit(); + return false; + } + } - _fileCounter++; - return true; + _fileCounter++; + return true; } - + private static void Heartbit() - { + { var s3Bucket = Config.Load().S3?.Bucket; var tryParse = int.TryParse(s3Bucket?.Split("-")[0], out var installationId); @@ -684,7 +689,7 @@ public static class Program } } } - + private static Byte[] CompresseBytes(String jsonToSend) { //Compress JSON data to a byte array