Merge branch 'main' of 91.92.155.224:Innovenergy/Innovenergy_trunk
This commit is contained in:
commit
5f1bcdb0c1
|
|
@ -6,11 +6,10 @@ namespace InnovEnergy.App.GrowattCommunication.DataTypes;
|
|||
public class Configuration
|
||||
{
|
||||
public Double MinimumSoC { get; set; }
|
||||
public Double GridSetPoint { get; set; }
|
||||
public Double MaximumDischargingCurrent { get; set; }
|
||||
public Double MaximumChargingCurrent { get; set; }
|
||||
public EssMode OperatingPriority { get; set; }
|
||||
public required Int16 BatteriesCount { get; set; }
|
||||
public Int16 BatteriesCount { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ namespace InnovEnergy.App.GrowattCommunication.ESS;
|
|||
|
||||
public record StatusRecord
|
||||
{
|
||||
public required WITGrowatRecord AcDcGrowatt { get; set; }
|
||||
public required WITGrowatRecord InverterRecord { get; set; }
|
||||
public required Config Config { get; set; }
|
||||
}
|
||||
|
|
@ -9,9 +9,9 @@ namespace InnovEnergy.App.GrowattCommunication.MiddlewareClasses;
|
|||
|
||||
public static class MiddlewareAgent
|
||||
{
|
||||
private static UdpClient _udpListener = null!;
|
||||
private static UdpClient _udpListener = null!;
|
||||
private static IPAddress? _controllerIpAddress;
|
||||
private static EndPoint? _endPoint;
|
||||
private static EndPoint? _endPoint;
|
||||
|
||||
public static void InitializeCommunicationToMiddleware()
|
||||
{
|
||||
|
|
@ -67,8 +67,8 @@ public static class MiddlewareAgent
|
|||
|
||||
if (config != null)
|
||||
{
|
||||
Console.WriteLine($"Received a configuration message: GridSetPoint is " + config.GridSetPoint +
|
||||
", MinimumSoC is " + config.MinimumSoC + " and operating priorty is " +config.OperatingPriority + "Number of batteries is " + config.BatteriesCount );
|
||||
Console.WriteLine($"Received a configuration message: " +
|
||||
"MinimumSoC is " + config.MinimumSoC + " and operating priorty is " +config.OperatingPriority + "Number of batteries is " + config.BatteriesCount + config.MaximumChargingCurrent + config.MaximumDischargingCurrent);
|
||||
|
||||
// Send the reply to the sender's endpoint
|
||||
_udpListener.Send(replyData, replyData.Length, serverEndpoint);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -129,42 +129,39 @@ 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
|
||||
|
||||
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 +170,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 +185,6 @@ public static class Program
|
|||
Console.WriteLine(e );
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +194,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 +209,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 +234,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
|
||||
});
|
||||
}
|
||||
}
|
||||
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()
|
||||
_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
|
||||
|
||||
|
|
@ -330,18 +328,19 @@ 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;
|
||||
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)
|
||||
private static Dictionary<String, UInt16> ConvertToModbusRegisters(Object value, String outputType,
|
||||
Int32 startingAddress)
|
||||
{
|
||||
var registers = new Dictionary<String, UInt16>();
|
||||
|
||||
|
|
@ -380,39 +379,41 @@ public static class Program
|
|||
{
|
||||
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.AcDcGrowatt.TotalPvPower.Value * 10), "UInt32", 32000);
|
||||
var result19 = ConvertToModbusRegisters((status.AcDcGrowatt.MeterPower * 10), "Int32", 33000);
|
||||
var result18 = ConvertToModbusRegisters((status.InverterRecord.PvPower.Value * 10), "UInt32", 32000);
|
||||
var result19 = ConvertToModbusRegisters((status.InverterRecord.GridPower * 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
|
||||
};
|
||||
|
||||
|
|
@ -548,63 +549,64 @@ 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()
|
||||
|
|
|
|||
|
|
@ -142,9 +142,9 @@ public static class Aggregator
|
|||
{
|
||||
batterySoc.Add((double)jsonObject["Battery"]["Soc"]);
|
||||
}
|
||||
if (jsonObject["PvOnDc"] != null && jsonObject["PvOnDc"]["DcWh"] != null)
|
||||
if (jsonObject["PvOnDc"] != null && jsonObject["PvOnDc"]["1"]["DcWh"] != null) // todo update to all pv
|
||||
{
|
||||
pvPowerSum.Add((double)jsonObject["PvOnDc"]["DcWh"]);
|
||||
pvPowerSum.Add((double)jsonObject["PvOnDc"]["1"]["DcWh"]);
|
||||
}
|
||||
if (jsonObject["Battery"] != null && jsonObject["Battery"]["Dc"]["Power"] != null)
|
||||
{
|
||||
|
|
@ -316,7 +316,7 @@ public static class Aggregator
|
|||
ChargingBatteryPower = batteryChargePower.Any() ? batteryChargePower.Average() : 0.0,
|
||||
GridExportPower = gridPowerExport.Any() ? gridPowerExport.Sum() : 0.0,
|
||||
GridImportPower = gridPowerImport.Any() ? gridPowerImport.Sum() : 0.0,
|
||||
PvPower = pvPower.Any() ? pvPower.Last() : 0.0,
|
||||
PvPower = pvPower.Any() ? pvPower.Max() : 0.0,
|
||||
HeatingPower = heatingPowerAvg.Any() ? heatingPowerAvg.Average() : 0.0,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
using InnovEnergy.Lib.Devices.Sinexcel_12K_TL.DataType;
|
||||
|
||||
namespace InnovEnergy.App.SinexcelCommunication.DataTypes;
|
||||
|
||||
public class Configuration
|
||||
{
|
||||
public Double MinimumSoC { get; set; }
|
||||
public Double GridSetPoint { get; set; }
|
||||
// public Double MaximumDischargingCurrent { get; set; }
|
||||
// public Double MaximumChargingCurrent { get; set; }
|
||||
// public EssMode OperatingPriority { get; set; }
|
||||
// public required Int16 BatteriesCount { get; set; }
|
||||
public Double MaximumDischargingCurrent { get; set; }
|
||||
public Double MaximumChargingCurrent { get; set; }
|
||||
public WorkingMode OperatingPriority { get; set; }
|
||||
public Int16 BatteriesCount { get; set; }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
namespace InnovEnergy.App.SinexcelCommunication;
|
||||
|
||||
public enum DeviceState
|
||||
{
|
||||
Disabled,
|
||||
Measured,
|
||||
Computed
|
||||
}
|
||||
|
|
@ -5,6 +5,6 @@ namespace InnovEnergy.App.SinexcelCommunication.ESS;
|
|||
|
||||
public record StatusRecord
|
||||
{
|
||||
public required SinexcelRecord SinexcelRecord { get; set; }
|
||||
public required SinexcelRecord InverterRecord { get; set; }
|
||||
public required Config Config { get; set; }
|
||||
}
|
||||
|
|
@ -67,8 +67,8 @@ public static class MiddlewareAgent
|
|||
|
||||
if (config != null)
|
||||
{
|
||||
Console.WriteLine($"Received a configuration message: GridSetPoint is " + config.GridSetPoint +
|
||||
", MinimumSoC is " + config.MinimumSoC + " and operating priorty is " );
|
||||
Console.WriteLine($"Received a configuration message: " +
|
||||
"MinimumSoC is " + config.MinimumSoC + " and operating priorty is " +config.OperatingPriority + "Number of batteries is " + config.BatteriesCount + config.MaximumChargingCurrent + config.MaximumDischargingCurrent);
|
||||
|
||||
// Send the reply to the sender's endpoint
|
||||
_udpListener.Send(replyData, replyData.Length, serverEndpoint);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ using Formatting = Newtonsoft.Json.Formatting;
|
|||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
using static InnovEnergy.App.SinexcelCommunication.MiddlewareClasses.MiddlewareAgent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using InnovEnergy.Lib.Devices.Sinexcel_12K_TL.DataType;
|
||||
|
||||
#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.SinexcelCommunication;
|
||||
|
|
@ -31,7 +33,7 @@ namespace InnovEnergy.App.SinexcelCommunication;
|
|||
[SuppressMessage("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic access otherwise can break functionality when trimming application code")]
|
||||
internal static class Program
|
||||
{
|
||||
private static readonly TimeSpan UpdateInterval = TimeSpan.FromSeconds(4);
|
||||
private static readonly TimeSpan UpdateInterval = TimeSpan.FromSeconds(5);
|
||||
private const UInt16 NbrOfFileToConcatenate = 15; // add this to config file
|
||||
private static UInt16 _fileCounter = 0;
|
||||
private static Channel _sinexcelChannel;
|
||||
|
|
@ -54,7 +56,7 @@ internal static class Program
|
|||
public static async Task Main(String[] args)
|
||||
{
|
||||
_sinexcelChannel = new SerialPortChannel(Port, BaudRate, Parity, DataBits, StopBits);
|
||||
|
||||
InitializeCommunicationToMiddleware();
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
|
|
@ -85,7 +87,7 @@ internal static class Program
|
|||
|
||||
return new StatusRecord
|
||||
{
|
||||
SinexcelRecord = sinexcelRecord,
|
||||
InverterRecord = sinexcelRecord,
|
||||
Config = config // load from disk every iteration, so config can be changed while running
|
||||
};
|
||||
}
|
||||
|
|
@ -111,61 +113,57 @@ internal static class Program
|
|||
|
||||
var startTime = DateTime.Now;
|
||||
Console.WriteLine("***************************** Reading Battery Data *********************************************");
|
||||
Console.WriteLine(startTime.ToString("HH:mm:ss.fff"));
|
||||
Console.WriteLine(startTime.ToString("HH:mm:ss.fff ")+ "Start Reading");
|
||||
|
||||
// the order matter of the next three lines
|
||||
var statusrecord = ReadStatus();
|
||||
if (statusrecord == null)
|
||||
return null;
|
||||
|
||||
statusrecord.SinexcelRecord.GridAPhaseVoltage.WriteLine(" = Grid A PhaseVoltage");
|
||||
statusrecord.SinexcelRecord.GridBPhaseVoltage.WriteLine(" = Grid B PhaseVoltage");
|
||||
statusrecord.SinexcelRecord.GridCPhaseVoltage.WriteLine(" = Grid C PhaseVoltage");
|
||||
// Console.WriteLine( statusrecord.InverterRecord.TimedChargeAndDischargeOff + " TimedChargeAndDischargeOff ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.Battery1Power + " Battery1Power ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.Battery1Soc + " Battery1Soc ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.RepetitiveWeeks + " RepetitiveWeeks ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.EffectiveStartDate + " EffectiveStartDate ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.EffectiveEndDate + " EffectiveEndDate ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.ChargingPowerPeriod1 + " ChargingPowerPeriod1 ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.ChargeStartTimePeriod1 + " ChargeStartTimePeriod1 ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.ChargeEndTimePeriod1 + " ChargeEndTimePeriod1 ");
|
||||
|
||||
statusrecord.SinexcelRecord.GridAPhaseCurrent.WriteLine(" = Grid A PhaseCurrent");
|
||||
statusrecord.SinexcelRecord.GridBPhaseCurrent.WriteLine(" = Grid B PhaseCurrent");
|
||||
statusrecord.SinexcelRecord.GridCPhaseCurrent.WriteLine(" = Grid C PhaseCurrent");
|
||||
Console.WriteLine( statusrecord.InverterRecord.DischargeStartTimePeriod1 + " DischargeStartTimePeriod1 ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.DischargeEndTimePeriod1 + " DischargeEndTimePeriod1 ");
|
||||
|
||||
Console.WriteLine( statusrecord.InverterRecord.PowerOn + " PowerOn ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.PowerOff + " PowerOff ");
|
||||
Console.WriteLine( statusrecord.InverterRecord.WorkingMode + " WorkingMode ");
|
||||
// Console.WriteLine( statusrecord.InverterRecord.FaultClearing + " FaultClearing ");
|
||||
SendSalimaxStateAlarm(GetSodiHomeStateAlarm(statusrecord),statusrecord);
|
||||
|
||||
statusrecord.SinexcelRecord.GridAPhaseActivePower.WriteLine(" = A Grid Active Power");
|
||||
statusrecord.SinexcelRecord.GridBPhaseActivePower.WriteLine(" = B Grid Active Power");
|
||||
statusrecord.SinexcelRecord.GridCPhaseActivePower.WriteLine(" = C Grid Active Power");
|
||||
|
||||
statusrecord.SinexcelRecord.GridVoltageFrequency.WriteLine(" = Frequency");
|
||||
|
||||
statusrecord.SinexcelRecord.ElectricMeterCPhaseActivePower.WriteLine(" Meter Phase C Power");
|
||||
statusrecord.SinexcelRecord.ElectricMeterBPhaseActivePower.WriteLine(" Meter Phase B Power");
|
||||
statusrecord.SinexcelRecord.ElectricMeterAPhaseActivePower.WriteLine(" Meter Phase A Power");
|
||||
|
||||
statusrecord.SinexcelRecord.ElectricMeterAPhaseCurrent.WriteLine(" Meter Phase C Current ");
|
||||
statusrecord.SinexcelRecord.ElectricMeterBPhaseCurrent.WriteLine(" Meter Phase B Current ");
|
||||
statusrecord.SinexcelRecord.ElectricMeterBPhaseCurrent.WriteLine(" Meter Phase A Current ");
|
||||
statusrecord.SinexcelRecord.WorkingMode.WriteLine(" workingmode");
|
||||
|
||||
statusrecord.SinexcelRecord.BatteryVoltage.WriteLine(" BatteryVoltage");
|
||||
statusrecord.SinexcelRecord.BatteryVoltage1.WriteLine(" BatteryVoltage1");
|
||||
statusrecord.SinexcelRecord.BatteryVoltage2.WriteLine(" BatteryVoltage2");
|
||||
|
||||
statusrecord.SinexcelRecord.BatteryPower1.WriteLine(" BatteryPower1");
|
||||
statusrecord.SinexcelRecord.BatteryPower2.WriteLine(" BatteryPower2");
|
||||
statusrecord.SinexcelRecord.TotalBatteryPower.WriteLine(" TotalBatteryPower");
|
||||
|
||||
statusrecord.SinexcelRecord.EnableBattery1.WriteLine(" EnableBattery1");
|
||||
statusrecord.SinexcelRecord.EnableBattery2.WriteLine(" EnableBattery2");
|
||||
|
||||
statusrecord.SinexcelRecord.MaxChargingCurrentBattery1.WriteLine(" MaxChargingCurrentBattery1");
|
||||
statusrecord.SinexcelRecord.MaxChargingCurrentBattery2.WriteLine(" MaxChargingCurrentBattery2");
|
||||
|
||||
statusrecord.SinexcelRecord.MaxDischargingCurrentBattery1.WriteLine(" MaxChargingCurrentBattery1");
|
||||
statusrecord.SinexcelRecord.MaxDischargingCurrentBattery2.WriteLine(" MaxChargingCurrentBattery2");
|
||||
|
||||
//EssModeControl(statusrecord);
|
||||
// statusrecord.ApplyDefaultSettings();
|
||||
Console.WriteLine( " ************************************ We are writing ************************************");
|
||||
var startWritingTime = DateTime.Now;
|
||||
Console.WriteLine(startWritingTime.ToString("HH:mm:ss.fff ") +"start Writing");
|
||||
statusrecord?.Config.Save(); // save the config file
|
||||
//sinexcelDevice.Write(statusrecord?.SinexcelRecord);
|
||||
|
||||
if (statusrecord != null)
|
||||
{
|
||||
statusrecord.InverterRecord.WorkingMode = WorkingMode.TimeChargeDischarge;
|
||||
|
||||
//statusrecord.InverterRecord.TimedChargeAndDischargeOff = 0;
|
||||
statusrecord.InverterRecord.RepetitiveWeeks = SinexcelWeekDays.All;
|
||||
statusrecord.InverterRecord.EffectiveStartDate = DateTime.Today.AddDays(-1);
|
||||
statusrecord.InverterRecord.EffectiveEndDate = DateTime.Today.AddDays(2);
|
||||
statusrecord.InverterRecord.ChargingPowerPeriod1 = 3;
|
||||
statusrecord.InverterRecord.DishargingPowerPeriod1 = 3;
|
||||
statusrecord.InverterRecord.DischargeStartTimePeriod1 = new TimeSpan(16, 00, 0);
|
||||
statusrecord.InverterRecord.DischargeEndTimePeriod1 = new TimeSpan(17, 03, 0);
|
||||
statusrecord.InverterRecord.PowerOn = 1;
|
||||
statusrecord.InverterRecord.PowerOff = 0;
|
||||
//statusrecord.InverterRecord.FaultClearing = 1;
|
||||
}
|
||||
if (statusrecord?.InverterRecord != null) sinexcelDevice.Write(statusrecord.InverterRecord);
|
||||
|
||||
var stopTime = DateTime.Now;
|
||||
Console.WriteLine(stopTime.ToString("HH:mm:ss.fff"));
|
||||
Console.WriteLine(stopTime.ToString("HH:mm:ss.fff ")+ "run iteration time finish");
|
||||
return statusrecord;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
@ -178,6 +176,61 @@ internal static class Program
|
|||
}
|
||||
}
|
||||
|
||||
private static StatusMessage GetSodiHomeStateAlarm(StatusRecord? record)
|
||||
{
|
||||
var s3Bucket = Config.Load().S3?.Bucket;
|
||||
|
||||
var alarmList = new List<AlarmOrWarning>();
|
||||
var warningList = new List<AlarmOrWarning>();
|
||||
/*
|
||||
if (record.SinexcelRecord.WorkingMode == 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.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()
|
||||
? SodistoreAlarmState.Orange
|
||||
: SodistoreAlarmState.Green; // this will be replaced by LedState
|
||||
|
||||
_sodiohomeAlarmState = alarmList.Any()
|
||||
? SodistoreAlarmState.Red
|
||||
: _sodiohomeAlarmState; // this will be replaced by LedState
|
||||
|
||||
var installationId = GetInstallationId(s3Bucket ?? string.Empty);
|
||||
|
||||
var returnedStatus = new StatusMessage
|
||||
{
|
||||
InstallationId = installationId,
|
||||
Product = 2,
|
||||
Status = _sodiohomeAlarmState,
|
||||
Type = MessageType.AlarmOrWarning,
|
||||
Alarms = alarmList,
|
||||
Warnings = warningList
|
||||
};
|
||||
|
||||
return returnedStatus;
|
||||
}
|
||||
|
||||
private static Int32 GetInstallationId(String s3Bucket)
|
||||
{
|
||||
var part = s3Bucket.Split('-').FirstOrDefault();
|
||||
|
|
@ -220,11 +273,10 @@ internal 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;
|
||||
//status.Config.BatteriesCount = config.BatteriesCount;
|
||||
status.Config.MaximumChargingCurrent = config.MaximumChargingCurrent;
|
||||
status.Config.MaximumDischargingCurrent = config.MaximumDischargingCurrent;
|
||||
status.Config.OperatingPriority = config.OperatingPriority;
|
||||
status.Config.BatteriesCount = config.BatteriesCount;
|
||||
}
|
||||
|
||||
private static async Task<Boolean> SaveModbusTcpFile(StatusRecord status)
|
||||
|
|
@ -232,10 +284,11 @@ internal static class Program
|
|||
var modbusData = new Dictionary<String, UInt16>();
|
||||
|
||||
// SYSTEM DATA
|
||||
var result1 = ConvertToModbusRegisters((status.Config.MinSoc * 10), "UInt16", 30001); // this to be updated to modbusTCP version
|
||||
var result2 = ConvertToModbusRegisters(status.SinexcelRecord.GridAPhaseVoltage, "UInt32", 30002);
|
||||
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);
|
||||
|
||||
// Merge all results into one dictionary
|
||||
|
||||
var allResults = new[]
|
||||
{
|
||||
result1,result2
|
||||
|
|
@ -254,43 +307,72 @@ internal static class Program
|
|||
|
||||
//Console.WriteLine("JSON file written successfully.");
|
||||
//Console.WriteLine(json);
|
||||
var stopTime = DateTime.Now;
|
||||
Console.WriteLine(stopTime.ToString("HH:mm:ss.fff" )+ " Finish the loop");
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Dictionary<String, UInt16> ConvertToModbusRegisters(Object value, String outputType, Int32 startingAddress)
|
||||
private static Dictionary<string, ushort> ConvertToModbusRegisters(object value, string outputType, int startingAddress)
|
||||
{
|
||||
var registers = new Dictionary<String, UInt16>();
|
||||
var regs = new Dictionary<string, ushort>(capacity: 2);
|
||||
|
||||
switch (outputType)
|
||||
{
|
||||
case "UInt16":
|
||||
registers[startingAddress.ToString()] = Convert.ToUInt16(value);
|
||||
{
|
||||
regs[$"{startingAddress}"] = Convert.ToUInt16(value);
|
||||
break;
|
||||
}
|
||||
|
||||
case "Int16":
|
||||
var int16Val = Convert.ToInt16(value);
|
||||
registers[startingAddress.ToString()] = (UInt16)int16Val; // reinterpret signed as ushort
|
||||
{
|
||||
short v = Convert.ToInt16(value);
|
||||
regs[$"{startingAddress}"] = unchecked((ushort)v); // reinterpret
|
||||
break;
|
||||
}
|
||||
|
||||
case "UInt32":
|
||||
var uint32Val = Convert.ToUInt32(value);
|
||||
registers[startingAddress.ToString()] = (UInt16)(uint32Val & 0xFFFF); // Low word
|
||||
registers[(startingAddress + 1).ToString()] = (UInt16)(uint32Val >> 16); // High word
|
||||
{
|
||||
uint v = Convert.ToUInt32(value);
|
||||
ushort hi = (ushort)(v >> 16);
|
||||
ushort lo = (ushort)(v & 0xFFFF);
|
||||
regs[$"{startingAddress}"] = hi; // HIGH word first (Modbus standard)
|
||||
regs[$"{startingAddress + 1}"] = lo; // then LOW word
|
||||
break;
|
||||
}
|
||||
|
||||
case "Int32":
|
||||
var int32Val = Convert.ToInt32(value);
|
||||
var raw = unchecked((UInt32)int32Val); // reinterprets signed int as unsigned
|
||||
registers[startingAddress.ToString()] = (UInt16)(raw & 0xFFFF);
|
||||
registers[(startingAddress + 1).ToString()] = (UInt16)(raw >> 16);
|
||||
{
|
||||
int v = Convert.ToInt32(value);
|
||||
uint raw = unchecked((uint)v); // bit-reinterpret
|
||||
ushort hi = (ushort)(raw >> 16);
|
||||
ushort lo = (ushort)(raw & 0xFFFF);
|
||||
regs[$"{startingAddress}"] = hi; // HIGH word
|
||||
regs[$"{startingAddress + 1}"] = lo; // LOW word
|
||||
break;
|
||||
}
|
||||
|
||||
case "Float": // IEEE-754 single
|
||||
{
|
||||
float f = Convert.ToSingle(value);
|
||||
// Convert to bytes, then to two big-endian 16-bit words
|
||||
var bytes = BitConverter.GetBytes(f); // little-endian on most platforms
|
||||
Array.Reverse(bytes); // to big-endian byte order
|
||||
ushort hi = (ushort)((bytes[0] << 8) | bytes[1]);
|
||||
ushort lo = (ushort)((bytes[2] << 8) | bytes[3]);
|
||||
regs[$"{startingAddress}"] = hi;
|
||||
regs[$"{startingAddress + 1}"] = lo;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new ArgumentException("Unsupported output type: " + outputType);
|
||||
throw new ArgumentException($"Unsupported output type: {outputType}");
|
||||
}
|
||||
return registers;
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
||||
private static async Task<Boolean> DataLogging(StatusRecord status, DateTime timeStamp)
|
||||
{
|
||||
var csv = status.ToCsv();
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
using InnovEnergy.Lib.Utils.Net;
|
||||
|
||||
namespace InnovEnergy.App.SinexcelCommunication;
|
||||
|
||||
public class SalimaxDevice : Ip4Address
|
||||
{
|
||||
public required DeviceState DeviceState { get; init; }
|
||||
|
||||
public override String ToString() => $"{base.ToString()} ({DeviceState})";
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), DeviceState);
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using InnovEnergy.Lib.Devices.Sinexcel_12K_TL.DataType;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using static System.Text.Json.JsonSerializer;
|
||||
|
||||
|
|
@ -17,16 +18,25 @@ public class Config
|
|||
|
||||
public required Double MinSoc { get; set; }
|
||||
public required Double GridSetPoint { get; set; }
|
||||
public required Double MaximumDischargingCurrent { get; set; }
|
||||
public required Double MaximumChargingCurrent { get; set; }
|
||||
public required WorkingMode OperatingPriority { get; set; }
|
||||
public required Int16 BatteriesCount { get; set; }
|
||||
public required Double ModbusProtcolNumber { get; set; }
|
||||
|
||||
public required S3Config? S3 { get; set; }
|
||||
|
||||
|
||||
private static String? LastSavedData { get; set; }
|
||||
|
||||
public static Config Default => new()
|
||||
{
|
||||
MinSoc = 20,
|
||||
GridSetPoint = 0,
|
||||
MaximumChargingCurrent = 180,
|
||||
MaximumDischargingCurrent = 180,
|
||||
OperatingPriority = WorkingMode.TimeChargeDischarge,
|
||||
BatteriesCount = 0,
|
||||
ModbusProtcolNumber = 1.2,
|
||||
S3 = new()
|
||||
{
|
||||
Bucket = "1-3e5b3069-214a-43ee-8d85-57d72000c19d",
|
||||
|
|
|
|||
|
|
@ -137,9 +137,9 @@ public static class Aggregator
|
|||
{
|
||||
batterySoc.Add((double)jsonObject["Battery"]["Soc"]);
|
||||
}
|
||||
if (jsonObject["PvOnDc"] != null && jsonObject["PvOnDc"]["DcWh"] != null)
|
||||
if (jsonObject["PvOnDc"] != null && jsonObject["PvOnDc"]["1"]["DcWh"] != null) // todo update to all pv
|
||||
{
|
||||
pvPowerSum.Add((double)jsonObject["PvOnDc"]["DcWh"]);
|
||||
pvPowerSum.Add((double)jsonObject["PvOnDc"]["1"]["DcWh"]);
|
||||
}
|
||||
if (jsonObject["Battery"] != null && jsonObject["Battery"]["Power"] != null)
|
||||
{
|
||||
|
|
@ -295,7 +295,7 @@ public static class Aggregator
|
|||
ChargingBatteryPower = batteryChargePower.Any() ? batteryChargePower.Average() : 0.0,
|
||||
GridExportPower = gridPowerExport.Any() ? gridPowerExport.Sum() : 0.0,
|
||||
GridImportPower = gridPowerImport.Any() ? gridPowerImport.Sum() : 0.0,
|
||||
PvPower = pvPower.Any() ? pvPower.Last() : 0.0,
|
||||
PvPower = pvPower.Any() ? pvPower.Max() : 0.0,
|
||||
HeatingPower = heatingPowerAvg.Any() ? heatingPowerAvg.Average() : 0.0,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,272 +0,0 @@
|
|||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DataCollectorWebApp;
|
||||
|
||||
public class LoginResponse
|
||||
{
|
||||
public string Token { get; set; }
|
||||
public object User { get; set; } // or a User class if needed
|
||||
public bool AccessToSalimax { get; set; }
|
||||
public bool AccessToSalidomo { get; set; }
|
||||
public bool AccessToSodiohome { get; set; }
|
||||
public bool AccessToSodistoreMax { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class Installation
|
||||
{
|
||||
//Each installation has 2 roles, a read role and a write role.
|
||||
//There are 2 keys per role a public key and a secret
|
||||
//Product can be 0 or 1, 0 for Salimax, 1 for Salidomo
|
||||
public String Name { get; set; }
|
||||
public String Location { get; set; }
|
||||
public String Region { get; set; } = "";
|
||||
public String Country { get; set; } = "";
|
||||
public String VpnIp { get; set; } = "";
|
||||
public String InstallationName { get; set; } = "";
|
||||
|
||||
public String S3Region { get; set; } = "sos-ch-dk-2";
|
||||
public String S3Provider { get; set; } = "exo.io";
|
||||
public String S3WriteKey { get; set; } = "";
|
||||
public String S3Key { get; set; } = "";
|
||||
public String S3WriteSecret { get; set; } = "";
|
||||
public String S3Secret { get; set; } = "";
|
||||
public int S3BucketId { get; set; } = 0;
|
||||
public String ReadRoleId { get; set; } = "";
|
||||
public String WriteRoleId { get; set; } = "";
|
||||
public Boolean TestingMode { get; set; } = false;
|
||||
public int Status { get; set; } = -1;
|
||||
public int Product { get; set; } = 0;
|
||||
public int Device { get; set; } = 0;
|
||||
public string SerialNumber { get; set; } = "";
|
||||
public string InverterSN { get; set; } = "";
|
||||
public string DataloggerSN { get; set; } = "";
|
||||
public String OrderNumbers { get; set; }
|
||||
public String VrmLink { get; set; } = "";
|
||||
}
|
||||
|
||||
[Controller]
|
||||
public class InstallationsController : Controller
|
||||
{
|
||||
|
||||
|
||||
|
||||
[HttpGet]
|
||||
[Route("/Installations")]
|
||||
[Produces("text/html")]
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
const string HtmlHeader = @"
|
||||
<html>
|
||||
<head>
|
||||
<title>Inesco Energy Installations Overview</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: 2rem;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
th, td {
|
||||
padding: 0.75rem;
|
||||
border: 1px solid rgb(200, 200, 200);
|
||||
text-align: left;
|
||||
}
|
||||
thead th {
|
||||
background-color: #f0f0f0;
|
||||
font-weight: bold;
|
||||
border-bottom: 2px solid #EB9486;
|
||||
}
|
||||
tbody tr:nth-child(odd) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
a {
|
||||
color: #0645AD;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.status-circle {
|
||||
display: inline-block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 50%;
|
||||
margin-left: 50%;
|
||||
}
|
||||
.status-0 { background-color: #4CAF50; } /* Green */
|
||||
.status-1 { background-color: #FF9800; } /* Orange */
|
||||
.status-2 { background-color: #F44336; } /* Red */
|
||||
|
||||
.centered {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.offline-symbol {
|
||||
font-size: 1.2rem;
|
||||
color: #F44336; /* Gray */
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 50%;
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
|
||||
.status-cell {
|
||||
text-align: center; /* center horizontally */
|
||||
vertical-align: middle; /* center vertically */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Installation Overview</h1>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class=""centered"">Name</th>
|
||||
<th class=""centered"">Product</th>
|
||||
<th class=""centered"">Location</th>
|
||||
<th class=""centered"">VPN IP</th>
|
||||
<th class=""centered"">Status</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
";
|
||||
|
||||
const string HtmlFooter = @"
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
";
|
||||
|
||||
|
||||
|
||||
string GetProductName(int productId)
|
||||
{
|
||||
return productId switch
|
||||
{
|
||||
0 => "Salimax",
|
||||
1 => "Salidomo",
|
||||
2 => "SodioHome",
|
||||
3 => "SodistoreMax",
|
||||
};
|
||||
}
|
||||
|
||||
string GetStatusHtml(int status)
|
||||
{
|
||||
if (status == -1)
|
||||
{
|
||||
return "<span class='offline-symbol' title='Offline'>×</span>";
|
||||
}
|
||||
|
||||
|
||||
var statusClass = $"status-{status}";
|
||||
var title = status switch
|
||||
{
|
||||
0 => "Online",
|
||||
1 => "Warning",
|
||||
2 => "Error",
|
||||
_ => "Unknown"
|
||||
};
|
||||
|
||||
return $"<span class='status-circle {statusClass}' title='{title}'></span>";
|
||||
}
|
||||
|
||||
|
||||
string BuildRowHtml(Installation i) => $@"
|
||||
<tr>
|
||||
<td>{i.Name}</td>
|
||||
<td>{GetProductName(i.Product)}</td>
|
||||
<td>{i.Location}</td>
|
||||
<td>{i.VpnIp}</td>
|
||||
<td>{GetStatusHtml(i.Status)}</td>
|
||||
</tr>
|
||||
";
|
||||
|
||||
var installations = await FetchInstallationsFromApi();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(HtmlHeader);
|
||||
|
||||
foreach (var i in installations)
|
||||
{
|
||||
sb.Append(BuildRowHtml(i));
|
||||
}
|
||||
|
||||
sb.Append(HtmlFooter);
|
||||
return Content(sb.ToString(), "text/html");
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Installation>?> FetchInstallationsFromApi()
|
||||
{
|
||||
|
||||
var username = "baumgartner@innov.energy";
|
||||
var password = "1234";
|
||||
|
||||
using var http = new HttpClient { BaseAddress = new Uri("https://monitor.inesco.energy/api/") };
|
||||
|
||||
// Step 1: Login
|
||||
var loginResponse = await http.PostAsync($"Login?username={username}&password={password}", null);
|
||||
if (!loginResponse.IsSuccessStatusCode)
|
||||
{
|
||||
Console.WriteLine("Login failed with status code {StatusCode}", loginResponse.StatusCode);
|
||||
return null;
|
||||
}
|
||||
|
||||
var loginData = await loginResponse.Content.ReadFromJsonAsync<LoginResponse>();
|
||||
if (loginData?.Token is null)
|
||||
{
|
||||
Console.WriteLine("Login succeeded but token was missing");
|
||||
return null;
|
||||
}
|
||||
|
||||
var token = loginData.Token;
|
||||
Console.WriteLine($"Token: {token}");
|
||||
var installations = new List<Installation>();
|
||||
|
||||
var getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=0&authToken={token}");
|
||||
|
||||
var newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
||||
if (newInstallations != null)
|
||||
{
|
||||
installations.AddRange(newInstallations);
|
||||
}
|
||||
|
||||
getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=1&authToken={token}");
|
||||
newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
||||
if (newInstallations != null)
|
||||
{
|
||||
installations.AddRange(newInstallations);
|
||||
}
|
||||
|
||||
getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=2&authToken={token}");
|
||||
newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
||||
if (newInstallations != null)
|
||||
{
|
||||
installations.AddRange(newInstallations);
|
||||
}
|
||||
|
||||
getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=3&authToken={token}");
|
||||
newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
||||
if (newInstallations != null)
|
||||
{
|
||||
installations.AddRange(newInstallations);
|
||||
}
|
||||
|
||||
|
||||
//Console.WriteLine("Installations retrieved ",installations);
|
||||
return installations;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace InnovEnergy.App.DataCollectorWebApp;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Starting DataCollectorWebApp");
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddControllers();
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapControllers();
|
||||
await app.RunAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -15,10 +15,10 @@ public partial class WITGrowatRecord
|
|||
//public BatteriesRecord? BatteriesRecords => BatteriesRecord.FromBatteries(Batteries);
|
||||
|
||||
|
||||
public ActivePower ConsumptionPower => MeterPower + InverterActivePower ;
|
||||
public ActivePower InverterActivePower => _ActivePower;
|
||||
public ReactivePower InverterReactivePower => _ReactivePower;
|
||||
public Frequency Frequency => _Frequency;
|
||||
public ActivePower ConsumptionPower => GridPower + InverterActivePower ;
|
||||
public ActivePower InverterActivePower => _activePower;
|
||||
public ReactivePower InverterReactivePower => _reactivePower;
|
||||
public Frequency Frequency => _frequency;
|
||||
|
||||
public VoltageRms GridAbLineVoltage => _GridAbLineVoltage;
|
||||
public VoltageRms GridBcLineVoltage => _GridBcLineVoltage;
|
||||
|
|
@ -27,7 +27,7 @@ public partial class WITGrowatRecord
|
|||
public CurrentRms PhaseBCurrent => _PhaseBCurrent;
|
||||
public CurrentRms PhaseCCurrent => _PhaseCCurrent;
|
||||
|
||||
public ActivePower MeterPower => _importedPowerFromGrid - _exportedPowerToGrid;
|
||||
public ActivePower GridPower => _importedPowerFromGrid - _exportedPowerToGrid;
|
||||
public ActivePower ExportedPowerToGridMeter => _exportedPowerToGrid;
|
||||
public ActivePower ImportedPowerFromGrid => _importedPowerFromGrid;
|
||||
|
||||
|
|
@ -38,34 +38,33 @@ public partial class WITGrowatRecord
|
|||
public Energy EnergyToGrid => _EnergyToGrid;
|
||||
public Energy TotalEnergyToGrid => _TotalEnergyToGrid;
|
||||
|
||||
public GrowattSystemStatus SystemOperatingMode => (GrowattSystemStatus)_SystemOperatingMode;
|
||||
public BatteryoperatinStatus BatteryOperatingMode => (BatteryoperatinStatus) _BatteryOperatingMode;
|
||||
public OperatingPriority OperatingPriority => (OperatingPriority)_OperatingPriority;
|
||||
public GrowattSystemStatus SystemOperatingMode => (GrowattSystemStatus)_systemOperatingMode;
|
||||
public BatteryoperatinStatus BatteryOperatingMode => (BatteryoperatinStatus) _batteryOperatingMode;
|
||||
public OperatingPriority OperatingMode => (OperatingPriority)_operatingPriority;
|
||||
|
||||
public UInt16 FaultMainCode => _FaultMainCode; // need to pre proceesed
|
||||
public UInt16 FaultSubCode => _FaultSubCode; // need to pre proceesed
|
||||
public UInt16 WarningMainCode => _WarningMainCode; // need to pre proceesed
|
||||
public UInt16 WarningSubCode => _WarningSubCode; // need to pre proceesed
|
||||
public UInt16 FaultMainCode => _faultMainCode; // need to pre proceesed
|
||||
public UInt16 FaultSubCode => _faultSubCode; // need to pre proceesed
|
||||
public UInt16 WarningMainCode => _warningMainCode; // need to pre proceesed
|
||||
public UInt16 WarningSubCode => _warningSubCode; // need to pre proceesed
|
||||
|
||||
public Voltage Pv1Voltage => _Pv1Voltage;
|
||||
public Current Pv1Current => _Pv1Current;
|
||||
public Voltage Pv2Voltage => _Pv2Voltage;
|
||||
public Current Pv2Current => _Pv2Current;
|
||||
public Voltage Pv3Voltage => _Pv3Voltage;
|
||||
public Current Pv3Current => _Pv3Current;
|
||||
public Voltage Pv4Voltage => _Pv4Voltage;
|
||||
public Current Pv4Current => _Pv4Current;
|
||||
public Voltage Pv5Voltage => _Pv5Voltage;
|
||||
public Current Pv5Current => _Pv5Current;
|
||||
public Voltage Pv6Voltage => _Pv6Voltage;
|
||||
public Current Pv6Current => _Pv6Current;
|
||||
public Voltage Pv1Voltage => _pv1Voltage;
|
||||
public Current Pv1Current => _pv1Current;
|
||||
public Voltage Pv2Voltage => _pv2Voltage;
|
||||
public Current Pv2Current => _pv2Current;
|
||||
public Voltage Pv3Voltage => _pv3Voltage;
|
||||
public Current Pv3Current => _pv3Current;
|
||||
public Voltage Pv4Voltage => _pv4Voltage;
|
||||
public Current Pv4Current => _pv4Current;
|
||||
public Voltage Pv5Voltage => _pv5Voltage;
|
||||
public Current Pv5Current => _pv5Current;
|
||||
public Voltage Pv6Voltage => _pv6Voltage;
|
||||
public Current Pv6Current => _pv6Current;
|
||||
|
||||
|
||||
public DcPower Pv1InpuPower => _Pv1InpuPower;
|
||||
public DcPower Pv1InpuPower => _pv1InpuPower;
|
||||
|
||||
|
||||
|
||||
public DcPower TotalPvPower => (Pv1Voltage * Pv1Current) + (Pv2Voltage * Pv2Current) +
|
||||
public DcPower PvPower => (Pv1Voltage * Pv1Current) + (Pv2Voltage * Pv2Current) +
|
||||
(Pv3Voltage * Pv3Current) + (Pv4Voltage * Pv4Current) +
|
||||
(Pv5Voltage * Pv5Current) + (Pv6Voltage * Pv6Current);
|
||||
// ********************************** Holding Registers (Control) *************************************************************
|
||||
|
|
@ -173,16 +172,16 @@ public partial class WITGrowatRecord
|
|||
set => _BatteryMaxDischargePower = value;
|
||||
}
|
||||
|
||||
public Percent ChargeCutoffSoc
|
||||
public Percent ChargeCutoffSocVoltage
|
||||
{
|
||||
get => _ChargeCutoffSoc;
|
||||
set => _ChargeCutoffSoc = (UInt16)value;
|
||||
get => _BatteryChargeCutoffVoltage;
|
||||
set => _BatteryChargeCutoffVoltage = (UInt16)value;
|
||||
}
|
||||
|
||||
public Percent DischargeCutoffSoc
|
||||
public Percent DischargeCutoffVoltage
|
||||
{
|
||||
get => _DischargeCutoffSoc;
|
||||
set => _DischargeCutoffSoc = (UInt16)value;
|
||||
get => _BatteryDischargeCutoffVoltage;
|
||||
set => _BatteryDischargeCutoffVoltage = (UInt16)value;
|
||||
}
|
||||
|
||||
public Percent LoadPriorityDischargeCutoffSoc
|
||||
|
|
@ -226,98 +225,61 @@ public partial class WITGrowatRecord
|
|||
set => _OffGridDischargeCutoffSoc = (UInt16)(value);
|
||||
}
|
||||
|
||||
public UInt16 BatteryChargeCutoffVoltage
|
||||
public UInt16 MaxSoc
|
||||
{
|
||||
get => _BatteryChargeCutoffVoltage;
|
||||
set => _BatteryChargeCutoffVoltage = value;
|
||||
get => _maxSoc;
|
||||
set => _maxSoc = value;
|
||||
}
|
||||
|
||||
public UInt16 BatteryDischargeCutoffVoltage
|
||||
public UInt16 MinSoc
|
||||
{
|
||||
get => _BatteryDischargeCutoffVoltage;
|
||||
set => _BatteryDischargeCutoffVoltage = value;
|
||||
get => _minSoc;
|
||||
set => _minSoc = value;
|
||||
}
|
||||
|
||||
public Double BatteryMaxChargeCurrent
|
||||
public Double BatteryMaxChargingCurrent
|
||||
{
|
||||
get => _BatteryMaxChargeCurrent;
|
||||
set => _BatteryMaxChargeCurrent = (UInt16)value;
|
||||
get => _batteryMaxChargingCurrent;
|
||||
set => _batteryMaxChargingCurrent = (UInt16)value;
|
||||
}
|
||||
|
||||
public Double BatteryMaxdischargeCurrent
|
||||
public Double BatteryMaxDischargingCurrent
|
||||
{
|
||||
get => _BatteryMaxdischargeCurrent;
|
||||
set => _BatteryMaxdischargeCurrent = (UInt16) value;
|
||||
get => _batteryMaxDischargingCurrent;
|
||||
set => _batteryMaxDischargingCurrent = (UInt16) value;
|
||||
}
|
||||
|
||||
public Double Battery1MaxDischargingCurrent => _batteryMaxDischargingCurrent;
|
||||
|
||||
public Double Battery1MaxChargingCurrent => _batteryMaxChargingCurrent;
|
||||
|
||||
public Percent Battery1Soc => _BatterySoc1;
|
||||
public Percent Battery1Soh => _BatterySoh1;
|
||||
public Current Battery1Current => _BatteryCurrent1;
|
||||
public Voltage Battery1Voltage => _BatteryVoltage1;
|
||||
public ActivePower Battery1Power => _BatteryPower1;
|
||||
public ActivePower Battery1MaxAllowableChargePower => _BatteryMaxAllowableChargePower1;
|
||||
public ActivePower Battery1MaxAllowableDischargePower => _BatteryMaxAllowableDischargePower1;
|
||||
public Energy Battery1DailyChargeEnergy => _DailyChargeEnergy1;
|
||||
public Energy Battery1DailyDischargeEnergy => _DailyDischargeEnergy1;
|
||||
public Energy Battery1AccumulatedChargeEnergy => _AccumulatedChargeEnergy1;
|
||||
public Energy Battery1AccumulatedDischargeEnergy => _AccumulatedDishargeEnergy1;
|
||||
public Temperature Battery1AmbientTemperature => _BatteryAmbientTemperature1;
|
||||
|
||||
public IReadOnlyList<BatteryRecord> Batteries => new List<BatteryRecord>
|
||||
{
|
||||
new BatteryRecord
|
||||
{
|
||||
Soc = _BatterySoc1,
|
||||
Soh = _BatterySoh1,
|
||||
//ClusterTotalNumber = _ClusterTotalNumber1,
|
||||
Current = _BatteryCurrent1,
|
||||
Voltage = _BatteryVoltage1,
|
||||
Power = _BatteryPower1,
|
||||
MaxAllowableChargePower = _BatteryMaxAllowableChargePower1,
|
||||
MaxAllowableDischargePower = _BatteryMaxAllowableDischargePower1,
|
||||
DailyChargeEnergy = _DailyChargeEnergy1,
|
||||
DailyDischargeEnergy = _DailyDischargeEnergy1,
|
||||
AccumulatedChargeEnergy = _AccumulatedChargeEnergy1,
|
||||
AccumulatedDischargeEnergy = _AccumulatedDishargeEnergy1,
|
||||
BatteryAmbientTemperature = _BatteryAmbientTemperature1
|
||||
public Percent Battery2Soc => _BatterySoc2;
|
||||
public Percent Battery2Soh => _BatterySoh2;
|
||||
public Current Battery2Current => _BatteryCurrent2;
|
||||
public Voltage Battery2Voltage => _BatteryVoltage2;
|
||||
public ActivePower Battery2Power => _batteryPower2;
|
||||
public ActivePower Battery2MaxAllowableChargePower => _BatteryMaxAllowableChargePower2;
|
||||
public ActivePower Battery2MaxAllowableDischargePower => _BatteryMaxAllowableDischargePower2;
|
||||
public Energy Battery2DailyChargeEnergy => _DailyChargeEnergy2;
|
||||
public Energy Battery2DailyDischargeEnergy => _DailyDischargeEnergy2;
|
||||
public Energy Battery2AccumulatedChargeEnergy => _AccumulatedChargeEnergy2;
|
||||
public Energy Battery2AccumulatedDischargeEnergy => _AccumulatedDischargeEnergy2;
|
||||
public Temperature Battery2AmbientTemperature => _BatteryAmbientTemperature2;
|
||||
|
||||
}
|
||||
/*
|
||||
new BatteryRecord
|
||||
{
|
||||
Soc = _BatterySoc2,
|
||||
Soh = _BatterySoh2,
|
||||
// ClusterTotalNumber = _ClusterTotalNumber2,
|
||||
Current = _BatteryCurrent2,
|
||||
Voltage = _BatteryVoltage2,
|
||||
Power = _BatteryPower2,
|
||||
MaxAllowableChargePower = _BatteryMaxAllowableChargePower2,
|
||||
MaxAllowableDischargePower = _BatteryMaxAllowableDischargePower2,
|
||||
DailyChargeEnergy = _DailyChargeEnergy2,
|
||||
DailyDischargeEnergy = _DailyDischargeEnergy2,
|
||||
AccumulatedChargeEnergy = _AccumulatedChargeEnergy2,
|
||||
AccumulatedDischargeEnergy = _AccumulatedDischargeEnergy2,
|
||||
BatteryAmbientTemperature = _BatteryAmbientTemperature2
|
||||
public Energy BatteryDailyChargeEnergy => _DailyChargeEnergy1 + _DailyChargeEnergy2;
|
||||
public Energy BatteryDailyDischargeEnergy => _DailyDischargeEnergy1 + _DailyDischargeEnergy2;
|
||||
|
||||
},*/
|
||||
/*
|
||||
new BatteryRecord
|
||||
{
|
||||
Soc = _BatterySoc3,
|
||||
Soh = _BatterySoh3,
|
||||
ClusterTotalNumber = _ClusterTotalNumber3,
|
||||
Current = _BatteryCurrent3,
|
||||
Voltage = _BatteryVoltage3,
|
||||
Power = _BatteryPower3,
|
||||
MaxAllowableChargePower = _BatteryMaxAllowableChargePower3,
|
||||
MaxAllowableDischargePower = _BatteryMaxAllowableDischargePower3,
|
||||
DailyChargeEnergy = _DailyChargeEnergy3,
|
||||
DailyDischargeEnergy = _DailyDischargeEnergy3
|
||||
},
|
||||
|
||||
new BatteryRecord
|
||||
{
|
||||
Soc = _BatterySoc4,
|
||||
Soh = _BatterySoh4,
|
||||
ClusterTotalNumber = _ClusterTotalNumber4,
|
||||
Current = _BatteryCurrent4,
|
||||
Voltage = _BatteryVoltage4,
|
||||
Power = _BatteryPower4,
|
||||
MaxAllowableChargePower = _BatteryMaxAllowableChargePower4,
|
||||
MaxAllowableDischargePower = _BatteryMaxAllowableDischargePower4,
|
||||
DailyChargeEnergy = _DailyChargeEnergy4,
|
||||
DailyDischargeEnergy = _DailyDischargeEnergy4
|
||||
}*/
|
||||
};
|
||||
public BatteriesRecord? BatteriesRecords => BatteriesRecord.FromBatteries(Batteries);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,36 +14,36 @@ public partial class WITGrowatRecord
|
|||
[InputRegister<Int32>(8083, Scale = 0.1)] private Int32 _exportedPowerToGrid;
|
||||
|
||||
// 31000–31009 — Operating Status Info
|
||||
[InputRegister(31000)] private UInt16 _SystemOperatingMode;
|
||||
[InputRegister(31001)] private UInt16 _BatteryOperatingMode;
|
||||
[InputRegister(31002)] private UInt16 _OperatingPriority;
|
||||
[InputRegister(31003)] private UInt16 _Reserved1;
|
||||
[InputRegister(31004)] private UInt16 _Reserved2;
|
||||
[InputRegister(31005)] private UInt16 _FaultMainCode;// Can we change this to warning?
|
||||
[InputRegister(31006)] private UInt16 _FaultSubCode; // Can we change this to warning?
|
||||
[InputRegister(31007)] private UInt16 _WarningMainCode;
|
||||
[InputRegister(31008)] private UInt16 _WarningSubCode;
|
||||
[InputRegister(31009)] private UInt16 _Reserved3;
|
||||
[InputRegister(31000)] private UInt16 _systemOperatingMode;
|
||||
[InputRegister(31001)] private UInt16 _batteryOperatingMode;
|
||||
[InputRegister(31002)] private UInt16 _operatingPriority;
|
||||
[InputRegister(31003)] private UInt16 _reserved1;
|
||||
[InputRegister(31004)] private UInt16 _reserved2;
|
||||
[InputRegister(31005)] private UInt16 _faultMainCode;// Can we change this to warning?
|
||||
[InputRegister(31006)] private UInt16 _faultSubCode; // Can we change this to warning?
|
||||
[InputRegister(31007)] private UInt16 _warningMainCode;
|
||||
[InputRegister(31008)] private UInt16 _warningSubCode;
|
||||
[InputRegister(31009)] private UInt16 _reserved3;
|
||||
// 31010–31099 — PV Parameters
|
||||
[InputRegister(31010,Scale = 0.1)] private Int16 _Pv1Voltage;
|
||||
[InputRegister(31011,Scale = 0.1)] private Int16 _Pv1Current;
|
||||
[InputRegister(31012,Scale = 0.1)] private Int16 _Pv2Voltage;
|
||||
[InputRegister(31013,Scale = 0.1)] private Int16 _Pv2Current;
|
||||
[InputRegister(31014,Scale = 0.1)] private Int16 _Pv3Voltage;
|
||||
[InputRegister(31015,Scale = 0.1)] private Int16 _Pv3Current;
|
||||
[InputRegister(31016,Scale = 0.1)] private Int16 _Pv4Voltage;
|
||||
[InputRegister(31017,Scale = 0.1)] private Int16 _Pv4Current;
|
||||
[InputRegister(31018,Scale = 0.1)] private Int16 _Pv5Voltage;
|
||||
[InputRegister(31019,Scale = 0.1)] private Int16 _Pv5Current;
|
||||
[InputRegister(31020,Scale = 0.1)] private Int16 _Pv6Voltage;
|
||||
[InputRegister(31021,Scale = 0.1)] private Int16 _Pv6Current;
|
||||
[InputRegister(31058)] private Int16 _Pv1InpuPower;
|
||||
[InputRegister(31010,Scale = 0.1)] private Int16 _pv1Voltage;
|
||||
[InputRegister(31011,Scale = 0.1)] private Int16 _pv1Current;
|
||||
[InputRegister(31012,Scale = 0.1)] private Int16 _pv2Voltage;
|
||||
[InputRegister(31013,Scale = 0.1)] private Int16 _pv2Current;
|
||||
[InputRegister(31014,Scale = 0.1)] private Int16 _pv3Voltage;
|
||||
[InputRegister(31015,Scale = 0.1)] private Int16 _pv3Current;
|
||||
[InputRegister(31016,Scale = 0.1)] private Int16 _pv4Voltage;
|
||||
[InputRegister(31017,Scale = 0.1)] private Int16 _pv4Current;
|
||||
[InputRegister(31018,Scale = 0.1)] private Int16 _pv5Voltage;
|
||||
[InputRegister(31019,Scale = 0.1)] private Int16 _pv5Current;
|
||||
[InputRegister(31020,Scale = 0.1)] private Int16 _pv6Voltage;
|
||||
[InputRegister(31021,Scale = 0.1)] private Int16 _pv6Current;
|
||||
[InputRegister(31058)] private Int16 _pv1InpuPower;
|
||||
|
||||
//— AC Side 31100 - 31199
|
||||
[InputRegister<Int32>(31100, Scale = 0.1)] private Int32 _ActivePower; // Positive: feed to grid, Negative: draw from the grid
|
||||
[InputRegister<Int32>(31102, Scale = 0.1)] private Int32 _ReactivePower; // Positive: capacitive, Negative: Inductive
|
||||
[InputRegister(31104, Scale = 0.1)] private Int16 _Reserved4;
|
||||
[InputRegister(31105, Scale = 0.01)] private UInt16 _Frequency;
|
||||
[InputRegister<Int32>(31100, Scale = 0.1)] private Int32 _activePower; // Positive: feed to grid, Negative: draw from the grid
|
||||
[InputRegister<Int32>(31102, Scale = 0.1)] private Int32 _reactivePower; // Positive: capacitive, Negative: Inductive
|
||||
[InputRegister(31104, Scale = 0.1)] private Int16 _reserved4;
|
||||
[InputRegister(31105, Scale = 0.01)] private UInt16 _frequency;
|
||||
|
||||
[InputRegister(31106, Scale = 0.1)] private UInt16 _GridAbLineVoltage;
|
||||
[InputRegister(31107, Scale = 0.1)] private UInt16 _GridBcLineVoltage;
|
||||
|
|
@ -88,7 +88,7 @@ public partial class WITGrowatRecord
|
|||
|
||||
|
||||
// 31300–31399 — Second Battery Cluster Info (incl. BDC and BMS)
|
||||
/* [InputRegister<Int32>(31300)] private Int32 _BatteryPower2; // positive Charge, Negative Discharge
|
||||
[InputRegister<Int32>(31300)] private Int32 _batteryPower2; // positive Charge, Negative Discharge
|
||||
[InputRegister<UInt32>(31302)] private UInt32 _DailyChargeEnergy2;
|
||||
[InputRegister<UInt32>(31304)] private UInt32 _AccumulatedChargeEnergy2;
|
||||
[InputRegister<UInt32>(31206)] private UInt32 _DailyDischargeEnergy2; //0.1kw
|
||||
|
|
@ -164,26 +164,26 @@ public partial class WITGrowatRecord
|
|||
//[HoldingRegister<UInt32>(30152, writable: true)] private UInt16 _Reserved11; //
|
||||
[HoldingRegister(30154, writable: true)] private UInt16 _ActivePowerPercent; // Limit percentage: [0, 100]; Default: 100; takes the smaller value of 30151 and 30154 as actual active limit; Not stored
|
||||
|
||||
[HoldingRegister(30162)] private UInt16 _PowerFactor; // [0, 2000] ∪ [18000, 20000]; Default: 20000; Actual PF = (Register Value - 10000)
|
||||
[HoldingRegister(30162)] private UInt16 _PowerFactor; // [0, 2000] ∪ [18000, 20000]; Default: 20000; Actual PF = (Register Value - 10000)
|
||||
[HoldingRegister(30203, writable : true)] private UInt16 _EmsCommunicationFailureTime; // [1,300] TODO to 30
|
||||
[HoldingRegister(30204, writable : true)] private Boolean _EnableEmsCommunicationFailureTime; // 0: disabled, 1 = enabled we should enable this TODO
|
||||
[HoldingRegister(30300)] private UInt16 _BatteryClusterIndex; // [0..3]
|
||||
[HoldingRegister(30300)] private UInt16 _BatteryClusterIndex; // [0..3]
|
||||
|
||||
[HoldingRegister<UInt32>(30400 , writable: true)] private UInt32 _BatteryMaxChargePower; //
|
||||
[HoldingRegister<UInt32>(30402 , writable: true)] private UInt32 _BatteryMaxDischargePower; //
|
||||
[HoldingRegister(30404, writable: true)] private UInt16 _ChargeCutoffSoc; //
|
||||
[HoldingRegister(30405, writable: true)] private UInt16 _DischargeCutoffSoc; //
|
||||
[HoldingRegister(30406, writable: true)] private UInt16 _LoadPriorityDischargeCutoffSoc; //
|
||||
[HoldingRegister(30407, writable: true)] private Boolean _RemotePowerControl; //
|
||||
[HoldingRegister(30408, writable: true)] private UInt16 _RemotePowerControlChargeDuration; //
|
||||
[HoldingRegister<Int16>(30409, writable: true)] private Int16 _RemoteChargDischargePower; //
|
||||
[HoldingRegister(30410, writable: true)] private Boolean _AcChargeEnable; //
|
||||
[HoldingRegister(30404, writable: true)] private UInt16 _maxSoc; //
|
||||
[HoldingRegister(30405, writable: true)] private UInt16 _minSoc; //
|
||||
[HoldingRegister(30406, writable: true)] private UInt16 _LoadPriorityDischargeCutoffSoc; //
|
||||
[HoldingRegister(30407, writable: true)] private Boolean _RemotePowerControl; //
|
||||
[HoldingRegister(30408, writable: true)] private UInt16 _RemotePowerControlChargeDuration; //
|
||||
[HoldingRegister<Int16>(30409, writable: true)] private Int16 _RemoteChargDischargePower; //
|
||||
[HoldingRegister(30410, writable: true)] private Boolean _AcChargeEnable; //
|
||||
|
||||
[HoldingRegister(30474)] private UInt16 _ActualChargeDischargePowerControlValue; //
|
||||
[HoldingRegister(30475)] private UInt16 _OffGridDischargeCutoffSoc; //
|
||||
|
||||
[HoldingRegister(30496, writable: true, Scale = 0.1)] private UInt16 _BatteryChargeCutoffVoltage; //
|
||||
[HoldingRegister(30497, writable: true, Scale = 0.1)] private UInt16 _BatteryDischargeCutoffVoltage; //
|
||||
[HoldingRegister(30498, writable: true, Scale = 0.1)] private UInt16 _BatteryMaxChargeCurrent; //
|
||||
[HoldingRegister(30499, writable: true, Scale = 0.1)] private UInt16 _BatteryMaxdischargeCurrent; //*/
|
||||
[HoldingRegister(30498, writable: true, Scale = 0.1)] private UInt16 _batteryMaxChargingCurrent; //
|
||||
[HoldingRegister(30499, writable: true, Scale = 0.1)] private UInt16 _batteryMaxDischargingCurrent; //*/
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ public class ModbusDevice<[DynamicallyAccessedMembers(All)] R> where R : notnull
|
|||
foreach (var batch in _Batches)
|
||||
{
|
||||
batch.Read(record);
|
||||
Thread.Sleep(30); // this added mainly for Growatt reading
|
||||
//Thread.Sleep(30); // this added mainly for Growatt reading
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ public class ModbusDevice<[DynamicallyAccessedMembers(All)] R> where R : notnull
|
|||
foreach (var batch in _Batches)
|
||||
{
|
||||
batch.Write(record);
|
||||
Thread.Sleep(50); // this added mainly for Growatt reading
|
||||
//Thread.Sleep(50); // this added mainly for Growatt reading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
namespace InnovEnergy.Lib.Devices.Sinexcel_12K_TL.DataType;
|
||||
|
||||
public enum SinexcelWeekDays : byte
|
||||
{
|
||||
None = 0b00000000,
|
||||
Sunday = 0b00000001,
|
||||
Monday = 0b00000010,
|
||||
Tuesday = 0b00000100,
|
||||
Wednesday= 0b00001000,
|
||||
Thursday = 0b00010000,
|
||||
Friday = 0b00100000,
|
||||
Saturday = 0b01000000,
|
||||
All = 0b01111111
|
||||
}
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using InnovEnergy.Lib.Devices.Sinexcel_12K_TL.DataType;
|
||||
using InnovEnergy.Lib.Units;
|
||||
using InnovEnergy.Lib.Units.Power;
|
||||
|
|
@ -9,6 +7,7 @@ namespace InnovEnergy.Lib.Devices.Sinexcel_12K_TL;
|
|||
public partial class SinexcelRecord
|
||||
{
|
||||
|
||||
private Int16 _factorFromKwtoW = 1000;
|
||||
// ───────────────────────────────────────────────
|
||||
// Public API — Decoded Float Values
|
||||
// ───────────────────────────────────────────────
|
||||
|
|
@ -30,17 +29,17 @@ public partial class SinexcelRecord
|
|||
public Current GridCPhaseCurrent => UIntToFloat(_grid_C_Phase_Current);
|
||||
public Current GridNWireCurrent => UIntToFloat(_grid_N_Wire_Current);
|
||||
|
||||
public ApparentPower GridAPhaseApparentPower => UIntToFloat(_gridAPhaseApparentPower);
|
||||
public ApparentPower GridBPhaseApparentPower => UIntToFloat(_gridBPhaseApparentPower);
|
||||
public ApparentPower GridCPhaseApparentPower => UIntToFloat(_gridCPhaseApparentPower);
|
||||
public ApparentPower GridAPhaseApparentPower => UIntToFloat(_gridAPhaseApparentPower) * _factorFromKwtoW;
|
||||
public ApparentPower GridBPhaseApparentPower => UIntToFloat(_gridBPhaseApparentPower) * _factorFromKwtoW;
|
||||
public ApparentPower GridCPhaseApparentPower => UIntToFloat(_gridCPhaseApparentPower) * _factorFromKwtoW;
|
||||
|
||||
public ActivePower GridAPhaseActivePower => UIntToFloat(_gridAPhaseActivePower);
|
||||
public ActivePower GridBPhaseActivePower => UIntToFloat(_gridBPhaseActivePower);
|
||||
public ActivePower GridCPhaseActivePower => UIntToFloat(_gridCPhaseActivePower);
|
||||
public ActivePower GridAPhaseActivePower => UIntToFloat(_gridAPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower GridBPhaseActivePower => UIntToFloat(_gridBPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower GridCPhaseActivePower => UIntToFloat(_gridCPhaseActivePower) * _factorFromKwtoW;
|
||||
|
||||
public ReactivePower GridAPhaseReactivePower => UIntToFloat(_gridAPhaseReactivePower);
|
||||
public ReactivePower GridBPhaseReactivePower => UIntToFloat(_gridBPhaseReactivePower);
|
||||
public ReactivePower GridCPhaseReactivePower => UIntToFloat(_gridCPhaseReactivePower);
|
||||
public ReactivePower GridAPhaseReactivePower => UIntToFloat(_gridAPhaseReactivePower) * _factorFromKwtoW;
|
||||
public ReactivePower GridBPhaseReactivePower => UIntToFloat(_gridBPhaseReactivePower) * _factorFromKwtoW;
|
||||
public ReactivePower GridCPhaseReactivePower => UIntToFloat(_gridCPhaseReactivePower) * _factorFromKwtoW;
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Load Measurements
|
||||
|
|
@ -60,17 +59,19 @@ public partial class SinexcelRecord
|
|||
public Current LoadCPhaseCurrent => UIntToFloat(_loadCPhaseCurrent);
|
||||
public Current LoadNWireCurrent => UIntToFloat(_loadNWireCurrent);
|
||||
|
||||
public ApparentPower LoadAPhaseApparentPower => UIntToFloat(_loadAPhaseApparentPower);
|
||||
public ApparentPower LoadBPhaseApparentPower => UIntToFloat(_loadBPhaseApparentPower);
|
||||
public ApparentPower LoadCPhaseApparentPower => UIntToFloat(_loadCPhaseApparentPower);
|
||||
public ApparentPower LoadAPhaseApparentPower => UIntToFloat(_loadAPhaseApparentPower) * _factorFromKwtoW;
|
||||
public ApparentPower LoadBPhaseApparentPower => UIntToFloat(_loadBPhaseApparentPower) * _factorFromKwtoW;
|
||||
public ApparentPower LoadCPhaseApparentPower => UIntToFloat(_loadCPhaseApparentPower) * _factorFromKwtoW;
|
||||
|
||||
public ActivePower LoadAPhaseActivePower => UIntToFloat(_loadAPhaseActivePower);
|
||||
public ActivePower LoadBPhaseActivePower => UIntToFloat(_loadBPhaseActivePower);
|
||||
public ActivePower LoadCPhaseActivePower => UIntToFloat(_loadCPhaseActivePower);
|
||||
public ActivePower LoadAPhaseActivePower => UIntToFloat(_loadAPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower LoadBPhaseActivePower => UIntToFloat(_loadBPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower LoadCPhaseActivePower => UIntToFloat(_loadCPhaseActivePower) * _factorFromKwtoW;
|
||||
|
||||
public ReactivePower LoadAPhaseReactivePower => UIntToFloat(_loadAPhaseReactivePower);
|
||||
public ReactivePower LoadBPhaseReactivePower => UIntToFloat(_loadBPhaseReactivePower);
|
||||
public ReactivePower LoadCPhaseReactivePower => UIntToFloat(_loadCPhaseReactivePower);
|
||||
public ActivePower ConsumptionPower => TotalLoadPower;
|
||||
|
||||
public ReactivePower LoadAPhaseReactivePower => UIntToFloat(_loadAPhaseReactivePower) * _factorFromKwtoW;
|
||||
public ReactivePower LoadBPhaseReactivePower => UIntToFloat(_loadBPhaseReactivePower) * _factorFromKwtoW;
|
||||
public ReactivePower LoadCPhaseReactivePower => UIntToFloat(_loadCPhaseReactivePower) * _factorFromKwtoW;
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Inverter Measurements
|
||||
|
|
@ -83,9 +84,11 @@ public partial class SinexcelRecord
|
|||
public Voltage InverterBcWireVoltage => UIntToFloat(_inverterBCWireVoltage);
|
||||
public Voltage InverterCaWireVoltage => UIntToFloat(_inverterCAWireVoltage);
|
||||
|
||||
public ActivePower InverterAPhaseActivePower => UIntToFloat(_inverterAPhaseActivePower);
|
||||
public ActivePower InverterBPhaseActivePower => UIntToFloat(_inverterBPhaseActivePower);
|
||||
public ActivePower InverterCPhaseActivePower => UIntToFloat(_inverterCPhaseActivePower);
|
||||
public ActivePower InverterAPhaseActivePower => UIntToFloat(_inverterAPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower InverterBPhaseActivePower => UIntToFloat(_inverterBPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower InverterCPhaseActivePower => UIntToFloat(_inverterCPhaseActivePower) * _factorFromKwtoW;
|
||||
|
||||
public ActivePower InverterActivePower => InverterAPhaseActivePower + InverterBPhaseActivePower + InverterCPhaseActivePower;
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// DC/AC Temperature Sensors (°C)
|
||||
|
|
@ -99,12 +102,14 @@ public partial class SinexcelRecord
|
|||
// ───────────────────────────────────────────────
|
||||
// Date / Time Information
|
||||
// ───────────────────────────────────────────────
|
||||
public Single Year => UIntToFloat(_year);
|
||||
public Single Month => UIntToFloat(_month);
|
||||
public Single Day => UIntToFloat(_day);
|
||||
public Single Hour => UIntToFloat(_hour);
|
||||
public Single Minute => UIntToFloat(_minute);
|
||||
public Single Second => UIntToFloat(_second);
|
||||
public UInt16 Year => (UInt16) ConvertBitPatternToFloat(_year);
|
||||
public UInt16 Month => (UInt16) ConvertBitPatternToFloat(_month);
|
||||
public UInt16 Day => (UInt16) ConvertBitPatternToFloat(_day);
|
||||
public UInt16 Hour => (UInt16) ConvertBitPatternToFloat(_hour);
|
||||
public UInt16 Minute => (UInt16) ConvertBitPatternToFloat(_minute);
|
||||
public UInt16 Second => (UInt16) ConvertBitPatternToFloat(_second);
|
||||
|
||||
public DateTime SystemDateTime => new(Year, Month, Day, Hour, Minute, Second);
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Diesel Generator Measurements
|
||||
|
|
@ -112,9 +117,9 @@ public partial class SinexcelRecord
|
|||
public Voltage DieselGenAPhaseVoltage => ConvertBitPatternToFloat(_dieselGenAPhaseVoltage);
|
||||
public Voltage DieselGenBPhaseVoltage => ConvertBitPatternToFloat(_dieselGenBPhaseVoltage);
|
||||
public Voltage DieselGenCPhaseVoltage => ConvertBitPatternToFloat(_dieselGenCPhaseVoltage);
|
||||
public Voltage DieselGenABWireVoltage => ConvertBitPatternToFloat(_dieselGenABWireVoltage);
|
||||
public Voltage DieselGenBCWireVoltage => ConvertBitPatternToFloat(_dieselGenBCWireVoltage);
|
||||
public Voltage DieselGenCAWireVoltage => ConvertBitPatternToFloat(_dieselGenCAWireVoltage);
|
||||
public Voltage DieselGenAbWireVoltage => ConvertBitPatternToFloat(_dieselGenABWireVoltage);
|
||||
public Voltage DieselGenBcWireVoltage => ConvertBitPatternToFloat(_dieselGenBCWireVoltage);
|
||||
public Voltage DieselGenCaWireVoltage => ConvertBitPatternToFloat(_dieselGenCAWireVoltage);
|
||||
|
||||
public Frequency DieselGenVoltageFrequency => ConvertBitPatternToFloat(_dieselGenVoltageFrequency);
|
||||
|
||||
|
|
@ -123,38 +128,39 @@ public partial class SinexcelRecord
|
|||
public Current DieselGenCPhaseCurrent => ConvertBitPatternToFloat(_dieselGenCPhaseCurrent);
|
||||
public Current DieselGenNWireCurrent => ConvertBitPatternToFloat(_dieselGenNWireCurrent);
|
||||
|
||||
public ApparentPower DieselGenAPhaseApparentPower => ConvertBitPatternToFloat(_dieselGenAPhaseApparentPower);
|
||||
public ApparentPower DieselGenBPhaseApparentPower => ConvertBitPatternToFloat(_dieselGenBPhaseApparentPower);
|
||||
public ApparentPower DieselGenCPhaseApparentPower => ConvertBitPatternToFloat(_dieselGenCPhaseApparentPower);
|
||||
public ApparentPower DieselGenAPhaseApparentPower => ConvertBitPatternToFloat(_dieselGenAPhaseApparentPower) * _factorFromKwtoW;
|
||||
public ApparentPower DieselGenBPhaseApparentPower => ConvertBitPatternToFloat(_dieselGenBPhaseApparentPower) * _factorFromKwtoW;
|
||||
public ApparentPower DieselGenCPhaseApparentPower => ConvertBitPatternToFloat(_dieselGenCPhaseApparentPower) * _factorFromKwtoW;
|
||||
|
||||
public ActivePower DieselGenAPhaseActivePower => ConvertBitPatternToFloat(_dieselGenAPhaseActivePower);
|
||||
public ActivePower DieselGenBPhaseActivePower => ConvertBitPatternToFloat(_dieselGenBPhaseActivePower);
|
||||
public ActivePower DieselGenCPhaseActivePower => ConvertBitPatternToFloat(_dieselGenCPhaseActivePower);
|
||||
public ActivePower DieselGenAPhaseActivePower => ConvertBitPatternToFloat(_dieselGenAPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower DieselGenBPhaseActivePower => ConvertBitPatternToFloat(_dieselGenBPhaseActivePower) * _factorFromKwtoW;
|
||||
public ActivePower DieselGenCPhaseActivePower => ConvertBitPatternToFloat(_dieselGenCPhaseActivePower) * _factorFromKwtoW;
|
||||
|
||||
public ReactivePower DieselGenAPhaseReactivePower => ConvertBitPatternToFloat(_dieselGenAPhaseReactivePower);
|
||||
public ReactivePower DieselGenBPhaseReactivePower => ConvertBitPatternToFloat(_dieselGenBPhaseReactivePower);
|
||||
public ReactivePower DieselGenCPhaseReactivePower => ConvertBitPatternToFloat(_dieselGenCPhaseReactivePower);
|
||||
public ReactivePower DieselGenAPhaseReactivePower => ConvertBitPatternToFloat(_dieselGenAPhaseReactivePower) * _factorFromKwtoW;
|
||||
public ReactivePower DieselGenBPhaseReactivePower => ConvertBitPatternToFloat(_dieselGenBPhaseReactivePower) * _factorFromKwtoW;
|
||||
public ReactivePower DieselGenCPhaseReactivePower => ConvertBitPatternToFloat(_dieselGenCPhaseReactivePower) * _factorFromKwtoW;
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Photovoltaic and Battery Measurements
|
||||
// ───────────────────────────────────────────────
|
||||
public Voltage PvVoltage1 => ConvertBitPatternToFloat(_pvVoltage1);
|
||||
public Current PvCurrent1 => ConvertBitPatternToFloat(_pvCurrent1);
|
||||
public ActivePower PvPower1 => ConvertBitPatternToFloat(_pvPower1);
|
||||
public ActivePower PvPower1 => ConvertBitPatternToFloat(_pvPower1) *_factorFromKwtoW;
|
||||
public Voltage PvVoltage2 => ConvertBitPatternToFloat(_pvVoltage2);
|
||||
public Current PvCurrent2 => ConvertBitPatternToFloat(_pvCurrent2);
|
||||
public ActivePower PvPower2 => ConvertBitPatternToFloat(_pvPower2);
|
||||
public ActivePower PvPower2 => ConvertBitPatternToFloat(_pvPower2) * _factorFromKwtoW;
|
||||
|
||||
public Voltage BatteryVoltage1 => ConvertBitPatternToFloat(_batteryVoltage1);
|
||||
public Current BatteryCurrent1 => ConvertBitPatternToFloat(_batteryCurrent1);
|
||||
public ActivePower BatteryPower1 => ConvertBitPatternToFloat(_batteryPower1);
|
||||
public Percent BatterySoc1 => ConvertBitPatternToFloat(_batterySoc1);
|
||||
public float BatteryFullLoadDuration1 => ConvertBitPatternToFloat(_batteryFullLoadDuration1);
|
||||
|
||||
public Voltage BatteryVoltage2 => ConvertBitPatternToFloat(_batteryVoltage2);
|
||||
public Current BatteryCurrent2 => ConvertBitPatternToFloat(_batteryCurrent2);
|
||||
public ActivePower BatteryPower2 => ConvertBitPatternToFloat(_batteryPower2);
|
||||
public Percent BatterySoc2 => ConvertBitPatternToFloat(_batterySoc2);
|
||||
public Voltage Battery1Voltage => ConvertBitPatternToFloat(_batteryVoltage1);
|
||||
public Current Battery1Current => ConvertBitPatternToFloat(_batteryCurrent1);
|
||||
public ActivePower Battery1Power => ConvertBitPatternToFloat(_batteryPower1) * _factorFromKwtoW;
|
||||
public Percent Battery1Soc => ConvertBitPatternToFloat(_batterySoc1);
|
||||
public float BatteryFullLoadDuration1 => ConvertBitPatternToFloat(_batteryFullLoadDuration1); // this is in hour
|
||||
|
||||
public Voltage Battery2Voltage => ConvertBitPatternToFloat(_batteryVoltage2);
|
||||
public Current Battery2Current => ConvertBitPatternToFloat(_batteryCurrent2);
|
||||
public ActivePower Battery2Power => ConvertBitPatternToFloat(_batteryPower2) * _factorFromKwtoW;
|
||||
public Percent Battery2Soc => ConvertBitPatternToFloat(_batterySoc2);
|
||||
public float BatteryFullLoadDuration2 => ConvertBitPatternToFloat(_batteryFullLoadDuration2);
|
||||
|
||||
public Temperature DcdcTemperature1 => ConvertBitPatternToFloat(_dcdcTemperature1);
|
||||
|
|
@ -166,8 +172,8 @@ public partial class SinexcelRecord
|
|||
// ───────────────────────────────────────────────
|
||||
// Energy and Power Summary
|
||||
// ───────────────────────────────────────────────
|
||||
public Energy ElectricityPurchased => ConvertBitPatternToFloat(_electricityPurchased);
|
||||
public Energy ElectricityFed => ConvertBitPatternToFloat(_electricityFed);
|
||||
public Energy TotalEnergyToUser => ConvertBitPatternToFloat(_electricityPurchased);
|
||||
public Energy TotalEnergyToGrid => ConvertBitPatternToFloat(_electricityFed);
|
||||
public Energy SelfGeneratedElectricity => ConvertBitPatternToFloat(_selfGeneratedElectricity);
|
||||
public Energy BatteryCharge => ConvertBitPatternToFloat(_batteryCharge);
|
||||
public Energy BatteryDischarge => ConvertBitPatternToFloat(_batteryDischarge);
|
||||
|
|
@ -175,21 +181,21 @@ public partial class SinexcelRecord
|
|||
public Energy DailySelfGeneratedElectricity => ConvertBitPatternToFloat(_dailySelfGeneratedElectricity);
|
||||
public Energy DailyElectricityPurchased => ConvertBitPatternToFloat(_dailyElectricityPurchased);
|
||||
public Energy DailyElectricityFed => ConvertBitPatternToFloat(_dailyElectricityFed);
|
||||
public Energy DailyBatteryCharge => ConvertBitPatternToFloat(_dailyBatteryCharge);
|
||||
public Energy DailyBatteryDischarge => ConvertBitPatternToFloat(_dailyBatteryDischarge);
|
||||
public Energy BatteryDailyChargeEnergy => ConvertBitPatternToFloat(_dailyBatteryCharge);
|
||||
public Energy BatteryDailyDischargeEnergy => ConvertBitPatternToFloat(_dailyBatteryDischarge);
|
||||
public Energy DailyLoadPowerConsumption => ConvertBitPatternToFloat(_dailyLoadPowerConsumption);
|
||||
public ActivePower TotalPhotovoltaicPower => ConvertBitPatternToFloat(_totalPhotovoltaicPower);
|
||||
public ActivePower TotalBatteryPower => ConvertBitPatternToFloat(_totalBatteryPower);
|
||||
public ActivePower TotalLoadPower => ConvertBitPatternToFloat(_totalLoadPower);
|
||||
public ActivePower TotalGridPower => ConvertBitPatternToFloat(_totalGridPower);
|
||||
public ActivePower ImportantLoadTotalPower => ConvertBitPatternToFloat(_importantLoadTotalPower);
|
||||
public ActivePower GeneralLoadTotalPower => ConvertBitPatternToFloat(_generalLoadTotalPower);
|
||||
public ActivePower TotalPhotovoltaicPower => ConvertBitPatternToFloat(_totalPhotovoltaicPower) * _factorFromKwtoW;
|
||||
public ActivePower TotalBatteryPower => ConvertBitPatternToFloat(_totalBatteryPower) * _factorFromKwtoW;
|
||||
public ActivePower TotalLoadPower => ConvertBitPatternToFloat(_totalLoadPower) * _factorFromKwtoW ;
|
||||
public ActivePower TotalGridPower => ConvertBitPatternToFloat(_totalGridPower) * _factorFromKwtoW ;
|
||||
public ActivePower ImportantLoadTotalPower => ConvertBitPatternToFloat(_importantLoadTotalPower)* _factorFromKwtoW;
|
||||
public ActivePower GeneralLoadTotalPower => ConvertBitPatternToFloat(_generalLoadTotalPower)* _factorFromKwtoW;
|
||||
public Voltage Pv3Voltage => ConvertBitPatternToFloat(_pv3Voltage);
|
||||
public Current Pv3Current => ConvertBitPatternToFloat(_pv3Current);
|
||||
public ActivePower Pv3Power => ConvertBitPatternToFloat(_pv3Power);
|
||||
public ActivePower Pv3Power => ConvertBitPatternToFloat(_pv3Power) * _factorFromKwtoW;
|
||||
public Voltage Pv4Voltage => ConvertBitPatternToFloat(_pv4Voltage);
|
||||
public Current Pv4Current => ConvertBitPatternToFloat(_pv4Current);
|
||||
public ActivePower Pv4Power => ConvertBitPatternToFloat(_pv4Power);
|
||||
public ActivePower Pv4Power => ConvertBitPatternToFloat(_pv4Power) * _factorFromKwtoW;
|
||||
public ActivePower GeneratorTotalPower => ConvertBitPatternToFloat(_generatorTotalPower);
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
|
|
@ -209,268 +215,269 @@ public partial class SinexcelRecord
|
|||
public ApparentPower RatedPowerKva => _ratedPower / 100f; // 0x2008 (value / 100)
|
||||
public SinexcelModel Model => (SinexcelModel)_model; // 0x200D
|
||||
|
||||
public ThreePhaseWireSystem ThreePhaseWireSystem
|
||||
{
|
||||
get => (ThreePhaseWireSystem)_threePhaseWireSystem;
|
||||
set => _threePhaseWireSystem = (UInt32)value;
|
||||
}
|
||||
|
||||
public InputFrequency InputFrequencyClass
|
||||
{
|
||||
get => (InputFrequency)_inputFrequencyClass;
|
||||
set => _inputFrequencyClass = (UInt32)value;
|
||||
}
|
||||
|
||||
//public ThreePhaseWireSystem ThreePhaseWireSystem
|
||||
//{
|
||||
// get => (ThreePhaseWireSystem)_threePhaseWireSystem;
|
||||
// //set => _threePhaseWireSystem = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public InputFrequency InputFrequencyClass
|
||||
//{
|
||||
// get => (InputFrequency)_inputFrequencyClass;
|
||||
// //set => _inputFrequencyClass = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
public WorkingMode WorkingMode
|
||||
{
|
||||
get => (WorkingMode)ConvertBitPatternToFloat(_workingMode);
|
||||
set => _workingMode = (UInt32)value;
|
||||
get => (WorkingMode)(int)BitConverter.Int32BitsToSingle(unchecked((int)_workingMode));
|
||||
set => _workingMode = BitConverter.ToUInt32(BitConverter.GetBytes((float)value), 0);
|
||||
}
|
||||
|
||||
public GridSwitchMethod GridSwitchMethod
|
||||
{
|
||||
get => (GridSwitchMethod)_methodSwitchMode;
|
||||
set => _methodSwitchMode = (UInt32)value;
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Inverter Control Configuration
|
||||
// ───────────────────────────────────────────────
|
||||
public SinexcelUnbalanceCompensation EnableOnGridUnbalanceCompensation
|
||||
{
|
||||
get => (SinexcelUnbalanceCompensation)_enableOnGridUnbalanceCompensation;
|
||||
set => _enableOnGridUnbalanceCompensation = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelTemperatureDrop TemperatureDrop
|
||||
{
|
||||
get => (SinexcelTemperatureDrop)ConvertBitPatternToFloat(_temperatureDrop);
|
||||
set => _temperatureDrop = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelHvrt Hvrt
|
||||
{
|
||||
get => (SinexcelHvrt)_hvrt;
|
||||
set => _hvrt = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelLvrt Lvrt
|
||||
{
|
||||
get => (SinexcelLvrt)_lvrt;
|
||||
set => _lvrt = (UInt32)value;
|
||||
}
|
||||
|
||||
// Fan Gear — numeric [0.5 ~ 1.0], default 1.0
|
||||
public float FanGear
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_fanGear));
|
||||
set => _fanGear = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Battery Configuration
|
||||
// ───────────────────────────────────────────────
|
||||
public SinexcelBatteryAccessMethod BatteryAccessMethod
|
||||
{
|
||||
get => (SinexcelBatteryAccessMethod)_batteryAccessMethod;
|
||||
set => _batteryAccessMethod = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelMeterAccessEnable MeterAccessEnable
|
||||
{
|
||||
get => (SinexcelMeterAccessEnable)ConvertBitPatternToFloat(_meterAccessEnable);
|
||||
set => _meterAccessEnable = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelBatteryEnable EnableBattery1
|
||||
{
|
||||
get => (SinexcelBatteryEnable)ConvertBitPatternToFloat(_enableBattery1);
|
||||
set => _enableBattery1 = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelBatteryEnable EnableBattery2
|
||||
{
|
||||
get => (SinexcelBatteryEnable)ConvertBitPatternToFloat(_enableBattery2);
|
||||
set => _enableBattery2 = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelPvEnable EnablePv1
|
||||
{
|
||||
get => (SinexcelPvEnable)ConvertBitPatternToFloat(_enablePv1);
|
||||
set => _enablePv1 = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelPvEnable EnablePv2
|
||||
{
|
||||
get => (SinexcelPvEnable)ConvertBitPatternToFloat(_enablePv2);
|
||||
set => _enablePv2 = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelBatteryType BatteryType
|
||||
{
|
||||
get => (SinexcelBatteryType)_batteryType;
|
||||
set => _batteryType = (UInt32)value;
|
||||
}
|
||||
|
||||
public float BatteryCapacity1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCapacity1));
|
||||
set => _batteryCapacity1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float MaxChargingCurrentBattery1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_maxChargingCurrentBattery1));
|
||||
set => _maxChargingCurrentBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float MaxDischargingCurrentBattery1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_maxDischargingCurrentBattery1));
|
||||
set => _maxDischargingCurrentBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float RatedBatteryVoltage1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_ratedBatteryVoltage1));
|
||||
set => _ratedBatteryVoltage1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float MinSocBattery1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_minSocBattery1));
|
||||
set => _minSocBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float SetValueBattery1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_setValueBattery1));
|
||||
set => _setValueBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public SinexcelActiveChargeDischarge ActiveChargeDischarge
|
||||
{
|
||||
get => (SinexcelActiveChargeDischarge)ConvertBitPatternToFloat(_activeChargeDischarge);
|
||||
set => _activeChargeDischarge = (UInt32)value;
|
||||
}
|
||||
|
||||
public float ActiveChargeDischargePower
|
||||
{
|
||||
get => ConvertBitPatternToFloat(_activeChargeDischargePower);
|
||||
set => _activeChargeDischargePower = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Protection & PV Mode
|
||||
// ───────────────────────────────────────────────
|
||||
public SinexcelIslandProtection EnableIslandProtection
|
||||
{
|
||||
get => (SinexcelIslandProtection)_enableIslandProtection;
|
||||
set => _enableIslandProtection = (UInt32)value;
|
||||
}
|
||||
|
||||
public SinexcelPvAccessMode PvAccessMode
|
||||
{
|
||||
get => (SinexcelPvAccessMode)_pvAccessMode;
|
||||
set => _pvAccessMode = (UInt32)value;
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// System-Level Parameters
|
||||
// ───────────────────────────────────────────────
|
||||
public float OutputVoltageAdjustmentFactor
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_outputVoltageAdjustmentFactor));
|
||||
set => _outputVoltageAdjustmentFactor = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float SetValueBatteryUndervoltage1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_setValueBatteryUndervoltage1));
|
||||
set => _setValueBatteryUndervoltage1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float InverterPowerLimit
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_inverterPowerLimit));
|
||||
set => _inverterPowerLimit = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Battery 2 Parameters
|
||||
// ───────────────────────────────────────────────
|
||||
public float Battery2Capacity
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2Capacity));
|
||||
set => _battery2Capacity = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float MaxChargingCurrentBattery2
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_maxChargingCurrentBattery2));
|
||||
set => _maxChargingCurrentBattery2 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float MaxDischargingCurrentBattery2
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_maxDischargingCurrentBattery2));
|
||||
set => _maxDischargingCurrentBattery2 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float Battery2RatedVoltage
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2RatedVoltage));
|
||||
set => _battery2RatedVoltage = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float Battery2MinSoc
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2MinSoc));
|
||||
set => _battery2MinSoc = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float Battery2OverVoltageSetting
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2OverVoltageSetting));
|
||||
set => _battery2OverVoltageSetting = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float Battery2UnderVoltageSetpoint
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2UnderVoltageSetpoint));
|
||||
set => _battery2UnderVoltageSetpoint = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Parallel / System Settings
|
||||
// ───────────────────────────────────────────────
|
||||
public SinexcelMachineMode MachineMode
|
||||
{
|
||||
get => (SinexcelMachineMode)ConvertBitPatternToFloat(_singleOrParallelMachine);
|
||||
set => _singleOrParallelMachine = (UInt32)value;
|
||||
}
|
||||
|
||||
public UInt32 NumberOfSystemModules
|
||||
{
|
||||
get => (UInt32)ConvertBitPatternToFloat(_numberOfSystemModules);
|
||||
set => _numberOfSystemModules = value;
|
||||
}
|
||||
|
||||
public UInt32 ParallelModuleMachineNumber
|
||||
{
|
||||
get => (UInt32)ConvertBitPatternToFloat(_parallelModuleMachineNumber);
|
||||
set => _parallelModuleMachineNumber = value;
|
||||
}
|
||||
|
||||
public AccreditedCountry AccreditedCountry
|
||||
{
|
||||
get => (AccreditedCountry)ConvertBitPatternToFloat(_accreditedCountries);
|
||||
set => _accreditedCountries = (UInt32)value;
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Control Commands
|
||||
// ───────────────────────────────────────────────
|
||||
//
|
||||
//public GridSwitchMethod GridSwitchMethod
|
||||
//{
|
||||
// get => (GridSwitchMethod)_methodSwitchMode;
|
||||
// //set => _methodSwitchMode = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// Inverter Control Configuration
|
||||
//// ───────────────────────────────────────────────
|
||||
//public SinexcelUnbalanceCompensation EnableOnGridUnbalanceCompensation
|
||||
//{
|
||||
// get => (SinexcelUnbalanceCompensation)_enableOnGridUnbalanceCompensation;
|
||||
// //set => _enableOnGridUnbalanceCompensation = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelTemperatureDrop TemperatureDrop
|
||||
//{
|
||||
// get => (SinexcelTemperatureDrop)ConvertBitPatternToFloat(_temperatureDrop);
|
||||
// //set => _temperatureDrop = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelHvrt Hvrt
|
||||
//{
|
||||
// get => (SinexcelHvrt)_hvrt;
|
||||
// //set => _hvrt = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelLvrt Lvrt
|
||||
//{
|
||||
// get => (SinexcelLvrt)_lvrt;
|
||||
// //set => _lvrt = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
// F//an Gear — numeric [0.5 ~ 1.0], default 1.0
|
||||
//public float FanGear
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_fanGear));
|
||||
// //set => _fanGear = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// Battery Configuration
|
||||
//// ───────────────────────────────────────────────
|
||||
//public SinexcelBatteryAccessMethod BatteryAccessMethod
|
||||
//{
|
||||
// get => (SinexcelBatteryAccessMethod)_batteryAccessMethod;
|
||||
// //set => _batteryAccessMethod = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelMeterAccessEnable MeterAccessEnable
|
||||
//{
|
||||
// get => (SinexcelMeterAccessEnable)ConvertBitPatternToFloat(_meterAccessEnable);
|
||||
// //set => _meterAccessEnable = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelBatteryEnable EnableBattery1
|
||||
//{
|
||||
// get => (SinexcelBatteryEnable)ConvertBitPatternToFloat(_enableBattery1);
|
||||
// //set => _enableBattery1 = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelBatteryEnable EnableBattery2
|
||||
//{
|
||||
// get => (SinexcelBatteryEnable)ConvertBitPatternToFloat(_enableBattery2);
|
||||
// //set => _enableBattery2 = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelPvEnable EnablePv1
|
||||
//{
|
||||
// get => (SinexcelPvEnable)ConvertBitPatternToFloat(_enablePv1);
|
||||
// //set => _enablePv1 = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelPvEnable EnablePv2
|
||||
//{
|
||||
// get => (SinexcelPvEnable)ConvertBitPatternToFloat(_enablePv2);
|
||||
// //set => _enablePv2 = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelBatteryType BatteryType
|
||||
//{
|
||||
// get => (SinexcelBatteryType)_batteryType;
|
||||
// //set => _batteryType = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public float BatteryCapacity1
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCapacity1));
|
||||
// //set => _batteryCapacity1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery1MaxChargingCurrent
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_maxChargingCurrentBattery1));
|
||||
// //set => _maxChargingCurrentBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery1MaxDischargingCurrent
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_maxDischargingCurrentBattery1));
|
||||
// //set => _maxDischargingCurrentBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float RatedBatteryVoltage1
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_ratedBatteryVoltage1));
|
||||
// //set => _ratedBatteryVoltage1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery1MinSoc
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_minSocBattery1));
|
||||
// //set => _minSocBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float SetValueBattery1
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_setValueBattery1));
|
||||
// //set => _setValueBattery1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public SinexcelActiveChargeDischarge ActiveChargeDischarge
|
||||
//{
|
||||
// get => (SinexcelActiveChargeDischarge)ConvertBitPatternToFloat(_activeChargeDischarge);
|
||||
// //set => _activeChargeDischarge = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public float ActiveChargeDischargePower
|
||||
//{
|
||||
// get => ConvertBitPatternToFloat(_activeChargeDischargePower) * _factorFromKwtoW;
|
||||
// //set => _activeChargeDischargePower = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0); // we should check this may need to convert from W to KW
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// Protection & PV Mode
|
||||
//// ───────────────────────────────────────────────
|
||||
//public SinexcelIslandProtection EnableIslandProtection
|
||||
//{
|
||||
// get => (SinexcelIslandProtection)_enableIslandProtection;
|
||||
// //set => _enableIslandProtection = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public SinexcelPvAccessMode PvAccessMode
|
||||
//{
|
||||
// get => (SinexcelPvAccessMode)_pvAccessMode;
|
||||
// //set => _pvAccessMode = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// System-Level Parameters
|
||||
//// ───────────────────────────────────────────────
|
||||
//public float OutputVoltageAdjustmentFactor
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_outputVoltageAdjustmentFactor));
|
||||
// //set => _outputVoltageAdjustmentFactor = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float SetValueBatteryUndervoltage1
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_setValueBatteryUndervoltage1));
|
||||
// //set => _setValueBatteryUndervoltage1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float InverterPowerLimit
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_inverterPowerLimit));
|
||||
// //set => _inverterPowerLimit = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// Battery 2 Parameters
|
||||
//// ───────────────────────────────────────────────
|
||||
//public float Battery2Capacity
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2Capacity));
|
||||
// //set => _battery2Capacity = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery2MaxChargingCurrent
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_maxChargingCurrentBattery2));
|
||||
// //set => _maxChargingCurrentBattery2 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery2MaxDischargingCurrent
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_maxDischargingCurrentBattery2));
|
||||
// //set => _maxDischargingCurrentBattery2 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery2RatedVoltage
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2RatedVoltage));
|
||||
// //set => _battery2RatedVoltage = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery2MinSoc
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2MinSoc));
|
||||
// //set => _battery2MinSoc = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery2OverVoltageSetting
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2OverVoltageSetting));
|
||||
// //set => _battery2OverVoltageSetting = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery2UnderVoltageSetpoint
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((int)_battery2UnderVoltageSetpoint));
|
||||
// //set => _battery2UnderVoltageSetpoint = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// Parallel / System Settings
|
||||
//// ───────────────────────────────────────────────
|
||||
//public SinexcelMachineMode MachineMode
|
||||
//{
|
||||
// get => (SinexcelMachineMode)ConvertBitPatternToFloat(_singleOrParallelMachine);
|
||||
// //set => _singleOrParallelMachine = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public UInt32 NumberOfSystemModules
|
||||
//{
|
||||
// get => (UInt32)ConvertBitPatternToFloat(_numberOfSystemModules);
|
||||
// //set => _numberOfSystemModules = value;
|
||||
//}
|
||||
//
|
||||
//public UInt32 ParallelModuleMachineNumber
|
||||
//{
|
||||
// get => (UInt32)ConvertBitPatternToFloat(_parallelModuleMachineNumber);
|
||||
// //set => _parallelModuleMachineNumber = value;
|
||||
//}
|
||||
//
|
||||
//public AccreditedCountry AccreditedCountry
|
||||
//{
|
||||
// get => (AccreditedCountry)ConvertBitPatternToFloat(_accreditedCountries);
|
||||
// //set => _accreditedCountries = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// Control Commands
|
||||
//// ───────────────────────────────────────────────
|
||||
public float PowerOn
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_powerOn));
|
||||
|
|
@ -482,45 +489,39 @@ public partial class SinexcelRecord
|
|||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_powerOff));
|
||||
set => _powerOff = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float FaultClearing
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_faultClearing));
|
||||
set => _faultClearing = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Meter & Battery Control
|
||||
// ───────────────────────────────────────────────
|
||||
public float MeterReverseManualDetection
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_meterReverseManualDetection));
|
||||
set => _meterReverseManualDetection = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public Voltage BatteryVoltage
|
||||
{
|
||||
get => (Voltage)ConvertBitPatternToFloat(_batteryVoltage);
|
||||
set => _batteryVoltage = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public SinexcelBatteryRating BatteryRating
|
||||
{
|
||||
get => (SinexcelBatteryRating)ConvertBitPatternToFloat(_batteryRating);
|
||||
set => _batteryRating = (UInt32)value;
|
||||
}
|
||||
|
||||
public float Battery1Activation
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_battery1Activation));
|
||||
set => _battery1Activation = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float Battery2Activation
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_battery2Activation));
|
||||
set => _battery2Activation = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
//
|
||||
//public float FaultClearingf
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_faultClearing));
|
||||
// // //set => _faultClearing = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//// ───────────────────────────────────────────────
|
||||
//// Meter & Battery Control
|
||||
//// ───────────────────────────────────────────────
|
||||
//public float MeterReverseManualDetection
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_meterReverseManualDetection));
|
||||
// //set => _meterReverseManualDetection = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public SinexcelBatteryRating BatteryVoltageRating
|
||||
//{
|
||||
// get => (SinexcelBatteryRating)ConvertBitPatternToFloat(_batteryVoltageRating);
|
||||
// //set => _batteryVoltageRating = (UInt32)value;
|
||||
//}
|
||||
//
|
||||
//public float Battery1Activation
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_battery1Activation));
|
||||
// //set => _battery1Activation = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
//
|
||||
//public float Battery2Activation
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_battery2Activation));
|
||||
// //set => _battery2Activation = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Electric Meter Operating State
|
||||
|
|
@ -571,23 +572,149 @@ public partial class SinexcelRecord
|
|||
// ───────────────────────────────────────────────
|
||||
public ActivePower ElectricMeterAPhaseActivePower
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_electricMeterAPhaseActivePower));
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_electricMeterAPhaseActivePower)) * _factorFromKwtoW;
|
||||
}
|
||||
|
||||
public ActivePower ElectricMeterBPhaseActivePower
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_electricMeterBPhaseActivePower));
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_electricMeterBPhaseActivePower)) * _factorFromKwtoW;
|
||||
}
|
||||
|
||||
public ActivePower ElectricMeterCPhaseActivePower
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_electricMeterCPhaseActivePower));
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_electricMeterCPhaseActivePower)) * _factorFromKwtoW;
|
||||
}
|
||||
|
||||
public ActivePower GridPower
|
||||
{
|
||||
get => ElectricMeterAPhaseActivePower + ElectricMeterBPhaseActivePower + ElectricMeterCPhaseActivePower;
|
||||
}
|
||||
|
||||
|
||||
// Energy (kW·h)
|
||||
public Energy Battery1TotalChargingEnergy => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab1TotalChargingEnergy)); // 0xB0FC
|
||||
public Energy Battery1TotalDischargedEnergy => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab1TotalDischargedEnergy)); // 0xB0FE
|
||||
|
||||
// Pack totals and status
|
||||
public Voltage Battery1PackTotalVoltage => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab1PackTotalVoltage)); // 0xB100 (0.01 V resolution per spec)
|
||||
public Current Battery1PackTotalCurrent => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab1PackTotalCurrent)); // 0xB102 (0.01 A resolution per spec)
|
||||
public Temperature Battery1Temperature => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab1Temperature)); // 0xB104 (0.01 °C resolution per spec)
|
||||
public Percent Battery1SocSecondvalue => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab1Soc)); // 0xB106 %
|
||||
public Percent Battery1Soh => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab1Soh)); // 0xB108 %
|
||||
|
||||
// Energy (kW·h)
|
||||
public float Battery2TotalChargingEnergy => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab2TotalChargingEnergy)); // 0xB1FC
|
||||
public float Battery2TotalDischargedEnergy => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab2TotalDischargedEnergy)); // 0xB1FE
|
||||
|
||||
// Pack Voltage / Current / Temperature
|
||||
public Voltage Battery2PackTotalVoltage => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab2PackTotalVoltage)); // 0xB200 (0.01 V resolution)
|
||||
public Current Battery2PackTotalCurrent => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab2PackTotalCurrent)); // 0xB202 (0.01 A resolution)
|
||||
public Temperature Battery2Socsecondvalue => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab2Soc)); // 0xB206 %
|
||||
public Percent Battery2Soh => BitConverter.Int32BitsToSingle(unchecked((Int32)_batteryCab2Soh)); // 0xB208 %
|
||||
|
||||
// Repetitive-week mask (bit-mapped 0–6 = Sun–Sat)
|
||||
//public float TimedChargeAndDischargeOff
|
||||
//{
|
||||
// get => BitConverter.Int32BitsToSingle(unchecked((Int32)_Timed_Charge_and_Discharge_Off)) ; // only 7 bits used
|
||||
// //set => _Timed_Charge_and_Discharge_Off = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
//}
|
||||
// Repetitive-week mask (bit-mapped 0–6 = Sun–Sat)
|
||||
/* public float OtherTimePeriodMode
|
||||
{
|
||||
get => _Other_time_period_mode ; // only 7 bits used
|
||||
//set => _Other_time_period_mode = (UInt32)value;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
// Repetitive-week mask (bit-mapped 0–6 = Sun–Sat)
|
||||
public SinexcelWeekDays RepetitiveWeeks
|
||||
{
|
||||
get => (SinexcelWeekDays)(_repetitiveWeeks & 0x7F); // only 7 bits used
|
||||
set => _repetitiveWeeks = (UInt32)value;
|
||||
}
|
||||
//
|
||||
// Effective start / end as UNIX timestamps
|
||||
public DateTime EffectiveStartDate
|
||||
{
|
||||
get => DateTimeOffset.FromUnixTimeSeconds(_effectiveStartDate).DateTime;
|
||||
set => _effectiveStartDate = (UInt32)new DateTimeOffset(value).ToUnixTimeSeconds();
|
||||
}
|
||||
//
|
||||
public DateTime EffectiveEndDate
|
||||
{
|
||||
get => DateTimeOffset.FromUnixTimeSeconds(_effectiveEndDate).DateTime;
|
||||
set => _effectiveEndDate = (UInt32)new DateTimeOffset(value).ToUnixTimeSeconds();
|
||||
}
|
||||
// // Charging power during time period 1 (kW)
|
||||
public float ChargingPowerPeriod1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_chargingPowerPeriod1));
|
||||
set => _chargingPowerPeriod1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
public float DishargingPowerPeriod1
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle(unchecked((Int32)_dischargingPowerPeriod1));
|
||||
set => _dischargingPowerPeriod1 = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
|
||||
}
|
||||
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Charging period 1
|
||||
// ───────────────────────────────────────────────
|
||||
public TimeSpan ChargeStartTimePeriod1
|
||||
{
|
||||
get => ConvertToTimeSpan(_chargeStartTimePeriod1);
|
||||
set => _chargeStartTimePeriod1 = ConvertFromTimeSpan(value);
|
||||
}
|
||||
public TimeSpan ChargeEndTimePeriod1
|
||||
{
|
||||
get => ConvertToTimeSpan(_chargeEndTimePeriod1);
|
||||
set => _chargeEndTimePeriod1 = ConvertFromTimeSpan(value);
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Discharging period 1
|
||||
// ───────────────────────────────────────────────
|
||||
public TimeSpan DischargeStartTimePeriod1
|
||||
{
|
||||
get => ConvertToTimeSpan(_dischargeStartTimePeriod1);
|
||||
set => _dischargeStartTimePeriod1 = ConvertFromTimeSpan(value);
|
||||
}
|
||||
//
|
||||
public TimeSpan DischargeEndTimePeriod1
|
||||
{
|
||||
get => ConvertToTimeSpan(_dischargeEndTimePeriod1);
|
||||
set => _dischargeEndTimePeriod1 = ConvertFromTimeSpan(value);
|
||||
}
|
||||
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Conversion methodes
|
||||
// ───────────────────────────────────────────────
|
||||
|
||||
private static TimeSpan ConvertToTimeSpan(UInt32 raw)
|
||||
{
|
||||
// raw is IEEE754 float bits, e.g. 0x44640000 for 912.0
|
||||
float f = BitConverter.Int32BitsToSingle(unchecked((int)raw));
|
||||
int hhmm = (int)Math.Round(f);
|
||||
|
||||
int hours = hhmm / 100;
|
||||
int minutes = hhmm % 100;
|
||||
|
||||
return new TimeSpan(hours, minutes, 0);
|
||||
}
|
||||
|
||||
private static UInt32 ConvertFromTimeSpan(TimeSpan time)
|
||||
{
|
||||
int hhmm = time.Hours * 100 + time.Minutes; // e.g. 9*100+12 = 912
|
||||
float f = (float)hhmm; // 912.0f
|
||||
// convert float to raw IEEE754 bits
|
||||
return BitConverter.ToUInt32(BitConverter.GetBytes(f), 0); // e.g. 0x44640000
|
||||
}
|
||||
|
||||
|
||||
private static Single IntToFloat(Int32 intValue)
|
||||
{
|
||||
byte[] intBytes = BitConverter.GetBytes(intValue);
|
||||
|
|
|
|||
|
|
@ -226,71 +226,70 @@ public partial class SinexcelRecord
|
|||
// ───────────────────────────────────────────────
|
||||
// System configuration / operation registers
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(12294, writable: true)] private UInt32 _threePhaseWireSystem; // 0x3006
|
||||
[HoldingRegister<UInt32>(12296, writable: true)] private UInt32 _remainnotused; // 0x3008
|
||||
[HoldingRegister<UInt32>(12298, writable: true)] private UInt32 _inputFrequencyClass; // 0x300A
|
||||
//[HoldingRegister<UInt32>(12294, writable: true)] private UInt32 _threePhaseWireSystem; // 0x3006
|
||||
//[HoldingRegister<UInt32>(12296, writable: true)] private UInt32 _remainnotused; // 0x3008
|
||||
//[HoldingRegister<UInt32>(12298, writable: true)] private UInt32 _inputFrequencyClass; // 0x300A
|
||||
[HoldingRegister<UInt32>(12300, writable: true)] private UInt32 _workingMode; // 0x300C
|
||||
[HoldingRegister<UInt32>(12302, writable: true)] private UInt32 _methodSwitchMode; // 0x300E
|
||||
//[HoldingRegister<UInt32>(12302, writable: true)] private UInt32 _methodSwitchMode; // 0x300E
|
||||
// ───────────────────────────────────────────────
|
||||
// Inverter Control and Protection Configuration
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(12304, writable: true)] private UInt32 _enableOnGridUnbalanceCompensation; // 0x3010
|
||||
[HoldingRegister<UInt32>(12306, writable: true)] private UInt32 _temperatureDrop; // 0x3012
|
||||
[HoldingRegister<UInt32>(12308, writable: true)] private UInt32 _hvrt; // 0x3014
|
||||
[HoldingRegister<UInt32>(12310, writable: true)] private UInt32 _lvrt; // 0x3016
|
||||
[HoldingRegister<UInt32>(12312, writable: true)] private UInt32 _fanGear; // 0x3018
|
||||
//[HoldingRegister<UInt32>(12304, writable: true)] private UInt32 _enableOnGridUnbalanceCompensation; // 0x3010
|
||||
//[HoldingRegister<UInt32>(12306, writable: true)] private UInt32 _temperatureDrop; // 0x3012
|
||||
//[HoldingRegister<UInt32>(12308, writable: true)] private UInt32 _hvrt; // 0x3014
|
||||
//[HoldingRegister<UInt32>(12310, writable: true)] private UInt32 _lvrt; // 0x3016
|
||||
//[HoldingRegister<UInt32>(12312, writable: true)] private UInt32 _fanGear; // 0x3018
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Battery & PV Configuration
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(12336, writable: true)] private UInt32 _batteryAccessMethod; // 0x3030
|
||||
[HoldingRegister<UInt32>(12338, writable: true)] private UInt32 _meterAccessEnable; // 0x3032
|
||||
[HoldingRegister<UInt32>(12340, writable: true)] private UInt32 _enableBattery1; // 0x3034
|
||||
[HoldingRegister<UInt32>(12342, writable: true)] private UInt32 _enableBattery2; // 0x3036
|
||||
[HoldingRegister<UInt32>(12344, writable: true)] private UInt32 _enablePv1; // 0x3038
|
||||
[HoldingRegister<UInt32>(12346, writable: true)] private UInt32 _enablePv2; // 0x303A
|
||||
[HoldingRegister<UInt32>(12348, writable: true)] private UInt32 _batteryType; // 0x303C
|
||||
[HoldingRegister<UInt32>(12350, writable: true)] private UInt32 _batteryCapacity1; // 0x303E
|
||||
[HoldingRegister<UInt32>(12352, writable: true)] private UInt32 _maxChargingCurrentBattery1; // 0x3040
|
||||
[HoldingRegister<UInt32>(12354, writable: true)] private UInt32 _maxDischargingCurrentBattery1; // 0x3042
|
||||
[HoldingRegister<UInt32>(12362, writable: true)] private UInt32 _ratedBatteryVoltage1; // 0x304A
|
||||
[HoldingRegister<UInt32>(12358, writable: true)] private UInt32 _minSocBattery1; // 0x3046
|
||||
[HoldingRegister<UInt32>(12360, writable: true)] private UInt32 _setValueBattery1; // 0x3048
|
||||
[HoldingRegister<UInt32>(12364, writable: true)] private UInt32 _activeChargeDischarge; // 0x304A
|
||||
[HoldingRegister<UInt32>(12366, writable: true)] private UInt32 _activeChargeDischargePower; // 0x304C
|
||||
[HoldingRegister<UInt32>(12380, writable: true)] private UInt32 _enableIslandProtection; // 0x305C
|
||||
[HoldingRegister<UInt32>(12382, writable: true)] private UInt32 _pvAccessMode; // 0x305E
|
||||
//[HoldingRegister<UInt32>(12336, writable: true)] private UInt32 _batteryAccessMethod; // 0x3030
|
||||
//[HoldingRegister<UInt32>(12338, writable: true)] private UInt32 _meterAccessEnable; // 0x3032
|
||||
//[HoldingRegister<UInt32>(12340, writable: true)] private UInt32 _enableBattery1; // 0x3034
|
||||
//[HoldingRegister<UInt32>(12342, writable: true)] private UInt32 _enableBattery2; // 0x3036
|
||||
//[HoldingRegister<UInt32>(12344, writable: true)] private UInt32 _enablePv1; // 0x3038
|
||||
//[HoldingRegister<UInt32>(12346, writable: true)] private UInt32 _enablePv2; // 0x303A
|
||||
//[HoldingRegister<UInt32>(12348, writable: true)] private UInt32 _batteryType; // 0x303C
|
||||
//[HoldingRegister<UInt32>(12350, writable: true)] private UInt32 _batteryCapacity1; // 0x303E
|
||||
//[HoldingRegister<UInt32>(12352, writable: true)] private UInt32 _maxChargingCurrentBattery1; // 0x3040
|
||||
//[HoldingRegister<UInt32>(12354, writable: true)] private UInt32 _maxDischargingCurrentBattery1; // 0x3042
|
||||
//[HoldingRegister<UInt32>(12362, writable: true)] private UInt32 _ratedBatteryVoltage1; // 0x304A
|
||||
//[HoldingRegister<UInt32>(12358, writable: true)] private UInt32 _minSocBattery1; // 0x3046
|
||||
//[HoldingRegister<UInt32>(12360, writable: true)] private UInt32 _setValueBattery1; // 0x3048
|
||||
//[HoldingRegister<UInt32>(12364, writable: true)] private UInt32 _activeChargeDischarge; // 0x304A
|
||||
//[HoldingRegister<UInt32>(12366, writable: true)] private UInt32 _activeChargeDischargePower; // 0x304C
|
||||
//[HoldingRegister<UInt32>(12380, writable: true)] private UInt32 _enableIslandProtection; // 0x305C
|
||||
//[HoldingRegister<UInt32>(12382, writable: true)] private UInt32 _pvAccessMode; // 0x305E
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// System & Battery-2 Configuration
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(12384, writable: true)] private UInt32 _outputVoltageAdjustmentFactor; // 0x3060
|
||||
[HoldingRegister<UInt32>(12386, writable: true)] private UInt32 _setValueBatteryUndervoltage1; // 0x3062
|
||||
[HoldingRegister<UInt32>(12388, writable: true)] private UInt32 _inverterPowerLimit; // 0x3064
|
||||
[HoldingRegister<UInt32>(12400, writable: true)] private UInt32 _battery2Capacity; // 0x30B0
|
||||
[HoldingRegister<UInt32>(12402, writable: true)] private UInt32 _maxChargingCurrentBattery2; // 0x30B2
|
||||
[HoldingRegister<UInt32>(12404, writable: true)] private UInt32 _maxDischargingCurrentBattery2; // 0x30B4
|
||||
[HoldingRegister<UInt32>(12406, writable: true)] private UInt32 _battery2RatedVoltage; // 0x30B6
|
||||
[HoldingRegister<UInt32>(12408, writable: true)] private UInt32 _battery2MinSoc; // 0x30B8
|
||||
[HoldingRegister<UInt32>(12410, writable: true)] private UInt32 _battery2OverVoltageSetting; // 0x30BA
|
||||
[HoldingRegister<UInt32>(12412, writable: true)] private UInt32 _battery2UnderVoltageSetpoint; // 0x30BC
|
||||
|
||||
[HoldingRegister<UInt32>(12414, writable: true)] private UInt32 _singleOrParallelMachine; // 0x30BE
|
||||
[HoldingRegister<UInt32>(12416, writable: true)] private UInt32 _numberOfSystemModules; // 0x30C0
|
||||
[HoldingRegister<UInt32>(12418, writable: true)] private UInt32 _parallelModuleMachineNumber; // 0x30C2
|
||||
[HoldingRegister<UInt32>(12420, writable: true)] private UInt32 _accreditedCountries; // 0x30C4
|
||||
//[HoldingRegister<UInt32>(12384, writable: true)] private UInt32 _outputVoltageAdjustmentFactor; // 0x3060
|
||||
//[HoldingRegister<UInt32>(12386, writable: true)] private UInt32 _setValueBatteryUndervoltage1; // 0x3062
|
||||
//[HoldingRegister<UInt32>(12388, writable: true)] private UInt32 _inverterPowerLimit; // 0x3064
|
||||
//[HoldingRegister<UInt32>(12400, writable: true)] private UInt32 _battery2Capacity; // 0x30B0
|
||||
//[HoldingRegister<UInt32>(12402, writable: true)] private UInt32 _maxChargingCurrentBattery2; // 0x30B2
|
||||
//[HoldingRegister<UInt32>(12404, writable: true)] private UInt32 _maxDischargingCurrentBattery2; // 0x30B4
|
||||
//[HoldingRegister<UInt32>(12406, writable: true)] private UInt32 _battery2RatedVoltage; // 0x30B6
|
||||
//[HoldingRegister<UInt32>(12408, writable: true)] private UInt32 _battery2MinSoc; // 0x30B8
|
||||
//[HoldingRegister<UInt32>(12410, writable: true)] private UInt32 _battery2OverVoltageSetting; // 0x30BA
|
||||
//[HoldingRegister<UInt32>(12412, writable: true)] private UInt32 _battery2UnderVoltageSetpoint; // 0x30BC
|
||||
//
|
||||
//[HoldingRegister<UInt32>(12414, writable: true)] private UInt32 _singleOrParallelMachine; // 0x30BE
|
||||
//[HoldingRegister<UInt32>(12416, writable: true)] private UInt32 _numberOfSystemModules; // 0x30C0
|
||||
//[HoldingRegister<UInt32>(12418, writable: true)] private UInt32 _parallelModuleMachineNumber; // 0x30C2
|
||||
//[HoldingRegister<UInt32>(12420, writable: true)] private UInt32 _accreditedCountries; // 0x30C4
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// System Control & Diagnostic Registers
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(15426, writable: true)] private UInt32 _powerOn; // 0x3C42
|
||||
[HoldingRegister<UInt32>(15428, writable: true)] private UInt32 _powerOff; // 0x3C44
|
||||
[HoldingRegister<UInt32>(15430, writable: true)] private UInt32 _faultClearing; // 0x3C46
|
||||
[HoldingRegister<UInt32>(15518, writable: true)] private UInt32 _meterReverseManualDetection; // 0x3C9E
|
||||
[HoldingRegister<UInt32>(15520, writable: true)] private UInt32 _batteryVoltage; // 0x3CA0
|
||||
[HoldingRegister<UInt32>(15522, writable: true)] private UInt32 _batteryRating; // 0x3CA2
|
||||
[HoldingRegister<UInt32>(15524, writable: true)] private UInt32 _battery1Activation; // 0x3CA4
|
||||
[HoldingRegister<UInt32>(15526, writable: true)] private UInt32 _battery2Activation; // 0x3CA6
|
||||
//[HoldingRegister<UInt32>(15430, writable: true)] private UInt32 _faultClearing; // 0x3C46
|
||||
//[HoldingRegister<UInt32>(15518, writable: true)] private UInt32 _meterReverseManualDetection; // 0x3C9E
|
||||
//[HoldingRegister<UInt32>(15520, writable: true)] private UInt32 _batteryVoltageRating; // 0x3CA0
|
||||
//[HoldingRegister<UInt32>(15524, writable: true)] private UInt32 _battery1Activation; // 0x3CA4
|
||||
//[HoldingRegister<UInt32>(15526, writable: true)] private UInt32 _battery2Activation; // 0x3CA6
|
||||
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
|
|
@ -310,4 +309,49 @@ public partial class SinexcelRecord
|
|||
[HoldingRegister<UInt32>(41236)] private UInt32 _electricMeterBPhaseActivePower; // 0xA114
|
||||
[HoldingRegister<UInt32>(41238)] private UInt32 _electricMeterCPhaseActivePower; // 0xA116
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Battery Cabinet 1 — Energy / Pack measurements (read-only)
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(45308)] private UInt32 _batteryCab1TotalChargingEnergy; // 0xB0FC kW·h
|
||||
[HoldingRegister<UInt32>(45310)] private UInt32 _batteryCab1TotalDischargedEnergy; // 0xB0FE kW·h
|
||||
|
||||
[HoldingRegister<UInt32>(45312)] private UInt32 _batteryCab1PackTotalVoltage; // 0xB100 (resolution 0.01 V)
|
||||
[HoldingRegister<UInt32>(45314)] private UInt32 _batteryCab1PackTotalCurrent; // 0xB102 (resolution 0.01 A)
|
||||
[HoldingRegister<UInt32>(45316)] private UInt32 _batteryCab1Temperature; // 0xB104 (resolution 0.01 °C)
|
||||
[HoldingRegister<UInt32>(45318)] private UInt32 _batteryCab1Soc; // 0xB106 %
|
||||
[HoldingRegister<UInt32>(45320)] private UInt32 _batteryCab1Soh; // 0xB108 %
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Battery Cabinet 2 — Energy / Pack Measurements (Read-Only)
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(45564)] private UInt32 _batteryCab2TotalChargingEnergy; // 0xB1FC kW·h
|
||||
[HoldingRegister<UInt32>(45566)] private UInt32 _batteryCab2TotalDischargedEnergy; // 0xB1FE kW·h
|
||||
|
||||
[HoldingRegister<UInt32>(45568)] private UInt32 _batteryCab2PackTotalVoltage; // 0xB200 (0.01 V)
|
||||
[HoldingRegister<UInt32>(45570)] private UInt32 _batteryCab2PackTotalCurrent; // 0xB202 (0.01 A)
|
||||
[HoldingRegister<UInt32>(45572)] private UInt32 _batteryCab2Temperature; // 0xB204 (0.01 °C)
|
||||
[HoldingRegister<UInt32>(45574)] private UInt32 _batteryCab2Soc; // 0xB206 %
|
||||
[HoldingRegister<UInt32>(45576)] private UInt32 _batteryCab2Soh; // 0xB208 %
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Time-based scheduling (period 1) configuration
|
||||
// ───────────────────────────────────────────────
|
||||
|
||||
//[HoldingRegister<UInt32>(49328, writable: true)] private UInt32 _Timed_Charge_and_Discharge_Off; // 0xC0B4, bit flags Sun–Sat
|
||||
//[HoldingRegister<UInt32>(49330, writable: true)] private UInt32 _Other_time_period_mode; // 0xC0B4, bit flags Sun–Sat
|
||||
[HoldingRegister<UInt32>(49332, writable: true)] private UInt32 _repetitiveWeeks; // 0xC0B4, bit flags Sun–Sat
|
||||
[HoldingRegister<UInt32>(49334, writable: true)] private UInt32 _effectiveStartDate; // 0xC0B6, UNIX timestamp (UTC+offset)
|
||||
[HoldingRegister<UInt32>(49336, writable: true)] private UInt32 _effectiveEndDate; // 0xC0B8, UNIX timestamp (UTC+offset)
|
||||
[HoldingRegister<UInt32>(49338, writable: true)] private UInt32 _chargingPowerPeriod1; // 0xC0BA, float [0–50] kW, default 5
|
||||
[HoldingRegister<UInt32>(49340, writable: true)] private UInt32 _dischargingPowerPeriod1; // 0xC0BA, float [0–50] kW, default 5
|
||||
|
||||
|
||||
// ───────────────────────────────────────────────
|
||||
// Time-based charge/discharge schedule period 1
|
||||
// ───────────────────────────────────────────────
|
||||
[HoldingRegister<UInt32>(49172, writable: true)] private UInt32 _chargeStartTimePeriod1; // 0xC014 [0-2359] (start)
|
||||
[HoldingRegister<UInt32>(49174, writable: true)] private UInt32 _chargeEndTimePeriod1; // 0xC016 [0-2359] (end)
|
||||
[HoldingRegister<UInt32>(49176, writable: true)] private UInt32 _dischargeStartTimePeriod1; // 0xC018 [0-2359] (start)
|
||||
[HoldingRegister<UInt32>(49178, writable: true)] private UInt32 _dischargeEndTimePeriod1; // 0xC01A [0-2359] (end)
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue