From fbab534dc6faf88d77fb4b2795844cb38f45d071 Mon Sep 17 00:00:00 2001 From: daniel-deptula Date: Fri, 29 Nov 2024 11:10:48 +0100 Subject: [PATCH 1/3] - New sensor for sg01hp3 that returns total DC power (a sum from multiple PV strings) - New sensor for sg01hp3 that reads the inverter status --- docs/metric_group_deye_sg01hp3.md | 2 ++ src/deye_sensors_deye_sg01hp3.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/docs/metric_group_deye_sg01hp3.md b/docs/metric_group_deye_sg01hp3.md index 4caee23..16f2b05 100644 --- a/docs/metric_group_deye_sg01hp3.md +++ b/docs/metric_group_deye_sg01hp3.md @@ -1,9 +1,11 @@ |Metric|MQTT topic suffix|Unit|Modbus address (dec)|Modbus address (hex)|Modbus data type|Scale factor| |---|---|:-:|:-:|:-:|:-:|:-:| +|Running status|`inverter/status`|N/A (0: standby, 1: selfcheck, 2: normal, 3: alarm, 4: fault)|500|1f4|U_WORD|1| |PV1 Power|`dc/pv1/power`|W|672|2a0|U_WORD|10| |PV2 Power|`dc/pv2/power`|W|673|2a1|U_WORD|10| |PV3 Power|`dc/pv3/power`|W|674|2a2|U_WORD|10| |PV4 Power|`dc/pv4/power`|W|675|2a3|U_WORD|10| +|DC Total Power|`dc/total_power`|W|672,673,674,675|2a0,2a1,2a2,2a3|U_WORD|10| |PV1 Voltage|`dc/pv1/voltage`|V|676|2a4|U_WORD|0.1| |PV1 Current|`dc/pv1/current`|A|677|2a5|U_WORD|0.1| |PV2 Voltage|`dc/pv2/voltage`|V|678|2a6|U_WORD|0.1| diff --git a/src/deye_sensors_deye_sg01hp3.py b/src/deye_sensors_deye_sg01hp3.py index ba4dffd..160b140 100644 --- a/src/deye_sensors_deye_sg01hp3.py +++ b/src/deye_sensors_deye_sg01hp3.py @@ -18,9 +18,14 @@ from deye_sensor import ( SingleRegisterSensor, DoubleRegisterSensor, + ComputedSumSensor, SensorRegisterRange, ) +deye_sg01hp3_inverter_500 = SingleRegisterSensor( + "Running status", 500, 1, mqtt_topic_suffix="inverter/status", unit="", signed=False, groups=["deye_sg01hp3"] +) + deye_sg01hp3_solar_672 = SingleRegisterSensor( "PV1 Power", 672, 10, mqtt_topic_suffix="dc/pv1/power", unit="W", signed=False, groups=["deye_sg01hp3"] ) @@ -642,8 +647,16 @@ groups=["deye_sg01hp3_bms"], ) +total_pv_power_sensor = ComputedSumSensor( + "DC Total Power", + [deye_sg01hp3_solar_672, deye_sg01hp3_solar_673, deye_sg01hp3_solar_674, deye_sg01hp3_solar_675], + mqtt_topic_suffix="dc/total_power", + unit="W", + groups=["deye_sg01hp3"], +) deye_sg01hp3_sensors = [ + deye_sg01hp3_inverter_500, deye_sg01hp3_solar_672, deye_sg01hp3_solar_673, deye_sg01hp3_solar_674, @@ -723,9 +736,11 @@ deye_sg01hp3_inverter_635, deye_sg01hp3_inverter_540, deye_sg01hp3_inverter_541, + total_pv_power_sensor, ] deye_sg01hp3_register_ranges = [ + SensorRegisterRange(group="deye_sg01hp3", first_reg_address=500, last_reg_address=500), SensorRegisterRange(group="deye_sg01hp3_ups", first_reg_address=514, last_reg_address=558), SensorRegisterRange(group="deye_sg01hp3", first_reg_address=514, last_reg_address=558), SensorRegisterRange(group="deye_sg01hp3_battery", first_reg_address=514, last_reg_address=558), From 63761c2e818ae5cce26243cadd466d3ec389d3ef Mon Sep 17 00:00:00 2001 From: daniel-deptula Date: Fri, 29 Nov 2024 14:40:21 +0100 Subject: [PATCH 2/3] Created a new sensor class for enum-type values that translate to strings (and made the sg01hp3 inverter status to use that class) --- src/deye_sensor.py | 37 ++++++++++++++++++++++++++++++++ src/deye_sensors_deye_sg01hp3.py | 5 +++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/deye_sensor.py b/src/deye_sensor.py index 1ccc37b..c6343fa 100644 --- a/src/deye_sensor.py +++ b/src/deye_sensor.py @@ -446,6 +446,43 @@ def get_registers(self) -> list[int]: return [] +class EnumValueSensor(AbstractSensor): + """ + Solar inverter sensor with enum value stored as 32-bit integer in a single Modbus register + """ + + def __init__( + self, + name: str, + reg_address: int, + signed=False, + mqtt_topic_suffix="", + groups=[], + enum_values={}, + ): + super().__init__(name, mqtt_topic_suffix, "", "", groups) + self.__reg_address = reg_address + self.__signed = signed + self.__enum_values = enum_values + + def read_value(self, registers: dict[int, bytearray]): + if self.__reg_address in registers: + reg_value = registers[self.__reg_address] + return self.__enum_values.get(int.from_bytes(reg_value, "big", signed=self.__signed), "") + else: + return None + + def get_registers(self) -> list[int]: + return [self.__reg_address] + + @property + def data_type(self) -> str: + return "S_WORD" if self.__signed else "U_WORD" + + def format_value(self, value): + return value + + class SensorRegisterRange: """ Declares a Modbus register range that must be read to provide values for sensors within a metrics group diff --git a/src/deye_sensors_deye_sg01hp3.py b/src/deye_sensors_deye_sg01hp3.py index 160b140..80eddac 100644 --- a/src/deye_sensors_deye_sg01hp3.py +++ b/src/deye_sensors_deye_sg01hp3.py @@ -20,10 +20,11 @@ DoubleRegisterSensor, ComputedSumSensor, SensorRegisterRange, + EnumValueSensor, ) -deye_sg01hp3_inverter_500 = SingleRegisterSensor( - "Running status", 500, 1, mqtt_topic_suffix="inverter/status", unit="", signed=False, groups=["deye_sg01hp3"] +deye_sg01hp3_inverter_500 = EnumValueSensor( + "Running status", 500, mqtt_topic_suffix="inverter/status", groups=["deye_sg01hp3"], enum_values={0: "standby", 1: "selfcheck", 2: "normal", 3: "alarm", 4: "fault"} ) deye_sg01hp3_solar_672 = SingleRegisterSensor( From 7869976388a9a3ac263357df2fed9ebf92debe26 Mon Sep 17 00:00:00 2001 From: daniel-deptula Date: Tue, 3 Dec 2024 00:10:47 +0100 Subject: [PATCH 3/3] Amending formatting --- src/deye_sensors_deye_sg01hp3.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/deye_sensors_deye_sg01hp3.py b/src/deye_sensors_deye_sg01hp3.py index 80eddac..0270e27 100644 --- a/src/deye_sensors_deye_sg01hp3.py +++ b/src/deye_sensors_deye_sg01hp3.py @@ -24,7 +24,11 @@ ) deye_sg01hp3_inverter_500 = EnumValueSensor( - "Running status", 500, mqtt_topic_suffix="inverter/status", groups=["deye_sg01hp3"], enum_values={0: "standby", 1: "selfcheck", 2: "normal", 3: "alarm", 4: "fault"} + "Running status", + 500, + mqtt_topic_suffix="inverter/status", + groups=["deye_sg01hp3"], + enum_values={0: "standby", 1: "selfcheck", 2: "normal", 3: "alarm", 4: "fault"}, ) deye_sg01hp3_solar_672 = SingleRegisterSensor(