Update the growattACDC to inverter Record

This commit is contained in:
atef 2025-11-12 15:58:37 +01:00
parent ce62bb5687
commit b122177e61
1 changed files with 165 additions and 160 deletions

View File

@ -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<AlarmOrWarning>();
var warningList = new List<AlarmOrWarning>();
var alarmList = new List<AlarmOrWarning>();
var warningList = new List<AlarmOrWarning>();
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<String, UInt16> 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<String, UInt16> ConvertToModbusRegisters(Object value, String outputType,
Int32 startingAddress)
{
var registers = new Dictionary<String, UInt16>();
switch (outputType)
{
case "UInt16":
@ -379,43 +381,45 @@ public static class Program
private static async Task<Boolean> SaveModbusTcpFile(StatusRecord status)
{
var modbusData = new Dictionary<String, UInt16>();
// 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<Boolean> 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