diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 5d50f4189f..59f5387e4e 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -51,7 +51,7 @@ class UpdateConfig: - DATASTORE_VERSION = 74 + DATASTORE_VERSION = 75 valid_topic = [ "^openWB/bat/config/configured$", "^openWB/bat/config/power_limit_mode$", @@ -1945,3 +1945,15 @@ def upgrade(topic: str, payload) -> Optional[dict]: return {topic: config_payload} self._loop_all_received_topics(upgrade) self.__update_topic("openWB/system/datastore_version", 74) + + def upgrade_datastore_74(self) -> None: + def upgrade(topic: str, payload) -> None: + if re.search("openWB/system/device/[0-9]+", topic) is not None: + payload = decode_payload(payload) + # update firmware of Sungrow + if payload.get("type") == "solax": + if "version" not in payload["configuration"]: + payload["configuration"].update({"version": "g3"}) + Pub().pub(topic, payload) + self._loop_all_received_topics(upgrade) + self.__update_topic("openWB/system/datastore_version", 75) diff --git a/packages/modules/devices/solax/solax/bat.py b/packages/modules/devices/solax/solax/bat.py index 4afe6efa65..b6cb8aedd8 100644 --- a/packages/modules/devices/solax/solax/bat.py +++ b/packages/modules/devices/solax/solax/bat.py @@ -10,27 +10,27 @@ from modules.common.modbus import ModbusDataType from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store -from modules.devices.solax.solax.config import SolaxBatSetup +from modules.devices.solax.solax.config import SolaxBatSetup, Solax class SolaxBat(AbstractBat): def __init__(self, - device_id: int, + device_config: Solax, component_config: Union[Dict, SolaxBatSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.__modbus_id = modbus_id + tcp_client: modbus.ModbusTcpClient_) -> None: + self.device_config = device_config self.component_config = dataclass_from_dict(SolaxBatSetup, component_config) self.__tcp_client = tcp_client - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") + 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)) def update(self) -> None: - with self.__tcp_client: - power = self.__tcp_client.read_input_registers(22, ModbusDataType.INT_16, unit=self.__modbus_id) - soc = self.__tcp_client.read_input_registers(28, ModbusDataType.UINT_16, unit=self.__modbus_id) + unit = self.device_config.configuration.modbus_id + + # kein Speicher für Versionen G2 und G4 + power = self.__tcp_client.read_input_registers(0x0016, ModbusDataType.INT_16, unit=unit) + soc = self.__tcp_client.read_input_registers(0x001C, ModbusDataType.UINT_16, unit=unit) imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/packages/modules/devices/solax/solax/config.py b/packages/modules/devices/solax/solax/config.py index 8694baef28..88db0b73ea 100644 --- a/packages/modules/devices/solax/solax/config.py +++ b/packages/modules/devices/solax/solax/config.py @@ -1,14 +1,19 @@ from typing import Optional from modules.common.component_setup import ComponentSetup +from modules.devices.solax.solax.version import SolaxVersion from ..vendor import vendor_descriptor class SolaxConfiguration: - def __init__(self, modbus_id: int = 1, ip_address: Optional[str] = None, port: int = 502): + def __init__(self, modbus_id: int = 1, + ip_address: Optional[str] = None, + port: int = 502, + version: SolaxVersion = SolaxVersion.G3): self.modbus_id = modbus_id self.ip_address = ip_address self.port = port + self.version = version class Solax: diff --git a/packages/modules/devices/solax/solax/counter.py b/packages/modules/devices/solax/solax/counter.py index 86f49cc8f4..53f55788ff 100644 --- a/packages/modules/devices/solax/solax/counter.py +++ b/packages/modules/devices/solax/solax/counter.py @@ -10,37 +10,52 @@ from modules.common.fault_state import ComponentInfo, FaultState from modules.common.modbus import ModbusDataType from modules.common.store import get_counter_value_store -from modules.devices.solax.solax.config import SolaxCounterSetup +from modules.devices.solax.solax.config import SolaxCounterSetup, Solax +from modules.devices.solax.solax.version import SolaxVersion class SolaxCounter(AbstractCounter): def __init__(self, - device_id: int, + device_config: Solax, component_config: Union[Dict, SolaxCounterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - + tcp_client: modbus.ModbusTcpClient_) -> None: + self.device_config = device_config self.component_config = dataclass_from_dict(SolaxCounterSetup, component_config) - self.__modbus_id = modbus_id self.__tcp_client = tcp_client self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self): - with self.__tcp_client: - power = self.__tcp_client.read_input_registers(70, ModbusDataType.INT_32, wordorder=Endian.Little, - unit=self.__modbus_id) * -1 - frequency = self.__tcp_client.read_input_registers(7, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 + unit = self.device_config.configuration.modbus_id + + if SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G2: + power = self.__tcp_client.read_input_registers( + 0x043B, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 + frequency = self.__tcp_client.read_input_registers(0x0407, ModbusDataType.UINT_16, unit=unit) / 100 + powers = [-value for value in self.__tcp_client.read_input_registers( + 0x0704, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=unit)] + exported, imported = [value * 10 for value in self.__tcp_client.read_input_registers( + 0x043D, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, unit=unit)] + + elif SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G3: + power = self.__tcp_client.read_input_registers( + 0x0046, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 + frequency = self.__tcp_client.read_input_registers(0x0007, ModbusDataType.UINT_16, unit=unit) / 100 try: powers = [-value for value in self.__tcp_client.read_input_registers( - 130, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=self.__modbus_id - )] + 0x0082, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=unit)] except Exception: powers = None - exported, imported = [value * 10 - for value in self.__tcp_client.read_input_registers( - 72, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, unit=self.__modbus_id - )] + exported, imported = [value * 10 for value in self.__tcp_client.read_input_registers( + 0x0048, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, unit=unit)] + + else: + power = self.__tcp_client.read_input_registers( + 0x0409, ModbusDataType.INT_32, wordorder=Endian.Little, unit=unit) * -1 + frequency = self.__tcp_client.read_input_registers(0x0406, ModbusDataType.UINT_16, unit=unit) / 100 + powers = None + exported, imported = [value * 100 for value in self.__tcp_client.read_input_registers( + 0x042F, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little, unit=unit)] counter_state = CounterState( imported=imported, diff --git a/packages/modules/devices/solax/solax/device.py b/packages/modules/devices/solax/solax/device.py index d612f2f16e..711f0e0b60 100644 --- a/packages/modules/devices/solax/solax/device.py +++ b/packages/modules/devices/solax/solax/device.py @@ -16,13 +16,13 @@ def create_device(device_config: Solax): def create_bat_component(component_config: SolaxBatSetup): - return SolaxBat(device_config.id, component_config, client, device_config.configuration.modbus_id) + return SolaxBat(device_config, component_config, client) def create_counter_component(component_config: SolaxCounterSetup): - return SolaxCounter(device_config.id, component_config, client, device_config.configuration.modbus_id) + return SolaxCounter(device_config, component_config, client) def create_inverter_component(component_config: SolaxInverterSetup): - return SolaxInverter(device_config.id, component_config, client, device_config.configuration.modbus_id) + return SolaxInverter(device_config, component_config, client) def update_components(components: Iterable[Union[SolaxBat, SolaxCounter, SolaxInverter]]): with client: diff --git a/packages/modules/devices/solax/solax/inverter.py b/packages/modules/devices/solax/solax/inverter.py index ec85d0d2fd..a65e4d15ea 100644 --- a/packages/modules/devices/solax/solax/inverter.py +++ b/packages/modules/devices/solax/solax/inverter.py @@ -10,27 +10,38 @@ from modules.common.fault_state import ComponentInfo, FaultState from modules.common.modbus import ModbusDataType from modules.common.store import get_inverter_value_store -from modules.devices.solax.solax.config import SolaxInverterSetup +from modules.devices.solax.solax.config import SolaxInverterSetup, Solax +from modules.devices.solax.solax.version import SolaxVersion class SolaxInverter(AbstractInverter): def __init__(self, - device_id: int, + device_config: Solax, component_config: Union[Dict, SolaxInverterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: + tcp_client: modbus.ModbusTcpClient_) -> None: + self.device_config = device_config self.component_config = dataclass_from_dict(SolaxInverterSetup, component_config) - self.__modbus_id = modbus_id self.__tcp_client = tcp_client self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self) -> None: - with self.__tcp_client: - power_temp = self.__tcp_client.read_input_registers(10, [ModbusDataType.UINT_16] * 2, unit=self.__modbus_id) + unit = self.device_config.configuration.modbus_id + + if SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G2: + power = self.__tcp_client.read_input_registers(0x0413, ModbusDataType.UINT_16, unit=unit) * -1 + exported = self.__tcp_client.read_input_registers( + 0x0423, ModbusDataType.UINT_32, wordorder=Endian.Little, unit=unit) * 100 + elif SolaxVersion(self.device_config.configuration.version) == SolaxVersion.G3: + power_temp = self.__tcp_client.read_input_registers(0x000A, [ModbusDataType.UINT_16] * 2, unit=unit) + power = sum(power_temp) * -1 + exported = self.__tcp_client.read_input_registers( + 0x0052, ModbusDataType.UINT_32, wordorder=Endian.Little, unit=unit) * 100 + else: + power_temp = self.__tcp_client.read_input_registers(0x0410, [ModbusDataType.UINT_16] * 2, unit=unit) power = sum(power_temp) * -1 - exported = self.__tcp_client.read_input_registers(82, ModbusDataType.UINT_32, wordorder=Endian.Little, - unit=self.__modbus_id) * 100 + exported = self.__tcp_client.read_input_registers( + 0x042B, ModbusDataType.UINT_32, wordorder=Endian.Little, unit=unit) * 100 inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/solax/solax/version.py b/packages/modules/devices/solax/solax/version.py new file mode 100644 index 0000000000..d782e1b32c --- /dev/null +++ b/packages/modules/devices/solax/solax/version.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class SolaxVersion(Enum): + G2 = "g2" + G3 = "g3" + G4 = "g4"