From 33eeb690701f6d39aa40e46cae1cf56758c68970 Mon Sep 17 00:00:00 2001 From: LKuemmel <76958050+LKuemmel@users.noreply.github.com> Date: Wed, 25 Sep 2024 07:56:20 +0200 Subject: [PATCH] Use create device 2: sma webbox, solax, sonnen, studer, sungrow (#1775) * sma webbox * solax * sonnenbatterie * studer * sungrow --- .../modules/devices/sma/sma_webbox/device.py | 61 ++----- .../modules/devices/solax/solax/device.py | 123 ++++--------- .../devices/sonnen/sonnenbatterie/device.py | 124 ++++--------- .../modules/devices/studer/studer/device.py | 109 ++++-------- .../modules/devices/sungrow/sungrow/device.py | 167 +++++------------- 5 files changed, 160 insertions(+), 424 deletions(-) diff --git a/packages/modules/devices/sma/sma_webbox/device.py b/packages/modules/devices/sma/sma_webbox/device.py index dc5ebc58e4..8e5ee62baf 100644 --- a/packages/modules/devices/sma/sma_webbox/device.py +++ b/packages/modules/devices/sma/sma_webbox/device.py @@ -1,59 +1,26 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union -from dataclass_utils import dataclass_from_dict +from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, IndependentComponentUpdater from modules.devices.sma.sma_webbox.config import SmaWebbox, SmaWebboxInverterSetup -from modules.devices.sma.sma_webbox import inverter -from modules.common.abstract_device import AbstractDevice, DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext +from modules.common.abstract_device import DeviceDescriptor +from modules.devices.sma.sma_webbox.inverter import SmaWebboxInverter log = logging.getLogger(__name__) -class Device(AbstractDevice): - COMPONENT_TYPE_TO_CLASS = { - "inverter": inverter.SmaWebboxInverter - } - - def __init__(self, device_config: Union[Dict, SmaWebbox]) -> None: - self.components = {} # type: Dict[str, inverter.SmaWebboxInverter] - try: - self.device_config = dataclass_from_dict(SmaWebbox, device_config) - except Exception: - log.exception("Fehler im Modul "+self.device_config.name) - - def add_component(self, component_config: Union[Dict, SmaWebboxInverterSetup]) -> None: - if isinstance(component_config, Dict): - component_type = component_config["type"] - else: - component_type = component_config.type - component_config = dataclass_from_dict(SmaWebboxInverterSetup, component_config) - if component_type in self.COMPONENT_TYPE_TO_CLASS: - self.components["component"+str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type]( - self.device_config.configuration.ip_address, - component_config)) - else: - raise Exception( - "illegal component type " + component_type + ". Allowed values: " + - ','.join(self.COMPONENT_TYPE_TO_CLASS.keys()) - ) - - def update(self) -> None: - log.debug("Start device reading " + str(self.components)) - if self.components: - for component in self.components.values(): - # Auch wenn bei einer Komponente ein Fehler auftritt, sollen alle anderen noch ausgelesen werden. - with SingleComponentUpdateContext(component.fault_state): - component.update() - else: - log.warning( - self.device_config.name + - ": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden." - ) - -# read_legacy in sma_modbus +def create_device(device_config: SmaWebbox): + def create_inverter_component(component_config: SmaWebboxInverterSetup): + return SmaWebboxInverter(device_config.configuration.ip_address, component_config) + + return ConfigurableDevice( + device_config=device_config, + component_factory=ComponentFactoryByType( + inverter=create_inverter_component, + ), + component_updater=IndependentComponentUpdater(lambda component: component.update()) + ) device_descriptor = DeviceDescriptor(configuration_factory=SmaWebbox) diff --git a/packages/modules/devices/solax/solax/device.py b/packages/modules/devices/solax/solax/device.py index 5c189ceb04..d612f2f16e 100644 --- a/packages/modules/devices/solax/solax/device.py +++ b/packages/modules/devices/solax/solax/device.py @@ -1,99 +1,48 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Optional, List, Union +from typing import Iterable, Union -from dataclass_utils import dataclass_from_dict -from helpermodules.cli import run_using_positional_cli_args -from modules.common import modbus -from modules.common.abstract_device import AbstractDevice, DeviceDescriptor +from modules.common.abstract_device import DeviceDescriptor from modules.common.component_context import SingleComponentUpdateContext -from modules.devices.solax.solax import bat -from modules.devices.solax.solax import counter -from modules.devices.solax.solax import inverter +from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater +from modules.common.modbus import ModbusTcpClient_ +from modules.devices.solax.solax.bat import SolaxBat from modules.devices.solax.solax.config import Solax, SolaxBatSetup, SolaxCounterSetup, SolaxInverterSetup +from modules.devices.solax.solax.counter import SolaxCounter +from modules.devices.solax.solax.inverter import SolaxInverter log = logging.getLogger(__name__) -class Device(AbstractDevice): - COMPONENT_TYPE_TO_CLASS = { - "bat": bat.SolaxBat, - "counter": counter.SolaxCounter, - "inverter": inverter.SolaxInverter - } - - def __init__(self, device_config: Union[Dict, Solax]) -> None: - self.components = {} # type: Dict[str, counter.SolaxCounter] - try: - self.device_config = dataclass_from_dict(Solax, device_config) - self.client = modbus.ModbusTcpClient_( - self.device_config.configuration.ip_address, self.device_config.configuration.port) - except Exception: - log.exception("Fehler im Modul "+self.device_config.name) - - def add_component(self, component_config: Union[Dict, - SolaxBatSetup, - SolaxCounterSetup, - SolaxInverterSetup]) -> None: - if isinstance(component_config, Dict): - component_type = component_config["type"] - else: - component_type = component_config.type - component_config = dataclass_from_dict(COMPONENT_TYPE_TO_MODULE[ - component_type].component_descriptor.configuration_factory, component_config) - if component_type in self.COMPONENT_TYPE_TO_CLASS: - self.components["component"+str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type]( - self.device_config.id, component_config, self.client, - self.device_config.configuration.modbus_id)) - else: - raise Exception( - "illegal component type " + component_type + ". Allowed values: " + - ','.join(self.COMPONENT_TYPE_TO_CLASS.keys()) - ) - - def update(self) -> None: - log.debug("Start device reading " + str(self.components)) - if self.components: - for component in self.components: - # Auch wenn bei einer Komponente ein Fehler auftritt, sollen alle anderen noch ausgelesen werden. - with SingleComponentUpdateContext(self.components[component].fault_state): - self.components[component].update() - else: - log.warning( - self.device_config.name + - ": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden.") - - -COMPONENT_TYPE_TO_MODULE = { - "bat": bat, - "counter": counter, - "inverter": inverter -} - - -def read_legacy(component_type: str, ip_address: str, modbus_id: int, num: Optional[int] = None) -> None: - device_config = Solax() - device_config.configuration.ip_address = ip_address - device_config.configuration.modbus_id = modbus_id - dev = Device(device_config) - if component_type in COMPONENT_TYPE_TO_MODULE: - component_config = COMPONENT_TYPE_TO_MODULE[component_type].component_descriptor.configuration_factory() - else: - raise Exception( - "illegal component type " + component_type + ". Allowed values: " + - ','.join(COMPONENT_TYPE_TO_MODULE.keys()) - ) - component_config.id = num - dev.add_component(component_config) - - log.debug('Solax IP-Adresse: ' + ip_address) - log.debug('Solax ID: ' + str(modbus_id)) - - dev.update() - - -def main(argv: List[str]): - run_using_positional_cli_args(read_legacy, argv) +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) + + def create_counter_component(component_config: SolaxCounterSetup): + return SolaxCounter(device_config.id, component_config, client, device_config.configuration.modbus_id) + + def create_inverter_component(component_config: SolaxInverterSetup): + return SolaxInverter(device_config.id, component_config, client, device_config.configuration.modbus_id) + + def update_components(components: Iterable[Union[SolaxBat, SolaxCounter, SolaxInverter]]): + with client: + for component in components: + with SingleComponentUpdateContext(component.fault_state): + component.update() + + try: + client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) + except Exception: + log.exception("Fehler in create_device") + return ConfigurableDevice( + device_config=device_config, + component_factory=ComponentFactoryByType( + bat=create_bat_component, + counter=create_counter_component, + inverter=create_inverter_component, + ), + component_updater=MultiComponentUpdater(update_components) + ) device_descriptor = DeviceDescriptor(configuration_factory=Solax) diff --git a/packages/modules/devices/sonnen/sonnenbatterie/device.py b/packages/modules/devices/sonnen/sonnenbatterie/device.py index c5ac46c461..bfd73cdb81 100644 --- a/packages/modules/devices/sonnen/sonnenbatterie/device.py +++ b/packages/modules/devices/sonnen/sonnenbatterie/device.py @@ -2,104 +2,48 @@ """ Modul zum Auslesen von sonnenBatterie Speichern. """ import logging -from typing import Dict, Union, Optional, List -from dataclass_utils import dataclass_from_dict -from helpermodules.cli import run_using_positional_cli_args -from modules.common.abstract_device import AbstractDevice, DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext -from modules.devices.sonnen.sonnenbatterie import bat, counter, inverter +from modules.common.abstract_device import DeviceDescriptor +from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, IndependentComponentUpdater +from modules.devices.sonnen.sonnenbatterie.bat import SonnenbatterieBat from modules.devices.sonnen.sonnenbatterie.config import (SonnenBatterie, SonnenbatterieBatSetup, SonnenbatterieCounterSetup, SonnenbatterieInverterSetup) -log = logging.getLogger(__name__) - - -sonnenbatterie_component_classes = Union[ - bat.SonnenbatterieBat, - counter.SonnenbatterieCounter, - inverter.SonnenbatterieInverter -] - - -class Device(AbstractDevice): - COMPONENT_TYPE_TO_CLASS = { - "bat": bat.SonnenbatterieBat, - "counter": counter.SonnenbatterieCounter, - "inverter": inverter.SonnenbatterieInverter - } - - def __init__(self, device_config: Union[Dict, SonnenBatterie]) -> None: - self.components = {} # type: Dict[str, sonnenbatterie_component_classes] - try: - self.device_config = dataclass_from_dict(SonnenBatterie, device_config) - except Exception: - log.exception("Fehler im Modul "+self.device_config.name) +from modules.devices.sonnen.sonnenbatterie.counter import SonnenbatterieCounter +from modules.devices.sonnen.sonnenbatterie.inverter import SonnenbatterieInverter - def add_component(self, component_config: Union[Dict, - SonnenbatterieBatSetup, - SonnenbatterieCounterSetup, - SonnenbatterieInverterSetup]) -> None: - if isinstance(component_config, Dict): - component_type = component_config["type"] - else: - component_type = component_config.type - component_config = dataclass_from_dict(COMPONENT_TYPE_TO_MODULE[ - component_type].component_descriptor.configuration_factory, component_config) - if component_type in self.COMPONENT_TYPE_TO_CLASS: - self.components["component"+str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type]( - self.device_config.id, - self.device_config.configuration.ip_address, - self.device_config.configuration.variant, - component_config)) - else: - raise Exception( - "illegal component type " + component_type + ". Allowed values: " + - ','.join(self.COMPONENT_TYPE_TO_CLASS.keys()) - ) - def update(self) -> None: - log.debug("Start device reading " + str(self.components)) - if self.components: - for component in self.components: - # Auch wenn bei einer Komponente ein Fehler auftritt, sollen alle anderen noch ausgelesen werden. - with SingleComponentUpdateContext(self.components[component].fault_state): - self.components[component].update() - else: - log.warning( - self.device_config.name + - ": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden." - ) - - -COMPONENT_TYPE_TO_MODULE = { - "bat": bat, - "counter": counter, - "inverter": inverter -} - - -def read_legacy(component_type: str, address: str, variant: int, num: Optional[int] = None) -> None: - device_config = SonnenBatterie() - device_config.configuration.ip_address = address - device_config.configuration.variant = variant - dev = Device(device_config) - if component_type in COMPONENT_TYPE_TO_MODULE: - component_config = COMPONENT_TYPE_TO_MODULE[component_type].component_descriptor.configuration_factory() - else: - raise Exception( - "illegal component type " + component_type + ". Allowed values: " + - ','.join(COMPONENT_TYPE_TO_MODULE.keys()) - ) - component_config.id = num - dev.add_component(component_config) - log.debug('SonnenBatterie address: ' + address) - log.debug('SonnenBatterie variant: ' + str(variant)) - dev.update() +log = logging.getLogger(__name__) -def main(argv: List[str]): - run_using_positional_cli_args(read_legacy, argv) +def create_device(device_config: SonnenBatterie): + def create_bat_component(component_config: SonnenbatterieBatSetup): + return SonnenbatterieBat(device_config.id, + device_config.configuration.ip_address, + device_config.configuration.variant, + component_config) + + def create_counter_component(component_config: SonnenbatterieCounterSetup): + return SonnenbatterieCounter(device_config.id, + device_config.configuration.ip_address, + device_config.configuration.variant, + component_config) + + def create_inverter_component(component_config: SonnenbatterieInverterSetup): + return SonnenbatterieInverter(device_config.id, + device_config.configuration.ip_address, + device_config.configuration.variant, + component_config) + + return ConfigurableDevice( + device_config=device_config, + component_factory=ComponentFactoryByType( + bat=create_bat_component, + counter=create_counter_component, + inverter=create_inverter_component, + ), + component_updater=IndependentComponentUpdater(lambda component: component.update()) + ) device_descriptor = DeviceDescriptor(configuration_factory=SonnenBatterie) diff --git a/packages/modules/devices/studer/studer/device.py b/packages/modules/devices/studer/studer/device.py index 0ca412a371..dbbd51528a 100644 --- a/packages/modules/devices/studer/studer/device.py +++ b/packages/modules/devices/studer/studer/device.py @@ -2,91 +2,44 @@ """ Modul zum Auslesen von Alpha Ess Speichern, Zählern und Wechselrichtern. """ import logging -from typing import Dict, List, Union, Optional +from typing import Iterable, Union -from dataclass_utils import dataclass_from_dict -from helpermodules.cli import run_using_positional_cli_args from modules.common import modbus -from modules.common.abstract_device import AbstractDevice, DeviceDescriptor +from modules.common.abstract_device import DeviceDescriptor from modules.common.component_context import SingleComponentUpdateContext -from modules.devices.studer.studer import bat -from modules.devices.studer.studer import inverter -from modules.devices.studer.studer.config import ( - Studer, StuderBatSetup, StuderInverterConfiguration, StuderInverterSetup) +from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater +from modules.devices.studer.studer.bat import StuderBat +from modules.devices.studer.studer.config import Studer, StuderBatSetup, StuderInverterSetup +from modules.devices.studer.studer.inverter import StuderInverter log = logging.getLogger(__name__) -class Device(AbstractDevice): - COMPONENT_TYPE_TO_CLASS = { - "bat": bat.StuderBat, - "inverter": inverter.StuderInverter - } - - def __init__(self, device_config: Union[Dict, Studer]) -> None: - self.components = {} # type: Dict[str, Union[bat.StuderBat, inverter.StuderInverter]] - try: - self.device_config = dataclass_from_dict(Studer, device_config) - self.client = modbus.ModbusTcpClient_( - self.device_config.configuration.ip_address, self.device_config.configuration.port) - except Exception: - log.exception("Fehler im Modul "+self.device_config.name) - - def add_component(self, component_config: Union[Dict, StuderBatSetup, StuderInverterSetup]) -> None: - if isinstance(component_config, Dict): - component_type = component_config["type"] - else: - component_type = component_config.type - component_config = dataclass_from_dict(COMPONENT_TYPE_TO_MODULE[ - component_type].component_descriptor.configuration_factory, component_config) - if component_type in self.COMPONENT_TYPE_TO_CLASS: - self.components["component"+str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type]( - component_config, self.client)) - else: - raise Exception( - "illegal component type " + component_type + ". Allowed values: " + - ','.join(self.COMPONENT_TYPE_TO_CLASS.keys()) - ) - - def update(self) -> None: - log.debug("Start device reading " + str(self.components)) - if self.components: - for component in self.components: - # Auch wenn bei einer Komponente ein Fehler auftritt, sollen alle anderen noch ausgelesen werden. - with SingleComponentUpdateContext(self.components[component].fault_state): - self.components[component].update() - else: - log.warning( - self.device_config.name + - ": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden." - ) - - -COMPONENT_TYPE_TO_MODULE = { - "bat": bat, - "inverter": inverter -} - - -def read_legacy(ip_address: str, component_config: Union[StuderBatSetup, StuderInverterSetup]): - device_config = Studer() - device_config.configuration.ip_address = ip_address - dev = Device(device_config) - dev.add_component(component_config) - dev.update() - - -def read_legacy_bat(ip_address: str, num: Optional[int] = None): - read_legacy(ip_address, bat.component_descriptor.configuration_factory(id=None)) - - -def read_legacy_inverter(ip_address: str, vc_count: int, vc_type: str, num: int): - read_legacy(ip_address, inverter.component_descriptor.configuration_factory( - id=num, configuration=StuderInverterConfiguration(vc_count=vc_count, vc_type=vc_type))) - - -def main(argv: List[str]): - run_using_positional_cli_args({"bat": read_legacy_bat, "inverter": read_legacy_inverter}, argv) +def create_device(device_config: Studer): + def create_bat_component(component_config: StuderBatSetup): + return StuderBat(component_config, client) + + def create_inverter_component(component_config: StuderInverterSetup): + return StuderInverter(component_config, client) + + def update_components(components: Iterable[Union[StuderBat, StuderInverter]]): + with client: + for component in components: + with SingleComponentUpdateContext(component.fault_state): + component.update() + + try: + client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) + except Exception: + log.exception("Fehler in create_device") + return ConfigurableDevice( + device_config=device_config, + component_factory=ComponentFactoryByType( + bat=create_bat_component, + inverter=create_inverter_component, + ), + component_updater=MultiComponentUpdater(update_components) + ) device_descriptor = DeviceDescriptor(configuration_factory=Studer) diff --git a/packages/modules/devices/sungrow/sungrow/device.py b/packages/modules/devices/sungrow/sungrow/device.py index 1c647c1f4e..9f00a7eef9 100644 --- a/packages/modules/devices/sungrow/sungrow/device.py +++ b/packages/modules/devices/sungrow/sungrow/device.py @@ -1,133 +1,56 @@ #!/usr/bin/env python3 import logging -from typing import Dict, List, Union +from typing import Iterable, Union -from dataclass_utils import dataclass_from_dict -from helpermodules.cli import run_using_positional_cli_args from modules.common import modbus -from modules.common.abstract_device import AbstractDevice, DeviceDescriptor -from modules.common.component_context import MultiComponentUpdateContext -from modules.devices.sungrow.sungrow import bat -from modules.devices.sungrow.sungrow import counter -from modules.devices.sungrow.sungrow import inverter -from modules.devices.sungrow.sungrow.config import (Sungrow, SungrowBatSetup, SungrowCounterConfiguration, - SungrowCounterSetup, - SungrowInverterSetup) -from modules.devices.sungrow.sungrow.version import Version +from modules.common.abstract_device import DeviceDescriptor +from modules.common.component_context import SingleComponentUpdateContext +from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater +from modules.devices.sungrow.sungrow.bat import SungrowBat +from modules.devices.sungrow.sungrow.config import Sungrow, SungrowBatSetup, SungrowCounterSetup, SungrowInverterSetup +from modules.devices.sungrow.sungrow.counter import SungrowCounter +from modules.devices.sungrow.sungrow.inverter import SungrowInverter log = logging.getLogger(__name__) -sungrow_component_classes = Union[bat.SungrowBat, counter.SungrowCounter, inverter.SungrowInverter] - -class Device(AbstractDevice): - COMPONENT_TYPE_TO_CLASS = { - "bat": bat.SungrowBat, - "counter": counter.SungrowCounter, - "inverter": inverter.SungrowInverter - } - - def __init__(self, device_config: Union[Dict, Sungrow]) -> None: - self.components = {} # type: Dict[str, sungrow_component_classes] - try: - self.device_config = dataclass_from_dict(Sungrow, device_config) - self.client = modbus.ModbusTcpClient_( - self.device_config.configuration.ip_address, self.device_config.configuration.port) - except Exception: - log.exception("Fehler im Modul " + self.device_config.name) - - def add_component(self, - component_config: Union[ - Dict, SungrowBatSetup, SungrowCounterSetup, SungrowInverterSetup]) -> None: - if isinstance(component_config, Dict): - component_type = component_config["type"] - else: - component_type = component_config.type - component_config = dataclass_from_dict( - COMPONENT_TYPE_TO_MODULE[component_type].component_descriptor.configuration_factory, component_config) - if component_type in self.COMPONENT_TYPE_TO_CLASS: - self.components["component" + str(component_config.id)] = (self.COMPONENT_TYPE_TO_CLASS[component_type]( - self.device_config, component_config, self.client)) - else: - raise Exception( - "illegal component type " + component_type + ". Allowed values: " + - ','.join(self.COMPONENT_TYPE_TO_CLASS.keys()) - ) - - def update(self) -> None: - log.debug("Start device reading " + str(self.components)) - if self.components: - with MultiComponentUpdateContext(self.components): - with self.client: - for component in self.components.values(): - if isinstance(component, inverter.SungrowInverter): - pv_power = component.update() - for component in self.components.values(): - if isinstance(component, counter.SungrowCounter): - component.update(pv_power) - for component in self.components.values(): - if isinstance(component, bat.SungrowBat): - component.update() - else: - log.warning( - self.device_config.name + - ": Es konnten keine Werte gelesen werden, da noch keine Komponenten konfiguriert wurden." - ) - - -COMPONENT_TYPE_TO_MODULE = { - "bat": bat, - "counter": counter, - "inverter": inverter -} - - -def read_legacy(ip_address: str, - port: int, - modbus_id: int, - version: int, - component_config: dict): - device_config = Sungrow() - device_config.configuration.ip_address = ip_address - device_config.configuration.port = port - device_config.configuration.modbus_id = modbus_id - device_config.configuration.version = Version(version) - dev = Device(device_config) - dev.add_component(component_config) - dev.update() - - -def read_legacy_bat(ip_address: str, port: int, modbus_id: int, version: int): - read_legacy(ip_address, port, modbus_id, version, bat.component_descriptor.configuration_factory(id=None)) - - -def read_legacy_counter(ip_address: str, port: int, modbus_id: int, version: int): - read_legacy(ip_address, port, modbus_id, version, counter.component_descriptor.configuration_factory( - id=None, configuration=SungrowCounterConfiguration())) - - -def read_legacy_inverter(ip_address: str, - port: int, - modbus_id: int, - num: int, - read_counter: int, - version: int): - device_config = Sungrow() - device_config.configuration.ip_address = ip_address - device_config.configuration.port = port - device_config.configuration.modbus_id = modbus_id - device_config.configuration.version = Version(version) - dev = Device(device_config) - dev.add_component(inverter.component_descriptor.configuration_factory(id=num)) - if read_counter == 1: - dev.add_component(counter.component_descriptor.configuration_factory( - id=None, configuration=SungrowCounterConfiguration())) - dev.update() - - -def main(argv: List[str]): - run_using_positional_cli_args( - {"bat": read_legacy_bat, "counter": read_legacy_counter, "inverter": read_legacy_inverter}, argv +def create_device(device_config: Sungrow): + def create_bat_component(component_config: SungrowBatSetup): + return SungrowBat(device_config, component_config, client) + + def create_counter_component(component_config: SungrowCounterSetup): + return SungrowCounter(device_config, component_config, client) + + def create_inverter_component(component_config: SungrowInverterSetup): + return SungrowInverter(device_config, component_config, client) + + def update_components(components: Iterable[Union[SungrowBat, SungrowCounter, SungrowInverter]]): + with client: + for component in components.values(): + if isinstance(component, SungrowInverter): + with SingleComponentUpdateContext(component.fault_state): + pv_power = component.update() + for component in components.values(): + if isinstance(component, SungrowCounter): + with SingleComponentUpdateContext(component.fault_state): + component.update(pv_power) + for component in components.values(): + if isinstance(component, SungrowBat): + with SingleComponentUpdateContext(component.fault_state): + component.update() + + try: + client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) + except Exception: + log.exception("Fehler in create_device") + return ConfigurableDevice( + device_config=device_config, + component_factory=ComponentFactoryByType( + bat=create_bat_component, + counter=create_counter_component, + inverter=create_inverter_component, + ), + component_updater=MultiComponentUpdater(update_components) )