From 0a7c3e4bbcf83fb33f50aa1be73ee83336061901 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Mon, 4 Aug 2025 19:04:26 +0200 Subject: [PATCH 1/8] New Modbus Registers --- .../modules/devices/sungrow/sungrow/bat.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index dd575a0887..52671c9a2e 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -38,20 +38,31 @@ def update(self) -> None: unit = self.device_config.configuration.modbus_id soc = int( self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, unit=unit) / 10) - # Es gibt nur einen DC Strom der Batterie, daher Aufteilen auf 3 Phasenströme - bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 + # Ab FW Version 95.09 gibt es ein neues Register für den Batteriestrom + try: + bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) * -0.1 + except Exception: + bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 currents = [bat_current / 3] * 3 - - if ( - Firmware(self.device_config.configuration.firmware) == Firmware.v2 - and self.device_config.configuration.version == Version.SH - ): + + firmware = Firmware(self.device_config.configuration.firmware) + version = self.device_config.configuration.version + + bat_power = None + if firmware == Firmware.v2: + try: + # Ab FW Version 95.09 gibt es ein neues Register für die Batterieleistung + bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, + wordorder=Endian.Little, unit=unit) * -1 + except Exception: + bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 + elif firmware == Firmware.v1 and version == Version.SH: bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 else: bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit) # Beim WiNet S-Dongle fehlt das Register für das Vorzeichen der Speicherleistung - if self.device_config.configuration.version == Version.SH_winet_dongle: + if version == Version.SH_winet_dongle: total_power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) pv_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32, From aa4257023a24850f3d09d821814a7cac1fa1ea3f Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Mon, 4 Aug 2025 19:15:30 +0200 Subject: [PATCH 2/8] Typo --- packages/modules/devices/sungrow/sungrow/bat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 52671c9a2e..73c4d08699 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -46,7 +46,7 @@ def update(self) -> None: currents = [bat_current / 3] * 3 firmware = Firmware(self.device_config.configuration.firmware) - version = self.device_config.configuration.version + version = Version(self.device_config.configuration.version) bat_power = None if firmware == Firmware.v2: From d5947558caabd5f7db7ce8eebbd3c9e9507f34a3 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Mon, 4 Aug 2025 19:47:34 +0200 Subject: [PATCH 3/8] Clean-up code --- packages/modules/devices/sungrow/sungrow/bat.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 73c4d08699..9dcef7320c 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -49,13 +49,14 @@ def update(self) -> None: version = Version(self.device_config.configuration.version) bat_power = None - if firmware == Firmware.v2: + if firmware == Firmware.v2 and version in (Version.SH, Version.SH_winet_dongle): try: # Ab FW Version 95.09 gibt es ein neues Register für die Batterieleistung bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 except Exception: bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 + elif firmware == Firmware.v1 and version == Version.SH: bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 else: @@ -71,11 +72,6 @@ def update(self) -> None: # Ist die Gesamtleistung des WR größer als die PV-Erzeugung wird der Speicher entladen if total_power > pv_power: bat_power = bat_power * -1 - else: - resp = self.__tcp_client._delegate.read_input_registers(13000, 1, unit=unit) - binary = bin(resp.registers[0])[2:].zfill(8) - if binary[5] == "1": - bat_power = bat_power * -1 imported, exported = self.sim_counter.sim_count(bat_power) bat_state = BatState( From 73754a225957c66ff28dbdd8edb7f92e90db60e6 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Mon, 4 Aug 2025 20:11:48 +0200 Subject: [PATCH 4/8] flake8 --- packages/modules/devices/sungrow/sungrow/bat.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 9dcef7320c..ac0a83062c 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -44,7 +44,7 @@ def update(self) -> None: except Exception: bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 currents = [bat_current / 3] * 3 - + firmware = Firmware(self.device_config.configuration.firmware) version = Version(self.device_config.configuration.version) @@ -52,11 +52,11 @@ def update(self) -> None: if firmware == Firmware.v2 and version in (Version.SH, Version.SH_winet_dongle): try: # Ab FW Version 95.09 gibt es ein neues Register für die Batterieleistung - bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, + bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 except Exception: bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 - + elif firmware == Firmware.v1 and version == Version.SH: bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 else: From bdf334da8a8ea2df470f358abd74626238aa7320 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Tue, 5 Aug 2025 11:26:09 +0200 Subject: [PATCH 5/8] Add firmware check and restructure --- .../modules/devices/sungrow/sungrow/bat.py | 67 +++++++++++-------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index ac0a83062c..76ac8b4039 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -33,46 +33,57 @@ def initialize(self) -> None: self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.last_mode = 'Undefined' + self.firmware_check = None - def update(self) -> None: - unit = self.device_config.configuration.modbus_id - soc = int( - self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, unit=unit) / 10) - # Ab FW Version 95.09 gibt es ein neues Register für den Batteriestrom + def check_firmware_register(self, unit): try: - bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) * -0.1 + self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) + self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, + wordorder=Endian.Little, unit=unit) + self.firmware_check = True + log.debug("Wechselrichter Firmware ist größer gleich 95.09") except Exception: - bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 - currents = [bat_current / 3] * 3 + self.firmware_check = False + log.debug("Wechselrichter Firmware ist kleiner als 95.09") + + def update(self) -> None: + unit = self.device_config.configuration.modbus_id + if self.firmware_check is None: + self.check_firmware_register(unit) + + soc = int(self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, unit=unit) / 10) firmware = Firmware(self.device_config.configuration.firmware) version = Version(self.device_config.configuration.version) - bat_power = None - if firmware == Firmware.v2 and version in (Version.SH, Version.SH_winet_dongle): - try: - # Ab FW Version 95.09 gibt es ein neues Register für die Batterieleistung + if firmware == Firmware.v2: + if self.firmware_check: # Firmware >= 95.09 + bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) * -0.1 bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 - except Exception: - bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 - - elif firmware == Firmware.v1 and version == Version.SH: - bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) * -1 - else: + else: # Firmware between 95.03 and 95.09 + bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 + if version == Version.SH: + bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.INT_16, unit=unit) + elif version == Version.SH_winet_dongle: + bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit) + total_power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32, + wordorder=Endian.Little, unit=unit) + pv_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32, + wordorder=Endian.Little, unit=unit) + if total_power > pv_power: + bat_power = bat_power * -1 + else: # Firmware.v1 (Firmware < 95.03) + bat_current = self.__tcp_client.read_input_registers(13020, ModbusDataType.INT_16, unit=unit) * -0.1 bat_power = self.__tcp_client.read_input_registers(13021, ModbusDataType.UINT_16, unit=unit) - - # Beim WiNet S-Dongle fehlt das Register für das Vorzeichen der Speicherleistung - if version == Version.SH_winet_dongle: - total_power = self.__tcp_client.read_input_registers(13033, ModbusDataType.INT_32, - wordorder=Endian.Little, unit=unit) - pv_power = self.__tcp_client.read_input_registers(5016, ModbusDataType.UINT_32, - wordorder=Endian.Little, unit=unit) - - # Ist die Gesamtleistung des WR größer als die PV-Erzeugung wird der Speicher entladen - if total_power > pv_power: + if version in (Version.SH, Version.SH_winet_dongle): + resp = self.__tcp_client._delegate.read_input_registers(13000, 1, unit=unit) + binary = bin(resp.registers[0])[2:].zfill(8) + if binary[5] == "1": bat_power = bat_power * -1 + currents = [bat_current / 3] * 3 + imported, exported = self.sim_counter.sim_count(bat_power) bat_state = BatState( power=bat_power, From 2cd7f458d2a69bafffc935677937f8bf96b1994b Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Tue, 5 Aug 2025 12:45:25 +0200 Subject: [PATCH 6/8] Call check_firmware_register with initialize --- packages/modules/devices/sungrow/sungrow/bat.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 76ac8b4039..c516a465eb 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -33,11 +33,11 @@ def initialize(self) -> None: self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.last_mode = 'Undefined' - self.firmware_check = None + self.check_firmware_register() - def check_firmware_register(self, unit): + def check_firmware_register(self): + unit = self.device_config.configuration.modbus_id try: - self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) self.firmware_check = True @@ -49,9 +49,6 @@ def check_firmware_register(self, unit): def update(self) -> None: unit = self.device_config.configuration.modbus_id - if self.firmware_check is None: - self.check_firmware_register(unit) - soc = int(self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, unit=unit) / 10) firmware = Firmware(self.device_config.configuration.firmware) version = Version(self.device_config.configuration.version) From fd0a0fb3aab68b762292e358095e6df22cc8b295 Mon Sep 17 00:00:00 2001 From: benderl Date: Wed, 6 Aug 2025 07:39:07 +0200 Subject: [PATCH 7/8] Update bat.py enhance usage of firmware_check --- packages/modules/devices/sungrow/sungrow/bat.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index c516a465eb..39a3522740 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -33,27 +33,28 @@ def initialize(self) -> None: self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.last_mode = 'Undefined' - self.check_firmware_register() + self.firmware_check = self.check_firmware_register() def check_firmware_register(self): + if Firmware(self.device_config.configuration.firmware) == Firmware.v1: + return False unit = self.device_config.configuration.modbus_id try: self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) - self.firmware_check = True log.debug("Wechselrichter Firmware ist größer gleich 95.09") + return True except Exception: - self.firmware_check = False log.debug("Wechselrichter Firmware ist kleiner als 95.09") + return False def update(self) -> None: unit = self.device_config.configuration.modbus_id soc = int(self.__tcp_client.read_input_registers(13022, ModbusDataType.UINT_16, unit=unit) / 10) - firmware = Firmware(self.device_config.configuration.firmware) version = Version(self.device_config.configuration.version) - if firmware == Firmware.v2: + if Firmware(self.device_config.configuration.firmware) == Firmware.v2: if self.firmware_check: # Firmware >= 95.09 bat_current = self.__tcp_client.read_input_registers(5630, ModbusDataType.INT_16, unit=unit) * -0.1 bat_power = self.__tcp_client.read_input_registers(5213, ModbusDataType.INT_32, From 411d186ddfc338228817740b6edf53a5b1b2f79c Mon Sep 17 00:00:00 2001 From: benderl Date: Wed, 6 Aug 2025 07:41:27 +0200 Subject: [PATCH 8/8] Update bat.py fix type hint --- packages/modules/devices/sungrow/sungrow/bat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 39a3522740..86c145e6cd 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -35,7 +35,7 @@ def initialize(self) -> None: self.last_mode = 'Undefined' self.firmware_check = self.check_firmware_register() - def check_firmware_register(self): + def check_firmware_register(self) -> bool: if Firmware(self.device_config.configuration.firmware) == Firmware.v1: return False unit = self.device_config.configuration.modbus_id