From 89becb4819f3383906051a5db74ccce5b811dad4 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Sun, 23 Feb 2025 10:37:49 +0100 Subject: [PATCH 1/6] Add batcontrol for set_power_limit --- .../modules/devices/sungrow/sungrow/bat.py | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 9dbeeea25e..146a622b71 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +import logging +from typing import Dict, Union, Optional from dataclass_utils import dataclass_from_dict from modules.common import modbus @@ -14,6 +15,7 @@ from modules.devices.sungrow.sungrow.version import Version from modules.devices.sungrow.sungrow.firmware import Firmware +log = logging.getLogger(__name__) class SungrowBat(AbstractBat): def __init__(self, @@ -64,5 +66,29 @@ def update(self) -> None: ) self.store.set(bat_state) + def set_power_limit(self, power_limit: Optional[int]) -> None: + unit = self.device_config.configuration.modbus_id + + if power_limit is None: + log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") + if self.last_mode != "auto": + self.__tcp_client.write_registers(13049, [0], data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) + self.last_mode = "auto" + elif power_limit == 0: + log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt") + if self.last_mode != "stop": + self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) + self.last_mode = "stop" + else: + log.debug("Aktive Batteriesteuerung. Batterie wird auf Entladen gesetzt") + if self.last_mode != "discharge": + self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) + self.__tcp_client.write_registers(13050, [0xBB], data_type=ModbusDataType.UINT_16, unit=unit) + self.last_mode = "discharge" + power_value = min(power_limit, 5000) + self.__tcp_client.write_registers(13051, [power_value], data_type=ModbusDataType.UINT_16, unit=unit) + component_descriptor = ComponentDescriptor(configuration_factory=SungrowBatSetup) From d1770796002616391ffee8ddb4de19eb977275c6 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Sun, 23 Feb 2025 10:50:45 +0100 Subject: [PATCH 2/6] fixed last_mode --- packages/modules/devices/sungrow/sungrow/bat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 146a622b71..448156b2d1 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -28,6 +28,7 @@ def __init__(self, self.sim_counter = SimCounter(self.device_config.id, self.component_config.id, prefix="speicher") self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) + self.last_mode = None def update(self) -> None: unit = self.device_config.configuration.modbus_id From 25f60e01709d14d7277354522c6ad0bee1d71723 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Sun, 23 Feb 2025 15:18:02 +0100 Subject: [PATCH 3/6] power_value has to be integer --- packages/modules/devices/sungrow/sungrow/bat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 448156b2d1..3264dc8f22 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -88,7 +88,8 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xBB], data_type=ModbusDataType.UINT_16, unit=unit) self.last_mode = "discharge" - power_value = min(power_limit, 5000) + #Die maximale Entladeleistung begrenzen auf 5000W + power_value = int(min(power_limit, 5000)) self.__tcp_client.write_registers(13051, [power_value], data_type=ModbusDataType.UINT_16, unit=unit) From d60827f86044085fe95954564b3d2a1ad7692405 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Wed, 5 Mar 2025 08:54:28 +0100 Subject: [PATCH 4/6] Fixed Flake8 --- packages/modules/devices/sungrow/sungrow/bat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 3264dc8f22..eef762bd48 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -17,6 +17,7 @@ log = logging.getLogger(__name__) + class SungrowBat(AbstractBat): def __init__(self, device_config: Union[Dict, Sungrow], @@ -88,7 +89,7 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xBB], data_type=ModbusDataType.UINT_16, unit=unit) self.last_mode = "discharge" - #Die maximale Entladeleistung begrenzen auf 5000W + # Die maximale Entladeleistung begrenzen auf 5000W power_value = int(min(power_limit, 5000)) self.__tcp_client.write_registers(13051, [power_value], data_type=ModbusDataType.UINT_16, unit=unit) From 85c0ef9aaf7183623a061bf25d837ebdf47d1d07 Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Fri, 7 Mar 2025 15:48:43 +0100 Subject: [PATCH 5/6] removed last_mode and read register instead --- .../modules/devices/sungrow/sungrow/bat.py | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index eef762bd48..8912b199d8 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -29,7 +29,6 @@ def __init__(self, self.sim_counter = SimCounter(self.device_config.id, self.component_config.id, prefix="speicher") self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.last_mode = None def update(self) -> None: unit = self.device_config.configuration.modbus_id @@ -71,26 +70,37 @@ def update(self) -> None: def set_power_limit(self, power_limit: Optional[int]) -> None: unit = self.device_config.configuration.modbus_id + try: + current_ems_mode = self.__tcp_client.read_holding_registers(13049, ModbusDataType.UINT_16, unit=unit) + log.debug(f"Aktueller EMS-Modus aus Register 13049: {current_ems_mode}") + except Exception as e: + log.error(f"Fehler beim Lesen des aktuellen Modus: {e}") + return + if power_limit is None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") - if self.last_mode != "auto": + if current_ems_mode != 0: self.__tcp_client.write_registers(13049, [0], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) - self.last_mode = "auto" elif power_limit == 0: - log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt") - if self.last_mode != "stop": + log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") + if current_ems_mode != 2: self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) - self.last_mode = "stop" - else: - log.debug("Aktive Batteriesteuerung. Batterie wird auf Entladen gesetzt") - if self.last_mode != "discharge": + else: + # Sicherstellen, dass Register 13050 auf 0xCC gesetzt ist + self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) + elif power_limit > 0: + log.debug("Aktive Batteriesteuerung. Batterie wird entladen für den Hausverbrauch") + if current_ems_mode != 2: self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xBB], data_type=ModbusDataType.UINT_16, unit=unit) - self.last_mode = "discharge" - # Die maximale Entladeleistung begrenzen auf 5000W + else: + # Sicherstellen, dass Register 13050 auf 0xBB gesetzt ist + self.__tcp_client.write_registers(13050, [0xBB], data_type=ModbusDataType.UINT_16, unit=unit) + # Die maximale Entladeleistung begrenzen auf 5000W, maximaler Wertebereich Modbusregister. power_value = int(min(power_limit, 5000)) + log.debug(f"Entladeleistung wird auf {power_value} W gesetzt") self.__tcp_client.write_registers(13051, [power_value], data_type=ModbusDataType.UINT_16, unit=unit) From 2360cfd0fec691106380d2fb2194d4c5ab2edbde Mon Sep 17 00:00:00 2001 From: SeaSpotter Date: Mon, 17 Mar 2025 18:02:12 +0100 Subject: [PATCH 6/6] Added last_mode again and improve logging --- .../modules/devices/sungrow/sungrow/bat.py | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 8912b199d8..3ee28a6afe 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -29,6 +29,7 @@ def __init__(self, self.sim_counter = SimCounter(self.device_config.id, self.component_config.id, prefix="speicher") 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' def update(self) -> None: unit = self.device_config.configuration.modbus_id @@ -69,38 +70,28 @@ def update(self) -> None: def set_power_limit(self, power_limit: Optional[int]) -> None: unit = self.device_config.configuration.modbus_id - - try: - current_ems_mode = self.__tcp_client.read_holding_registers(13049, ModbusDataType.UINT_16, unit=unit) - log.debug(f"Aktueller EMS-Modus aus Register 13049: {current_ems_mode}") - except Exception as e: - log.error(f"Fehler beim Lesen des aktuellen Modus: {e}") - return + log.debug(f'last_mode: {self.last_mode}') if power_limit is None: log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") - if current_ems_mode != 0: + if self.last_mode is not None: self.__tcp_client.write_registers(13049, [0], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) + self.last_mode = None elif power_limit == 0: log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen") - if current_ems_mode != 2: + if self.last_mode != 'stop': self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) - else: - # Sicherstellen, dass Register 13050 auf 0xCC gesetzt ist - self.__tcp_client.write_registers(13050, [0xCC], data_type=ModbusDataType.UINT_16, unit=unit) + self.last_mode = 'stop' elif power_limit > 0: - log.debug("Aktive Batteriesteuerung. Batterie wird entladen für den Hausverbrauch") - if current_ems_mode != 2: + log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch") + if self.last_mode != 'discharge': self.__tcp_client.write_registers(13049, [2], data_type=ModbusDataType.UINT_16, unit=unit) self.__tcp_client.write_registers(13050, [0xBB], data_type=ModbusDataType.UINT_16, unit=unit) - else: - # Sicherstellen, dass Register 13050 auf 0xBB gesetzt ist - self.__tcp_client.write_registers(13050, [0xBB], data_type=ModbusDataType.UINT_16, unit=unit) + self.last_mode = 'discharge' # Die maximale Entladeleistung begrenzen auf 5000W, maximaler Wertebereich Modbusregister. power_value = int(min(power_limit, 5000)) - log.debug(f"Entladeleistung wird auf {power_value} W gesetzt") self.__tcp_client.write_registers(13051, [power_value], data_type=ModbusDataType.UINT_16, unit=unit)