diff --git a/docs/samples/sample_modbus/__init__.py b/docs/samples/sample_modbus/__init__ .py similarity index 100% rename from docs/samples/sample_modbus/__init__.py rename to docs/samples/sample_modbus/__init__ .py diff --git a/docs/samples/sample_modbus/device.py b/docs/samples/sample_modbus/device.py deleted file mode 100644 index 07f9a88026..0000000000 --- a/docs/samples/sample_modbus/device.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 -import logging -from typing import Iterable, Optional, Union, List - -from helpermodules.cli import run_using_positional_cli_args -from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext -from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater -from modules.common.modbus import ModbusTcpClient_ -from modules.devices.sample_modbus import bat, counter, inverter -from modules.devices.sample_modbus.bat import SampleBat -from modules.devices.sample_modbus.config import Sample, SampleConfiguration, SampleBatSetup, SampleCounterSetup, SampleInverterSetup -from modules.devices.sample_modbus.counter import SampleCounter -from modules.devices.sample_modbus.inverter import SampleInverter - -log = logging.getLogger(__name__) - - -def create_device(device_config: Sample): - def create_bat_component(component_config: SampleBatSetup): - return SampleBat(device_config.id, component_config, device_config.configuration.ip_address, client) - - def create_counter_component(component_config: SampleCounterSetup): - return SampleCounter(device_config.id, component_config, device_config.configuration.ip_address, client) - - def create_inverter_component(component_config: SampleInverterSetup): - return SampleInverter(device_config.id, component_config, device_config.configuration.ip_address, client) - - def update_components(components: Iterable[Union[SampleBat, SampleCounter, SampleInverter]]): - 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) - ) - - -COMPONENT_TYPE_TO_MODULE = { - "bat": bat, - "counter": counter, - "inverter": inverter -} - - -def read_legacy(component_type: str, ip_address: str, id: int, num: Optional[int]) -> None: - device_config = Sample(configuration=SampleConfiguration(ip_address=ip_address, id=id)) - dev = create_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('Sample IP-Adresse: ' + ip_address) - log.debug('Sample ID: ' + str(id)) - - dev.update() - - -def main(argv: List[str]): - run_using_positional_cli_args(read_legacy, argv) - - -device_descriptor = DeviceDescriptor(configuration_factory=Sample) diff --git a/docs/samples/sample_request_by_component/__init__.py b/docs/samples/sample_modbus/sample_modbus/__init__.py similarity index 100% rename from docs/samples/sample_request_by_component/__init__.py rename to docs/samples/sample_modbus/sample_modbus/__init__.py diff --git a/docs/samples/sample_modbus/bat.py b/docs/samples/sample_modbus/sample_modbus/bat.py similarity index 71% rename from docs/samples/sample_modbus/bat.py rename to docs/samples/sample_modbus/sample_modbus/bat.py index eaee6a3f48..2d70856b12 100644 --- a/docs/samples/sample_modbus/bat.py +++ b/docs/samples/sample_modbus/sample_modbus/bat.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -from typing import Optional -from dataclass_utils import dataclass_from_dict +from typing import Optional, TypedDict, Any from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -8,20 +7,30 @@ from modules.common.modbus import ModbusDataType, ModbusTcpClient_ from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store -from modules.devices.sample_modbus.config import SampleBatSetup +from modules.devices.sample_modbus.sample_modbus.config import SampleBatSetup + + +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ class SampleBat(AbstractBat): - def __init__(self, device_id: int, component_config: SampleBatSetup, client: ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleBatSetup, component_config) + def __init__(self, component_config: SampleBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_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.client = client def update(self) -> None: + unit = self.component_config.configuration.modbus_id power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) + soc = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/docs/samples/sample_request_by_device/config.py b/docs/samples/sample_modbus/sample_modbus/config.py similarity index 84% rename from docs/samples/sample_request_by_device/config.py rename to docs/samples/sample_modbus/sample_modbus/config.py index 0d011cd9f3..c4ec32026a 100644 --- a/docs/samples/sample_request_by_device/config.py +++ b/docs/samples/sample_modbus/sample_modbus/config.py @@ -5,8 +5,9 @@ @auto_str class SampleConfiguration: - def __init__(self, ip_address: Optional[str] = None): + def __init__(self, ip_address: Optional[str] = None, port: int = 502): self.ip_address = ip_address + self.port = port @auto_str @@ -24,8 +25,8 @@ def __init__(self, @auto_str class SampleBatConfiguration: - def __init__(self): - pass + def __init__(self, modbus_id: int = 1): + self.modbus_id = modbus_id @auto_str @@ -40,8 +41,8 @@ def __init__(self, @auto_str class SampleCounterConfiguration: - def __init__(self): - pass + def __init__(self, modbus_id: int = 1): + self.modbus_id = modbus_id @auto_str @@ -56,8 +57,8 @@ def __init__(self, @auto_str class SampleInverterConfiguration: - def __init__(self): - pass + def __init__(self, modbus_id: int = 1): + self.modbus_id = modbus_id @auto_str diff --git a/docs/samples/sample_modbus/counter.py b/docs/samples/sample_modbus/sample_modbus/counter.py similarity index 71% rename from docs/samples/sample_modbus/counter.py rename to docs/samples/sample_modbus/sample_modbus/counter.py index 5b9650c742..206d9bdbb8 100644 --- a/docs/samples/sample_modbus/counter.py +++ b/docs/samples/sample_modbus/sample_modbus/counter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -7,17 +7,25 @@ from modules.common.modbus import ModbusDataType, ModbusTcpClient_ from modules.common.simcount import SimCounter from modules.common.store import get_counter_value_store -from modules.devices.sample_modbus.config import SampleCounterSetup +from modules.devices.sample_modbus.sample_modbus.config import SampleCounterSetup + + +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ class SampleCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: SampleCounterSetup, client: ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleCounterSetup, component_config) + def __init__(self, component_config: SampleCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.client = client def update(self): power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) diff --git a/docs/samples/sample_modbus/sample_modbus/device.py b/docs/samples/sample_modbus/sample_modbus/device.py new file mode 100644 index 0000000000..e16fa7335b --- /dev/null +++ b/docs/samples/sample_modbus/sample_modbus/device.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import logging +from typing import Iterable, Union + +from modules.common.abstract_device import DeviceDescriptor +from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater +from modules.common.modbus import ModbusTcpClient_ +from modules.devices.sample_modbus.sample_modbus.bat import SampleBat +from modules.devices.sample_modbus.sample_modbus.config import Sample, SampleBatSetup, SampleCounterSetup, SampleInverterSetup +from modules.devices.sample_modbus.sample_modbus.counter import SampleCounter +from modules.devices.sample_modbus.sample_modbus.inverter import SampleInverter + +log = logging.getLogger(__name__) + + +def create_device(device_config: Sample): + client = None + + def create_bat_component(component_config: SampleBatSetup): + nonlocal client + return SampleBat(component_config, device_id=device_config.id, client=client) + + def create_counter_component(component_config: SampleCounterSetup): + nonlocal client + return SampleCounter(component_config, device_id=device_config.id, client=client) + + def create_inverter_component(component_config: SampleInverterSetup): + nonlocal client + return SampleInverter(component_config, device_id=device_config.id, client=client) + + def update_components(components: Iterable[Union[SampleBat, SampleCounter, SampleInverter]]): + with client: + for component in components: + component.update() + + def initializer(): + nonlocal client + client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) + + return ConfigurableDevice( + device_config=device_config, + initializer=initializer, + 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=Sample) diff --git a/docs/samples/sample_modbus/inverter.py b/docs/samples/sample_modbus/sample_modbus/inverter.py similarity index 69% rename from docs/samples/sample_modbus/inverter.py rename to docs/samples/sample_modbus/sample_modbus/inverter.py index 4cf593294a..6fda28c90f 100644 --- a/docs/samples/sample_modbus/inverter.py +++ b/docs/samples/sample_modbus/sample_modbus/inverter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -7,17 +7,25 @@ from modules.common.modbus import ModbusDataType, ModbusTcpClient_ from modules.common.simcount import SimCounter from modules.common.store import get_inverter_value_store -from modules.devices.sample_modbus.config import SampleInverterSetup +from modules.devices.sample_modbus.sample_modbus.config import SampleInverterSetup + + +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ class SampleInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: SampleInverterSetup, client: ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleInverterSetup, component_config) + def __init__(self, component_config: SampleInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.client = client def update(self) -> None: power = self.client.read_holding_registers(reg, ModbusDataType.INT_32, unit=unit) diff --git a/docs/samples/sample_modbus/vendor.py b/docs/samples/sample_modbus/vendor.py new file mode 100644 index 0000000000..9741383ef5 --- /dev/null +++ b/docs/samples/sample_modbus/vendor.py @@ -0,0 +1,14 @@ +from pathlib import Path + +from modules.common.abstract_device import DeviceDescriptor +from modules.devices.vendors import VendorGroup + + +class Vendor: + def __init__(self): + self.type = Path(__file__).parent.name + self.vendor = "Sample" + self.group = VendorGroup.VENDORS.value + + +vendor_descriptor = DeviceDescriptor(configuration_factory=Vendor) diff --git a/docs/samples/sample_request_by_device/__init__.py b/docs/samples/sample_request_by_component/__init__ .py similarity index 100% rename from docs/samples/sample_request_by_device/__init__.py rename to docs/samples/sample_request_by_component/__init__ .py diff --git a/docs/samples/sample_request_by_component/device.py b/docs/samples/sample_request_by_component/device.py deleted file mode 100644 index a6804f877a..0000000000 --- a/docs/samples/sample_request_by_component/device.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python3 -import logging -from typing import Optional, List - -from helpermodules.cli import run_using_positional_cli_args -from modules.common.abstract_device import DeviceDescriptor -from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, IndependentComponentUpdater -from modules.devices.sample_request_by_component import bat, counter, inverter -from modules.devices.sample_request_by_component.bat import SampleBat -from modules.devices.sample_request_by_component.config import Sample, SampleConfiguration, SampleBatSetup, SampleCounterSetup, SampleInverterSetup -from modules.devices.sample_request_by_component.counter import SampleCounter -from modules.devices.sample_request_by_component.inverter import SampleInverter - -log = logging.getLogger(__name__) - - -def create_device(device_config: Sample): - def create_bat_component(component_config: SampleBatSetup): - return SampleBat(device_config.id, component_config, device_config.configuration.ip_address) - - def create_counter_component(component_config: SampleCounterSetup): - return SampleCounter(device_config.id, component_config, device_config.configuration.ip_address) - - def create_inverter_component(component_config: SampleInverterSetup): - return SampleInverter(device_config.id, component_config, device_config.configuration.ip_address) - - 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()) - ) - - -COMPONENT_TYPE_TO_MODULE = { - "bat": bat, - "counter": counter, - "inverter": inverter -} - - -def read_legacy(component_type: str, ip_address: str, id: int, num: Optional[int]) -> None: - device_config = Sample(configuration=SampleConfiguration(ip_address=ip_address, id=id)) - dev = create_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('Sample IP-Adresse: ' + ip_address) - log.debug('Sample ID: ' + str(id)) - - dev.update() - - -def main(argv: List[str]): - run_using_positional_cli_args(read_legacy, argv) - - -device_descriptor = DeviceDescriptor(configuration_factory=Sample) diff --git a/docs/samples/sample_request_by_component/sample_request_by_component/__init__.py b/docs/samples/sample_request_by_component/sample_request_by_component/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/samples/sample_request_by_component/bat.py b/docs/samples/sample_request_by_component/sample_request_by_component/bat.py similarity index 63% rename from docs/samples/sample_request_by_component/bat.py rename to docs/samples/sample_request_by_component/sample_request_by_component/bat.py index 0623ba06c7..b06120e94f 100644 --- a/docs/samples/sample_request_by_component/bat.py +++ b/docs/samples/sample_request_by_component/sample_request_by_component/bat.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common import req from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -7,20 +7,30 @@ from modules.common.fault_state import ComponentInfo, FaultState from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store -from modules.devices.sample_request_by_component.config import SampleBatSetup, SampleConfiguration +from modules.devices.sample_request_by_component.sample_request_by_component.config import SampleBatSetup, SampleConfiguration + + +class KwargsDict(TypedDict): + device_id: int + ip_address: str class SampleBat(AbstractBat): - def __init__(self, device_id: int, component_config: SampleBatSetup, ip_address: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleBatSetup, component_config) - self.ip_address = ip_address + def __init__(self, component_config: SampleBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.ip_address: str = self.kwargs['ip_address'] self.sim_counter = SimCounter(self.__device_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: resp = req.get_http_session().get(self.ip_address) + power = resp.json().get("power") + soc = resp.json().get("soc") imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/docs/samples/sample_modbus/config.py b/docs/samples/sample_request_by_component/sample_request_by_component/config.py similarity index 100% rename from docs/samples/sample_modbus/config.py rename to docs/samples/sample_request_by_component/sample_request_by_component/config.py diff --git a/docs/samples/sample_request_by_component/counter.py b/docs/samples/sample_request_by_component/sample_request_by_component/counter.py similarity index 68% rename from docs/samples/sample_request_by_component/counter.py rename to docs/samples/sample_request_by_component/sample_request_by_component/counter.py index 3dff0611ee..d069831e56 100644 --- a/docs/samples/sample_request_by_component/counter.py +++ b/docs/samples/sample_request_by_component/sample_request_by_component/counter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common import req from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -7,20 +7,29 @@ from modules.common.fault_state import ComponentInfo, FaultState from modules.common.simcount import SimCounter from modules.common.store import get_counter_value_store -from modules.devices.sample_request_by_component.config import SampleCounterSetup, SampleConfiguration +from modules.devices.sample_request_by_component.sample_request_by_component.config import SampleCounterSetup + + +class KwargsDict(TypedDict): + device_id: int + ip_address: str class SampleCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: SampleCounterSetup, ip_address: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleCounterSetup, component_config) - self.ip_address = ip_address + def __init__(self, component_config: SampleCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.ip_address: str = self.kwargs['ip_address'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self): resp = req.get_http_session().get(self.ip_address) + power = resp.json().get("power") imported, exported = self.sim_counter.sim_count(power) counter_state = CounterState( diff --git a/docs/samples/sample_request_by_component/sample_request_by_component/device.py b/docs/samples/sample_request_by_component/sample_request_by_component/device.py new file mode 100644 index 0000000000..508546fbc9 --- /dev/null +++ b/docs/samples/sample_request_by_component/sample_request_by_component/device.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +import logging + +from modules.common.abstract_device import DeviceDescriptor +from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, IndependentComponentUpdater +from modules.devices.sample_request_by_component.sample_request_by_component.bat import SampleBat +from modules.devices.sample_request_by_component.sample_request_by_component.config import Sample, SampleBatSetup, SampleCounterSetup, SampleInverterSetup +from modules.devices.sample_request_by_component.sample_request_by_component.counter import SampleCounter +from modules.devices.sample_request_by_component.sample_request_by_component.inverter import SampleInverter + +log = logging.getLogger(__name__) + + +def create_device(device_config: Sample): + session = None + + def create_bat_component(component_config: SampleBatSetup): + return SampleBat(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address) + + def create_counter_component(component_config: SampleCounterSetup): + return SampleCounter(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address) + + def create_inverter_component(component_config: SampleInverterSetup): + return SampleInverter(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address) + + def initializer(): + nonlocal session + session = req.get_http_session() + + return ConfigurableDevice( + device_config=device_config, + initializer=initializer, + component_factory=ComponentFactoryByType( + bat=create_bat_component, + counter=create_counter_component, + inverter=create_inverter_component, + ), + component_updater=IndependentComponentUpdater(lambda component: component.update(session)) + ) + + +device_descriptor = DeviceDescriptor(configuration_factory=Sample) diff --git a/docs/samples/sample_request_by_component/inverter.py b/docs/samples/sample_request_by_component/sample_request_by_component/inverter.py similarity index 63% rename from docs/samples/sample_request_by_component/inverter.py rename to docs/samples/sample_request_by_component/sample_request_by_component/inverter.py index 963e5e77bc..9ea314435a 100644 --- a/docs/samples/sample_request_by_component/inverter.py +++ b/docs/samples/sample_request_by_component/sample_request_by_component/inverter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common import req from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -7,20 +7,31 @@ from modules.common.fault_state import ComponentInfo, FaultState from modules.common.simcount import SimCounter from modules.common.store import get_inverter_value_store -from modules.devices.sample_request_by_component.config import SampleInverterSetup, SampleConfiguration +from modules.devices.sample_request_by_component.sample_request_by_component.config import SampleInverterSetup + + +class KwargsDict(TypedDict): + device_id: int + ip_address: str class SampleInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: SampleInverterSetup, ip_address: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleInverterSetup, component_config) - self.ip_address = ip_address + def __init__(self, component_config: SampleInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.ip_address: str = self.kwargs['ip_address'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") 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: resp = req.get_http_session().get(self.ip_address) + power = resp.json().get("power") + currents = resp.json().get("currents") + dc_power = resp.json().get("dc_power") exported = self.sim_counter.sim_count(power)[1] inverter_state = InverterState( diff --git a/docs/samples/sample_request_by_component/vendor.py b/docs/samples/sample_request_by_component/vendor.py new file mode 100644 index 0000000000..9741383ef5 --- /dev/null +++ b/docs/samples/sample_request_by_component/vendor.py @@ -0,0 +1,14 @@ +from pathlib import Path + +from modules.common.abstract_device import DeviceDescriptor +from modules.devices.vendors import VendorGroup + + +class Vendor: + def __init__(self): + self.type = Path(__file__).parent.name + self.vendor = "Sample" + self.group = VendorGroup.VENDORS.value + + +vendor_descriptor = DeviceDescriptor(configuration_factory=Vendor) diff --git a/docs/samples/sample_request_by_device/__init__ .py b/docs/samples/sample_request_by_device/__init__ .py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/samples/sample_request_by_device/device.py b/docs/samples/sample_request_by_device/device.py deleted file mode 100644 index bfc3d414e3..0000000000 --- a/docs/samples/sample_request_by_device/device.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -import logging -from typing import Iterable, Optional, Union, List - -from helpermodules.cli import run_using_positional_cli_args -from modules.common import req -from modules.common.abstract_device import DeviceDescriptor -from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater -from modules.devices.sample_request_by_device import bat, counter, inverter -from modules.devices.sample_request_by_device.bat import SampleBat -from modules.devices.sample_request_by_device.config import Sample, SampleConfiguration, SampleBatSetup, SampleCounterSetup, SampleInverterSetup -from modules.devices.sample_request_by_device.counter import SampleCounter -from modules.devices.sample_request_by_device.inverter import SampleInverter - -log = logging.getLogger(__name__) - - -def create_device(device_config: Sample): - def create_bat_component(component_config: SampleBatSetup): - return SampleBat(device_config.id, component_config) - - def create_counter_component(component_config: SampleCounterSetup): - return SampleCounter(device_config.id, component_config) - - def create_inverter_component(component_config: SampleInverterSetup): - return SampleInverter(device_config.id, component_config) - - def update_components(components: Iterable[Union[SampleBat, SampleCounter, SampleInverter]]): - response = req.get_http_session().get(device_config.configuration.ip_address, timeout=5).json() - for component in components: - component.update(response) - - 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) - ) - - -COMPONENT_TYPE_TO_MODULE = { - "bat": bat, - "counter": counter, - "inverter": inverter -} - - -def read_legacy(component_type: str, ip_address: str, id: int, num: Optional[int]) -> None: - device_config = Sample(configuration=SampleConfiguration(ip_address=ip_address, id=id)) - dev = create_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('Sample IP-Adresse: ' + ip_address) - log.debug('Sample ID: ' + str(id)) - - dev.update() - # Hier kann es notwendig sein, für 1.9 eine eigene Update-Methode zu implemenitieren, die die Werte wie benötigt miteinander verrechnet. - # Hier muss auch bei Hybrid-Systemen die Speicher-und PV-Leistung verrechnet werden. - - -def main(argv: List[str]): - run_using_positional_cli_args(read_legacy, argv) - - -device_descriptor = DeviceDescriptor(configuration_factory=Sample) diff --git a/docs/samples/sample_request_by_device/sample_request_by_device/__init__.py b/docs/samples/sample_request_by_device/sample_request_by_device/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/samples/sample_request_by_device/bat.py b/docs/samples/sample_request_by_device/sample_request_by_device/bat.py similarity index 67% rename from docs/samples/sample_request_by_device/bat.py rename to docs/samples/sample_request_by_device/sample_request_by_device/bat.py index 8c84673029..90aa3832ce 100644 --- a/docs/samples/sample_request_by_device/bat.py +++ b/docs/samples/sample_request_by_device/sample_request_by_device/bat.py @@ -1,24 +1,33 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store -from modules.devices.sample_request_by_device.config import SampleBatSetup +from modules.devices.sample_request_by_device.sample_request_by_device.config import SampleBatSetup + + +class KwargsDict(TypedDict): + device_id: int class SampleBat(AbstractBat): - def __init__(self, device_id: int, component_config: SampleBatSetup) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleBatSetup, component_config) + def __init__(self, component_config: SampleBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_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, response) -> None: # hier die Werte aus der response parsen + power = response.get("power") + soc = response.get("soc") imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/docs/samples/sample_request_by_component/config.py b/docs/samples/sample_request_by_device/sample_request_by_device/config.py similarity index 100% rename from docs/samples/sample_request_by_component/config.py rename to docs/samples/sample_request_by_device/sample_request_by_device/config.py diff --git a/docs/samples/sample_request_by_device/counter.py b/docs/samples/sample_request_by_device/sample_request_by_device/counter.py similarity index 63% rename from docs/samples/sample_request_by_device/counter.py rename to docs/samples/sample_request_by_device/sample_request_by_device/counter.py index fbb409b3dd..bb92a8eba4 100644 --- a/docs/samples/sample_request_by_device/counter.py +++ b/docs/samples/sample_request_by_device/sample_request_by_device/counter.py @@ -1,24 +1,37 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState from modules.common.simcount import SimCounter from modules.common.store import get_counter_value_store -from modules.devices.sample_request_by_device.config import SampleCounterSetup +from modules.devices.sample_request_by_device.sample_request_by_device.config import SampleCounterSetup + + +class KwargsDict(TypedDict): + device_id: int class SampleCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: SampleCounterSetup) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleCounterSetup, component_config) + def __init__(self, component_config: SampleCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self, response): # hier die Werte aus der response parsen + power = response.get("power") + currents = response.get("currents") + frequency = response.get("frequency") + power_factors = response.get("power_factors") + powers = response.get("powers") + voltages = response.get("voltages") imported, exported = self.sim_counter.sim_count(power) counter_state = CounterState( diff --git a/docs/samples/sample_request_by_device/sample_request_by_device/device.py b/docs/samples/sample_request_by_device/sample_request_by_device/device.py new file mode 100644 index 0000000000..c08525efaf --- /dev/null +++ b/docs/samples/sample_request_by_device/sample_request_by_device/device.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import logging +from typing import Iterable, Union + +from modules.common import req +from modules.common.abstract_device import DeviceDescriptor +from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater +from modules.devices.sample_request_by_device.sample_request_by_device.bat import SampleBat +from modules.devices.sample_request_by_device.sample_request_by_device.config import Sample, SampleBatSetup, SampleCounterSetup, SampleInverterSetup +from modules.devices.sample_request_by_device.sample_request_by_device.counter import SampleCounter +from modules.devices.sample_request_by_device.sample_request_by_device.inverter import SampleInverter + +log = logging.getLogger(__name__) + + +def create_device(device_config: Sample): + def create_bat_component(component_config: SampleBatSetup): + return SampleBat(component_config, device_id=device_config.id) + + def create_counter_component(component_config: SampleCounterSetup): + return SampleCounter(component_config, device_id=device_config.id) + + def create_inverter_component(component_config: SampleInverterSetup): + return SampleInverter(component_config, device_id=device_config.id) + + def update_components(components: Iterable[Union[SampleBat, SampleCounter, SampleInverter]]): + response = req.get_http_session().get(device_config.configuration.ip_address, timeout=5).json() + for component in components: + component.update(response) + + 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=Sample) diff --git a/docs/samples/sample_request_by_device/inverter.py b/docs/samples/sample_request_by_device/sample_request_by_device/inverter.py similarity index 65% rename from docs/samples/sample_request_by_device/inverter.py rename to docs/samples/sample_request_by_device/sample_request_by_device/inverter.py index 3ee036e764..20ce4fe886 100644 --- a/docs/samples/sample_request_by_device/inverter.py +++ b/docs/samples/sample_request_by_device/sample_request_by_device/inverter.py @@ -1,24 +1,34 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState from modules.common.simcount import SimCounter from modules.common.store import get_inverter_value_store -from modules.devices.sample_request_by_device.config import SampleInverterSetup +from modules.devices.sample_request_by_device.sample_request_by_device.config import SampleInverterSetup + + +class KwargsDict(TypedDict): + device_id: int class SampleInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: SampleInverterSetup) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SampleInverterSetup, component_config) + def __init__(self, component_config: SampleInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self, response) -> None: # hier die Werte aus der response parsen + power = response.get("power") + currents = response.get("currents") + dc_power = response.get("dc_power") exported = self.sim_counter.sim_count(power)[1] inverter_state = InverterState( diff --git a/docs/samples/sample_request_by_device/vendor.py b/docs/samples/sample_request_by_device/vendor.py new file mode 100644 index 0000000000..9741383ef5 --- /dev/null +++ b/docs/samples/sample_request_by_device/vendor.py @@ -0,0 +1,14 @@ +from pathlib import Path + +from modules.common.abstract_device import DeviceDescriptor +from modules.devices.vendors import VendorGroup + + +class Vendor: + def __init__(self): + self.type = Path(__file__).parent.name + self.vendor = "Sample" + self.group = VendorGroup.VENDORS.value + + +vendor_descriptor = DeviceDescriptor(configuration_factory=Vendor) diff --git a/packages/modules/common/abstract_device.py b/packages/modules/common/abstract_device.py index b0c235b9ed..46968be4e9 100644 --- a/packages/modules/common/abstract_device.py +++ b/packages/modules/common/abstract_device.py @@ -18,7 +18,12 @@ def update(self) -> None: class AbstractBat: @abstractmethod - def __init__(self, *kwargs) -> None: + def __init__(self, component_config, **kwargs) -> None: + self.component_config = component_config + self.kwargs = kwargs + + @abstractmethod + def initializer(self): pass @abstractmethod @@ -33,7 +38,12 @@ def set_power_limit(self, power_limit: Optional[int]) -> None: class AbstractCounter: @abstractmethod - def __init__(self, *kwargs) -> None: + def __init__(self, component_config, **kwargs) -> None: + self.component_config = component_config + self.kwargs = kwargs + + @abstractmethod + def initializer(self): pass @abstractmethod @@ -43,7 +53,12 @@ def update(self, *kwargs) -> None: class AbstractInverter: @abstractmethod - def __init__(self, *kwargs) -> None: + def __init__(self, component_config, **kwargs) -> None: + self.component_config = component_config + self.kwargs = kwargs + + @abstractmethod + def initializer(self): pass @abstractmethod diff --git a/packages/modules/common/component_context.py b/packages/modules/common/component_context.py index 534bc25416..5e67b018fb 100644 --- a/packages/modules/common/component_context.py +++ b/packages/modules/common/component_context.py @@ -1,6 +1,6 @@ import logging import threading -from typing import Optional, List, Union, Any, Dict +from typing import Callable, Optional, List, Union, Any, Dict from helpermodules.constants import NO_ERROR from modules.common.fault_state import ComponentInfo, FaultState, FaultStateLevel @@ -17,10 +17,15 @@ class SingleComponentUpdateContext: component.update() """ - def __init__(self, fault_state: FaultState, update_always: bool = True, reraise: bool = False): + def __init__(self, + fault_state: FaultState, + error_handler: Callable = None, + update_always: bool = True, + reraise: bool = False): self.__fault_state = fault_state self.update_always = update_always self.reraise = reraise + self.error_handler = error_handler def __enter__(self): log.debug("Update Komponente ['"+self.__fault_state.component_info.name+"']") @@ -30,6 +35,8 @@ def __enter__(self): def __exit__(self, exception_type, exception, exception_traceback) -> bool: MultiComponentUpdateContext.override_subcomponent_state(self.__fault_state, exception, self.update_always) + if isinstance(exception, Exception) and self.error_handler is not None: + self.error_handler() if self.reraise is False: return True else: @@ -46,10 +53,11 @@ class MultiComponentUpdateContext: """ __thread_local = threading.local() - def __init__(self, device_components: Union[Dict[Any, Any], List[Any]]): + def __init__(self, device_components: Union[Dict[Any, Any], List[Any]], error_handler: Optional[callable] = None): self.__device_components = \ device_components.values() if isinstance(device_components, dict) else device_components self.__ignored_components = [] # type: List[ComponentInfo] + self.error_handler = error_handler def __enter__(self): if hasattr(self.__thread_local, "active_context"): @@ -69,6 +77,8 @@ def __exit__(self, exception_type, exception, exception_traceback) -> bool: fault_state.from_exception(exception) fault_state.store_error() delattr(MultiComponentUpdateContext.__thread_local, "active_context") + if isinstance(exception, Exception) and self.error_handler is not None: + self.error_handler() return True def ignore_subcomponent_state(self, component: ComponentInfo): diff --git a/packages/modules/common/configurable_device.py b/packages/modules/common/configurable_device.py index cfa5963f96..660b1d5171 100644 --- a/packages/modules/common/configurable_device.py +++ b/packages/modules/common/configurable_device.py @@ -1,10 +1,11 @@ import inspect +import logging from typing import TypeVar, Generic, Dict, Any, Callable, Iterable, List from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractDevice from modules.common.component_context import SingleComponentUpdateContext, MultiComponentUpdateContext -from modules.common.fault_state import FaultState +from modules.common.fault_state import ComponentInfo, FaultState T_DEVICE_CONFIG = TypeVar("T_DEVICE_CONFIG") T_COMPONENT = TypeVar("T_COMPONENT") @@ -13,14 +14,16 @@ ComponentUpdater = Callable[[Iterable[T_COMPONENT]], None] ComponentFactory = Callable[[T_COMPONENT_CONFIG], T_COMPONENT] +log = logging.getLogger(__name__) + class IndependentComponentUpdater(Generic[T_COMPONENT]): def __init__(self, updater: Callable[[T_COMPONENT], None]): self.__updater = updater - def __call__(self, components: Iterable[T_COMPONENT]) -> None: + def __call__(self, components: Iterable[T_COMPONENT], error_handler: Callable) -> None: for component in components: - with SingleComponentUpdateContext(component.fault_state): + with SingleComponentUpdateContext(component.fault_state, error_handler): self.__updater(component) @@ -28,9 +31,9 @@ class MultiComponentUpdater: def __init__(self, updater: Callable[[List[T_COMPONENT]], None]): self.__updater = updater - def __call__(self, components: Iterable[T_COMPONENT]) -> None: + def __call__(self, components: Iterable[T_COMPONENT], error_handler: Callable) -> None: components_list = list(components) - with MultiComponentUpdateContext(components_list): + with MultiComponentUpdateContext(components_list, error_handler): if not components: raise FaultState.warning("Keine Komponenten konfiguriert") self.__updater(components_list) @@ -62,14 +65,36 @@ class ConfigurableDevice(Generic[T_COMPONENT, T_DEVICE_CONFIG, T_COMPONENT_CONFI def __init__(self, device_config: T_DEVICE_CONFIG, component_factory: ComponentFactory[Any, T_COMPONENT], - component_updater: ComponentUpdater[T_COMPONENT]) -> None: + component_updater: ComponentUpdater[T_COMPONENT], + initializer: Callable = lambda: None) -> None: + self.__initializer = initializer self.__component_factory = component_factory self.__component_updater = component_updater self.device_config = device_config self.components: Dict[str, T_COMPONENT] = {} + try: + self.__initializer() + except Exception: + log.exception(f"Initialisierung von Gerät {self.device_config.name} fehlgeschlagen") + + def error_handler(self): + self.__initializer() + for component in self.components.values(): + component.initialize() + def add_component(self, component_config: T_COMPONENT_CONFIG) -> None: - self.components["component" + str(component_config.id)] = self.__component_factory(component_config) + with SingleComponentUpdateContext(FaultState(ComponentInfo.from_component_config(component_config)), + self.__initializer): + component = self.__component_factory(component_config) + component.initialized = False + self.components["component" + str(component_config.id)] = component + component.initialize() + component.initialized = True def update(self): - self.__component_updater(self.components.values()) + initialized_components = [] + for component in self.components.values(): + if hasattr(component, "initialized") and component.initialized: + initialized_components.append(component) + self.__component_updater(initialized_components, self.error_handler) diff --git a/packages/modules/devices/alpha_ess/alpha_ess/bat.py b/packages/modules/devices/alpha_ess/alpha_ess/bat.py index 4dcc0ca9e5..3d332d0f85 100644 --- a/packages/modules/devices/alpha_ess/alpha_ess/bat.py +++ b/packages/modules/devices/alpha_ess/alpha_ess/bat.py @@ -1,33 +1,33 @@ -#!/usr/bin/env python3 import logging import time -from typing import Dict, Union - -from dataclass_utils import dataclass_from_dict -from modules.devices.alpha_ess.alpha_ess.config import AlphaEssBatSetup, AlphaEssConfiguration -from modules.common import modbus +from typing import TypedDict, Any from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState -from modules.common.modbus import ModbusDataType +from modules.common.modbus import ModbusDataType, ModbusTcpClient_ from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store +from modules.devices.alpha_ess.alpha_ess.config import AlphaEssBatSetup log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + tcp_client: ModbusTcpClient_ + modbus_id: int + + class AlphaEssBat(AbstractBat): - def __init__(self, device_id: int, - component_config: Union[Dict, AlphaEssBatSetup], - tcp_client: modbus.ModbusTcpClient_, - device_config: AlphaEssConfiguration, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(AlphaEssBatSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") + def __init__(self, component_config: AlphaEssBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: ModbusTcpClient_ = self.kwargs['tcp_client'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.sim_counter = SimCounter(self.kwargs['device_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)) diff --git a/packages/modules/devices/alpha_ess/alpha_ess/counter.py b/packages/modules/devices/alpha_ess/alpha_ess/counter.py index 9682ab8333..855dddcce8 100644 --- a/packages/modules/devices/alpha_ess/alpha_ess/counter.py +++ b/packages/modules/devices/alpha_ess/alpha_ess/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import time -from typing import Callable, Dict, Union +from typing import Callable, Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.devices.alpha_ess.alpha_ess.config import AlphaEssConfiguration, AlphaEssCounterSetup from modules.common import modbus from modules.common.abstract_device import AbstractCounter @@ -13,24 +12,27 @@ from modules.common.store import get_counter_value_store +class KwargsDict(TypedDict): + tcp_client: modbus.ModbusTcpClient_ + device_config: AlphaEssConfiguration + modbus_id: int + + class AlphaEssCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, AlphaEssCounterSetup], - tcp_client: modbus.ModbusTcpClient_, - device_config: AlphaEssConfiguration, - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(AlphaEssCounterSetup, component_config) - self.__tcp_client = tcp_client - self.__device_config = device_config - self.__modbus_id = modbus_id + def __init__(self, component_config: AlphaEssCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client'] + self.__device_config: AlphaEssConfiguration = self.kwargs['device_config'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self): time.sleep(0.1) - factory_method = self.__get_values_factory() - counter_state = factory_method(self.__modbus_id) + counter_state = self.__get_values_factory() self.store.set(counter_state) def __get_values_factory(self) -> Callable[[int], CounterState]: @@ -39,13 +41,13 @@ def __get_values_factory(self) -> Callable[[int], CounterState]: else: return self.__get_values_since_v123 - def __get_values_before_v123(self, unit: int) -> CounterState: + def __get_values_before_v123(self) -> CounterState: power, exported, imported = self.__tcp_client.read_holding_registers( - 0x6, [modbus.ModbusDataType.INT_32] * 3, unit=unit) + 0x6, [modbus.ModbusDataType.INT_32] * 3, unit=self.__modbus_id) exported *= 10 imported *= 10 currents = [val / 230 for val in self.__tcp_client.read_holding_registers( - 0x0000, [ModbusDataType.INT_32]*3, unit=unit)] + 0x0000, [ModbusDataType.INT_32]*3, unit=self.__modbus_id)] counter_state = CounterState( currents=currents, @@ -55,13 +57,14 @@ def __get_values_before_v123(self, unit: int) -> CounterState: ) return counter_state - def __get_values_since_v123(self, unit: int) -> CounterState: - power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, unit=unit) + def __get_values_since_v123(self) -> CounterState: + power = self.__tcp_client.read_holding_registers(0x0021, ModbusDataType.INT_32, unit=self.__modbus_id) exported, imported = [ val * 10 for val in self.__tcp_client.read_holding_registers( - 0x0010, [ModbusDataType.INT_32] * 2, unit=unit)] + 0x0010, [ModbusDataType.INT_32] * 2, unit=self.__modbus_id + )] currents = [val / 1000 for val in self.__tcp_client.read_holding_registers( - 0x0017, [ModbusDataType.INT_16]*3, unit=unit)] + 0x0017, [ModbusDataType.INT_16]*3, unit=self.__modbus_id)] counter_state = CounterState( currents=currents, diff --git a/packages/modules/devices/alpha_ess/alpha_ess/device.py b/packages/modules/devices/alpha_ess/alpha_ess/device.py index 65d887dd7c..e55bc3acaf 100644 --- a/packages/modules/devices/alpha_ess/alpha_ess/device.py +++ b/packages/modules/devices/alpha_ess/alpha_ess/device.py @@ -7,7 +7,6 @@ AlphaEss, AlphaEssBatSetup, AlphaEssCounterSetup, AlphaEssInverterSetup) from modules.common import modbus from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.devices.alpha_ess.alpha_ess import bat from modules.devices.alpha_ess.alpha_ess import counter from modules.devices.alpha_ess.alpha_ess import inverter @@ -19,43 +18,47 @@ def create_device(device_config: AlphaEss): + client = None + def create_bat_component(component_config: AlphaEssBatSetup): - return bat.AlphaEssBat(device_config.id, - component_config, - client, - device_config.configuration, - device_config.configuration.modbus_id) + nonlocal client + return bat.AlphaEssBat(component_config, + device_id=device_config.id, + tcp_client=client, + modbus_id=device_config.configuration.modbus_id) def create_counter_component(component_config: AlphaEssCounterSetup): - return counter.AlphaEssCounter(device_config.id, - component_config, - client, - device_config.configuration, - device_config.configuration.modbus_id) + nonlocal client + return counter.AlphaEssCounter(component_config, + tcp_client=client, + device_config=device_config.configuration, + modbus_id=device_config.configuration.modbus_id) def create_inverter_component(component_config: AlphaEssInverterSetup): - return inverter.AlphaEssInverter(device_config.id, - component_config, - client, - device_config.configuration, - device_config.configuration.modbus_id) + nonlocal client + return inverter.AlphaEssInverter(component_config=component_config, + device_id=device_config.id, + tcp_client=client, + device_config=device_config.configuration, + modbus_id=device_config.configuration.modbus_id) def update_components(components: Iterable[Union[alpha_ess_component_classes]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client if device_config.configuration.source == 0: client = modbus.ModbusTcpClient_("192.168.193.125", 8899) else: 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/alpha_ess/alpha_ess/inverter.py b/packages/modules/devices/alpha_ess/alpha_ess/inverter.py index 624fe2dd15..1724266f52 100644 --- a/packages/modules/devices/alpha_ess/alpha_ess/inverter.py +++ b/packages/modules/devices/alpha_ess/alpha_ess/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.devices.alpha_ess.alpha_ess.config import AlphaEssConfiguration, AlphaEssInverterSetup from modules.common import modbus from modules.common.abstract_device import AbstractInverter @@ -13,17 +12,23 @@ from modules.common.store import get_inverter_value_store +class KwargsDict(TypedDict): + device_id: int + tcp_client: modbus.ModbusTcpClient_ + device_config: AlphaEssConfiguration + modbus_id: int + + class AlphaEssInverter(AbstractInverter): - def __init__(self, device_id: int, - component_config: Union[Dict, AlphaEssInverterSetup], - tcp_client: modbus.ModbusTcpClient_, - device_config: AlphaEssConfiguration, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(AlphaEssInverterSetup, component_config) - self.__tcp_client = tcp_client - self.__device_config = device_config - self.__modbus_id = modbus_id + def __init__(self, component_config: AlphaEssInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client'] + self.__device_config: AlphaEssConfiguration = self.kwargs['device_config'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/ampere/ampere/bat.py b/packages/modules/devices/ampere/ampere/bat.py index 297efd9178..ceb9891788 100644 --- a/packages/modules/devices/ampere/ampere/bat.py +++ b/packages/modules/devices/ampere/ampere/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union -from dataclass_utils import dataclass_from_dict +from typing import Any, TypedDict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -12,21 +11,31 @@ from modules.devices.ampere.ampere.config import AmpereBatSetup +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: ModbusTcpClient_ + + class AmpereBat(AbstractBat): def __init__(self, - device_id: int, - component_config: Union[Dict, AmpereBatSetup], - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(AmpereBatSetup, component_config) - self.modbus_id = modbus_id - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") + component_config: AmpereBatSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + device_id: int = self.kwargs['device_id'] + self.modbus_id: int = self.kwargs['modbus_id'] + self.sim_counter = SimCounter(device_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.client = self.kwargs['client'] - def update(self, client: ModbusTcpClient_) -> None: - power = client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) - soc = client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id) + def update(self) -> None: + if self.client and self.modbus_id is not None: + power = self.client.read_input_registers(535, ModbusDataType.INT_16, unit=self.modbus_id) + soc = self.client.read_input_registers(1339, ModbusDataType.UINT_16, unit=self.modbus_id) imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/packages/modules/devices/ampere/ampere/counter.py b/packages/modules/devices/ampere/ampere/counter.py index 0f8b64603d..ae07db2712 100644 --- a/packages/modules/devices/ampere/ampere/counter.py +++ b/packages/modules/devices/ampere/ampere/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -12,21 +11,30 @@ from modules.devices.ampere.ampere.config import AmpereCounterSetup +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: ModbusTcpClient_ + + class AmpereCounter(AbstractCounter): def __init__(self, - device_id: int, - component_config: Union[Dict, AmpereCounterSetup], - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(AmpereCounterSetup, component_config) - self.modbus_id = modbus_id + component_config: AmpereCounterSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_): - powers = client.read_input_registers(1349, [ModbusDataType.INT_16]*3, unit=self.modbus_id) - power = client.read_input_registers(1348, ModbusDataType.INT_16, unit=self.modbus_id) + def update(self): + powers = self.client.read_input_registers(1349, [ModbusDataType.INT_16]*3, unit=self.modbus_id) + power = self.client.read_input_registers(1348, ModbusDataType.INT_16, unit=self.modbus_id) imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/ampere/ampere/device.py b/packages/modules/devices/ampere/ampere/device.py index ee0e7b942e..d6dfc393f0 100644 --- a/packages/modules/devices/ampere/ampere/device.py +++ b/packages/modules/devices/ampere/ampere/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union 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.common.modbus import ModbusTcpClient_ from modules.devices.ampere.ampere.bat import AmpereBat @@ -15,28 +14,41 @@ def create_device(device_config: Ampere): + client = None + def create_bat_component(component_config: AmpereBatSetup): - return AmpereBat(device_config.id, component_config, device_config.configuration.modbus_id) + nonlocal client + return AmpereBat(component_config=component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_counter_component(component_config: AmpereCounterSetup): - return AmpereCounter(device_config.id, component_config, device_config.configuration.modbus_id) + nonlocal client + return AmpereCounter(component_config=component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_inverter_component(component_config: AmpereInverterSetup): - return AmpereInverter(device_config.id, component_config, device_config.configuration.modbus_id) + nonlocal client + return AmpereInverter(component_config=component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def update_components(components: Iterable[Union[AmpereBat, AmpereCounter, AmpereInverter]]): with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(client) - - try: - client = ModbusTcpClient_(device_config.configuration.ip_address, - device_config.configuration.port) - except Exception: - log.exception("Fehler in create_device") + component.update() + + def initializer(): + nonlocal client + client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/ampere/ampere/inverter.py b/packages/modules/devices/ampere/ampere/inverter.py index a7dc6efb42..67f2d673e6 100644 --- a/packages/modules/devices/ampere/ampere/inverter.py +++ b/packages/modules/devices/ampere/ampere/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,21 +11,30 @@ from modules.devices.ampere.ampere.config import AmpereInverterSetup +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: ModbusTcpClient_ + + class AmpereInverter(AbstractInverter): def __init__(self, - device_id: int, - component_config: Union[Dict, AmpereInverterSetup], - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(AmpereInverterSetup, component_config) - self.modbus_id = modbus_id + component_config: AmpereInverterSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: - pv1_power = client.read_holding_registers(519, ModbusDataType.INT_16, unit=self.modbus_id) * -1 - pv2_power = client.read_holding_registers(522, ModbusDataType.INT_16, unit=self.modbus_id) * -1 + def update(self) -> None: + pv1_power = self.client.read_holding_registers(519, ModbusDataType.INT_16, unit=self.modbus_id) * -1 + pv2_power = self.client.read_holding_registers(522, ModbusDataType.INT_16, unit=self.modbus_id) * -1 power = pv1_power + pv2_power diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py index f906db80b3..42c2da0931 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -11,27 +10,34 @@ from modules.devices.azzurro_zcs.azzurro_zcs.config import ZCSBatSetup +class KwargsDict(TypedDict): + modbus_id: int + client: ModbusTcpClient_ + + class ZCSBat(AbstractBat): - def __init__(self, - component_config: Union[Dict, ZCSBatSetup], - modbus_id: int) -> None: - self.__modbus_id = modbus_id - self.component_config = dataclass_from_dict(ZCSBatSetup, component_config) + def __init__(self, component_config: ZCSBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: - # 0x020D Battery charge-discharge power Int16 -10-10 kW accury 0,01 kW pos charge, neg discharge + def update(self) -> None: + # 0x020D Battery charge-discharge power Int16 -10-10 kW accuracy 0,01 kW pos charge, neg discharge # 0x020E Battery voltage Cell UInt16 0-100 V accuracy 0,1 V # 0x020F Battery charge-discharge current Int -100-100 A accuracy 0,01A - power = client.read_input_registers(0x020D, ModbusDataType.INT_16, unit=self.__modbus_id) + power = self.client.read_input_registers(0x020D, ModbusDataType.INT_16, unit=self.__modbus_id) # 0x0210 SoC UInt16 0-100 % - soc = client.read_input_registers(0x0210, ModbusDataType.UINT_16, unit=self.__modbus_id) + soc = self.client.read_input_registers(0x0210, ModbusDataType.UINT_16, unit=self.__modbus_id) # 0x0227 Total energy charging battery low UInt16 in kWh LSB - imported = client.read_input_registers( + imported = self.client.read_input_registers( 0x0227, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 # 0x0229 Total energy discharging battery low UInt16 in kWh LSB - exported = client.read_input_registers( + exported = self.client.read_input_registers( 0x0229, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 bat_state = BatState( diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py index 3840cdf853..0bb0ecc349 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -12,42 +11,40 @@ from modules.devices.azzurro_zcs.azzurro_zcs.config import ZCSCounterSetup +class KwargsDict(TypedDict): + modbus_id: int + client: ModbusTcpClient_ + + class ZCSCounter(AbstractCounter): def __init__(self, - component_config: Union[Dict, ZCSCounterSetup], - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(ZCSCounterSetup, component_config) - self.__modbus_id = modbus_id + component_config: ZCSCounterSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_): + def update(self) -> None: # 0x0212 Grid Power Int16 -10-10 kW Unit 0,01kW Feed in/out power # 0x0214 Input/Output power Int16 -10-10kW 0,01kW Energy storage power inverter - power = client.read_input_registers(0x0212, ModbusDataType.INT_16, wordorder=Endian.Little, - unit=self.__modbus_id) * -1 + power = self.client.read_input_registers(0x0212, ModbusDataType.INT_16, wordorder=Endian.Little, + unit=self.__modbus_id) * -1 # 0x020C Grid frequency UInt 0-100 Hz Unit 0,01 Hz - frequency = client.read_input_registers( + frequency = self.client.read_input_registers( 0x020C, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 - try: - # 0x0206 A phase voltage UInt 0-1000V unit 0,1V - # 0x0207 A phase current Int 0-100A Unit 0,01A, rms - # 0x0230 R-Phase voltage UInt Unit 0,1V - # 0x0231 R-Phase current UInt Unit 0,01A - powers = (client.read_input_registers( - 0x0206, ModbusDataType.UINT_16, unit=self.__modbus_id) / 10) * \ - (client.read_input_registers(0x0207, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) - except Exception: - powers = None - exported = [value * 10 - for value in client.read_input_registers( + for value in self.client.read_input_registers( # 0x021E Total energy injected into the grid UInt16 Unit 1kWh high # 0x021F Total energy injected into the grid UInt16 Unit 1kWh low 0x021E, [ModbusDataType.UINT_16] * 10, wordorder=Endian.Little, unit=self.__modbus_id)] imported = [value * 10 - for value in client.read_input_registers( + for value in self.client.read_input_registers( # 0x0220 Total energy taken from the grid UInt16 Unit 1kWh high # 0x0221 Total energy taken from the grid UInt16 Unit 1kWh low 0x0220, [ModbusDataType.UINT_16] * 10, @@ -57,7 +54,6 @@ def update(self, client: ModbusTcpClient_): imported=imported, exported=exported, power=power, - powers=powers, frequency=frequency, ) self.store.set(counter_state) diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs/device.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs/device.py index b175b75ce8..4551329419 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs/device.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.azzurro_zcs.azzurro_zcs.bat import ZCSBat @@ -15,27 +14,37 @@ def create_device(device_config: ZCS): + client = None + def create_bat_component(component_config: ZCSBatSetup): - return ZCSBat(component_config, device_config.configuration.modbus_id) + nonlocal client + return ZCSBat(component_config=component_config, modbus_id=device_config.configuration.modbus_id, client=client) def create_counter_component(component_config: ZCSCounterSetup): - return ZCSCounter(component_config, device_config.configuration.modbus_id) + nonlocal client + return ZCSCounter(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_inverter_component(component_config: ZCSInverterSetup): - return ZCSInverter(component_config, device_config.configuration.modbus_id) + nonlocal client + return ZCSInverter(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + client=client) def update_components(components: Iterable[Union[ZCSBat, ZCSCounter, ZCSInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py b/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py index b37117c616..966084e70f 100644 --- a/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py +++ b/packages/modules/devices/azzurro_zcs/azzurro_zcs/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,32 +11,39 @@ from modules.devices.azzurro_zcs.azzurro_zcs.config import ZCSInverterSetup +class KwargsDict(TypedDict): + modbus_id: int + client: ModbusTcpClient_ + + class ZCSInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, ZCSInverterSetup], - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(ZCSInverterSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: ZCSInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_) -> None: + def update(self) -> None: # 0x0252 PV1 Power UInt16 0-100kW Unit 0,01kW # 0x0250 PV1 Voltage UInt16 0-1000V Unit 0,1V # 0x0251 PV1 current Int16 0-100A Unit 0,01A - power_string1 = (client.read_input_registers( + power_string1 = (self.client.read_input_registers( 0x0250, ModbusDataType.UINT_16, unit=self.__modbus_id) / 10) * \ - (client.read_input_registers(0x0251, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + (self.client.read_input_registers(0x0251, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) # 0x0255 PV2 Power UInt16 0-100 kW Unit 0,01kW # 0x0253 PV2 Voltage UInt16 0-1000V Unit 0,1V # 0x0254 PV2 current Int16 0-100A Unit 0,01A - power_string2 = (client.read_input_registers( + power_string2 = (self.client.read_input_registers( 0x0253, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) * \ - (client.read_input_registers(0x0254, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + (self.client.read_input_registers(0x0254, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) power = (power_string1 + power_string2) * -1 # 0x0215 PV Power generation UInt16 0 -10 kW Unit 0,01kW - exported = client.read_input_registers(0x0215, ModbusDataType.UINT_16, wordorder=Endian.Little, - unit=self.__modbus_id) * 100 + exported = self.client.read_input_registers(0x0215, ModbusDataType.UINT_16, wordorder=Endian.Little, + unit=self.__modbus_id) * 100 inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/batterx/batterx/bat.py b/packages/modules/devices/batterx/batterx/bat.py index 7828ea72cc..2a5b6949a8 100644 --- a/packages/modules/devices/batterx/batterx/bat.py +++ b/packages/modules/devices/batterx/batterx/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Dict, TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.devices.batterx.batterx.config import BatterXBatSetup from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -11,10 +10,17 @@ from modules.common.store import get_bat_value_store +class KwargsDict(TypedDict): + device_id: int + + class BatterXBat(AbstractBat): - def __init__(self, device_id: int, component_config: Union[Dict, BatterXBatSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(BatterXBatSetup, component_config) + def __init__(self, component_config: BatterXBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/batterx/batterx/counter.py b/packages/modules/devices/batterx/batterx/counter.py index a38c177a2a..8d3fcae70b 100644 --- a/packages/modules/devices/batterx/batterx/counter.py +++ b/packages/modules/devices/batterx/batterx/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, List, Union +from typing import Any, Dict, List, TypedDict -from dataclass_utils import dataclass_from_dict from modules.devices.batterx.batterx.config import BatterXCounterSetup from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -14,10 +13,17 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class BatterXCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: Union[Dict, BatterXCounterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(BatterXCounterSetup, component_config) + def __init__(self, component_config: BatterXCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/batterx/batterx/device.py b/packages/modules/devices/batterx/batterx/device.py index 69bf308394..a505bc06eb 100644 --- a/packages/modules/devices/batterx/batterx/device.py +++ b/packages/modules/devices/batterx/batterx/device.py @@ -23,16 +23,16 @@ def create_device(device_config: BatterX): def create_bat_component(component_config: BatterXBatSetup): - return bat.BatterXBat(device_config.id, component_config) + return bat.BatterXBat(component_config=component_config, device_id=device_config.id) def create_counter_component(component_config: BatterXCounterSetup): - return counter.BatterXCounter(device_config.id, component_config) + return counter.BatterXCounter(component_config=component_config, device_id=device_config.id) def create_inverter_component(component_config: BatterXInverterSetup): - return inverter.BatterXInverter(device_config.id, component_config) + return inverter.BatterXInverter(component_config=component_config, device_id=device_config.id) def create_external_inverter_component(component_config: BatterXExternalInverterSetup): - return external_inverter.BatterXExternalInverter(device_config.id, component_config) + return external_inverter.BatterXExternalInverter(component_config=component_config, device_id=device_config.id) def update_components(components: Iterable[batterx_component_classes]): resp_json = req.get_http_session().get( diff --git a/packages/modules/devices/batterx/batterx/external_inverter.py b/packages/modules/devices/batterx/batterx/external_inverter.py index b8fc4faed3..b103b507a5 100644 --- a/packages/modules/devices/batterx/batterx/external_inverter.py +++ b/packages/modules/devices/batterx/batterx/external_inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, Dict, TypedDict -from dataclass_utils import dataclass_from_dict from modules.devices.batterx.batterx.config import BatterXExternalInverterSetup from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -11,10 +10,17 @@ from modules.common.store import get_inverter_value_store +class KwargsDict(TypedDict): + device_id: int + + class BatterXExternalInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, BatterXExternalInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(BatterXExternalInverterSetup, component_config) + def __init__(self, component_config: BatterXExternalInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/batterx/batterx/inverter.py b/packages/modules/devices/batterx/batterx/inverter.py index 6bad375b11..65e110c65c 100644 --- a/packages/modules/devices/batterx/batterx/inverter.py +++ b/packages/modules/devices/batterx/batterx/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Dict, TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.devices.batterx.batterx.config import BatterXInverterSetup from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -11,10 +10,17 @@ from modules.common.store import get_inverter_value_store +class KwargsDict(TypedDict): + device_id: int + + class BatterXInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, BatterXInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(BatterXInverterSetup, component_config) + def __init__(self, component_config: BatterXInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/benning/benning/config.py b/packages/modules/devices/benning/benning/config.py index e040dce6ff..bb320652b3 100644 --- a/packages/modules/devices/benning/benning/config.py +++ b/packages/modules/devices/benning/benning/config.py @@ -9,7 +9,7 @@ @auto_str class BenningConfiguration(JsonConfiguration): def __init__(self, url: Optional[str] = None): - self.url = "http://" + url + "/getentries.cgi?oids=11369,19000" + self.url = f"http://{url}/getentries.cgi?oids=11369,19000" @auto_str diff --git a/packages/modules/devices/byd/byd/bat.py b/packages/modules/devices/byd/byd/bat.py index 0770b272ef..3157c95d58 100644 --- a/packages/modules/devices/byd/byd/bat.py +++ b/packages/modules/devices/byd/byd/bat.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 import logging from html.parser import HTMLParser -from typing import Dict, List, Union, Tuple +from typing import Any, List, Tuple, TypedDict -from dataclass_utils import dataclass_from_dict -from modules.devices.byd.byd.config import BYDBatSetup +from modules.devices.byd.byd.config import BYD, BYDBatSetup from modules.common import req from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -16,13 +15,18 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_config: BYD + + class BYDBat(AbstractBat): - def __init__(self, - component_config: Union[Dict, BYDBatSetup], - device_config) -> None: - self.__device_config = device_config - self.component_config = dataclass_from_dict(BYDBatSetup, component_config) - self.sim_counter = SimCounter(self.__device_config.id, self.component_config.id, prefix="speicher") + def __init__(self, component_config: BYDBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.device_config: BYD = self.kwargs['device_config'] + 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)) @@ -44,8 +48,8 @@ def get_values(self) -> Tuple[float, float]: RunData.asp auf ganze kW gerundet und somit für openWB nicht brauchbar. ''' resp = req.get_http_session().get( - 'http://' + self.__device_config.configuration.ip_address + '/asp/Home.asp', - auth=(self.__device_config.configuration.user, self.__device_config.configuration.password)) + 'http://' + self.device_config.configuration.ip_address + '/asp/Home.asp', + auth=(self.device_config.configuration.user, self.device_config.configuration.password)) return BydParser.parse(resp.text) @@ -53,7 +57,7 @@ class BydParser(HTMLParser): values = {"SOC:": 0, "Power:": 0} armed = None - @ staticmethod + @staticmethod def parse(html: str): parser = BydParser() parser.feed(html) diff --git a/packages/modules/devices/byd/byd/device.py b/packages/modules/devices/byd/byd/device.py index ac0adcc25c..ac82b4d897 100644 --- a/packages/modules/devices/byd/byd/device.py +++ b/packages/modules/devices/byd/byd/device.py @@ -11,7 +11,7 @@ def create_device(device_config: BYD): def create_bat_component(component_config: BYDBatSetup): - return bat.BYDBat(component_config, device_config) + return bat.BYDBat(component_config=component_config, device_config=device_config) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py b/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py index 3646e1d3e1..394d0bb2f0 100644 --- a/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py +++ b/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/counter.py @@ -1,9 +1,8 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.devices.carlo_gavazzi.carlo_gavazzi.config import CarloGavazziCounterSetup from modules.common import modbus from modules.common.abstract_device import AbstractCounter @@ -15,16 +14,21 @@ from modules.common.store import get_counter_value_store +class KwargsDict(TypedDict): + device_id: int + tcp_client: modbus.ModbusTcpClient_ + modbus_id: int + + class CarloGavazziCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, CarloGavazziCounterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(CarloGavazziCounterSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: CarloGavazziCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/device.py b/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/device.py index 4d6bf627cd..37d752412b 100644 --- a/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/device.py +++ b/packages/modules/devices/carlo_gavazzi/carlo_gavazzi/device.py @@ -7,28 +7,31 @@ from modules.devices.carlo_gavazzi.carlo_gavazzi.config import CarloGavazzi, CarloGavazziCounterSetup from modules.common import modbus from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext log = logging.getLogger(__name__) def create_device(device_config: CarloGavazzi): + client = None + def create_counter_component(component_config: CarloGavazziCounterSetup): - return counter.CarloGavazziCounter(device_config.id, component_config, client, - device_config.configuration.modbus_id) + nonlocal client + return counter.CarloGavazziCounter(component_config=component_config, device_id=device_config.id, + tcp_client=client, modbus_id=device_config.configuration.modbus_id) def update_components(components: Iterable[counter.CarloGavazziCounter]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( counter=create_counter_component ), diff --git a/packages/modules/devices/deye/deye/bat.py b/packages/modules/devices/deye/deye/bat.py index 0584c89cf3..e106275eb4 100644 --- a/packages/modules/devices/deye/deye/bat.py +++ b/packages/modules/devices/deye/deye/bat.py @@ -1,6 +1,5 @@ -#!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -14,18 +13,24 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class DeyeBat(AbstractBat): - def __init__(self, device_id: int, - component_config: DeyeBatSetup, - client: ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(DeyeBatSetup, component_config) + def __init__(self, component_config: DeyeBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id - self.client = client self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") self.device_type = DeviceType(self.client.read_holding_registers( - 0, ModbusDataType.INT_16, unit=component_config.configuration.modbus_id)) + 0, ModbusDataType.INT_16, unit=self.component_config.configuration.modbus_id)) def update(self) -> None: unit = self.component_config.configuration.modbus_id @@ -35,9 +40,7 @@ def update(self) -> None: soc = self.client.read_holding_registers(184, ModbusDataType.INT_16, unit=unit) if self.device_type == DeviceType.SINGLE_PHASE_HYBRID: - # 516: Geladen in kWh * 0,1 imported = self.client.read_holding_registers(72, ModbusDataType.UINT_16, unit=unit) * 100 - # 518: Entladen in kWh * 0,1 exported = self.client.read_holding_registers(74, ModbusDataType.UINT_16, unit=unit) * 100 elif self.device_type == DeviceType.SINGLE_PHASE_STRING: @@ -49,9 +52,7 @@ def update(self) -> None: if self.device_type == DeviceType.THREE_PHASE_HV: power = power * 10 soc = self.client.read_holding_registers(588, ModbusDataType.INT_16, unit=unit) - # 516: Geladen in kWh * 0,1 imported = self.client.read_holding_registers(516, ModbusDataType.UINT_16, unit=unit) * 100 - # 518: Entladen in kWh * 0,1 exported = self.client.read_holding_registers(518, ModbusDataType.UINT_16, unit=unit) * 100 bat_state = BatState( diff --git a/packages/modules/devices/deye/deye/counter.py b/packages/modules/devices/deye/deye/counter.py index ddc1f63ecb..a2769bc967 100644 --- a/packages/modules/devices/deye/deye/counter.py +++ b/packages/modules/devices/deye/deye/counter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -11,18 +12,24 @@ from modules.devices.deye.deye.device_type import DeviceType +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class DeyeCounter(AbstractCounter): - def __init__(self, device_id: int, - component_config: DeyeCounterSetup, - client: ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(DeyeCounterSetup, component_config) + def __init__(self, component_config: DeyeCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id - self.client = client self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.device_type = DeviceType(self.client.read_holding_registers( - 0, ModbusDataType.INT_16, unit=component_config.configuration.modbus_id)) + 0, ModbusDataType.INT_16, unit=self.component_config.configuration.modbus_id)) def update(self): unit = self.component_config.configuration.modbus_id @@ -35,7 +42,6 @@ def update(self): currents = [0]*3 voltages = [0]*3 power = [0] - # High und low word vom import sind nicht in aufeinanderfolgenden Registern imported, exported = self.sim_counter.sim_count(power) elif self.device_type == DeviceType.SINGLE_PHASE_STRING: @@ -51,20 +57,16 @@ def update(self): currents = [c / 100 for c in self.client.read_holding_registers(613, [ModbusDataType.INT_16]*3, unit=unit)] voltages = [v / 10 for v in self.client.read_holding_registers(644, [ModbusDataType.INT_16]*3, unit=unit)] powers = self.client.read_holding_registers(616, [ModbusDataType.INT_16]*3, unit=unit) - power = self.client.read_holding_registers(625, ModbusDataType.INT_16, unit=unit) - frequency = self.client.read_holding_registers(609, ModbusDataType.INT_16, unit=unit) / 100 - - # Wenn der Import/export Netz in wh gerechnet wird => *100 !! kommt in kw/h *0.1 - imported = self.client.read_holding_registers(522, ModbusDataType.INT_16, unit=unit) * 100 - exported = self.client.read_holding_registers(524, ModbusDataType.INT_16, unit=unit) * 100 + power = sum(powers) + imported, exported = self.sim_counter.sim_count(power) counter_state = CounterState( currents=currents, + voltages=voltages, + powers=powers, + power=power, imported=imported, exported=exported, - power=power, - powers=powers, - voltages=voltages, frequency=frequency ) self.store.set(counter_state) diff --git a/packages/modules/devices/deye/deye/device.py b/packages/modules/devices/deye/deye/device.py index bdbe5eb769..e25e8952f1 100644 --- a/packages/modules/devices/deye/deye/device.py +++ b/packages/modules/devices/deye/deye/device.py @@ -4,7 +4,6 @@ from helpermodules.cli import run_using_positional_cli_args from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.deye.deye.bat import DeyeBat @@ -17,27 +16,33 @@ def create_device(device_config: Deye): + client = None + def create_bat_component(component_config: DeyeBatSetup): - return DeyeBat(device_config.id, component_config, client) + nonlocal client + return DeyeBat(component_config=component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: DeyeCounterSetup): - return DeyeCounter(device_config.id, component_config, client) + nonlocal client + return DeyeCounter(component_config=component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: DeyeInverterSetup): - return DeyeInverter(device_config.id, component_config, client) + nonlocal client + return DeyeInverter(component_config=component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[Union[DeyeBat, DeyeCounter, DeyeInverter]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/deye/deye/inverter.py b/packages/modules/devices/deye/deye/inverter.py index a2e66a3530..37a41d6b93 100644 --- a/packages/modules/devices/deye/deye/inverter.py +++ b/packages/modules/devices/deye/deye/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -13,18 +12,24 @@ from modules.devices.deye.deye.device_type import DeviceType +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class DeyeInverter(AbstractInverter): - def __init__(self, device_id: int, - component_config: Union[Dict, DeyeInverterSetup], - client: ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(DeyeInverterSetup, component_config) + def __init__(self, component_config: DeyeInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id - self.client = client self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.device_type = DeviceType(self.client.read_holding_registers( - 0, ModbusDataType.INT_16, unit=component_config.configuration.modbus_id)) + 0, ModbusDataType.INT_16, unit=self.component_config.configuration.modbus_id)) def update(self) -> None: unit = self.component_config.configuration.modbus_id diff --git a/packages/modules/devices/discovergy/discovergy/counter.py b/packages/modules/devices/discovergy/discovergy/counter.py index aeb2347f8b..14f69ff0ab 100644 --- a/packages/modules/devices/discovergy/discovergy/counter.py +++ b/packages/modules/devices/discovergy/discovergy/counter.py @@ -11,6 +11,8 @@ class DiscovergyCounter(AbstractCounter): def __init__(self, component_config: DiscovergyCounterSetup) -> None: self.component_config = component_config + + def initialize(self) -> None: self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/discovergy/discovergy/device.py b/packages/modules/devices/discovergy/discovergy/device.py index 8edbfa85bd..c9bb1f125b 100644 --- a/packages/modules/devices/discovergy/discovergy/device.py +++ b/packages/modules/devices/discovergy/discovergy/device.py @@ -18,16 +18,22 @@ def create_device(device_config: Discovergy): + session = None + def create_counter_component(component_config: DiscovergyCounterSetup): - return counter.DiscovergyCounter(component_config) + return counter.DiscovergyCounter(component_config=component_config) def create_inverter_component(component_config: DiscovergyInverterSetup): - return inverter.DiscovergyInverter(component_config) + return inverter.DiscovergyInverter(component_config=component_config) + + def initializer(): + nonlocal session + session = get_http_session() + session.auth = (device_config.configuration.user, device_config.configuration.password) - session = get_http_session() - session.auth = (device_config.configuration.user, device_config.configuration.password) return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType(counter=create_counter_component, inverter=create_inverter_component), component_updater=IndependentComponentUpdater(lambda component: component.update(session)), ) diff --git a/packages/modules/devices/discovergy/discovergy/inverter.py b/packages/modules/devices/discovergy/discovergy/inverter.py index 57330c2ede..18eca9da3f 100644 --- a/packages/modules/devices/discovergy/discovergy/inverter.py +++ b/packages/modules/devices/discovergy/discovergy/inverter.py @@ -12,6 +12,8 @@ class DiscovergyInverter(AbstractInverter): def __init__(self, component_config: DiscovergyInverterSetup) -> None: self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/e3dc/e3dc/bat.py b/packages/modules/devices/e3dc/e3dc/bat.py index bbe3d01cce..5d4773ba80 100644 --- a/packages/modules/devices/e3dc/e3dc/bat.py +++ b/packages/modules/devices/e3dc/e3dc/bat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Tuple +from typing import Tuple, TypedDict, Any from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -11,7 +11,6 @@ from modules.common.simcount._simcounter import SimCounter from modules.devices.e3dc.e3dc.config import E3dcBatSetup - log = logging.getLogger(__name__) @@ -23,21 +22,27 @@ def read_bat(client: modbus.ModbusTcpClient_, modbus_id: int) -> Tuple[int, int] return soc, power +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: modbus.ModbusTcpClient_ + + class E3dcBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: E3dcBatSetup, - modbus_id: int) -> None: + def __init__(self, component_config: E3dcBatSetup, **kwargs: Any) -> None: self.component_config = component_config - self.__modbus_id = modbus_id - # bat - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="speicher") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter(self.__device_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, client: modbus.ModbusTcpClient_) -> None: - - soc, power = read_bat(client, self.__modbus_id) + def update(self) -> None: + soc, power = read_bat(self.client, self.__modbus_id) imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( power=power, diff --git a/packages/modules/devices/e3dc/e3dc/counter.py b/packages/modules/devices/e3dc/e3dc/counter.py index d5a42e374e..7357d3180c 100644 --- a/packages/modules/devices/e3dc/e3dc/counter.py +++ b/packages/modules/devices/e3dc/e3dc/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Tuple, List +from typing import Tuple, List, TypedDict, Any from modules.common import modbus from modules.common.abstract_device import AbstractCounter @@ -40,19 +40,27 @@ def read_counter(client: modbus.ModbusTcpClient_, modbus_id: int) -> Tuple[int, return power, powers +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: modbus.ModbusTcpClient_ + + class E3dcCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: E3dcCounterSetup, - modbus_id: int) -> None: + def __init__(self, component_config: E3dcCounterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.__modbus_id = modbus_id - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="bezug") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: modbus.ModbusTcpClient_) -> None: - power, powers = read_counter(client, self.__modbus_id) + def update(self) -> None: + power, powers = read_counter(self.client, self.__modbus_id) imported, exported = self.sim_counter.sim_count(power) counter_state = CounterState( imported=imported, @@ -61,7 +69,6 @@ def update(self, client: modbus.ModbusTcpClient_) -> None: power=power ) self.store.set(counter_state) - log.debug("Update completed successfully") component_descriptor = ComponentDescriptor(configuration_factory=E3dcCounterSetup) diff --git a/packages/modules/devices/e3dc/e3dc/device.py b/packages/modules/devices/e3dc/e3dc/device.py index 549569c624..06eac88a92 100644 --- a/packages/modules/devices/e3dc/e3dc/device.py +++ b/packages/modules/devices/e3dc/e3dc/device.py @@ -4,8 +4,7 @@ from helpermodules.cli import run_using_positional_cli_args from modules.common.abstract_device import DeviceDescriptor -from modules.common.configurable_device import (ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater, - SingleComponentUpdateContext) +from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common import modbus from modules.devices.e3dc.e3dc.bat import E3dcBat, read_bat from modules.devices.e3dc.e3dc.inverter import E3dcInverter, read_inverter @@ -25,40 +24,49 @@ def create_device(device_config: E3dc) -> ConfigurableDevice: + client = None + def create_bat_component(component_config: E3dcBatSetup) -> E3dcBat: - return E3dcBat(device_config.id, - component_config, - device_config.configuration.modbus_id) + nonlocal client + return E3dcBat(component_config=component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_counter_component(component_config: E3dcCounterSetup) -> E3dcCounter: - return E3dcCounter(device_config.id, - component_config, - device_config.configuration.modbus_id) + nonlocal client + return E3dcCounter(component_config=component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_inverter_component(component_config: E3dcInverterSetup) -> E3dcInverter: - return E3dcInverter(device_config.id, - component_config, - device_config.configuration.modbus_id) + nonlocal client + return E3dcInverter(component_config=component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_external_inverter_component(component_config: E3dcExternalInverterSetup) -> E3dcExternalInverter: - return E3dcExternalInverter(device_config.id, - component_config, - device_config.configuration.modbus_id) + nonlocal client + return E3dcExternalInverter(component_config=component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def update_components(components: Iterable[Union[E3dcBat, E3dcCounter, E3dcInverter, E3dcExternalInverter]]) -> None: - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client client = modbus.ModbusTcpClient_(device_config.configuration.address, device_config.configuration.port) - except Exception: - log.exception("Fehler in create_device") - return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/e3dc/e3dc/external_inverter.py b/packages/modules/devices/e3dc/e3dc/external_inverter.py index 64a71253d3..87e1e45233 100644 --- a/packages/modules/devices/e3dc/e3dc/external_inverter.py +++ b/packages/modules/devices/e3dc/e3dc/external_inverter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import logging +from typing import Any, TypedDict from modules.common import modbus from modules.common.abstract_device import AbstractInverter @@ -11,31 +12,36 @@ from modules.common.simcount._simcounter import SimCounter from modules.devices.e3dc.e3dc.config import E3dcExternalInverterSetup - log = logging.getLogger(__name__) def read_external_inverter(client: modbus.ModbusTcpClient_, modbus_id: int) -> int: - # 40075 externe PV Leistung pv_external = int(client.read_holding_registers( 40075, ModbusDataType.INT_32, wordorder=Endian.Little, unit=modbus_id)) return pv_external +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: modbus.ModbusTcpClient_ + + class E3dcExternalInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: E3dcExternalInverterSetup, - modbus_id: int) -> None: + def __init__(self, component_config: E3dcExternalInverterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.__modbus_id = modbus_id - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="pv") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: modbus.ModbusTcpClient_) -> None: - - pv_external = read_external_inverter(client, self.__modbus_id) + def update(self) -> None: + pv_external = read_external_inverter(self.client, self.__modbus_id) # pv_external - > pv Leistung # die als externe Produktion an e3dc angeschlossen ist # Im gegensatz zur Implementierung in Version 1.9 wird nicht mehr die PV diff --git a/packages/modules/devices/e3dc/e3dc/inverter.py b/packages/modules/devices/e3dc/e3dc/inverter.py index 395589e43a..10914bd25d 100644 --- a/packages/modules/devices/e3dc/e3dc/inverter.py +++ b/packages/modules/devices/e3dc/e3dc/inverter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import logging +from typing import Any, TypedDict from modules.common import modbus from modules.common.abstract_device import AbstractInverter @@ -11,30 +12,35 @@ from modules.common.simcount._simcounter import SimCounter from modules.devices.e3dc.e3dc.config import E3dcInverterSetup - log = logging.getLogger(__name__) def read_inverter(client: modbus.ModbusTcpClient_, modbus_id: int) -> int: - # 40067 PV Leistung pv = int(client.read_holding_registers(40067, ModbusDataType.INT_32, wordorder=Endian.Little, unit=modbus_id) * -1) return pv +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: modbus.ModbusTcpClient_ + + class E3dcInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: E3dcInverterSetup, - modbus_id: int) -> None: + def __init__(self, component_config: E3dcInverterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.__modbus_id = modbus_id - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="pv") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: modbus.ModbusTcpClient_) -> None: - - pv = read_inverter(client, self.__modbus_id) + def update(self) -> None: + pv = read_inverter(self.client, self.__modbus_id) # Im gegensatz zur Implementierung in Version 1.9 wird nicht mehr die PV # Leistung vom WR1 gelesen, da die durch v2.0 separat gehandelt wird _, pv_exported = self.sim_counter.sim_count(pv) diff --git a/packages/modules/devices/enphase/enphase/bat.py b/packages/modules/devices/enphase/enphase/bat.py index af0d906d11..3dd1cbb4e0 100644 --- a/packages/modules/devices/enphase/enphase/bat.py +++ b/packages/modules/devices/enphase/enphase/bat.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Any, Dict, Optional, Union +from typing import Any, Dict, Optional, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -14,12 +13,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class EnphaseBat(AbstractBat): - def __init__(self, device_id: int, component_config: Union[Dict, EnphaseBatSetup]) -> None: - self.component_config = dataclass_from_dict(EnphaseBatSetup, component_config) + def __init__(self, component_config: EnphaseBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") def update(self, response, live_data: Optional[Dict[str, Any]] = None) -> None: diff --git a/packages/modules/devices/enphase/enphase/counter.py b/packages/modules/devices/enphase/enphase/counter.py index 295c779243..638682c363 100644 --- a/packages/modules/devices/enphase/enphase/counter.py +++ b/packages/modules/devices/enphase/enphase/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Any, Dict, Union +from typing import Any, Dict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -14,8 +13,10 @@ class EnphaseCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: Union[Dict, EnphaseCounterSetup]) -> None: - self.component_config = dataclass_from_dict(EnphaseCounterSetup, component_config) + def __init__(self, component_config: EnphaseCounterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/enphase/enphase/device.py b/packages/modules/devices/enphase/enphase/device.py index e054d46766..c5ed9dbcc9 100644 --- a/packages/modules/devices/enphase/enphase/device.py +++ b/packages/modules/devices/enphase/enphase/device.py @@ -25,13 +25,13 @@ def create_device(device_config: Enphase): def create_bat_component(component_config: EnphaseBatSetup): nonlocal read_live_data read_live_data = True - return EnphaseBat(device_config.id, component_config) + return EnphaseBat(component_config=component_config, device_id=device_config.id) def create_counter_component(component_config: EnphaseCounterSetup): - return EnphaseCounter(device_config.id, component_config) + return EnphaseCounter(component_config=component_config) def create_inverter_component(component_config: EnphaseInverterSetup): - return EnphaseInverter(device_config.id, component_config) + return EnphaseInverter(component_config=component_config) def check_token() -> bool: if (device_config.configuration.token is None or diff --git a/packages/modules/devices/enphase/enphase/inverter.py b/packages/modules/devices/enphase/enphase/inverter.py index 7469922176..b728435943 100644 --- a/packages/modules/devices/enphase/enphase/inverter.py +++ b/packages/modules/devices/enphase/enphase/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Any, Dict, Union +from typing import Any, Dict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -14,8 +13,10 @@ class EnphaseInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, EnphaseInverterSetup]) -> None: - self.component_config = dataclass_from_dict(EnphaseInverterSetup, component_config) + def __init__(self, component_config: EnphaseInverterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/fems/fems/bat.py b/packages/modules/devices/fems/fems/bat.py index 04709c0cfe..a30981958d 100644 --- a/packages/modules/devices/fems/fems/bat.py +++ b/packages/modules/devices/fems/fems/bat.py @@ -1,6 +1,6 @@ import logging from requests import Session -from helpermodules.scale_metric import scale_metric +from typing import TypedDict, Any from modules.devices.fems.fems.config import FemsBatSetup from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -8,14 +8,24 @@ from modules.common.fault_state import ComponentInfo, FaultState from modules.common.store import get_bat_value_store from modules.devices.fems.fems.version import FemsVersion, get_version +from helpermodules.scale_metric import scale_metric + log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + ip_address: str + session: Session + + class FemsBat(AbstractBat): - def __init__(self, ip_address: str, component_config: FemsBatSetup, session: Session) -> None: - self.ip_address = ip_address + def __init__(self, component_config: FemsBatSetup, **kwargs: Any) -> None: self.component_config = component_config - self.session = session + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: str = self.kwargs['ip_address'] + self.session: Session = self.kwargs['session'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) if self.component_config.configuration.num == 1: @@ -75,7 +85,6 @@ def update(self) -> None: pv = scale_metric(singleValue['value'], singleValue.get('unit'), 'W') elif address == "_sum/ConsumptionActivePower": haus = scale_metric(singleValue['value'], singleValue.get('unit'), 'W') - # keine Berechnung im Gerät, da grid nicht der Leistung aus der Zählerkomponente entspricht. power = grid + pv - haus bat_state = BatState( power=power, diff --git a/packages/modules/devices/fems/fems/counter.py b/packages/modules/devices/fems/fems/counter.py index 5f2ee65d38..e9c0b14e76 100644 --- a/packages/modules/devices/fems/fems/counter.py +++ b/packages/modules/devices/fems/fems/counter.py @@ -1,5 +1,7 @@ import logging +from typing import Any, TypedDict from requests import Session + from helpermodules.scale_metric import scale_metric from modules.devices.fems.fems.config import FemsCounterSetup from modules.common.abstract_device import AbstractCounter @@ -12,11 +14,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + ip_address: str + session: Session + + class FemsCounter(AbstractCounter): - def __init__(self, ip_address: str, component_config: FemsCounterSetup, session: Session) -> None: - self.ip_address = ip_address + def __init__(self, component_config: FemsCounterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.session = session + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: str = self.kwargs['ip_address'] + self.session: Session = self.kwargs['session'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.version = get_version(self.get_data_by_multiple_segement_regex_query) diff --git a/packages/modules/devices/fems/fems/device.py b/packages/modules/devices/fems/fems/device.py index 1ade03bc6f..9e1781ee71 100644 --- a/packages/modules/devices/fems/fems/device.py +++ b/packages/modules/devices/fems/fems/device.py @@ -13,27 +13,33 @@ def create_device(device_config: Fems): + session = None + def create_bat_component(component_config: FemsBatSetup): - return bat.FemsBat(device_config.configuration.ip_address, - component_config, session) + nonlocal session + return bat.FemsBat(component_config, ip_address=device_config.configuration.ip_address, session=session) def create_counter_component(component_config: FemsCounterSetup): - return counter.FemsCounter(device_config.configuration.ip_address, - component_config, session) + nonlocal session + return counter.FemsCounter(component_config, ip_address=device_config.configuration.ip_address, session=session) def create_inverter_component(component_config: FemsInverterSetup): - return inverter.FemsInverter(device_config.configuration.ip_address, - component_config, session) + nonlocal session + return inverter.FemsInverter(component_config, ip_address=device_config.configuration.ip_address, + session=session) def update_components(components: Iterable[Union[bat.FemsBat, counter.FemsCounter, inverter.FemsInverter]]): for component in components: component.update() - session = req.get_http_session() - session.auth = ("x", device_config.configuration.password) + def initializer(): + nonlocal session + session = req.get_http_session() + session.auth = ("x", device_config.configuration.password) return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/fems/fems/inverter.py b/packages/modules/devices/fems/fems/inverter.py index bcb5dfbc76..33425bb3e7 100644 --- a/packages/modules/devices/fems/fems/inverter.py +++ b/packages/modules/devices/fems/fems/inverter.py @@ -1,5 +1,6 @@ import logging from requests import Session +from typing import TypedDict, Any from helpermodules.scale_metric import scale_metric from modules.devices.fems.fems.config import FemsInverterSetup from modules.common.abstract_device import AbstractInverter @@ -8,14 +9,23 @@ from modules.common.fault_state import ComponentInfo, FaultState from modules.common.store import get_inverter_value_store from modules.devices.fems.fems.version import FemsVersion, get_version + log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + ip_address: str + session: Session + + class FemsInverter(AbstractInverter): - def __init__(self, ip_address: str, component_config: FemsInverterSetup, session: Session) -> None: - self.ip_address = ip_address + def __init__(self, component_config: FemsInverterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.session = session + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: str = self.kwargs['ip_address'] + self.session: Session = self.kwargs['session'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.version = get_version(self.get_data_by_multiple_segement_regex_query) diff --git a/packages/modules/devices/fox_ess/fox_ess/bat.py b/packages/modules/devices/fox_ess/fox_ess/bat.py index 1e9f2c50e8..e9d27e69ae 100644 --- a/packages/modules/devices/fox_ess/fox_ess/bat.py +++ b/packages/modules/devices/fox_ess/fox_ess/bat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -12,21 +12,29 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + + class FoxEssBat(AbstractBat): - def __init__(self, component_config: FoxEssBatSetup) -> None: - self.component_config = dataclass_from_dict(FoxEssBatSetup, component_config) + def __init__(self, component_config: FoxEssBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = client.read_holding_registers(31036, ModbusDataType.INT_16, unit=unit) * -1 - soc = client.read_holding_registers(31038, ModbusDataType.UINT_16, unit=unit) + power = self.client.read_holding_registers(31036, ModbusDataType.INT_16, unit=unit) * -1 + soc = self.client.read_holding_registers(31038, ModbusDataType.UINT_16, unit=unit) # Geladen in kWh * 0,1 - imported = client.read_holding_registers(32003, ModbusDataType.UINT_32, unit=unit) * 100 + imported = self.client.read_holding_registers(32003, ModbusDataType.UINT_32, unit=unit) * 100 # Entladen in kWh * 0,1 - exported = client.read_holding_registers(32006, ModbusDataType.UINT_32, unit=unit) * 100 + exported = self.client.read_holding_registers(32006, ModbusDataType.UINT_32, unit=unit) * 100 bat_state = BatState( power=power, diff --git a/packages/modules/devices/fox_ess/fox_ess/counter.py b/packages/modules/devices/fox_ess/fox_ess/counter.py index dc6a963434..ba96b14221 100644 --- a/packages/modules/devices/fox_ess/fox_ess/counter.py +++ b/packages/modules/devices/fox_ess/fox_ess/counter.py @@ -1,29 +1,36 @@ -#!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict -from modules.common.abstract_device import AbstractCounter -from modules.common.component_state import CounterState -from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState from modules.common.modbus import ModbusDataType, ModbusTcpClient_ from modules.common.store import get_counter_value_store from modules.devices.fox_ess.fox_ess.config import FoxEssCounterSetup +from modules.common.abstract_device import AbstractCounter +from modules.common.component_state import CounterState +from modules.common.component_type import ComponentDescriptor +from typing import TypedDict, Any + + +class KwargsDict(TypedDict): + client: ModbusTcpClient_ class FoxEssCounter(AbstractCounter): - def __init__(self, component_config: FoxEssCounterSetup) -> None: - self.component_config = dataclass_from_dict(FoxEssCounterSetup, component_config) + def __init__(self, component_config: FoxEssCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_): + def update(self) -> None: unit = self.component_config.configuration.modbus_id powers = [val * -1 for val in - client.read_holding_registers(31026, [ModbusDataType.INT_16]*3, unit=unit)] + self.client.read_holding_registers(31026, [ModbusDataType.INT_16]*3, unit=unit)] power = sum(powers) - frequency = client.read_holding_registers(31015, ModbusDataType.UINT_16, unit=unit) / 100 - imported = client.read_holding_registers(32018, ModbusDataType.UINT_32, unit=unit) * 100 - exported = client.read_holding_registers(32015, ModbusDataType.UINT_32, unit=unit) * 100 + frequency = self.client.read_holding_registers(31015, ModbusDataType.UINT_16, unit=unit) / 100 + imported = self.client.read_holding_registers(32018, ModbusDataType.UINT_32, unit=unit) * 100 + exported = self.client.read_holding_registers(32015, ModbusDataType.UINT_32, unit=unit) * 100 counter_state = CounterState( imported=imported, diff --git a/packages/modules/devices/fox_ess/fox_ess/device.py b/packages/modules/devices/fox_ess/fox_ess/device.py index 3194ecfed7..73f2452f7c 100644 --- a/packages/modules/devices/fox_ess/fox_ess/device.py +++ b/packages/modules/devices/fox_ess/fox_ess/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.fox_ess.fox_ess.bat import FoxEssBat @@ -15,27 +14,33 @@ def create_device(device_config: FoxEss): + client = None + def create_bat_component(component_config: FoxEssBatSetup): - return FoxEssBat(component_config) + nonlocal client + return FoxEssBat(component_config=component_config, client=client) def create_counter_component(component_config: FoxEssCounterSetup): - return FoxEssCounter(component_config) + nonlocal client + return FoxEssCounter(component_config=component_config, client=client) def create_inverter_component(component_config: FoxEssInverterSetup): - return FoxEssInverter(component_config) + nonlocal client + return FoxEssInverter(component_config=component_config, client=client) def update_components(components: Iterable[Union[FoxEssBat, FoxEssCounter, FoxEssInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/fox_ess/fox_ess/inverter.py b/packages/modules/devices/fox_ess/fox_ess/inverter.py index b2b22e48d3..be8b608c43 100644 --- a/packages/modules/devices/fox_ess/fox_ess/inverter.py +++ b/packages/modules/devices/fox_ess/fox_ess/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,20 +10,28 @@ from modules.devices.fox_ess.fox_ess.config import FoxEssInverterSetup +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + + class FoxEssInverter(AbstractInverter): - def __init__(self, component_config: Union[Dict, FoxEssInverterSetup]) -> None: - self.component_config = dataclass_from_dict(FoxEssInverterSetup, component_config) + def __init__(self, component_config: FoxEssInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id # PV1 + PV2 Power - power = sum([client.read_holding_registers( + power = sum([self.client.read_holding_registers( reg, ModbusDataType.INT_16, unit=unit) for reg in [31002, 31005]]) * -1 # Gesamt Produktion Wechselrichter unsigned integer in kWh * 0,1 - exported = client.read_holding_registers(32000, ModbusDataType.UINT_32, unit=unit) * 100 + exported = self.client.read_holding_registers(32000, ModbusDataType.UINT_32, unit=unit) * 100 inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/fronius/fronius/bat.py b/packages/modules/devices/fronius/fronius/bat.py index 30c08215f0..528032c6e2 100644 --- a/packages/modules/devices/fronius/fronius/bat.py +++ b/packages/modules/devices/fronius/fronius/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,14 +12,19 @@ from modules.devices.fronius.fronius.config import FroniusConfiguration +class KwargsDict(TypedDict): + device_config: FroniusConfiguration + device_id: int + + class FroniusBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, FroniusBatSetup], - device_config: FroniusConfiguration) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(FroniusBatSetup, component_config) - self.device_config = device_config + def __init__(self, component_config: FroniusBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.device_config: FroniusConfiguration = self.kwargs['device_config'] + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/fronius/fronius/bat_test.py b/packages/modules/devices/fronius/fronius/bat_test.py index 5a6a5cc449..64d43e19ce 100644 --- a/packages/modules/devices/fronius/fronius/bat_test.py +++ b/packages/modules/devices/fronius/fronius/bat_test.py @@ -23,7 +23,9 @@ def test_update(monkeypatch, requests_mock: requests_mock.Mocker, mock_ramdisk, device_config = FroniusConfiguration() device_config.ip_address = SAMPLE_IP assert component_config.configuration.meter_id == 0 - battery = bat.FroniusBat(0, component_config, dataclass_from_dict(FroniusConfiguration, device_config)) + battery = bat.FroniusBat(component_config, device_config=dataclass_from_dict( + FroniusConfiguration, device_config), device_id=0) + battery.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) diff --git a/packages/modules/devices/fronius/fronius/counter_s0.py b/packages/modules/devices/fronius/fronius/counter_s0.py index c9bf82884d..6528a168a4 100644 --- a/packages/modules/devices/fronius/fronius/counter_s0.py +++ b/packages/modules/devices/fronius/fronius/counter_s0.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -12,14 +11,19 @@ from modules.devices.fronius.fronius.config import FroniusConfiguration, FroniusS0CounterSetup +class KwargsDict(TypedDict): + device_id: int + device_config: FroniusConfiguration + + class FroniusS0Counter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, FroniusS0CounterSetup], - device_config: FroniusConfiguration) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(FroniusS0CounterSetup, component_config) - self.device_config = device_config + def __init__(self, component_config: FroniusS0CounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.device_config: FroniusConfiguration = self.kwargs['device_config'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/fronius/fronius/counter_s0_test.py b/packages/modules/devices/fronius/fronius/counter_s0_test.py index 88725b49b5..e29f815e0c 100644 --- a/packages/modules/devices/fronius/fronius/counter_s0_test.py +++ b/packages/modules/devices/fronius/fronius/counter_s0_test.py @@ -22,8 +22,9 @@ def test_update(monkeypatch, requests_mock: requests_mock.Mocker, mock_ramdisk, component_config = FroniusS0CounterSetup() device_config = FroniusConfiguration() device_config.ip_address = SAMPLE_IP - counter = counter_s0.FroniusS0Counter( - 0, component_config, dataclass_from_dict(FroniusConfiguration, device_config)) + counter = counter_s0.FroniusS0Counter(component_config, device_config=dataclass_from_dict( + FroniusConfiguration, device_config), device_id=0) + counter.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) diff --git a/packages/modules/devices/fronius/fronius/counter_sm.py b/packages/modules/devices/fronius/fronius/counter_sm.py index 23ab966a5b..c7adfd6f74 100644 --- a/packages/modules/devices/fronius/fronius/counter_sm.py +++ b/packages/modules/devices/fronius/fronius/counter_sm.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Tuple, Union +from typing import Tuple, TypedDict, Any from requests import Session -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -18,14 +17,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + device_config: FroniusConfiguration + + class FroniusSmCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, FroniusSmCounterSetup], - device_config: FroniusConfiguration) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(FroniusSmCounterSetup, component_config) - self.device_config = device_config + def __init__(self, component_config: FroniusSmCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.device_config: FroniusConfiguration = self.kwargs['device_config'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/fronius/fronius/counter_sm_test.py b/packages/modules/devices/fronius/fronius/counter_sm_test.py index c03558397a..1dfc235b44 100644 --- a/packages/modules/devices/fronius/fronius/counter_sm_test.py +++ b/packages/modules/devices/fronius/fronius/counter_sm_test.py @@ -24,7 +24,9 @@ def test_update_grid(monkeypatch, requests_mock: requests_mock.Mocker, mock_ramd device_config = FroniusConfiguration() device_config.ip_address = SAMPLE_IP assert component_config.configuration.meter_id == 0 - counter = counter_sm.FroniusSmCounter(0, component_config, dataclass_from_dict(FroniusConfiguration, device_config)) + counter = counter_sm.FroniusSmCounter(component_config, device_config=dataclass_from_dict( + FroniusConfiguration, device_config), device_id=0) + counter.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) @@ -54,7 +56,9 @@ def test_update_grid_var2(monkeypatch, requests_mock: requests_mock.Mocker, mock device_config = FroniusConfiguration() device_config.ip_address = SAMPLE_IP assert component_config.configuration.meter_id == 0 - counter = counter_sm.FroniusSmCounter(0, component_config, dataclass_from_dict(FroniusConfiguration, device_config)) + counter = counter_sm.FroniusSmCounter(component_config, device_config=dataclass_from_dict( + FroniusConfiguration, device_config), device_id=0) + counter.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) @@ -83,7 +87,9 @@ def test_update_external_var2(monkeypatch, requests_mock: requests_mock.Mocker, device_config = FroniusConfiguration() device_config.ip_address = SAMPLE_IP component_config.configuration.meter_id = 1 - counter = counter_sm.FroniusSmCounter(0, component_config, dataclass_from_dict(FroniusConfiguration, device_config)) + counter = counter_sm.FroniusSmCounter(component_config, device_config=dataclass_from_dict( + FroniusConfiguration, device_config), device_id=0) + counter.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) @@ -112,7 +118,9 @@ def test_update_load(monkeypatch, requests_mock: requests_mock.Mocker, mock_ramd device_config = FroniusConfiguration() device_config.ip_address = SAMPLE_IP component_config.configuration.meter_id = 2 - counter = counter_sm.FroniusSmCounter(0, component_config, dataclass_from_dict(FroniusConfiguration, device_config)) + counter = counter_sm.FroniusSmCounter(component_config, device_config=dataclass_from_dict( + FroniusConfiguration, device_config), device_id=0) + counter.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) diff --git a/packages/modules/devices/fronius/fronius/device.py b/packages/modules/devices/fronius/fronius/device.py index a5ea75c214..a8eb412a7b 100644 --- a/packages/modules/devices/fronius/fronius/device.py +++ b/packages/modules/devices/fronius/fronius/device.py @@ -6,7 +6,6 @@ from modules.common import req 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.fronius.fronius.bat import FroniusBat from modules.devices.fronius.fronius.config import (Fronius, FroniusBatSetup, FroniusSecondaryInverterSetup, @@ -25,47 +24,53 @@ def create_device(device_config: Fronius): def create_bat_component(component_config: FroniusBatSetup): - return FroniusBat(device_config.id, component_config, device_config.configuration) + return FroniusBat(component_config=component_config, + device_id=device_config.id, + device_config=device_config.configuration) def create_counter_sm_component(component_config: FroniusSmCounterSetup): - return FroniusSmCounter(device_config.id, component_config, device_config.configuration) + return FroniusSmCounter(component_config=component_config, + device_id=device_config.id, + device_config=device_config.configuration) def create_counter_s0_component(component_config: FroniusS0CounterSetup): - return FroniusS0Counter(device_config.id, component_config, device_config.configuration) + return FroniusS0Counter(component_config=component_config, + device_id=device_config.id, + device_config=device_config.configuration) def create_inverter_component(component_config: FroniusInverterSetup): - return FroniusInverter(device_config.id, component_config) + return FroniusInverter(component_config=component_config, + device_id=device_config.id) def create_inverter_secondary_component(component_config: FroniusSecondaryInverterSetup): - return FroniusSecondaryInverter(device_config.id, component_config) + return FroniusSecondaryInverter(component_config=component_config, + device_id=device_config.id) def update_components(components: Iterable[fronius_component_classes]): inverter_response = None for component in components: - with SingleComponentUpdateContext(component.fault_state): - if ( - component.component_config.type == "inverter" or - component.component_config.type == "inverter_secondary" - ): - if inverter_response is None: - try: - inverter_response = req.get_http_session().get( - (f'http://{device_config.configuration.ip_address}' - '/solar_api/v1/GetPowerFlowRealtimeData.fcgi'), - params=(('Scope', 'System'),), - timeout=3).json() - except (requests.ConnectTimeout, requests.ConnectionError) as e: - inverter_response = e - # Nachtmodus: WR ist ausgeschaltet - component.update(inverter_response) + if ( + component.component_config.type == "inverter" or + component.component_config.type == "inverter_secondary" + ): + if inverter_response is None: + try: + inverter_response = req.get_http_session().get( + (f'http://{device_config.configuration.ip_address}' + '/solar_api/v1/GetPowerFlowRealtimeData.fcgi'), + params=(('Scope', 'System'),), + timeout=3).json() + except (requests.ConnectTimeout, requests.ConnectionError) as e: + inverter_response = e + # Nachtmodus: WR ist ausgeschaltet + component.update(inverter_response) for component in components: - with SingleComponentUpdateContext(component.fault_state): - if ( - component.component_config.type != "inverter" and - component.component_config.type != "inverter_secondary" - ): - component.update() + if ( + component.component_config.type != "inverter" and + component.component_config.type != "inverter_secondary" + ): + component.update() return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/fronius/fronius/inverter.py b/packages/modules/devices/fronius/fronius/inverter.py index de9486ec07..b3afaa7eab 100644 --- a/packages/modules/devices/fronius/fronius/inverter.py +++ b/packages/modules/devices/fronius/fronius/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Dict, TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,12 +10,17 @@ from modules.devices.fronius.fronius.config import FroniusInverterSetup +class KwargsDict(TypedDict): + device_id: int + + class FroniusInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, FroniusInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(FroniusInverterSetup, component_config) + def __init__(self, component_config: FroniusInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/fronius/fronius/inverter_secondary.py b/packages/modules/devices/fronius/fronius/inverter_secondary.py index de4a64ac27..10bacae7b9 100644 --- a/packages/modules/devices/fronius/fronius/inverter_secondary.py +++ b/packages/modules/devices/fronius/fronius/inverter_secondary.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Dict, TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,12 +10,17 @@ from modules.devices.fronius.fronius.config import FroniusSecondaryInverterSetup +class KwargsDict(TypedDict): + device_id: int + + class FroniusSecondaryInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, FroniusSecondaryInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(FroniusSecondaryInverterSetup, component_config) + def __init__(self, component_config: FroniusSecondaryInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/fronius/fronius/inverter_secondary_test.py b/packages/modules/devices/fronius/fronius/inverter_secondary_test.py index 5b4111f7e1..a8038e8c88 100644 --- a/packages/modules/devices/fronius/fronius/inverter_secondary_test.py +++ b/packages/modules/devices/fronius/fronius/inverter_secondary_test.py @@ -7,7 +7,9 @@ def test_update(monkeypatch, mock_simcount): - wr = FroniusSecondaryInverter(0, FroniusSecondaryInverterSetup(FroniusSecondaryInverterConfiguration(id=1))) + wr = FroniusSecondaryInverter(FroniusSecondaryInverterSetup( + FroniusSecondaryInverterConfiguration(id=1)), device_id=0) + wr.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) diff --git a/packages/modules/devices/fronius/fronius/inverter_test.py b/packages/modules/devices/fronius/fronius/inverter_test.py index 5b4111f7e1..a8038e8c88 100644 --- a/packages/modules/devices/fronius/fronius/inverter_test.py +++ b/packages/modules/devices/fronius/fronius/inverter_test.py @@ -7,7 +7,9 @@ def test_update(monkeypatch, mock_simcount): - wr = FroniusSecondaryInverter(0, FroniusSecondaryInverterSetup(FroniusSecondaryInverterConfiguration(id=1))) + wr = FroniusSecondaryInverter(FroniusSecondaryInverterSetup( + FroniusSecondaryInverterConfiguration(id=1)), device_id=0) + wr.initialize() mock = Mock(return_value=None) monkeypatch.setattr(LoggingValueStore, "set", mock) diff --git a/packages/modules/devices/generic/http/bat.py b/packages/modules/devices/generic/http/bat.py index 8b9bc5600a..7835bc1f94 100644 --- a/packages/modules/devices/generic/http/bat.py +++ b/packages/modules/devices/generic/http/bat.py @@ -1,9 +1,8 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict from requests import Session -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -14,18 +13,28 @@ from modules.devices.generic.http.config import HttpBatSetup +class KwargsDict(TypedDict): + device_id: int + url: str + + class HttpBat(AbstractBat): - def __init__(self, device_id: int, component_config: Union[Dict, HttpBatSetup], url: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(HttpBatSetup, component_config) + def __init__(self, component_config: HttpBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_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.__get_power = create_request_function(url, self.component_config.configuration.power_path) - self.__get_imported = create_request_function(url, self.component_config.configuration.imported_path) - self.__get_exported = create_request_function(url, self.component_config.configuration.exported_path) - self.__get_soc = create_request_function(url, self.component_config.configuration.soc_path) + self.__get_power = create_request_function(self.kwargs['url'], self.component_config.configuration.power_path) + self.__get_imported = create_request_function( + self.kwargs['url'], self.component_config.configuration.imported_path) + self.__get_exported = create_request_function( + self.kwargs['url'], self.component_config.configuration.exported_path) + self.__get_soc = create_request_function(self.kwargs['url'], self.component_config.configuration.soc_path) def update(self, session: Session) -> None: power = self.__get_power(session) diff --git a/packages/modules/devices/generic/http/counter.py b/packages/modules/devices/generic/http/counter.py index 99a771926b..2924c7c178 100644 --- a/packages/modules/devices/generic/http/counter.py +++ b/packages/modules/devices/generic/http/counter.py @@ -1,9 +1,8 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any from requests import Session -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -14,21 +13,30 @@ from modules.devices.generic.http.config import HttpCounterSetup +class KwargsDict(TypedDict): + device_id: int + url: str + + class HttpCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: Union[Dict, HttpCounterSetup], url: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(HttpCounterSetup, component_config) + def __init__(self, component_config: HttpCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.url: str = self.kwargs['url'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__get_power = create_request_function(url, self.component_config.configuration.power_path) - self.__get_imported = create_request_function(url, self.component_config.configuration.imported_path) - self.__get_exported = create_request_function(url, self.component_config.configuration.exported_path) - self.__get_currents = create_request_function_array(url, [ - component_config.configuration.current_l1_path, - component_config.configuration.current_l2_path, - component_config.configuration.current_l3_path, + self.__get_power = create_request_function(self.url, self.component_config.configuration.power_path) + self.__get_imported = create_request_function(self.url, self.component_config.configuration.imported_path) + self.__get_exported = create_request_function(self.url, self.component_config.configuration.exported_path) + self.__get_currents = create_request_function_array(self.url, [ + self.component_config.configuration.current_l1_path, + self.component_config.configuration.current_l2_path, + self.component_config.configuration.current_l3_path, ]) def update(self, session: Session) -> None: diff --git a/packages/modules/devices/generic/http/device.py b/packages/modules/devices/generic/http/device.py index c18a2d34dc..34662d71de 100644 --- a/packages/modules/devices/generic/http/device.py +++ b/packages/modules/devices/generic/http/device.py @@ -19,18 +19,30 @@ def create_device(device_config: HTTP): + session = None + def create_bat_component(component_config: HttpBatSetup): - return HttpBat(device_config.id, component_config, device_config.configuration.url) + return HttpBat(component_config=component_config, + device_id=device_config.id, + url=device_config.configuration.url) def create_counter_component(component_config: HttpCounterSetup): - return HttpCounter(device_config.id, component_config, device_config.configuration.url) + return HttpCounter(component_config=component_config, + device_id=device_config.id, + url=device_config.configuration.url) def create_inverter_component(component_config: HttpInverterSetup): - return HttpInverter(device_config.id, component_config, device_config.configuration.url) + return HttpInverter(component_config=component_config, + device_id=device_config.id, + url=device_config.configuration.url) + + def initializer(): + nonlocal session + session = req.get_http_session() - session = req.get_http_session() return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/generic/http/inverter.py b/packages/modules/devices/generic/http/inverter.py index 750ee128ff..c542bb7eb3 100644 --- a/packages/modules/devices/generic/http/inverter.py +++ b/packages/modules/devices/generic/http/inverter.py @@ -1,9 +1,8 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any from requests import Session -from dataclass_utils import dataclass_from_dict from helpermodules import compatibility from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -15,16 +14,25 @@ from modules.devices.generic.http.config import HttpInverterSetup +class KwargsDict(TypedDict): + device_id: int + url: str + + class HttpInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, HttpInverterSetup], url: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(HttpInverterSetup, component_config) + def __init__(self, component_config: HttpInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.url: str = self.kwargs['url'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__get_power = create_request_function(url, self.component_config.configuration.power_path) - self.__get_exported = create_request_function(url, self.component_config.configuration.exported_path) + self.__get_power = create_request_function(self.url, self.component_config.configuration.power_path) + self.__get_exported = create_request_function(self.url, self.component_config.configuration.exported_path) def update(self, session: Session) -> None: power = self.__get_power(session) diff --git a/packages/modules/devices/generic/json/bat.py b/packages/modules/devices/generic/json/bat.py index 12f638c8ac..191cddc157 100644 --- a/packages/modules/devices/generic/json/bat.py +++ b/packages/modules/devices/generic/json/bat.py @@ -1,9 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union - +from typing import TypedDict, Any import jq -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -13,10 +11,17 @@ from modules.devices.generic.json.config import JsonBatSetup +class KwargsDict(TypedDict): + device_id: int + + class JsonBat(AbstractBat): - def __init__(self, device_id: int, component_config: Union[Dict, JsonBatSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(JsonBatSetup, component_config) + def __init__(self, component_config: JsonBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/generic/json/counter.py b/packages/modules/devices/generic/json/counter.py index 5496b026ed..fd925b4558 100644 --- a/packages/modules/devices/generic/json/counter.py +++ b/packages/modules/devices/generic/json/counter.py @@ -1,9 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union - +from typing import TypedDict, Any import jq -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -13,15 +11,22 @@ from modules.devices.generic.json.config import JsonCounterSetup +class KwargsDict(TypedDict): + device_id: int + + class JsonCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: Union[Dict, JsonCounterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(JsonCounterSetup, component_config) + def __init__(self, component_config: JsonCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, response): + def update(self, response) -> None: config = self.component_config.configuration power = float(jq.compile(config.jq_power).input(response).first()) diff --git a/packages/modules/devices/generic/json/device.py b/packages/modules/devices/generic/json/device.py index 43be25603e..a7a74c1fee 100644 --- a/packages/modules/devices/generic/json/device.py +++ b/packages/modules/devices/generic/json/device.py @@ -25,13 +25,13 @@ def create_device(device_config: Json): def create_bat(component_config: JsonBatSetup) -> JsonBat: - return JsonBat(device_config.id, component_config) + return JsonBat(component_config=component_config, device_id=device_config.id) def create_counter(component_config: JsonCounterSetup) -> JsonCounter: - return JsonCounter(device_config.id, component_config) + return JsonCounter(component_config=component_config, device_id=device_config.id) def create_inverter(component_config: JsonInverterSetup) -> JsonInverter: - return JsonInverter(device_config.id, component_config) + return JsonInverter(component_config=component_config, device_id=device_config.id) def update_components(components: Iterable[JsonComponent]): response = req.get_http_session().get(device_config.configuration.url, timeout=5).json() diff --git a/packages/modules/devices/generic/json/inverter.py b/packages/modules/devices/generic/json/inverter.py index 409c966720..7201562bd6 100644 --- a/packages/modules/devices/generic/json/inverter.py +++ b/packages/modules/devices/generic/json/inverter.py @@ -1,9 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union - +from typing import TypedDict, Any import jq -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -13,10 +11,17 @@ from modules.devices.generic.json.config import JsonInverterSetup +class KwargsDict(TypedDict): + device_id: int + + class JsonInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, JsonInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(JsonInverterSetup, component_config) + def __init__(self, component_config: JsonInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/generic/mqtt/bat.py b/packages/modules/devices/generic/mqtt/bat.py index 5f518c26e7..d098e7a95c 100644 --- a/packages/modules/devices/generic/mqtt/bat.py +++ b/packages/modules/devices/generic/mqtt/bat.py @@ -1,17 +1,17 @@ #!/usr/bin/env python3 -from typing import Dict, Optional, Union +from typing import Optional from modules.common.abstract_device import AbstractBat from modules.common.fault_state import ComponentInfo, FaultState - -from dataclass_utils import dataclass_from_dict from modules.common.component_type import ComponentDescriptor from modules.devices.generic.mqtt.config import MqttBatSetup class MqttBat(AbstractBat): - def __init__(self, component_config: Union[Dict, MqttBatSetup]) -> None: - self.component_config = dataclass_from_dict(MqttBatSetup, component_config) - self.fault_state = FaultState(ComponentInfo.from_component_config(component_config)) + def __init__(self, component_config: MqttBatSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: + self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def set_power_limit(self, power_limit: Optional[int]) -> None: # wird bereits in Regelung gesetzt, eigene Implementierung notwendig, um zu erkennen, diff --git a/packages/modules/devices/generic/mqtt/counter.py b/packages/modules/devices/generic/mqtt/counter.py index 8fa9f4d5f2..80285cf20e 100644 --- a/packages/modules/devices/generic/mqtt/counter.py +++ b/packages/modules/devices/generic/mqtt/counter.py @@ -1,16 +1,15 @@ #!/usr/bin/env python3 -from typing import Dict, Union from modules.common.abstract_device import AbstractCounter from modules.common.fault_state import ComponentInfo, FaultState - -from dataclass_utils import dataclass_from_dict from modules.common.component_type import ComponentDescriptor from modules.devices.generic.mqtt.config import MqttCounterSetup class MqttCounter(AbstractCounter): - def __init__(self, component_config: Union[Dict, MqttCounterSetup]) -> None: - self.component_config = dataclass_from_dict(MqttCounterSetup, component_config) + def __init__(self, component_config: MqttCounterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/generic/mqtt/inverter.py b/packages/modules/devices/generic/mqtt/inverter.py index 039a0a4a61..5e6d1596f5 100644 --- a/packages/modules/devices/generic/mqtt/inverter.py +++ b/packages/modules/devices/generic/mqtt/inverter.py @@ -1,16 +1,15 @@ #!/usr/bin/env python3 -from typing import Dict, Union from modules.common.abstract_device import AbstractInverter from modules.common.fault_state import ComponentInfo, FaultState - -from dataclass_utils import dataclass_from_dict from modules.common.component_type import ComponentDescriptor from modules.devices.generic.mqtt.config import MqttInverterSetup class MqttInverter(AbstractInverter): - def __init__(self, component_config: Union[Dict, MqttInverterSetup]) -> None: - self.component_config = dataclass_from_dict(MqttInverterSetup, component_config) + def __init__(self, component_config: MqttInverterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/generic/virtual/counter.py b/packages/modules/devices/generic/virtual/counter.py index e324f155ba..6311a9c46a 100644 --- a/packages/modules/devices/generic/virtual/counter.py +++ b/packages/modules/devices/generic/virtual/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -11,11 +10,17 @@ from modules.devices.generic.virtual.config import VirtualCounterSetup +class KwargsDict(TypedDict): + device_id: int + + class VirtualCounter(AbstractCounter): + def __init__(self, component_config: VirtualCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs - def __init__(self, device_id: int, component_config: Union[Dict, VirtualCounterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VirtualCounterSetup, component_config) + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id, add_child_values=True) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/generic/virtual/counter_test.py b/packages/modules/devices/generic/virtual/counter_test.py index 9f2c71879c..6aea8b8c90 100644 --- a/packages/modules/devices/generic/virtual/counter_test.py +++ b/packages/modules/devices/generic/virtual/counter_test.py @@ -50,8 +50,9 @@ def __init__(self, name: str, init_func: Callable[[], None], expected_state: Cou @pytest.mark.parametrize("params", cases, ids=[c.name for c in cases]) def test_virtual_counter(mock_pub: Mock, params): # setup - c = counter.VirtualCounter(0, VirtualCounterSetup( - id=6, configuration=VirtualCounterConfiguration(external_consumption=0))) + c = counter.VirtualCounter(VirtualCounterSetup( + id=6, configuration=VirtualCounterConfiguration(external_consumption=0)), device_id=0) + c.initialize() params.init_func() # execution @@ -76,8 +77,9 @@ def test_virtual_counter(mock_pub: Mock, params): pytest.param(hierarchy_nested, id="nested")]) def test_virtual_counter_hierarchies(counter_all: Callable[[], CounterAll], data_, mock_pub: Mock): # setup - virtual_counter = counter.VirtualCounter(0, VirtualCounterSetup( - id=0, configuration=VirtualCounterConfiguration(external_consumption=0))) + virtual_counter = counter.VirtualCounter(VirtualCounterSetup( + id=0, configuration=VirtualCounterConfiguration(external_consumption=0)), device_id=0) + virtual_counter.initialize() data.data.counter_all_data = counter_all() # execution diff --git a/packages/modules/devices/generic/virtual/device.py b/packages/modules/devices/generic/virtual/device.py index 47e1c2e67b..ed111b480b 100644 --- a/packages/modules/devices/generic/virtual/device.py +++ b/packages/modules/devices/generic/virtual/device.py @@ -10,7 +10,7 @@ def create_device(device_config: Virtual): def create_counter_component(component_config: VirtualCounterSetup): - return VirtualCounter(device_config.id, component_config) + return VirtualCounter(component_config, device_id=device_config.id) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/good_we/good_we/bat.py b/packages/modules/devices/good_we/good_we/bat.py index f203bcfddd..3b10004f8b 100644 --- a/packages/modules/devices/good_we/good_we/bat.py +++ b/packages/modules/devices/good_we/good_we/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,18 +12,23 @@ from modules.devices.good_we.good_we.version import GoodWeVersion +class KwargsDict(TypedDict): + modbus_id: int + version: GoodWeVersion + firmware: int + client: modbus.ModbusTcpClient_ + + class GoodWeBat(AbstractBat): - def __init__(self, - modbus_id: int, - version: GoodWeVersion, - firmware: int, - component_config: Union[Dict, GoodWeBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__modbus_id = modbus_id - self.version = version - self.firmware = firmware - self.component_config = dataclass_from_dict(GoodWeBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: GoodWeBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.version: GoodWeVersion = self.kwargs['version'] + self.firmware: int = self.kwargs['firmware'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/good_we/good_we/counter.py b/packages/modules/devices/good_we/good_we/counter.py index 24f0516625..56c1f82e0d 100644 --- a/packages/modules/devices/good_we/good_we/counter.py +++ b/packages/modules/devices/good_we/good_we/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -14,25 +13,29 @@ from modules.devices.good_we.good_we.version import GoodWeVersion +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + version: GoodWeVersion + firmware: int + client: modbus.ModbusTcpClient_ + + class GoodWeCounter(AbstractCounter): - def __init__(self, - device_id: int, - modbus_id: int, - version: GoodWeVersion, - firmware: int, - component_config: Union[Dict, GoodWeCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.__modbus_id = modbus_id - self.version = version - self.firmware = firmware - self.component_config = dataclass_from_dict(GoodWeCounterSetup, component_config) - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") - self.__tcp_client = tcp_client + def __init__(self, component_config: GoodWeCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.version: GoodWeVersion = self.kwargs['version'] + self.firmware: int = self.kwargs['firmware'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter(self.kwargs['device_id'], self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self): + def update(self) -> None: with self.__tcp_client: if self.firmware < 9: power = self.__tcp_client.read_holding_registers( diff --git a/packages/modules/devices/good_we/good_we/device.py b/packages/modules/devices/good_we/good_we/device.py index 03c6543406..e4ff4db18e 100644 --- a/packages/modules/devices/good_we/good_we/device.py +++ b/packages/modules/devices/good_we/good_we/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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.good_we.good_we import bat from modules.devices.good_we.good_we import counter @@ -18,36 +17,46 @@ def create_device(device_config: GoodWe): + client = None + def create_bat_component(component_config: GoodWeBatSetup): - return bat.GoodWeBat(device_config.configuration.modbus_id, - GoodWeVersion(device_config.configuration.version), - device_config.configuration.firmware, - component_config, client) + nonlocal client + return bat.GoodWeBat(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + version=GoodWeVersion(device_config.configuration.version), + firmware=device_config.configuration.firmware, + client=client) def create_counter_component(component_config: GoodWeCounterSetup): - return counter.GoodWeCounter(device_config.id, device_config.configuration.modbus_id, - GoodWeVersion(device_config.configuration.version), - device_config.configuration.firmware, - component_config, client) + nonlocal client + return counter.GoodWeCounter(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + version=GoodWeVersion(device_config.configuration.version), + firmware=device_config.configuration.firmware, + client=client, + device_id=device_config.id) def create_inverter_component(component_config: GoodWeInverterSetup): - return inverter.GoodWeInverter(device_config.configuration.modbus_id, - GoodWeVersion(device_config.configuration.version), - device_config.configuration.firmware, - component_config, client) + nonlocal client + return inverter.GoodWeInverter(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + version=GoodWeVersion(device_config.configuration.version), + firmware=device_config.configuration.firmware, + client=client) def update_components(components: Iterable[good_we_component_classes]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() - try: + component.update() + + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/good_we/good_we/inverter.py b/packages/modules/devices/good_we/good_we/inverter.py index 41acbdaaf6..10f66a44c1 100644 --- a/packages/modules/devices/good_we/good_we/inverter.py +++ b/packages/modules/devices/good_we/good_we/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -13,18 +12,23 @@ from modules.devices.good_we.good_we.version import GoodWeVersion +class KwargsDict(TypedDict): + modbus_id: int + version: GoodWeVersion + firmware: int + client: modbus.ModbusTcpClient_ + + class GoodWeInverter(AbstractInverter): - def __init__(self, - modbus_id: int, - version: GoodWeVersion, - firmware: int, - component_config: Union[Dict, GoodWeInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__modbus_id = modbus_id - self.version = version - self.firmware = firmware - self.component_config = dataclass_from_dict(GoodWeInverterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: GoodWeInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.version: GoodWeVersion = self.kwargs['version'] + self.firmware: int = self.kwargs['firmware'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/growatt/growatt/bat.py b/packages/modules/devices/growatt/growatt/bat.py index 71d6a75f15..66054b257f 100644 --- a/packages/modules/devices/growatt/growatt/bat.py +++ b/packages/modules/devices/growatt/growatt/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -12,41 +11,48 @@ from modules.devices.growatt.growatt.version import GrowattVersion +class KwargsDict(TypedDict): + modbus_id: int + version: GrowattVersion + client: ModbusTcpClient_ + + class GrowattBat(AbstractBat): - def __init__(self, - component_config: Union[Dict, GrowattBatSetup], - modbus_id: int, - version: GrowattVersion) -> None: - self.__modbus_id = modbus_id - self.version = version - self.component_config = dataclass_from_dict(GrowattBatSetup, component_config) + def __init__(self, component_config: GrowattBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.version: GrowattVersion = self.kwargs['version'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: if self.version == GrowattVersion.max_series: - power_in = client.read_input_registers( + power_in = self.client.read_input_registers( 1011, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 - power_out = client.read_input_registers( + power_out = self.client.read_input_registers( 1009, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 power = power_in + power_out - soc = client.read_input_registers(1014, ModbusDataType.UINT_16, unit=self.__modbus_id) - imported = client.read_input_registers( + soc = self.client.read_input_registers(1014, ModbusDataType.UINT_16, unit=self.__modbus_id) + imported = self.client.read_input_registers( 1058, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 - exported = client.read_input_registers( + exported = self.client.read_input_registers( 1054, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 else: - power_in = client.read_input_registers( + power_in = self.client.read_input_registers( 3180, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 - power_out = client.read_input_registers( + power_out = self.client.read_input_registers( 3178, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 power = power_in + power_out - soc = client.read_input_registers(3171, ModbusDataType.UINT_16, unit=self.__modbus_id) - imported = client.read_input_registers( + soc = self.client.read_input_registers(3171, ModbusDataType.UINT_16, unit=self.__modbus_id) + imported = self.client.read_input_registers( 3131, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 - exported = client.read_input_registers( + exported = self.client.read_input_registers( 3127, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 bat_state = BatState( diff --git a/packages/modules/devices/growatt/growatt/counter.py b/packages/modules/devices/growatt/growatt/counter.py index af75551031..cc69bd150a 100644 --- a/packages/modules/devices/growatt/growatt/counter.py +++ b/packages/modules/devices/growatt/growatt/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -12,53 +11,60 @@ from modules.devices.growatt.growatt.version import GrowattVersion +class KwargsDict(TypedDict): + modbus_id: int + version: GrowattVersion + client: ModbusTcpClient_ + + class GrowattCounter(AbstractCounter): - def __init__(self, - component_config: Union[Dict, GrowattCounterSetup], - modbus_id: int, - version: GrowattVersion) -> None: - self.component_config = dataclass_from_dict(GrowattCounterSetup, component_config) - self.__modbus_id = modbus_id - self.version = version + def __init__(self, component_config: GrowattCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.version: GrowattVersion = self.kwargs['version'] + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_): + def update(self) -> None: if self.version == GrowattVersion.max_series: - power_in = client.read_input_registers(1021, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 - power_out = client.read_input_registers(1029, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 + power_in = self.client.read_input_registers(1021, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 + power_out = self.client.read_input_registers(1029, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 power = power_in + power_out powers = [ - client.read_input_registers( + self.client.read_input_registers( 40, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, - client.read_input_registers( + self.client.read_input_registers( 44, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, - client.read_input_registers( + self.client.read_input_registers( 48, ModbusDataType.INT_32, unit=self.__modbus_id) / 10] # Einheit 0.1 kWh - exported = client.read_input_registers(1050, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 - imported = client.read_input_registers(1046, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + exported = self.client.read_input_registers(1050, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + imported = self.client.read_input_registers(1046, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 # TL-X Dokumentation hat die gleichen Register wie die MAX Serie, # zusätzlich sind aber auch unten abweichende enthalten else: - power_in = client.read_input_registers(3041, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 - power_out = client.read_input_registers(3043, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 + power_in = self.client.read_input_registers(3041, ModbusDataType.UINT_32, unit=self.__modbus_id) * 0.1 + power_out = self.client.read_input_registers(3043, ModbusDataType.UINT_32, unit=self.__modbus_id) * -0.1 power = power_in + power_out powers = [ - client.read_input_registers( + self.client.read_input_registers( 3028, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, - client.read_input_registers( + self.client.read_input_registers( 3032, ModbusDataType.INT_32, unit=self.__modbus_id) / 10, - client.read_input_registers( + self.client.read_input_registers( 3036, ModbusDataType.INT_32, unit=self.__modbus_id) / 10] # Einheit 0.1 kWh - exported = client.read_input_registers(3073, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 - imported = client.read_input_registers(3069, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + exported = self.client.read_input_registers(3073, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 + imported = self.client.read_input_registers(3069, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 counter_state = CounterState( imported=imported, diff --git a/packages/modules/devices/growatt/growatt/device.py b/packages/modules/devices/growatt/growatt/device.py index 84faf5d728..783223047f 100644 --- a/packages/modules/devices/growatt/growatt/device.py +++ b/packages/modules/devices/growatt/growatt/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.growatt.growatt.bat import GrowattBat @@ -16,34 +15,42 @@ def create_device(device_config: Growatt): + client = None + def create_bat_component(component_config: GrowattBatSetup): - return GrowattBat(component_config, - device_config.configuration.modbus_id, - GrowattVersion(device_config.configuration.version)) + nonlocal client + return GrowattBat(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + version=GrowattVersion(device_config.configuration.version), + client=client) def create_counter_component(component_config: GrowattCounterSetup): - return GrowattCounter(component_config, - device_config.configuration.modbus_id, - GrowattVersion(device_config.configuration.version)) + nonlocal client + return GrowattCounter(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + version=GrowattVersion(device_config.configuration.version), + client=client) def create_inverter_component(component_config: GrowattInverterSetup): - return GrowattInverter(component_config, - device_config.configuration.modbus_id, - GrowattVersion(device_config.configuration.version)) + nonlocal client + return GrowattInverter(component_config=component_config, + modbus_id=device_config.configuration.modbus_id, + version=GrowattVersion(device_config.configuration.version), + client=client) def update_components(components: Iterable[Union[GrowattBat, GrowattCounter, GrowattInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/growatt/growatt/inverter.py b/packages/modules/devices/growatt/growatt/inverter.py index fe7e9fa0e7..0044b8f5e9 100644 --- a/packages/modules/devices/growatt/growatt/inverter.py +++ b/packages/modules/devices/growatt/growatt/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,27 +11,34 @@ from modules.devices.growatt.growatt.version import GrowattVersion +class KwargsDict(TypedDict): + modbus_id: int + version: GrowattVersion + client: ModbusTcpClient_ + + class GrowattInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, GrowattInverterSetup], - modbus_id: int, - version: GrowattVersion) -> None: - self.component_config = dataclass_from_dict(GrowattInverterSetup, component_config) - self.__modbus_id = modbus_id - self.version = version + def __init__(self, component_config: GrowattInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.version: GrowattVersion = self.kwargs['version'] + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_) -> None: + def update(self) -> None: if self.version == GrowattVersion.max_series: - power = client.read_input_registers( + power = self.client.read_input_registers( 1, ModbusDataType.UINT_32, unit=self.__modbus_id) / -10 - exported = client.read_input_registers( + exported = self.client.read_input_registers( 91, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 else: - power = client.read_input_registers( + power = self.client.read_input_registers( 3001, ModbusDataType.UINT_32, unit=self.__modbus_id) / -10 - exported = client.read_input_registers( + exported = self.client.read_input_registers( 3053, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 inverter_state = InverterState( diff --git a/packages/modules/devices/huawei/huawei/bat.py b/packages/modules/devices/huawei/huawei/bat.py index b9539968a2..7e74530e40 100644 --- a/packages/modules/devices/huawei/huawei/bat.py +++ b/packages/modules/devices/huawei/huawei/bat.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import time -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -14,27 +13,34 @@ from modules.devices.huawei.huawei.type import HuaweiType +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + type: HuaweiType + client: ModbusTcpClient_ + + class HuaweiBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, HuaweiBatSetup], - modbus_id: int, - type: HuaweiType) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(HuaweiBatSetup, component_config) - self.modbus_id = modbus_id - self.type = type + def __init__(self, component_config: HuaweiBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.modbus_id: int = self.kwargs['modbus_id'] + self.type: HuaweiType = self.kwargs['type'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_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, client: ModbusTcpClient_) -> None: + def update(self) -> None: if self.type == HuaweiType.SDongle: time.sleep(1) - power = client.read_holding_registers(37765, ModbusDataType.INT_32, unit=self.modbus_id) + power = self.client.read_holding_registers(37765, ModbusDataType.INT_32, unit=self.modbus_id) if self.type == HuaweiType.SDongle: time.sleep(1) - soc = client.read_holding_registers(37760, ModbusDataType.INT_16, unit=self.modbus_id) / 10 + soc = self.client.read_holding_registers(37760, ModbusDataType.INT_16, unit=self.modbus_id) / 10 imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/packages/modules/devices/huawei/huawei/counter.py b/packages/modules/devices/huawei/huawei/counter.py index ecaa1e7236..4c2e440073 100644 --- a/packages/modules/devices/huawei/huawei/counter.py +++ b/packages/modules/devices/huawei/huawei/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import time -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -14,28 +13,35 @@ from modules.devices.huawei.huawei.type import HuaweiType +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + type: HuaweiType + client: ModbusTcpClient_ + + class HuaweiCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, HuaweiCounterSetup], - modbus_id: int, - type: HuaweiType) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(HuaweiCounterSetup, component_config) - self.modbus_id = modbus_id - self.type = type + def __init__(self, component_config: HuaweiCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.modbus_id: int = self.kwargs['modbus_id'] + self.type: HuaweiType = self.kwargs['type'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_): + def update(self) -> None: if self.type == HuaweiType.SDongle: time.sleep(1) - currents = client.read_holding_registers(37107, [ModbusDataType.INT_32]*3, unit=self.modbus_id) + currents = self.client.read_holding_registers(37107, [ModbusDataType.INT_32]*3, unit=self.modbus_id) currents = [val / -100 for val in currents] if self.type == HuaweiType.SDongle: time.sleep(1) - power = client.read_holding_registers(37113, ModbusDataType.INT_32, unit=self.modbus_id) * -1 + power = self.client.read_holding_registers(37113, ModbusDataType.INT_32, unit=self.modbus_id) * -1 imported, exported = self.sim_counter.sim_count(power) diff --git a/packages/modules/devices/huawei/huawei/device.py b/packages/modules/devices/huawei/huawei/device.py index 59d1fbe8fe..83adf585ec 100644 --- a/packages/modules/devices/huawei/huawei/device.py +++ b/packages/modules/devices/huawei/huawei/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union 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.common.modbus import ModbusTcpClient_ from modules.devices.huawei.huawei.bat import HuaweiBat @@ -16,41 +15,50 @@ def create_device(device_config: Huawei): + client = None + def create_bat_component(component_config: HuaweiBatSetup): - return HuaweiBat(device_config.id, - component_config, - device_config.configuration.modbus_id, - HuaweiType(device_config.configuration.type)) + nonlocal client + return HuaweiBat(component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + type=HuaweiType(device_config.configuration.type), + client=client) def create_counter_component(component_config: HuaweiCounterSetup): - return HuaweiCounter(device_config.id, - component_config, - device_config.configuration.modbus_id, - HuaweiType(device_config.configuration.type)) + nonlocal client + return HuaweiCounter(component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + type=HuaweiType(device_config.configuration.type), + client=client) def create_inverter_component(component_config: HuaweiInverterSetup): - return HuaweiInverter(device_config.id, - component_config, - device_config.configuration.modbus_id, - HuaweiType(device_config.configuration.type)) + nonlocal client + return HuaweiInverter(component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + type=HuaweiType(device_config.configuration.type), + client=client) def update_components(components: Iterable[Union[HuaweiBat, HuaweiCounter, HuaweiInverter]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(client) + component.update() - try: + def initializer(): + nonlocal client if HuaweiType(device_config.configuration.type) == HuaweiType.SDongle: client = ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port, sleep_after_connect=7) else: 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/huawei/huawei/inverter.py b/packages/modules/devices/huawei/huawei/inverter.py index 125da608d0..56ada1ce8b 100644 --- a/packages/modules/devices/huawei/huawei/inverter.py +++ b/packages/modules/devices/huawei/huawei/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import time -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -14,24 +13,31 @@ from modules.devices.huawei.huawei.type import HuaweiType +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + type: HuaweiType + client: ModbusTcpClient_ + + class HuaweiInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, HuaweiInverterSetup], - modbus_id: int, - type: HuaweiType) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(HuaweiInverterSetup, component_config) - self.modbus_id = modbus_id - self.type = type + def __init__(self, component_config: HuaweiInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.modbus_id: int = self.kwargs['modbus_id'] + self.type: HuaweiType = self.kwargs['type'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: if self.type == HuaweiType.SDongle: time.sleep(1) - power = client.read_holding_registers(32064, ModbusDataType.INT_32, unit=self.modbus_id) * -1 + power = self.client.read_holding_registers(32064, ModbusDataType.INT_32, unit=self.modbus_id) * -1 _, exported = self.sim_counter.sim_count(power) inverter_state = InverterState( diff --git a/packages/modules/devices/huawei/huawei_smartlogger/bat.py b/packages/modules/devices/huawei/huawei_smartlogger/bat.py index 342ee8b5dd..b2349ecad0 100644 --- a/packages/modules/devices/huawei/huawei_smartlogger/bat.py +++ b/packages/modules/devices/huawei/huawei_smartlogger/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,14 +12,19 @@ from modules.devices.huawei.huawei_smartlogger.config import Huawei_SmartloggerBatSetup +class KwargsDict(TypedDict): + device_id: int + tcp_client: modbus.ModbusTcpClient_ + + class Huawei_SmartloggerBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, Huawei_SmartloggerBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(Huawei_SmartloggerBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: Huawei_SmartloggerBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/huawei/huawei_smartlogger/counter.py b/packages/modules/devices/huawei/huawei_smartlogger/counter.py index 0190e76c36..60ee45a7b7 100644 --- a/packages/modules/devices/huawei/huawei_smartlogger/counter.py +++ b/packages/modules/devices/huawei/huawei_smartlogger/counter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -11,18 +11,24 @@ from modules.devices.huawei.huawei_smartlogger.config import Huawei_SmartloggerCounterSetup +class KwargsDict(TypedDict): + device_id: int + tcp_client: modbus.ModbusTcpClient_ + + class Huawei_SmartloggerCounter(AbstractCounter): - def __init__(self, device_id: int, - component_config: Huawei_SmartloggerCounterSetup, - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(Huawei_SmartloggerCounterSetup, component_config) - self.client = tcp_client + def __init__(self, component_config: Huawei_SmartloggerCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self): + def update(self) -> None: modbus_id = self.component_config.configuration.modbus_id power = self.client.read_holding_registers(32278, ModbusDataType.INT_32, unit=modbus_id) currents = [val / 100 for val in self.client.read_holding_registers( diff --git a/packages/modules/devices/huawei/huawei_smartlogger/device.py b/packages/modules/devices/huawei/huawei_smartlogger/device.py index cfb7333a7a..dcd8b0a031 100644 --- a/packages/modules/devices/huawei/huawei_smartlogger/device.py +++ b/packages/modules/devices/huawei/huawei_smartlogger/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common import modbus from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater from modules.devices.huawei.huawei_smartlogger import counter @@ -23,27 +22,33 @@ def create_device(device_config: Huawei_Smartlogger): + client = None + def create_bat_component(component_config: Huawei_SmartloggerBatSetup): - return bat.Huawei_SmartloggerBat(device_config.id, component_config, client) + nonlocal client + return bat.Huawei_SmartloggerBat(component_config, device_id=device_config.id, tcp_client=client) def create_counter_component(component_config: Huawei_SmartloggerCounterSetup): - return counter.Huawei_SmartloggerCounter(device_config.id, component_config, client) + nonlocal client + return counter.Huawei_SmartloggerCounter(component_config, device_id=device_config.id, tcp_client=client) def create_inverter_component(component_config: Huawei_SmartloggerInverterSetup): - return inverter.Huawei_SmartloggerInverter(device_config.id, component_config, client) + nonlocal client + return inverter.Huawei_SmartloggerInverter(component_config, device_id=device_config.id, tcp_client=client) def update_components(components: Iterable[huawei_smartlogger_component_classes]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/huawei/huawei_smartlogger/inverter.py b/packages/modules/devices/huawei/huawei_smartlogger/inverter.py index 76bd2528e3..3ad1ce9f1d 100644 --- a/packages/modules/devices/huawei/huawei_smartlogger/inverter.py +++ b/packages/modules/devices/huawei/huawei_smartlogger/inverter.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -14,14 +15,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + tcp_client: modbus.ModbusTcpClient_ + + class Huawei_SmartloggerInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Huawei_SmartloggerInverterSetup, - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(Huawei_SmartloggerInverterSetup, component_config) - self.client = tcp_client + def __init__(self, component_config: Huawei_SmartloggerInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/janitza/janitza/counter.py b/packages/modules/devices/janitza/janitza/counter.py index 5ab5948452..5cb2c4f64e 100644 --- a/packages/modules/devices/janitza/janitza/counter.py +++ b/packages/modules/devices/janitza/janitza/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -13,21 +12,26 @@ from modules.devices.janitza.janitza.config import JanitzaCounterSetup +class KwargsDict(TypedDict): + device_id: int + tcp_client: modbus.ModbusTcpClient_ + modbus_id: int + + class JanitzaCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, JanitzaCounterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(JanitzaCounterSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: JanitzaCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self): + def update(self) -> None: with self.__tcp_client: power = self.__tcp_client.read_holding_registers(19026, ModbusDataType.FLOAT_32, unit=self.__modbus_id) powers = self.__tcp_client.read_holding_registers( diff --git a/packages/modules/devices/janitza/janitza/device.py b/packages/modules/devices/janitza/janitza/device.py index f3b268be94..162100f646 100644 --- a/packages/modules/devices/janitza/janitza/device.py +++ b/packages/modules/devices/janitza/janitza/device.py @@ -5,7 +5,6 @@ from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater from modules.common import modbus from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.devices.janitza.janitza import counter from modules.devices.janitza.janitza.config import Janitza, JanitzaCounterSetup @@ -13,22 +12,26 @@ def create_device(device_config: Janitza): + client = None + def create_counter_component(component_config: JanitzaCounterSetup): - return counter.JanitzaCounter(device_config.id, component_config, client, - device_config.configuration.modbus_id) + nonlocal client + return counter.JanitzaCounter(component_config, device_id=device_config.id, tcp_client=client, + modbus_id=device_config.configuration.modbus_id) def update_components(components: Iterable[counter.JanitzaCounter]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( counter=create_counter_component, ), diff --git a/packages/modules/devices/kostal/kostal_piko/counter.py b/packages/modules/devices/kostal/kostal_piko/counter.py index 4210348b23..683fbf4129 100644 --- a/packages/modules/devices/kostal/kostal_piko/counter.py +++ b/packages/modules/devices/kostal/kostal_piko/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, List, Tuple, Union +from typing import Any, List, Tuple, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -15,11 +14,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + ip_address: str + + class KostalPikoCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: Union[Dict, KostalPikoCounterSetup], ip_address: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(KostalPikoCounterSetup, component_config) - self.ip_address = ip_address + def __init__(self, component_config: KostalPikoCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.ip_address: str = self.kwargs['ip_address'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/kostal/kostal_piko/device.py b/packages/modules/devices/kostal/kostal_piko/device.py index 464dfcad02..fa5675ac6c 100644 --- a/packages/modules/devices/kostal/kostal_piko/device.py +++ b/packages/modules/devices/kostal/kostal_piko/device.py @@ -12,10 +12,13 @@ def create_device(device_config: KostalPiko): def create_counter_component(component_config: KostalPikoCounterSetup): - return counter.KostalPikoCounter(device_config.id, component_config, device_config.configuration.ip_address) + return counter.KostalPikoCounter(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address) def create_inverter_component(component_config: KostalPikoInverterSetup): - return inverter.KostalPikoInverter(device_config.id, component_config, device_config.configuration.ip_address) + return inverter.KostalPikoInverter(component_config, + ip_address=device_config.configuration.ip_address) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/kostal/kostal_piko/inverter.py b/packages/modules/devices/kostal/kostal_piko/inverter.py index e3e3427189..47ee4e8357 100644 --- a/packages/modules/devices/kostal/kostal_piko/inverter.py +++ b/packages/modules/devices/kostal/kostal_piko/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Tuple, Union +from typing import Tuple, TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,13 +10,17 @@ from modules.devices.kostal.kostal_piko.config import KostalPikoInverterSetup +class KwargsDict(TypedDict): + ip_address: str + + class KostalPikoInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, KostalPikoInverterSetup], - ip_address: str) -> None: - self.component_config = dataclass_from_dict(KostalPikoInverterSetup, component_config) - self.ip_address = ip_address + def __init__(self, component_config: KostalPikoInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: str = self.kwargs['ip_address'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) @@ -30,7 +33,7 @@ def update(self) -> Tuple[float, float]: resp = req.get_http_session().get('http://'+self.ip_address+'/api/dxs.json', params=params, timeout=3).json() power = float(resp["dxsEntries"][0]["value"]) if power > 5: - power = power*-1 + power = power * -1 exported = float(resp["dxsEntries"][1]["value"]) * 1000 diff --git a/packages/modules/devices/kostal/kostal_piko_old/device.py b/packages/modules/devices/kostal/kostal_piko_old/device.py index 5e972c48fd..8c604bffde 100644 --- a/packages/modules/devices/kostal/kostal_piko_old/device.py +++ b/packages/modules/devices/kostal/kostal_piko_old/device.py @@ -18,7 +18,7 @@ def create_device(device_config: KostalPikoOld): def create_inverter_component(component_config: KostalPikoOldInverterSetup): - return KostalPikoOldInverter(device_config.id, component_config) + return KostalPikoOldInverter(component_config, device_id=device_config.id) def update_components(components: Iterable[KostalPikoOldInverter]): response = req.get_http_session().get(device_config.configuration.url, verify=False, auth=( diff --git a/packages/modules/devices/kostal/kostal_piko_old/inverter.py b/packages/modules/devices/kostal/kostal_piko_old/inverter.py index ac61403b00..a785aa10b6 100644 --- a/packages/modules/devices/kostal/kostal_piko_old/inverter.py +++ b/packages/modules/devices/kostal/kostal_piko_old/inverter.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python3 import logging import re +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,19 +10,25 @@ from modules.common.store import get_inverter_value_store from modules.devices.kostal.kostal_piko_old.config import KostalPikoOldInverterSetup - log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class KostalPikoOldInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: KostalPikoOldInverterSetup) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(KostalPikoOldInverterSetup, component_config) + def __init__(self, component_config: KostalPikoOldInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, response) -> None: + def update(self, response: str) -> None: # power may be a string "xxx" when the inverter is offline, so we cannot match as a number # state is just for debugging currently known states: # - Aus diff --git a/packages/modules/devices/kostal/kostal_piko_old/inverter_test.py b/packages/modules/devices/kostal/kostal_piko_old/inverter_test.py index ea1dbb42b1..3a6655bea9 100644 --- a/packages/modules/devices/kostal/kostal_piko_old/inverter_test.py +++ b/packages/modules/devices/kostal/kostal_piko_old/inverter_test.py @@ -18,7 +18,8 @@ def test_parse_html(sample_file_name, expected_inverter_state, monkeypatch): sample = (Path(__file__).parent / sample_file_name).read_text() mock_inverter_value_store = Mock() monkeypatch.setattr(inverter, 'get_inverter_value_store', Mock(return_value=mock_inverter_value_store)) - inv = inverter.KostalPikoOldInverter(0, KostalPikoOldInverterSetup()) + inv = inverter.KostalPikoOldInverter(KostalPikoOldInverterSetup(), device_id=0) + inv.initialize() # execution inv.update(sample) diff --git a/packages/modules/devices/kostal/kostal_plenticore/bat.py b/packages/modules/devices/kostal/kostal_plenticore/bat.py index 2296969127..2357adae06 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/bat.py +++ b/packages/modules/devices/kostal/kostal_plenticore/bat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Any, Callable +from typing import Any, Callable, TypedDict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -13,13 +13,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class KostalPlenticoreBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: KostalPlenticoreBatSetup) -> None: + def __init__(self, component_config: KostalPlenticoreBatSetup, **kwargs: Any) -> None: self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.store = get_bat_value_store(self.component_config.id) - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="speicher") + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def read_state(self, reader: Callable[[int, ModbusDataType], Any]) -> BatState: diff --git a/packages/modules/devices/kostal/kostal_plenticore/counter.py b/packages/modules/devices/kostal/kostal_plenticore/counter.py index a3950a6fe4..ed91eb0120 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/counter.py +++ b/packages/modules/devices/kostal/kostal_plenticore/counter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from typing import Any, Callable +from typing import Any, Callable, TypedDict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -10,13 +10,19 @@ from modules.devices.kostal.kostal_plenticore.config import KostalPlenticoreCounterSetup +class KwargsDict(TypedDict): + device_id: int + + class KostalPlenticoreCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: KostalPlenticoreCounterSetup) -> None: + def __init__(self, component_config: KostalPlenticoreCounterSetup, **kwargs: Any) -> None: self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.store = get_counter_value_store(self.component_config.id) - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="bezug") + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def get_values(self, reader: Callable[[int, ModbusDataType], Any]) -> CounterState: diff --git a/packages/modules/devices/kostal/kostal_plenticore/device.py b/packages/modules/devices/kostal/kostal_plenticore/device.py index b164807d46..87a729beca 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/device.py +++ b/packages/modules/devices/kostal/kostal_plenticore/device.py @@ -48,11 +48,14 @@ def update( def create_device(device_config: KostalPlenticore): + client = None + reader = None + def create_bat_component(component_config: KostalPlenticoreBatSetup): - return KostalPlenticoreBat(device_config.id, component_config) + return KostalPlenticoreBat(component_config, device_id=device_config.id) def create_counter_component(component_config: KostalPlenticoreCounterSetup): - return KostalPlenticoreCounter(device_config.id, component_config) + return KostalPlenticoreCounter(component_config, device_id=device_config.id) def create_inverter_component(component_config: KostalPlenticoreInverterSetup): return KostalPlenticoreInverter(component_config) @@ -60,16 +63,18 @@ def create_inverter_component(component_config: KostalPlenticoreInverterSetup): def update_components( components: Iterable[Union[KostalPlenticoreBat, KostalPlenticoreCounter, KostalPlenticoreInverter]] ): - with tcp_client: + nonlocal client, reader + with client: update(components, reader) - try: - tcp_client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) - reader = _create_reader(tcp_client, device_config.configuration.modbus_id) - except Exception: - log.exception("Fehler in create_device") + def initializer(): + nonlocal client, reader + client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) + reader = _create_reader(client, device_config.configuration.modbus_id) + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, inverter=create_inverter_component), component_updater=MultiComponentUpdater(update_components), diff --git a/packages/modules/devices/kostal/kostal_plenticore/inverter.py b/packages/modules/devices/kostal/kostal_plenticore/inverter.py index 14fd66f817..ba6a7db640 100644 --- a/packages/modules/devices/kostal/kostal_plenticore/inverter.py +++ b/packages/modules/devices/kostal/kostal_plenticore/inverter.py @@ -10,9 +10,10 @@ class KostalPlenticoreInverter(AbstractInverter): - def __init__(self, - component_config: KostalPlenticoreInverterSetup) -> None: + def __init__(self, component_config: KostalPlenticoreInverterSetup) -> None: self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/kostal/kostal_sem/counter.py b/packages/modules/devices/kostal/kostal_sem/counter.py index aeb6219e7d..f14fbc0dbf 100644 --- a/packages/modules/devices/kostal/kostal_sem/counter.py +++ b/packages/modules/devices/kostal/kostal_sem/counter.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from typing import TypedDict, Any from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -9,14 +10,19 @@ from modules.devices.kostal.kostal_sem.config import KostalSemCounterSetup +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + modbus_id: int + + class KostalSemCounter(AbstractCounter): - def __init__(self, - component_config: KostalSemCounterSetup, - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: + def __init__(self, component_config: KostalSemCounterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/kostal/kostal_sem/device.py b/packages/modules/devices/kostal/kostal_sem/device.py index 46dd917f53..75416056f4 100644 --- a/packages/modules/devices/kostal/kostal_sem/device.py +++ b/packages/modules/devices/kostal/kostal_sem/device.py @@ -1,37 +1,27 @@ -import logging -from typing import List - -from helpermodules.cli import run_using_positional_cli_args from modules.common import modbus from modules.common.abstract_device import DeviceDescriptor from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, IndependentComponentUpdater from modules.devices.kostal.kostal_sem.counter import KostalSemCounter -from modules.devices.kostal.kostal_sem.config import KostalSem, KostalSemConfiguration, KostalSemCounterSetup - -log = logging.getLogger(__name__) +from modules.devices.kostal.kostal_sem.config import KostalSem, KostalSemCounterSetup def create_device(device_config: KostalSem): + client = None + def create_counter_component(component_config: KostalSemCounterSetup): - return KostalSemCounter(component_config, client, device_config.configuration.modbus_id) + nonlocal client + return KostalSemCounter(component_config, client=client, modbus_id=device_config.configuration.modbus_id) + + def initializer(): + nonlocal client + client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) - client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port) return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType(counter=create_counter_component), component_updater=IndependentComponentUpdater(lambda component: component.update()), ) -def read_legacy(address: str) -> None: - device = create_device(KostalSem(configuration=KostalSemConfiguration(ip_address=address))) - device.add_component(KostalSemCounterSetup(id=None)) - log.debug('KSEM address: ' + address) - device.update() - - -def main(argv: List[str]): - run_using_positional_cli_args(read_legacy, argv) - - device_descriptor = DeviceDescriptor(configuration_factory=KostalSem) diff --git a/packages/modules/devices/kostal/kostal_steca/device.py b/packages/modules/devices/kostal/kostal_steca/device.py index c1a489a832..dd3169ebe0 100644 --- a/packages/modules/devices/kostal/kostal_steca/device.py +++ b/packages/modules/devices/kostal/kostal_steca/device.py @@ -1,22 +1,14 @@ #!/usr/bin/env python3 -import logging -from typing import Optional, List -from helpermodules.cli import run_using_positional_cli_args from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext -from modules.common.component_state import InverterState from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, IndependentComponentUpdater -from modules.devices.kostal.kostal_steca import inverter from modules.devices.kostal.kostal_steca.config import KostalSteca, KostalStecaInverterSetup from modules.devices.kostal.kostal_steca.inverter import KostalStecaInverter -log = logging.getLogger(__name__) - def create_device(device_config: KostalSteca): def create_inverter_component(component_config: KostalStecaInverterSetup): - return KostalStecaInverter(component_config, device_config.configuration.ip_address) + return KostalStecaInverter(component_config, ip_address=device_config.configuration.ip_address) return ConfigurableDevice( device_config=device_config, @@ -27,38 +19,4 @@ def create_inverter_component(component_config: KostalStecaInverterSetup): ) -COMPONENT_TYPE_TO_MODULE = { - "inverter": inverter -} - - -def read_legacy(component_type: str, ip_address: str, variant: int, num: Optional[int]) -> None: - 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 - component_config.configuration.variant_steca = True if variant == 0 else False - inverter = KostalStecaInverter(component_config, ip_address) - - log.debug('KostalSteca IP-Adresse: ' + ip_address) - log.debug('KostalSteca Variant: ' + str(variant)) - - with SingleComponentUpdateContext(inverter.component_info): - power, exported = inverter.get_values() - if exported is None: - log.debug("PVkWh: NaN get prev. Value") - with open("/var/www/html/openWB/ramdisk/pv2kwh", "r") as f: - exported = f.read() - - inverter.store.set(InverterState(power=power, exported=exported)) - - -def main(argv: List[str]): - run_using_positional_cli_args(read_legacy, argv) - - device_descriptor = DeviceDescriptor(configuration_factory=KostalSteca) diff --git a/packages/modules/devices/kostal/kostal_steca/inverter.py b/packages/modules/devices/kostal/kostal_steca/inverter.py index 38fe3105a3..b05e3d3089 100644 --- a/packages/modules/devices/kostal/kostal_steca/inverter.py +++ b/packages/modules/devices/kostal/kostal_steca/inverter.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 import logging -from typing import Optional, Tuple -import xml.etree.ElementTree as ET import re +from typing import Any, Optional, Tuple, TypedDict +import xml.etree.ElementTree as ET from math import isnan from modules.common import req @@ -16,10 +16,17 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + ip_address: str + + class KostalStecaInverter(AbstractInverter): - def __init__(self, component_config: KostalStecaInverterSetup, ip_address: str) -> None: - self.ip_address = ip_address + def __init__(self, component_config: KostalStecaInverterSetup, **kwargs: Any) -> None: self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: str = self.kwargs['ip_address'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/kostal/kostal_steca/inverter_test.py b/packages/modules/devices/kostal/kostal_steca/inverter_test.py index 1a2553ad60..b0a7f3d0c6 100644 --- a/packages/modules/devices/kostal/kostal_steca/inverter_test.py +++ b/packages/modules/devices/kostal/kostal_steca/inverter_test.py @@ -14,7 +14,8 @@ ]) def test_get_values(measurements_file, expected_power, requests_mock): # setup - inverter = KostalStecaInverter(KostalStecaInverterSetup(), SAMPLE_IP) + inverter = KostalStecaInverter(KostalStecaInverterSetup(), ip_address=SAMPLE_IP) + inverter.initialize() with open("packages/modules/devices/kostal/kostal_steca/"+measurements_file, "r") as f: measurements_sample = f.read() diff --git a/packages/modules/devices/lg/lg/bat.py b/packages/modules/devices/lg/lg/bat.py index 82d30cf11e..0890f187c6 100644 --- a/packages/modules/devices/lg/lg/bat.py +++ b/packages/modules/devices/lg/lg/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -11,10 +10,17 @@ from modules.devices.lg.lg.config import LgBatSetup +class KwargsDict(TypedDict): + device_id: int + + class LgBat(AbstractBat): - def __init__(self, device_id: int, component_config: Union[Dict, LgBatSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(LgBatSetup, component_config) + def __init__(self, component_config: LgBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/lg/lg/counter.py b/packages/modules/devices/lg/lg/counter.py index 9cdcdc9473..fba44df091 100644 --- a/packages/modules/devices/lg/lg/counter.py +++ b/packages/modules/devices/lg/lg/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -11,10 +10,17 @@ from modules.devices.lg.lg.config import LgCounterSetup +class KwargsDict(TypedDict): + device_id: int + + class LgCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: Union[Dict, LgCounterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(LgCounterSetup, component_config) + def __init__(self, component_config: LgCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/lg/lg/device.py b/packages/modules/devices/lg/lg/device.py index 39b96c865a..4cb8d40341 100644 --- a/packages/modules/devices/lg/lg/device.py +++ b/packages/modules/devices/lg/lg/device.py @@ -39,13 +39,13 @@ def _request_data(session: Session, session_key: str, ip_address: str) -> Dict: def create_device(device_config: LG): def create_bat_component(component_config: LgBatSetup): - return LgBat(device_config.id, component_config) + return LgBat(component_config, device_id=device_config.id) def create_counter_component(component_config: LgCounterSetup): - return LgCounter(device_config.id, component_config) + return LgCounter(component_config, device_id=device_config.id) def create_inverter_component(component_config: LgInverterSetup): - return LgInverter(device_config.id, component_config) + return LgInverter(component_config, device_id=device_config.id) def update_components(components: Iterable[Union[LgBat, LgCounter, LgInverter]]): nonlocal session_key diff --git a/packages/modules/devices/lg/lg/inverter.py b/packages/modules/devices/lg/lg/inverter.py index f7c2782a00..c94b747de1 100644 --- a/packages/modules/devices/lg/lg/inverter.py +++ b/packages/modules/devices/lg/lg/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Dict, TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,10 +10,17 @@ from modules.devices.lg.lg.config import LgInverterSetup +class KwargsDict(TypedDict): + device_id: int + + class LgInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, LgInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(LgInverterSetup, component_config) + def __init__(self, component_config: LgInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/mtec/mtec/bat.py b/packages/modules/devices/mtec/mtec/bat.py index 98c2c40585..bbff74c22d 100644 --- a/packages/modules/devices/mtec/mtec/bat.py +++ b/packages/modules/devices/mtec/mtec/bat.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -13,25 +14,34 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class MTecBat(AbstractBat): - def __init__(self, device_id: int, component_config: MTecBatSetup) -> None: - self.component_config = dataclass_from_dict(MTecBatSetup, component_config) + def __init__(self, component_config: MTecBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id generation = self.component_config.configuration.generation if generation == 2: - power = client.read_holding_registers(40258, ModbusDataType.INT_32, unit=unit) * -1 + power = self.client.read_holding_registers(40258, ModbusDataType.INT_32, unit=unit) * -1 # soc unit 0.01% - soc = client.read_holding_registers(43000, ModbusDataType.UINT_16, unit=unit) / 100 + soc = self.client.read_holding_registers(43000, ModbusDataType.UINT_16, unit=unit) / 100 else: - power = client.read_holding_registers(30258, ModbusDataType.INT_32, unit=unit) * -1 - soc = client.read_holding_registers(33000, ModbusDataType.UINT_16, unit=unit) / 100 + power = self.client.read_holding_registers(30258, ModbusDataType.INT_32, unit=unit) * -1 + soc = self.client.read_holding_registers(33000, ModbusDataType.UINT_16, unit=unit) / 100 imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/packages/modules/devices/mtec/mtec/counter.py b/packages/modules/devices/mtec/mtec/counter.py index e9c6ea5a34..87049381e7 100644 --- a/packages/modules/devices/mtec/mtec/counter.py +++ b/packages/modules/devices/mtec/mtec/counter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -10,19 +11,28 @@ from modules.devices.mtec.mtec.config import MTecCounterSetup +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class MTecCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: MTecCounterSetup) -> None: - self.component_config = dataclass_from_dict(MTecCounterSetup, component_config) + def __init__(self, component_config: MTecCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") - def update(self, client: ModbusTcpClient_): + def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = client.read_holding_registers(11000, ModbusDataType.INT_32, unit=unit) - powers = client.read_holding_registers(10994, [ModbusDataType.INT_32]*3, unit=unit) + power = self.client.read_holding_registers(11000, ModbusDataType.INT_32, unit=unit) + powers = self.client.read_holding_registers(10994, [ModbusDataType.INT_32]*3, unit=unit) imported, exported = self.sim_counter.sim_count(power) counter_state = CounterState( diff --git a/packages/modules/devices/mtec/mtec/device.py b/packages/modules/devices/mtec/mtec/device.py index bab588d6eb..4611fcbc70 100644 --- a/packages/modules/devices/mtec/mtec/device.py +++ b/packages/modules/devices/mtec/mtec/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.mtec.mtec.bat import MTecBat @@ -15,27 +14,33 @@ def create_device(device_config: MTec): + client = None + def create_bat_component(component_config: MTecBatSetup): - return MTecBat(device_config.id, component_config) + nonlocal client + return MTecBat(component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: MTecCounterSetup): - return MTecCounter(device_config.id, component_config) + nonlocal client + return MTecCounter(component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: MTecInverterSetup): - return MTecInverter(device_config.id, component_config) + nonlocal client + return MTecInverter(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[Union[MTecBat, MTecCounter, MTecInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/mtec/mtec/inverter.py b/packages/modules/devices/mtec/mtec/inverter.py index 0036cb24a0..15ddd58dd8 100644 --- a/packages/modules/devices/mtec/mtec/inverter.py +++ b/packages/modules/devices/mtec/mtec/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,18 +11,27 @@ from modules.devices.mtec.mtec.config import MTecInverterSetup +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class MTecInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, MTecInverterSetup]) -> None: - self.component_config = dataclass_from_dict(MTecInverterSetup, component_config) + def __init__(self, component_config: MTecInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = client.read_holding_registers(11028, ModbusDataType.UINT_32, unit=unit) * -1 + power = self.client.read_holding_registers(11028, ModbusDataType.UINT_32, unit=unit) * -1 _, exported = self.sim_counter.sim_count(power) inverter_state = InverterState( diff --git a/packages/modules/devices/opendtu/opendtu/config.py b/packages/modules/devices/opendtu/opendtu/config.py index 794fe1dbd7..c55dc62b82 100644 --- a/packages/modules/devices/opendtu/opendtu/config.py +++ b/packages/modules/devices/opendtu/opendtu/config.py @@ -9,7 +9,7 @@ @auto_str class OpenDTUConfiguration(JsonConfiguration): def __init__(self, url: Optional[str] = None): - self.url = "http://" + url + "/api/livedata/status" + self.url = f"http://{url}/api/livedata/status" @auto_str diff --git a/packages/modules/devices/openwb/openwb_bat_kit/bat.py b/packages/modules/devices/openwb/openwb_bat_kit/bat.py index b39e8b1f4c..818b7e3653 100644 --- a/packages/modules/devices/openwb/openwb_bat_kit/bat.py +++ b/packages/modules/devices/openwb/openwb_bat_kit/bat.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from typing import Union +from typing import Union, TypedDict, Any from modules.common import modbus from modules.common.abstract_device import AbstractBat @@ -10,12 +10,19 @@ from modules.devices.openwb.openwb_flex.config import convert_to_flex_setup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class BatKit(BatKitFlex, AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[BatKitBatSetup, EvuKitBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: + def __init__(self, component_config: Union[BatKitBatSetup, EvuKitBatSetup], **kwargs: Any) -> None: self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: modbus.ModbusTcpClient_ = self.kwargs['client'] version = self.component_config.configuration.version if version == 0: id = 1 @@ -26,7 +33,10 @@ def __init__(self, else: raise ValueError("Version " + str(version) + " unbekannt.") - super().__init__(device_id, convert_to_flex_setup(self.component_config, id), tcp_client) + super().__init__(convert_to_flex_setup(self.component_config, id), + device_id=self.__device_id, + client=self.client) + super().initialize() component_descriptor = ComponentDescriptor(configuration_factory=BatKitBatSetup) diff --git a/packages/modules/devices/openwb/openwb_bat_kit/device.py b/packages/modules/devices/openwb/openwb_bat_kit/device.py index a363126239..f3e5e5c8f3 100644 --- a/packages/modules/devices/openwb/openwb_bat_kit/device.py +++ b/packages/modules/devices/openwb/openwb_bat_kit/device.py @@ -2,7 +2,6 @@ from typing import Iterable from modules.common import modbus -from modules.common.component_context import SingleComponentUpdateContext from modules.common.abstract_device import DeviceDescriptor from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater from modules.devices.openwb.openwb_bat_kit.config import BatKitSetup, BatKitBatSetup @@ -12,21 +11,25 @@ def create_device(device_config: BatKitSetup): + client = None + def create_bat_component(component_config: BatKitBatSetup): - return BatKit(device_config.id, component_config, client) + nonlocal client + return BatKit(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[BatKit]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client client = modbus.ModbusTcpClient_("192.168.193.19", 8899) - except Exception: - log.exception("Fehler in create_device") + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, ), diff --git a/packages/modules/devices/openwb/openwb_evu_kit/counter.py b/packages/modules/devices/openwb/openwb_evu_kit/counter.py index 0fd755c71b..2cb3cfdbd3 100644 --- a/packages/modules/devices/openwb/openwb_evu_kit/counter.py +++ b/packages/modules/devices/openwb/openwb_evu_kit/counter.py @@ -1,7 +1,6 @@ -# !/usr/bin/env python3 -from typing import Dict, Union +#!/usr/bin/env python3 +from typing import Dict, Union, TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_type import ComponentDescriptor @@ -10,12 +9,21 @@ from modules.devices.openwb.openwb_flex.config import convert_to_flex_setup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class EvuKit(EvuKitFlex, AbstractCounter): def __init__(self, - device_id: int, - component_config: Union[Dict, EvuKitCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(EvuKitCounterSetup, component_config) + component_config: Union[Dict, EvuKitCounterSetup], + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] version = self.component_config.configuration.version if version == 0: id = 5 @@ -28,7 +36,10 @@ def __init__(self, else: raise ValueError("Version " + str(version) + " unbekannt.") - super().__init__(device_id, convert_to_flex_setup(self.component_config, id), tcp_client) + super().__init__(convert_to_flex_setup(self.component_config, id), + device_id=self.__device_id, + client=self.__tcp_client) + super().initialize() component_descriptor = ComponentDescriptor(configuration_factory=EvuKitCounterSetup) diff --git a/packages/modules/devices/openwb/openwb_evu_kit/device.py b/packages/modules/devices/openwb/openwb_evu_kit/device.py index d7661b08b5..f3aae3d429 100644 --- a/packages/modules/devices/openwb/openwb_evu_kit/device.py +++ b/packages/modules/devices/openwb/openwb_evu_kit/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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.openwb.openwb_bat_kit.bat import BatKit from modules.devices.openwb.openwb_evu_kit.counter import EvuKit @@ -16,28 +15,34 @@ def create_device(device_config: EvuKitSetup): + client = None + def create_bat_component(component_config: EvuKitBatSetup): - return BatKit(device_config.id, component_config, client) + nonlocal client + return BatKit(component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: EvuKitCounterSetup): - return EvuKit(device_config.id, component_config, client) + nonlocal client + return EvuKit(component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: EvuKitInverterSetup): - return PvKit(device_config.id, component_config, client) + nonlocal client + return PvKit(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[Union[BatKit, EvuKit, PvKit]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() - time.sleep(0.2) + component.update() + time.sleep(0.2) - try: + def initializer(): + nonlocal client client = modbus.ModbusTcpClient_("192.168.193.15", 8899) - except Exception: - log.exception("Fehler in create_device") + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/openwb/openwb_flex/bat.py b/packages/modules/devices/openwb/openwb_flex/bat.py index 1861eb24f6..78d7dc220b 100644 --- a/packages/modules/devices/openwb/openwb_flex/bat.py +++ b/packages/modules/devices/openwb/openwb_flex/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -16,18 +15,21 @@ from modules.devices.openwb.openwb_flex.versions import kit_bat_version_factory +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class BatKitFlex(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, BatKitFlexSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(BatKitFlexSetup, component_config) - factory = kit_bat_version_factory( - self.component_config.configuration.version) - self.__client = factory(self.component_config.configuration.id, - tcp_client) - self.__tcp_client = tcp_client + def __init__(self, component_config: BatKitFlexSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + factory = kit_bat_version_factory(self.component_config.configuration.version) + self.__client = factory(self.component_config.configuration.id, self.__tcp_client) self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/openwb/openwb_flex/consumption_counter.py b/packages/modules/devices/openwb/openwb_flex/consumption_counter.py index 21dda11082..aa6f0eb748 100644 --- a/packages/modules/devices/openwb/openwb_flex/consumption_counter.py +++ b/packages/modules/devices/openwb/openwb_flex/consumption_counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -13,22 +12,26 @@ from modules.devices.openwb.openwb_flex.versions import consumption_counter_factory +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class ConsumptionCounterFlex(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, ConsumptionCounterFlexSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(ConsumptionCounterFlexSetup, component_config) - factory = consumption_counter_factory( - self.component_config.configuration.type) - self.__client = factory(self.component_config.configuration.id, tcp_client) - self.__tcp_client = tcp_client + def __init__(self, component_config: ConsumptionCounterFlexSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + factory = consumption_counter_factory(self.component_config.configuration.type) + self.__client = factory(self.component_config.configuration.id, self.__tcp_client) self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self): + def update(self) -> None: with self.__tcp_client: voltages = self.__client.get_voltages() powers, power = self.__client.get_power() diff --git a/packages/modules/devices/openwb/openwb_flex/counter.py b/packages/modules/devices/openwb/openwb_flex/counter.py index b0ecc9301e..7376ff0b25 100644 --- a/packages/modules/devices/openwb/openwb_flex/counter.py +++ b/packages/modules/devices/openwb/openwb_flex/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -16,18 +15,21 @@ from modules.devices.openwb.openwb_flex.versions import kit_counter_version_factory +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class EvuKitFlex(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, EvuKitFlexSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(EvuKitFlexSetup, component_config) - factory = kit_counter_version_factory( - self.component_config.configuration.version) - self.__client = factory(self.component_config.configuration.id, - tcp_client) - self.__tcp_client = tcp_client + def __init__(self, component_config: EvuKitFlexSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + factory = kit_counter_version_factory(self.component_config.configuration.version) + self.__client = factory(self.component_config.configuration.id, self.__tcp_client) self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/openwb/openwb_flex/device.py b/packages/modules/devices/openwb/openwb_flex/device.py index d74764b4d0..2733df5c77 100644 --- a/packages/modules/devices/openwb/openwb_flex/device.py +++ b/packages/modules/devices/openwb/openwb_flex/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.openwb.openwb_flex.bat import BatKitFlex @@ -20,29 +19,36 @@ def create_device(device_config: Flex): + client = None + def create_bat_component(component_config: BatKitFlexSetup): - return BatKitFlex(device_config.id, component_config, client) + nonlocal client + return BatKitFlex(component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: EvuKitFlexSetup): - return EvuKitFlex(device_config.id, component_config, client) + nonlocal client + return EvuKitFlex(component_config, device_id=device_config.id, client=client) def create_consumption_counter_component(component_config: ConsumptionCounterFlexSetup): - return ConsumptionCounterFlex(device_config.id, component_config, client) + nonlocal client + return ConsumptionCounterFlex(component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: PvKitFlexSetup): - return PvKitFlex(device_config.id, component_config, client) + nonlocal client + return PvKitFlex(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[Union[BatKitFlex, ConsumptionCounterFlex, EvuKitFlex, PvKitFlex]]): for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() - try: + component.update() + + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, consumption_counter=create_consumption_counter_component, diff --git a/packages/modules/devices/openwb/openwb_flex/inverter.py b/packages/modules/devices/openwb/openwb_flex/inverter.py index b1b68a47a7..0d72c2a5bc 100644 --- a/packages/modules/devices/openwb/openwb_flex/inverter.py +++ b/packages/modules/devices/openwb/openwb_flex/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -15,17 +14,21 @@ from modules.devices.openwb.openwb_flex.versions import kit_inverter_version_factory +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class PvKitFlex(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, PvKitFlexSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(PvKitFlexSetup, component_config) - factory = kit_inverter_version_factory( - self.component_config.configuration.version) - self.__client = factory(self.component_config.configuration.id, tcp_client) - self.__tcp_client = tcp_client + def __init__(self, component_config: PvKitFlexSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + factory = kit_inverter_version_factory(self.component_config.configuration.version) + self.__client = factory(self.component_config.configuration.id, self.__tcp_client) self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.simulation = {} self.store = get_inverter_value_store(self.component_config.id) diff --git a/packages/modules/devices/openwb/openwb_pv_kit/device.py b/packages/modules/devices/openwb/openwb_pv_kit/device.py index e2704eeee2..c410efd6b9 100644 --- a/packages/modules/devices/openwb/openwb_pv_kit/device.py +++ b/packages/modules/devices/openwb/openwb_pv_kit/device.py @@ -3,7 +3,6 @@ from modules.common import modbus 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.openwb.openwb_pv_kit import inverter from modules.devices.openwb.openwb_pv_kit.config import PvKitSetup, PvKitInverterSetup @@ -12,21 +11,25 @@ def create_device(device_config: PvKitSetup): + client = None + def create_inverter_component(component_config: PvKitInverterSetup): - return inverter.PvKit(device_config.id, component_config, client) + nonlocal client + return inverter.PvKit(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[inverter.PvKit]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client client = modbus.ModbusTcpClient_("192.168.193.13", 8899) - except Exception: - log.exception("Fehler in create_device") + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( inverter=create_inverter_component, ), diff --git a/packages/modules/devices/openwb/openwb_pv_kit/inverter.py b/packages/modules/devices/openwb/openwb_pv_kit/inverter.py index 4659b68bc5..5de66dcd22 100644 --- a/packages/modules/devices/openwb/openwb_pv_kit/inverter.py +++ b/packages/modules/devices/openwb/openwb_pv_kit/inverter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from typing import Union +from typing import Union, TypedDict, Any from modules.common import modbus from modules.common.abstract_device import AbstractInverter @@ -10,12 +10,21 @@ from modules.devices.openwb.openwb_pv_kit.config import PvKitInverterSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class PvKit(PvKitFlex, AbstractInverter): def __init__(self, - device_id: int, component_config: Union[EvuKitInverterSetup, PvKitInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: + **kwargs: Any) -> None: self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] version = self.component_config.configuration.version if version == 0 or version == 1: id = 8 @@ -24,7 +33,10 @@ def __init__(self, else: raise ValueError("Version "+str(version) + " unbekannt.") - super().__init__(device_id, convert_to_flex_setup(self.component_config, id), tcp_client) + super().__init__(convert_to_flex_setup(self.component_config, id), + device_id=self.__device_id, + client=self.__tcp_client) + super().initialize() component_descriptor = ComponentDescriptor(configuration_factory=PvKitInverterSetup) diff --git a/packages/modules/devices/powerdog/powerdog/counter.py b/packages/modules/devices/powerdog/powerdog/counter.py index ca83073f5d..9aa98760c6 100644 --- a/packages/modules/devices/powerdog/powerdog/counter.py +++ b/packages/modules/devices/powerdog/powerdog/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -16,21 +15,26 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + modbus_id: int + + class PowerdogCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, PowerdogCounterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(PowerdogCounterSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: PowerdogCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, inverter_power: float): + def update(self, inverter_power: float) -> None: with self.__tcp_client: if self.component_config.configuration.position_evu: export_power = self.__tcp_client.read_input_registers( diff --git a/packages/modules/devices/powerdog/powerdog/device.py b/packages/modules/devices/powerdog/powerdog/device.py index 697320a827..901b8f0d2e 100644 --- a/packages/modules/devices/powerdog/powerdog/device.py +++ b/packages/modules/devices/powerdog/powerdog/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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.powerdog.powerdog.config import Powerdog, PowerdogCounterSetup, PowerdogInverterSetup from modules.devices.powerdog.powerdog.counter import PowerdogCounter @@ -14,19 +13,29 @@ def create_device(device_config: Powerdog): + client = None + def create_counter_component(component_config: PowerdogCounterSetup): - return PowerdogCounter(device_config.id, component_config, client, device_config.configuration.modbus_id) + nonlocal client + return PowerdogCounter(component_config, + device_id=device_config.id, + client=client, + modbus_id=device_config.configuration.modbus_id) def create_inverter_component(component_config: PowerdogInverterSetup): - return PowerdogInverter(device_config.id, component_config, client, device_config.configuration.modbus_id) + nonlocal client + return PowerdogInverter(component_config, + device_id=device_config.id, + client=client, + modbus_id=device_config.configuration.modbus_id) def update_components(components: Iterable[Union[PowerdogCounter, PowerdogInverter]]): + nonlocal client with client: if len(components) == 1: for component in components: if isinstance(component, PowerdogInverter): - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() else: raise Exception( "Wenn ein EVU-Zähler konfiguriert wurde, muss immer auch ein WR konfiguriert sein.") @@ -47,12 +56,13 @@ def update_components(components: Iterable[Union[PowerdogCounter, PowerdogInvert + "wurden." ) - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( counter=create_counter_component, inverter=create_inverter_component, diff --git a/packages/modules/devices/powerdog/powerdog/inverter.py b/packages/modules/devices/powerdog/powerdog/inverter.py index 93dfb3d96b..83abb5faeb 100644 --- a/packages/modules/devices/powerdog/powerdog/inverter.py +++ b/packages/modules/devices/powerdog/powerdog/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -16,16 +15,21 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + modbus_id: int + + class PowerdogInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, PowerdogInverterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(PowerdogInverterSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: PowerdogInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/powerfox/powerfox/counter.py b/packages/modules/devices/powerfox/powerfox/counter.py index 33edb6ec65..ee572767d2 100644 --- a/packages/modules/devices/powerfox/powerfox/counter.py +++ b/packages/modules/devices/powerfox/powerfox/counter.py @@ -1,10 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union from requests import Session - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -16,14 +13,15 @@ class PowerfoxCounter(AbstractCounter): - def __init__(self, - component_config: Union[Dict, PowerfoxCounterSetup]) -> None: - self.component_config = dataclass_from_dict(PowerfoxCounterSetup, component_config) + def __init__(self, component_config: PowerfoxCounterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self, session: Session) -> None: - response = session.get('https://backend.powerfox.energy/api/2.0/my/'+self.component_config.configuration.id + + response = session.get('https://backend.powerfox.energy/api/2.0/my/' + self.component_config.configuration.id + '/current', timeout=3).json() self.store.set(CounterState( diff --git a/packages/modules/devices/powerfox/powerfox/device.py b/packages/modules/devices/powerfox/powerfox/device.py index 472b00e5d2..216e992c37 100644 --- a/packages/modules/devices/powerfox/powerfox/device.py +++ b/packages/modules/devices/powerfox/powerfox/device.py @@ -15,16 +15,22 @@ def create_device(device_config: Powerfox): + session = None + def create_counter_component(component_config: PowerfoxCounterSetup): return PowerfoxCounter(component_config) def create_inverter_component(component_config: PowerfoxInverterSetup): return PowerfoxInverter(component_config) - session = get_http_session() - session.auth = (device_config.configuration.user, device_config.configuration.password) + def initializer(): + nonlocal session + session = get_http_session() + session.auth = (device_config.configuration.user, device_config.configuration.password) + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( counter=create_counter_component, inverter=create_inverter_component, diff --git a/packages/modules/devices/powerfox/powerfox/inverter.py b/packages/modules/devices/powerfox/powerfox/inverter.py index 808f27e3fa..646daf97b4 100644 --- a/packages/modules/devices/powerfox/powerfox/inverter.py +++ b/packages/modules/devices/powerfox/powerfox/inverter.py @@ -1,10 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union from requests import Session - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -16,14 +13,15 @@ class PowerfoxInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, PowerfoxInverterSetup]) -> None: - self.component_config = dataclass_from_dict(PowerfoxInverterSetup, component_config) + def __init__(self, component_config: PowerfoxInverterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self, session: Session) -> None: - response = session.get('https://backend.powerfox.energy/api/2.0/my/'+self.component_config.configuration.id + + response = session.get('https://backend.powerfox.energy/api/2.0/my/' + self.component_config.configuration.id + '/current', timeout=3).json() self.store.set(InverterState( diff --git a/packages/modules/devices/qcells/qcells/bat.py b/packages/modules/devices/qcells/qcells/bat.py index ebef8b12d0..f381a7894f 100644 --- a/packages/modules/devices/qcells/qcells/bat.py +++ b/packages/modules/devices/qcells/qcells/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -11,21 +10,28 @@ from modules.devices.qcells.qcells.config import QCellsBatSetup +class KwargsDict(TypedDict): + modbus_id: int + client: ModbusTcpClient_ + + class QCellsBat(AbstractBat): - def __init__(self, - component_config: Union[Dict, QCellsBatSetup], - modbus_id: int) -> None: - self.__modbus_id = modbus_id - self.component_config = dataclass_from_dict(QCellsBatSetup, component_config) + def __init__(self, component_config: QCellsBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: - power = client.read_input_registers(0x0016, ModbusDataType.INT_16, unit=self.__modbus_id) - soc = client.read_input_registers(0x001C, ModbusDataType.UINT_16, unit=self.__modbus_id) - imported = client.read_input_registers( + def update(self) -> None: + power = self.client.read_input_registers(0x0016, ModbusDataType.INT_16, unit=self.__modbus_id) + soc = self.client.read_input_registers(0x001C, ModbusDataType.UINT_16, unit=self.__modbus_id) + imported = self.client.read_input_registers( 0x0021, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 - exported = client.read_input_registers( + exported = self.client.read_input_registers( 0x001D, ModbusDataType.UINT_16, unit=self.__modbus_id) * 100 bat_state = BatState( diff --git a/packages/modules/devices/qcells/qcells/counter.py b/packages/modules/devices/qcells/qcells/counter.py index 9af9320be6..e05c996491 100644 --- a/packages/modules/devices/qcells/qcells/counter.py +++ b/packages/modules/devices/qcells/qcells/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -12,55 +11,49 @@ from modules.devices.qcells.qcells.config import QCellsCounterSetup +class KwargsDict(TypedDict): + modbus_id: int + client: ModbusTcpClient_ + + class QCellsCounter(AbstractCounter): - def __init__(self, - component_config: Union[Dict, QCellsCounterSetup], - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(QCellsCounterSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: QCellsCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_): - power = client.read_input_registers(0x0046, ModbusDataType.INT_32, wordorder=Endian.Little, - unit=self.__modbus_id) * -1 - frequency = client.read_input_registers( + def update(self) -> None: + power = self.client.read_input_registers(0x0046, ModbusDataType.INT_32, wordorder=Endian.Little, + unit=self.__modbus_id) * -1 + frequency = self.client.read_input_registers( 0x0007, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 try: - powers = [-value for value in client.read_input_registers( + powers = [-value for value in self.client.read_input_registers( 0x0082, [ModbusDataType.INT_32] * 3, wordorder=Endian.Little, unit=self.__modbus_id )] except Exception: powers = None try: - voltages = [client.read_input_registers( + voltages = [self.client.read_input_registers( 0x006A, ModbusDataType.UINT_16, unit=self.__modbus_id - ) / 10, client.read_input_registers( + ) / 10, self.client.read_input_registers( + 0x006C, ModbusDataType.UINT_16, unit=self.__modbus_id + ) / 10, self.client.read_input_registers( 0x006E, ModbusDataType.UINT_16, unit=self.__modbus_id - ) / 10, client.read_input_registers( - 0x0072, ModbusDataType.UINT_16, unit=self.__modbus_id ) / 10] - if voltages[0] < 1: - voltages[0] = 230 - if voltages[1] < 1: - voltages[1] = 230 - if voltages[2] < 1: - voltages[2] = 230 except Exception: - voltages = [230, 230, 230] - exported, imported = [value * 10 - for value in client.read_input_registers( - 0x0048, [ModbusDataType.UINT_32] * 2, - wordorder=Endian.Little, unit=self.__modbus_id - )] + voltages = None counter_state = CounterState( - imported=imported, - exported=exported, power=power, - powers=powers, frequency=frequency, - voltages=voltages, + powers=powers, + voltages=voltages ) self.store.set(counter_state) diff --git a/packages/modules/devices/qcells/qcells/device.py b/packages/modules/devices/qcells/qcells/device.py index f3228596ed..da11f67057 100644 --- a/packages/modules/devices/qcells/qcells/device.py +++ b/packages/modules/devices/qcells/qcells/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.qcells.qcells.bat import QCellsBat @@ -15,31 +14,33 @@ def create_device(device_config: QCells): + client = None + def create_bat_component(component_config: QCellsBatSetup): - return QCellsBat(component_config, - device_config.configuration.modbus_id) + nonlocal client + return QCellsBat(component_config, modbus_id=device_config.configuration.modbus_id, client=client) def create_counter_component(component_config: QCellsCounterSetup): - return QCellsCounter(component_config, - device_config.configuration.modbus_id) + nonlocal client + return QCellsCounter(component_config, modbus_id=device_config.configuration.modbus_id, client=client) def create_inverter_component(component_config: QCellsInverterSetup): - return QCellsInverter(component_config, - device_config.configuration.modbus_id) + nonlocal client + return QCellsInverter(component_config, modbus_id=device_config.configuration.modbus_id, client=client) def update_components(components: Iterable[Union[QCellsBat, QCellsCounter, QCellsInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/qcells/qcells/inverter.py b/packages/modules/devices/qcells/qcells/inverter.py index 0d2d5dab27..4d0a638145 100644 --- a/packages/modules/devices/qcells/qcells/inverter.py +++ b/packages/modules/devices/qcells/qcells/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,25 +11,32 @@ from modules.devices.qcells.qcells.config import QCellsInverterSetup +class KwargsDict(TypedDict): + modbus_id: int + client: ModbusTcpClient_ + + class QCellsInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, QCellsInverterSetup], - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(QCellsInverterSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: QCellsInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['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, client: ModbusTcpClient_) -> None: - power_string1 = (client.read_input_registers( + def update(self) -> None: + power_string1 = (self.client.read_input_registers( 0x0003, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) * \ - (client.read_input_registers(0x0005, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) - power_string2 = (client.read_input_registers( + (self.client.read_input_registers(0x0005, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + power_string2 = (self.client.read_input_registers( 0x0004, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) * \ - (client.read_input_registers(0x0006, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) + (self.client.read_input_registers(0x0006, ModbusDataType.INT_16, unit=self.__modbus_id) / 10) power = (power_string1 + power_string2) * -1 - exported = client.read_input_registers(0x0094, ModbusDataType.UINT_32, wordorder=Endian.Little, - unit=self.__modbus_id) * 100 + exported = self.client.read_input_registers(0x0094, ModbusDataType.UINT_32, wordorder=Endian.Little, + unit=self.__modbus_id) * 100 inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/rct/rct/bat.py b/packages/modules/devices/rct/rct/bat.py index f0f7673471..5a5fd7643b 100644 --- a/packages/modules/devices/rct/rct/bat.py +++ b/packages/modules/devices/rct/rct/bat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict + from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -14,7 +14,9 @@ class RctBat(AbstractBat): def __init__(self, component_config: RctBatSetup) -> None: - self.component_config = dataclass_from_dict(RctBatSetup, component_config) + self.component_config = component_config + + 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)) diff --git a/packages/modules/devices/rct/rct/counter.py b/packages/modules/devices/rct/rct/counter.py index 7060ee900f..9f75bafbf4 100644 --- a/packages/modules/devices/rct/rct/counter.py +++ b/packages/modules/devices/rct/rct/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict + from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -14,7 +14,9 @@ class RctCounter(AbstractCounter): def __init__(self, component_config: RctCounterSetup) -> None: - self.component_config = dataclass_from_dict(RctCounterSetup, component_config) + self.component_config = component_config + + def initialize(self) -> None: self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/rct/rct/inverter.py b/packages/modules/devices/rct/rct/inverter.py index 8255a95295..026fa3de46 100644 --- a/packages/modules/devices/rct/rct/inverter.py +++ b/packages/modules/devices/rct/rct/inverter.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,7 +10,9 @@ class RctInverter(AbstractInverter): def __init__(self, component_config: RctInverterSetup) -> None: - self.component_config = dataclass_from_dict(RctInverterSetup, component_config) + self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/saxpower/saxpower/bat.py b/packages/modules/devices/saxpower/saxpower/bat.py index 9cfc481163..887fe74c84 100644 --- a/packages/modules/devices/saxpower/saxpower/bat.py +++ b/packages/modules/devices/saxpower/saxpower/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,16 +12,21 @@ from modules.devices.saxpower.saxpower.config import SaxpowerBatSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + modbus_id: int + + class SaxpowerBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, SaxpowerBatSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SaxpowerBatSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: SaxpowerBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/saxpower/saxpower/device.py b/packages/modules/devices/saxpower/saxpower/device.py index 5078f3c887..55305dff36 100644 --- a/packages/modules/devices/saxpower/saxpower/device.py +++ b/packages/modules/devices/saxpower/saxpower/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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.saxpower.saxpower.bat import SaxpowerBat from modules.devices.saxpower.saxpower.config import Saxpower, SaxpowerBatSetup @@ -13,21 +12,28 @@ def create_device(device_config: Saxpower): + client = None + def create_bat_component(component_config: SaxpowerBatSetup): - return SaxpowerBat(device_config.id, component_config, client, device_config.configuration.modbus_id) + nonlocal client + return SaxpowerBat(component_config, + device_id=device_config.id, + client=client, + modbus_id=device_config.configuration.modbus_id) def update_components(components: Iterable[SaxpowerBat]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, ), diff --git a/packages/modules/devices/shelly/shelly/bat.py b/packages/modules/devices/shelly/shelly/bat.py index 7d4fdc91ee..994f7a7208 100644 --- a/packages/modules/devices/shelly/shelly/bat.py +++ b/packages/modules/devices/shelly/shelly/bat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Optional +from typing import Optional, TypedDict, Any from modules.common import req from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,21 +13,26 @@ log = logging.getLogger(__name__) -class ShellyBat(AbstractBat): +class KwargsDict(TypedDict): + device_id: int + ip_address: str + factor: int + generation: Optional[int] + - def __init__(self, - device_id: int, - component_config: ShellyBatSetup, - address: str, - factor: int, - generation: Optional[int]) -> None: +class ShellyBat(AbstractBat): + def __init__(self, component_config: ShellyBatSetup, **kwargs: Any) -> None: self.component_config = component_config - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="speicher") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.address: str = self.kwargs['ip_address'] + self.factor: int = self.kwargs['factor'] + self.generation: Optional[int] = self.kwargs['generation'] + self.sim_counter = SimCounter(self.__device_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.address = address - self.factor = factor - self.generation = generation def total_power_from_shelly(self) -> int: total = 0 diff --git a/packages/modules/devices/shelly/shelly/counter.py b/packages/modules/devices/shelly/shelly/counter.py index 6bbb8900a8..995bda7df0 100644 --- a/packages/modules/devices/shelly/shelly/counter.py +++ b/packages/modules/devices/shelly/shelly/counter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Optional +from typing import Optional, TypedDict, Any from modules.common import req from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -13,21 +13,26 @@ log = logging.getLogger(__name__) -class ShellyCounter(AbstractCounter): +class KwargsDict(TypedDict): + device_id: int + ip_address: str + factor: int + generation: Optional[int] + - def __init__(self, - device_id: int, - component_config: ShellyCounterSetup, - address: str, - factor: int, - generation: Optional[int]) -> None: +class ShellyCounter(AbstractCounter): + def __init__(self, component_config: ShellyCounterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="bezug") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.address: str = self.kwargs['ip_address'] + self.factor: int = self.kwargs['factor'] + self.generation: Optional[int] = self.kwargs['generation'] + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.address = address - self.factor = factor - self.generation = generation def update(self) -> None: power = 0 diff --git a/packages/modules/devices/shelly/shelly/device.py b/packages/modules/devices/shelly/shelly/device.py index 6b207bddaf..3b06de3dfd 100644 --- a/packages/modules/devices/shelly/shelly/device.py +++ b/packages/modules/devices/shelly/shelly/device.py @@ -30,19 +30,25 @@ def get_device_generation(address: str) -> int: def create_device(device_config: Shelly) -> ConfigurableDevice: def create_counter_component(component_config: ShellyCounterSetup) -> ShellyCounter: - return ShellyCounter(device_config.id, component_config, device_config.configuration.ip_address, - device_config.configuration.factor, - get_device_generation(device_config.configuration.ip_address)) + return ShellyCounter(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address, + factor=device_config.configuration.factor, + generation=get_device_generation(device_config.configuration.ip_address)) def create_inverter_component(component_config: ShellyInverterSetup) -> ShellyInverter: - return ShellyInverter(device_config.id, component_config, device_config.configuration.ip_address, - device_config.configuration.factor, - get_device_generation(device_config.configuration.ip_address)) + return ShellyInverter(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address, + factor=device_config.configuration.factor, + generation=get_device_generation(device_config.configuration.ip_address)) def create_bat_component(component_config: ShellyBatSetup) -> ShellyBat: - return ShellyBat(device_config.id, component_config, device_config.configuration.ip_address, - device_config.configuration.factor, - get_device_generation(device_config.configuration.ip_address)) + return ShellyBat(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address, + factor=device_config.configuration.factor, + generation=get_device_generation(device_config.configuration.ip_address)) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/shelly/shelly/inverter.py b/packages/modules/devices/shelly/shelly/inverter.py index 81d67e4aad..89ecef8611 100644 --- a/packages/modules/devices/shelly/shelly/inverter.py +++ b/packages/modules/devices/shelly/shelly/inverter.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Optional +from typing import Optional, TypedDict, Any from modules.common import req from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -13,21 +13,26 @@ log = logging.getLogger(__name__) -class ShellyInverter(AbstractInverter): +class KwargsDict(TypedDict): + device_id: int + address: str + factor: int + generation: Optional[int] + - def __init__(self, - device_id: int, - component_config: ShellyInverterSetup, - address: str, - factor: int, - generation: Optional[int]) -> None: +class ShellyInverter(AbstractInverter): + def __init__(self, component_config: ShellyInverterSetup, **kwargs: Any) -> None: self.component_config = component_config - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="pv") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.address: str = self.kwargs['address'] + self.factor: int = self.kwargs['factor'] + self.generation: Optional[int] = self.kwargs['generation'] + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.address = address - self.factor = factor - self.generation = generation def total_power_from_shelly(self) -> int: total = 0 diff --git a/packages/modules/devices/shelly/shelly/shelly_test.py b/packages/modules/devices/shelly/shelly/shelly_test.py index 8a07f69809..7825623a5f 100644 --- a/packages/modules/devices/shelly/shelly/shelly_test.py +++ b/packages/modules/devices/shelly/shelly/shelly_test.py @@ -45,7 +45,8 @@ def test_counter_shelly_minipm_g3(monkeypatch, requests_mock: requests_mock.mock requests_mock.get(f"http://{SAMPLE_IP}/rpc/Shelly.GetStatus", json=DATA_MINPM_G3) mock_counter_value_store = Mock() monkeypatch.setattr(counter, "get_counter_value_store", Mock(return_value=mock_counter_value_store)) - c = counter.ShellyCounter(0, ShellyCounterSetup(), SAMPLE_IP, 1, 2) + c = counter.ShellyCounter(ShellyCounterSetup(), device_id=0, ip_address=SAMPLE_IP, factor=1, generation=2) + c.initialize() # execution c.update() diff --git a/packages/modules/devices/siemens/siemens/bat.py b/packages/modules/devices/siemens/siemens/bat.py index ce974fbdde..594856e24a 100644 --- a/packages/modules/devices/siemens/siemens/bat.py +++ b/packages/modules/devices/siemens/siemens/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,16 +12,21 @@ from modules.devices.siemens.siemens.config import SiemensBatSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + modbus_id: int + + class SiemensBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, SiemensBatSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SiemensBatSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: SiemensBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/siemens/siemens/counter.py b/packages/modules/devices/siemens/siemens/counter.py index 00e873c4b8..499692cd44 100644 --- a/packages/modules/devices/siemens/siemens/counter.py +++ b/packages/modules/devices/siemens/siemens/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -13,22 +12,26 @@ from modules.devices.siemens.siemens.config import SiemensCounterSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + modbus_id: int + + class SiemensCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, SiemensCounterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SiemensCounterSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: SiemensCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self): - + def update(self) -> None: with self.__tcp_client: power = self.__tcp_client.read_holding_registers(14, ModbusDataType.INT_32, unit=self.__modbus_id) diff --git a/packages/modules/devices/siemens/siemens/device.py b/packages/modules/devices/siemens/siemens/device.py index 9689db1312..7463172fb4 100644 --- a/packages/modules/devices/siemens/siemens/device.py +++ b/packages/modules/devices/siemens/siemens/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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.siemens.siemens.bat import SiemensBat from modules.devices.siemens.siemens.config import Siemens, SiemensBatSetup, SiemensCounterSetup, SiemensInverterSetup @@ -18,27 +17,42 @@ def create_device(device_config: Siemens): + client = None + def create_bat_component(component_config: SiemensBatSetup): - return SiemensBat(device_config.id, component_config, client, device_config.configuration.modbus_id) + nonlocal client + return SiemensBat(component_config, + device_id=device_config.id, + client=client, + modbus_id=device_config.configuration.modbus_id) def create_counter_component(component_config: SiemensCounterSetup): - return SiemensCounter(device_config.id, component_config, client, device_config.configuration.modbus_id) + nonlocal client + return SiemensCounter(component_config, + device_id=device_config.id, + client=client, + modbus_id=device_config.configuration.modbus_id) def create_inverter_component(component_config: SiemensInverterSetup): - return SiemensInverter(device_config.id, component_config, client, device_config.configuration.modbus_id) + nonlocal client + return SiemensInverter(component_config, + device_id=device_config.id, + client=client, + modbus_id=device_config.configuration.modbus_id) def update_components(components: Iterable[siemens_component_classes]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/siemens/siemens/inverter.py b/packages/modules/devices/siemens/siemens/inverter.py index 93307209bb..de765d5ccd 100644 --- a/packages/modules/devices/siemens/siemens/inverter.py +++ b/packages/modules/devices/siemens/siemens/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -13,16 +12,21 @@ from modules.devices.siemens.siemens.config import SiemensInverterSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + modbus_id: int + + class SiemensInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, SiemensInverterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SiemensInverterSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: SiemensInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/siemens/siemens_sentron/counter.py b/packages/modules/devices/siemens/siemens_sentron/counter.py index 05bca774ed..3d74f9d5f1 100644 --- a/packages/modules/devices/siemens/siemens_sentron/counter.py +++ b/packages/modules/devices/siemens/siemens_sentron/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -12,18 +11,23 @@ from modules.devices.siemens.siemens_sentron.config import SiemensSentronCounterSetup +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + modbus_id: int + + class SiemensSentronCounter(AbstractCounter): - def __init__(self, - component_config: Union[Dict, SiemensSentronCounterSetup], - tcp_client: modbus.ModbusTcpClient_, - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(SiemensSentronCounterSetup, component_config) - self.__tcp_client = tcp_client - self.__modbus_id = modbus_id + def __init__(self, component_config: SiemensSentronCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self): + def update(self) -> None: with self.__tcp_client: imported = self.__tcp_client.read_holding_registers(801, ModbusDataType.FLOAT_64, unit=self.__modbus_id) exported = self.__tcp_client.read_holding_registers(809, ModbusDataType.FLOAT_64, unit=self.__modbus_id) diff --git a/packages/modules/devices/siemens/siemens_sentron/device.py b/packages/modules/devices/siemens/siemens_sentron/device.py index 4347f62ab4..5b57b33916 100644 --- a/packages/modules/devices/siemens/siemens_sentron/device.py +++ b/packages/modules/devices/siemens/siemens_sentron/device.py @@ -3,7 +3,6 @@ from typing import Iterable 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.common.modbus import ModbusTcpClient_ from modules.devices.siemens.siemens_sentron.config import SiemensSentron, SiemensSentronCounterSetup @@ -13,21 +12,25 @@ def create_device(device_config: SiemensSentron): + client = None + def create_counter_component(component_config: SiemensSentronCounterSetup): - return SiemensSentronCounter(component_config, client, device_config.configuration.modbus_id) + nonlocal client + return SiemensSentronCounter(component_config, client=client, modbus_id=device_config.configuration.modbus_id) def update_components(components: Iterable[SiemensSentronCounter]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( counter=create_counter_component, ), diff --git a/packages/modules/devices/sigenergy/sigenergy/bat.py b/packages/modules/devices/sigenergy/sigenergy/bat.py index d6ac7662ea..55adf95bd1 100644 --- a/packages/modules/devices/sigenergy/sigenergy/bat.py +++ b/packages/modules/devices/sigenergy/sigenergy/bat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -13,20 +13,29 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class SigenergyBat(AbstractBat): - def __init__(self, device_id: int, component_config: SigenergyBatSetup) -> None: - self.component_config = dataclass_from_dict(SigenergyBatSetup, component_config) + def __init__(self, component_config: SigenergyBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = client.read_holding_registers(30037, ModbusDataType.INT_32, unit=unit) + power = self.client.read_holding_registers(30037, ModbusDataType.INT_32, unit=unit) # soc unit 0.1% - soc = client.read_holding_registers(30014, ModbusDataType.UINT_16, unit=unit) / 10 + soc = self.client.read_holding_registers(30014, ModbusDataType.UINT_16, unit=unit) / 10 imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/packages/modules/devices/sigenergy/sigenergy/counter.py b/packages/modules/devices/sigenergy/sigenergy/counter.py index 6c36db2762..589d8c06cf 100644 --- a/packages/modules/devices/sigenergy/sigenergy/counter.py +++ b/packages/modules/devices/sigenergy/sigenergy/counter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState @@ -9,19 +9,28 @@ from modules.devices.sigenergy.sigenergy.config import SigenergyCounterSetup +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class SigenergyCounter: - def __init__(self, device_id: int, component_config: SigenergyCounterSetup) -> None: - self.component_config = dataclass_from_dict(SigenergyCounterSetup, component_config) + def __init__(self, component_config: SigenergyCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") - def update(self, client: ModbusTcpClient_): + def update(self): unit = self.component_config.configuration.modbus_id - powers = client.read_holding_registers(30052, [ModbusDataType.INT_32]*3, unit=unit) - power = client.read_holding_registers(30005, ModbusDataType.INT_32, unit=unit) + powers = self.client.read_holding_registers(30052, [ModbusDataType.INT_32]*3, unit=unit) + power = self.client.read_holding_registers(30005, ModbusDataType.INT_32, unit=unit) imported, exported = self.sim_counter.sim_count(power) counter_state = CounterState( diff --git a/packages/modules/devices/sigenergy/sigenergy/device.py b/packages/modules/devices/sigenergy/sigenergy/device.py index df90216673..8fc7d700f9 100644 --- a/packages/modules/devices/sigenergy/sigenergy/device.py +++ b/packages/modules/devices/sigenergy/sigenergy/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.sigenergy.sigenergy.bat import SigenergyBat @@ -20,27 +19,33 @@ def create_device(device_config: Sigenergy): + client = None + def create_bat_component(component_config: SigenergyBatSetup): - return SigenergyBat(device_config.id, component_config) + nonlocal client + return SigenergyBat(component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: SigenergyCounterSetup): - return SigenergyCounter(device_config.id, component_config) + nonlocal client + return SigenergyCounter(component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: SigenergyInverterSetup): - return SigenergyInverter(device_config.id, component_config) + nonlocal client + return SigenergyInverter(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[Union[SigenergyBat, SigenergyCounter, SigenergyInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/sigenergy/sigenergy/inverter.py b/packages/modules/devices/sigenergy/sigenergy/inverter.py index 489e3a15ed..3ceffcf844 100644 --- a/packages/modules/devices/sigenergy/sigenergy/inverter.py +++ b/packages/modules/devices/sigenergy/sigenergy/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState @@ -11,18 +10,27 @@ from modules.devices.sigenergy.sigenergy.config import SigenergyInverterSetup +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class SigenergyInverter: - def __init__(self, device_id: int, component_config: Union[Dict, SigenergyInverterSetup]) -> None: - self.component_config = dataclass_from_dict(SigenergyInverterSetup, component_config) + def __init__(self, component_config: SigenergyInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.__device_id = device_id self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = client.read_holding_registers(30035, ModbusDataType.INT_32, unit=unit) * -1 + power = self.client.read_holding_registers(30035, ModbusDataType.INT_32, unit=unit) * -1 _, exported = self.sim_counter.sim_count(power) inverter_state = InverterState( diff --git a/packages/modules/devices/sma/sma_shm/counter.py b/packages/modules/devices/sma/sma_shm/counter.py index bb61df6b1b..8683e8faef 100644 --- a/packages/modules/devices/sma/sma_shm/counter.py +++ b/packages/modules/devices/sma/sma_shm/counter.py @@ -34,7 +34,7 @@ def get_power(phase_str: str = ""): def create_component(component_config: SmaHomeManagerCounterSetup): - return SpeedwireComponent(get_counter_value_store, parse_datagram, component_config) + return SpeedwireComponent(component_config, value_store_factory=get_counter_value_store, parser=parse_datagram) component_descriptor = ComponentDescriptor(configuration_factory=SmaHomeManagerCounterSetup) diff --git a/packages/modules/devices/sma/sma_shm/counter_test.py b/packages/modules/devices/sma/sma_shm/counter_test.py index a457c6c778..33fc7ee062 100644 --- a/packages/modules/devices/sma/sma_shm/counter_test.py +++ b/packages/modules/devices/sma/sma_shm/counter_test.py @@ -32,6 +32,7 @@ def test_process_datagram_energy_meter(mock_ramdisk): data = base64.b64decode(SAMPLE_SMA_ENERGY_EM) sma_data = speedwiredecoder.decode_speedwire(data) sma_counter = counter.create_component(counter.component_descriptor.configuration_factory()) + sma_counter.initialize() # execution sma_counter.read_datagram(sma_data) diff --git a/packages/modules/devices/sma/sma_shm/inverter.py b/packages/modules/devices/sma/sma_shm/inverter.py index fe54b52aa6..3467e8988d 100644 --- a/packages/modules/devices/sma/sma_shm/inverter.py +++ b/packages/modules/devices/sma/sma_shm/inverter.py @@ -15,7 +15,7 @@ def parse_datagram(sma_data: dict): def create_component(component_config: SmaHomeManagerInverterSetup): - return SpeedwireComponent(get_inverter_value_store, parse_datagram, component_config) + return SpeedwireComponent(component_config, value_store_factory=get_inverter_value_store, parser=parse_datagram) component_descriptor = ComponentDescriptor(configuration_factory=SmaHomeManagerInverterSetup) diff --git a/packages/modules/devices/sma/sma_shm/utils.py b/packages/modules/devices/sma/sma_shm/utils.py index cf17307f8e..31b81f3785 100644 --- a/packages/modules/devices/sma/sma_shm/utils.py +++ b/packages/modules/devices/sma/sma_shm/utils.py @@ -1,5 +1,5 @@ import logging -from typing import TypeVar, Generic, Callable, Optional, Union +from typing import Any, TypeVar, Generic, Callable, Optional, Union, TypedDict from modules.common.component_context import SingleComponentUpdateContext from modules.common.fault_state import ComponentInfo, FaultState @@ -14,21 +14,28 @@ def _create_serial_matcher(serial: Optional[int]) -> Callable[[dict], bool]: if isinstance(serial, int): return lambda sma_data: sma_data["serial"] == serial if serial is not None: - log.error("Serial <%s> must bei an int or None, but is <%s>. Assuming None.", serial, type(serial)) + log.error("Serial <%s> must be an int or None, but is <%s>. Assuming None.", serial, type(serial)) return lambda _: True +class KwargsDict(TypedDict): + value_store_factory: Callable[[int], ValueStore[T]] + parser: Callable[[dict], T] + + class SpeedwireComponent(Generic[T]): def __init__(self, - value_store_factory: Callable[[int], ValueStore[T]], - parser: Callable[[dict], T], - component_config: Union[SmaHomeManagerCounterSetup, SmaHomeManagerInverterSetup]): - self.store = value_store_factory(component_config.id) - self.__parser = parser - self.__serial_matcher = _create_serial_matcher(component_config.configuration.serials) - self.fault_state = FaultState(ComponentInfo.from_component_config(component_config)) + component_config: Union[SmaHomeManagerCounterSetup, SmaHomeManagerInverterSetup], + **kwargs: Any): + self.kwargs: KwargsDict = kwargs self.component_config = component_config + def initialize(self) -> None: + self.store = self.kwargs['value_store_factory'](self.component_config.id) + self.__parser = self.kwargs['parser'] + self.__serial_matcher = _create_serial_matcher(self.component_config.configuration.serials) + self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) + def read_datagram(self, datagram: dict) -> bool: if self.__serial_matcher(datagram): with SingleComponentUpdateContext(self.fault_state): diff --git a/packages/modules/devices/sma/sma_sunny_boy/bat.py b/packages/modules/devices/sma/sma_sunny_boy/bat.py index 99624e1295..8ba3840526 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/bat.py +++ b/packages/modules/devices/sma/sma_sunny_boy/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -11,15 +10,19 @@ from modules.devices.sma.sma_sunny_boy.config import SmaSunnyBoyBatSetup +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + + class SunnyBoyBat(AbstractBat): SMA_UINT_64_NAN = 0xFFFFFFFFFFFFFFFF # SMA uses this value to represent NaN - def __init__(self, - device_id: int, - component_config: Union[Dict, SmaSunnyBoyBatSetup], - tcp_client: ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(SmaSunnyBoyBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SmaSunnyBoyBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py b/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py index b5b5d61845..f0d811f4cd 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py +++ b/packages/modules/devices/sma/sma_sunny_boy/bat_smart_energy.py @@ -1,29 +1,29 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState from modules.common.modbus import ModbusTcpClient_, ModbusDataType -from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store from modules.devices.sma.sma_sunny_boy.config import SmaSunnyBoySmartEnergyBatSetup +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + + class SunnyBoySmartEnergyBat(AbstractBat): SMA_UINT32_NAN = 0xFFFFFFFF # SMA uses this value to represent NaN SMA_UINT_64_NAN = 0xFFFFFFFFFFFFFFFF # SMA uses this value to represent NaN - def __init__(self, - device_id: int, - component_config: Union[Dict, SmaSunnyBoySmartEnergyBatSetup], - tcp_client: ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SmaSunnyBoySmartEnergyBatSetup, component_config) - self.__tcp_client = tcp_client - self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") + def __init__(self, component_config: SmaSunnyBoySmartEnergyBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py b/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py index 9fe38a8ed1..42a0ca6089 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py +++ b/packages/modules/devices/sma/sma_sunny_boy/bat_tesvolt.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from typing import TypedDict, Any from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -10,14 +11,20 @@ from modules.devices.sma.sma_sunny_boy.config import SmaTesvoltBatSetup +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class TesvoltBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: SmaTesvoltBatSetup, - tcp_client: ModbusTcpClient_) -> None: + def __init__(self, component_config: SmaTesvoltBatSetup, **kwargs: Any) -> None: self.component_config = component_config - self.__tcp_client = tcp_client - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="bezug") + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sma/sma_sunny_boy/counter.py b/packages/modules/devices/sma/sma_sunny_boy/counter.py index 2210c320da..4c3e641770 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/counter.py +++ b/packages/modules/devices/sma/sma_sunny_boy/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -13,14 +12,19 @@ from modules.devices.sma.sma_sunny_boy.config import SmaSunnyBoyCounterSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class SmaSunnyBoyCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, SmaSunnyBoyCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SmaSunnyBoyCounterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SmaSunnyBoyCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sma/sma_sunny_boy/device.py b/packages/modules/devices/sma/sma_sunny_boy/device.py index a09f4547dc..f1bb394b1e 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/device.py +++ b/packages/modules/devices/sma/sma_sunny_boy/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union 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.common.modbus import ModbusTcpClient_ from modules.devices.sma.sma_sunny_boy.bat import SunnyBoyBat @@ -27,33 +26,40 @@ def create_device(device_config: SmaSunnyBoy): + client = None + def create_bat_component(component_config: SmaSunnyBoyBatSetup): - return SunnyBoyBat(device_config.id, component_config, client) + nonlocal client + return SunnyBoyBat(component_config, device_id=device_config.id, client=client) def create_bat_smart_energy_component(component_config: SmaSunnyBoySmartEnergyBatSetup): - return SunnyBoySmartEnergyBat(device_config.id, component_config, client) + nonlocal client + return SunnyBoySmartEnergyBat(component_config, client=client) def create_bat_tesvolt_component(component_config: SmaTesvoltBatSetup): - return TesvoltBat(device_config.id, component_config, client) + return TesvoltBat(component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: SmaSunnyBoyCounterSetup): - return SmaSunnyBoyCounter(device_config.id, component_config, client) + nonlocal client + return SmaSunnyBoyCounter(component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: SmaSunnyBoyInverterSetup): - return SmaSunnyBoyInverter(device_config.id, component_config, client) + nonlocal client + return SmaSunnyBoyInverter(component_config, client=client) def update_components(components: Iterable[sma_modbus_tcp_component_classes]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, bat_smart_energy=create_bat_smart_energy_component, diff --git a/packages/modules/devices/sma/sma_sunny_boy/inverter.py b/packages/modules/devices/sma/sma_sunny_boy/inverter.py index 8685fd7410..7ef1bf3018 100644 --- a/packages/modules/devices/sma/sma_sunny_boy/inverter.py +++ b/packages/modules/devices/sma/sma_sunny_boy/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -16,6 +15,10 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + + class SmaSunnyBoyInverter(AbstractInverter): SMA_INT32_NAN = -0x80000000 # SMA uses this value to represent NaN @@ -23,11 +26,13 @@ class SmaSunnyBoyInverter(AbstractInverter): SMA_NAN = -0xC000 def __init__(self, - device_id: int, - component_config: Union[Dict, SmaSunnyBoyInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(SmaSunnyBoyInverterSetup, component_config) - self.tcp_client = tcp_client + component_config: SmaSunnyBoyInverterSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.tcp_client = self.kwargs['client'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sma/sma_sunny_island/bat.py b/packages/modules/devices/sma/sma_sunny_island/bat.py index 30fc0479a8..fbf58abf9c 100644 --- a/packages/modules/devices/sma/sma_sunny_island/bat.py +++ b/packages/modules/devices/sma/sma_sunny_island/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -12,12 +11,17 @@ from modules.devices.sma.sma_sunny_island.config import SmaSunnyIslandBatSetup +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + + class SunnyIslandBat(AbstractBat): - def __init__(self, - component_config: Union[Dict, SmaSunnyIslandBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(SmaSunnyIslandBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SmaSunnyIslandBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sma/sma_sunny_island/device.py b/packages/modules/devices/sma/sma_sunny_island/device.py index 9d11cbafec..6b89ae8b39 100644 --- a/packages/modules/devices/sma/sma_sunny_island/device.py +++ b/packages/modules/devices/sma/sma_sunny_island/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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.sma.sma_sunny_island.bat import SunnyIslandBat from modules.devices.sma.sma_sunny_island.config import SmaSunnyIsland, SmaSunnyIslandBatSetup @@ -13,21 +12,25 @@ def create_device(device_config: SmaSunnyIsland): + client = None + def create_bat_component(component_config: SmaSunnyIslandBatSetup): - return SunnyIslandBat(component_config, client) + nonlocal client + return SunnyIslandBat(component_config, client=client) def update_components(components: Iterable[SunnyIslandBat]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, ), diff --git a/packages/modules/devices/sma/sma_webbox/device.py b/packages/modules/devices/sma/sma_webbox/device.py index 8e5ee62baf..87db5b6de6 100644 --- a/packages/modules/devices/sma/sma_webbox/device.py +++ b/packages/modules/devices/sma/sma_webbox/device.py @@ -12,7 +12,7 @@ def create_device(device_config: SmaWebbox): def create_inverter_component(component_config: SmaWebboxInverterSetup): - return SmaWebboxInverter(device_config.configuration.ip_address, component_config) + return SmaWebboxInverter(component_config, ip_address=device_config.configuration.ip_address) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/sma/sma_webbox/inverter.py b/packages/modules/devices/sma/sma_webbox/inverter.py index f652365dbf..3447f884ac 100644 --- a/packages/modules/devices/sma/sma_webbox/inverter.py +++ b/packages/modules/devices/sma/sma_webbox/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, Dict, Union, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -11,10 +10,17 @@ from modules.devices.sma.sma_webbox.config import SmaWebboxInverterSetup +class KwargsDict(TypedDict): + ip_address: str + + class SmaWebboxInverter(AbstractInverter): - def __init__(self, device_address: str, component_config: Union[Dict, SmaWebboxInverterSetup]) -> None: - self.__device_address = device_address - self.component_config = dataclass_from_dict(SmaWebboxInverterSetup, component_config) + def __init__(self, component_config: Union[Dict, SmaWebboxInverterSetup], **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: str = self.kwargs['ip_address'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) @@ -23,8 +29,7 @@ def update(self) -> None: def read(self) -> InverterState: data = {'RPC': '{"version": "1.0","proc": "GetPlantOverview","id": "1","format": "JSON"}'} - response = req.get_http_session().post( - 'http://' + self.__device_address + '/rpc', data=data, timeout=3).json() + response = req.get_http_session().post(f'http://{self.ip_address}/rpc', data=data, timeout=3).json() return InverterState( exported=float(response["result"]["overview"][2]["value"]) * 1000, diff --git a/packages/modules/devices/smart_me/smart_me/counter.py b/packages/modules/devices/smart_me/smart_me/counter.py index 1eb957ad63..3a4c9f0db3 100644 --- a/packages/modules/devices/smart_me/smart_me/counter.py +++ b/packages/modules/devices/smart_me/smart_me/counter.py @@ -1,10 +1,8 @@ #!/usr/bin/env python3 import logging -from typing import Dict, List, Union +from typing import List from requests import Session - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -16,9 +14,10 @@ class SmartMeCounter(AbstractCounter): - def __init__(self, - component_config: Union[Dict, SmartMeCounterSetup]) -> None: - self.component_config = dataclass_from_dict(SmartMeCounterSetup, component_config) + def __init__(self, component_config: SmartMeCounterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/smart_me/smart_me/device.py b/packages/modules/devices/smart_me/smart_me/device.py index 8a2046e8cd..50029ccb01 100644 --- a/packages/modules/devices/smart_me/smart_me/device.py +++ b/packages/modules/devices/smart_me/smart_me/device.py @@ -15,16 +15,22 @@ def create_device(device_config: SmartMe): + session = None + def create_counter_component(component_config: SmartMeCounterSetup): return SmartMeCounter(component_config) def create_inverter_component(component_config: SmartMeInverterSetup): return SmartMeInverter(component_config) - session = get_http_session() - session.auth = (device_config.configuration.user, device_config.configuration.password) + def initializer(): + nonlocal session + session = get_http_session() + session.auth = (device_config.configuration.user, device_config.configuration.password) + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( counter=create_counter_component, inverter=create_inverter_component, diff --git a/packages/modules/devices/smart_me/smart_me/inverter.py b/packages/modules/devices/smart_me/smart_me/inverter.py index af113d297d..6db8543b5e 100644 --- a/packages/modules/devices/smart_me/smart_me/inverter.py +++ b/packages/modules/devices/smart_me/smart_me/inverter.py @@ -1,10 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union from requests import Session - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -16,9 +13,10 @@ class SmartMeInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, SmartMeInverterSetup]) -> None: - self.component_config = dataclass_from_dict(SmartMeInverterSetup, component_config) + def __init__(self, component_config: SmartMeInverterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/smartfox/smartfox/counter.py b/packages/modules/devices/smartfox/smartfox/counter.py index 29c14db4ac..5950c7eb01 100644 --- a/packages/modules/devices/smartfox/smartfox/counter.py +++ b/packages/modules/devices/smartfox/smartfox/counter.py @@ -1,9 +1,8 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Any, TypedDict import xml.etree.ElementTree as ET -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -15,12 +14,17 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + ip_address: str + + class SmartfoxCounter(AbstractCounter): - def __init__(self, - device_address: str, - component_config: Union[Dict, SmartfoxCounterSetup]) -> None: - self.__device_address = device_address - self.component_config = dataclass_from_dict(SmartfoxCounterSetup, component_config) + def __init__(self, component_config: SmartfoxCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: int = self.kwargs['ip_address'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) @@ -35,11 +39,11 @@ def get_xml_text(attribute_value: str) -> str: headers = { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', - 'Host': self.__device_address, + 'Host': self.ip_address, 'Connection': 'keep-alive)', } - response = req.get_http_session().get('http://'+self.__device_address+'/values.xml', + response = req.get_http_session().get('http://'+self.ip_address+'/values.xml', headers=headers, timeout=5) response.encoding = 'utf-8' diff --git a/packages/modules/devices/smartfox/smartfox/device.py b/packages/modules/devices/smartfox/smartfox/device.py index 162c23ce75..e8d2eba6b8 100644 --- a/packages/modules/devices/smartfox/smartfox/device.py +++ b/packages/modules/devices/smartfox/smartfox/device.py @@ -12,7 +12,7 @@ def create_device(device_config: Smartfox): def create_counter_component(component_config: SmartfoxCounterSetup): - return SmartfoxCounter(device_config.configuration.ip_address, component_config) + return SmartfoxCounter(component_config, ip_address=device_config.configuration.ip_address) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/sofar/sofar/bat.py b/packages/modules/devices/sofar/sofar/bat.py index 000b64378e..097883b790 100644 --- a/packages/modules/devices/sofar/sofar/bat.py +++ b/packages/modules/devices/sofar/sofar/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -11,37 +10,44 @@ from modules.devices.sofar.sofar.config import SofarBatSetup +class KwargsDict(TypedDict): + modbus_id: int + client: ModbusTcpClient_ + + class SofarBat(AbstractBat): - def __init__(self, - component_config: Union[Dict, SofarBatSetup], - modbus_id: int) -> None: - self.__modbus_id = modbus_id - self.component_config = dataclass_from_dict(SofarBatSetup, component_config) + def __init__(self, component_config: SofarBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: # 0x0606 Power_bat1 Int16 in kW accuracy 0,01 # 0x060D Power_bat2, 0x0614 Power_bat3, 0x061B Power_bat4, 0x0622 Power_bat5, # 0x0629 Power_bat6, 0x0630 Power_bat7, 0x0637 Power_bat8 # 0x0646 Power_bat9, 0x064D Power_bat10, 0x0654 Power_bat11, 0x065B Power_bat12 - power = sum(client.read_input_registers(reg, ModbusDataType.INT_16, unit=self.__modbus_id) + power = sum(self.client.read_input_registers(reg, ModbusDataType.INT_16, unit=self.__modbus_id) for reg in [0x0606, 0x060D, 0x0614, 0x061B, 0x0622, 0x0629, 0x0630, 0x0637, 0x0646, 0x064D, 0x0654, 0x065B]) # 0x0608 SOC_Bat1 UInt16 in % accuracy 1 # 0x060F SOC_bat2, 0x0616 SOC_bat3, 0x061D SOC_bat4, 0x0624 SOC_bat5, # 0x062B SOC_bat6, 0x0632 SOC_bat7, 0x0639 SOC_bat_8 # 0x0648 SOC_bat9, 0x064F SOC_bat10, 0x0656 SOC_bat11, 0x065D SOC_bat12 - soc = sum(client.read_input_registers(0x0608, ModbusDataType.UINT_16, unit=self.__modbus_id) + soc = sum(self.client.read_input_registers(0x0608, ModbusDataType.UINT_16, unit=self.__modbus_id) for reg in [0x0608, 0x060F, 0x0616, 0x061D, 0x0624, 0x062B, 0x0632, 0x0639, 0x0648, 0x064F, 0x0656, 0x065D]) # 0x0696 Bat_charge_total LSB UInt32 0,1 kWh # 0x0697 Bat_charge_total UInt32 0,1 kWh - imported = client.read_input_registers( + imported = self.client.read_input_registers( 0x0696, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 # 0x069A Bat_discharge_total LSB UInt32 0,1 kWh # 0x069B Bat:discharge_total UInt32 0,1 kWh - exported = client.read_input_registers( + exported = self.client.read_input_registers( 0x069A, ModbusDataType.UINT_32, unit=self.__modbus_id) * 100 bat_state = BatState( diff --git a/packages/modules/devices/sofar/sofar/counter.py b/packages/modules/devices/sofar/sofar/counter.py index 91bc7e6b19..33379791a2 100644 --- a/packages/modules/devices/sofar/sofar/counter.py +++ b/packages/modules/devices/sofar/sofar/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -12,39 +11,46 @@ from modules.devices.sofar.sofar.config import SofarCounterSetup +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + modbus_id: int + + class SofarCounter(AbstractCounter): - def __init__(self, - component_config: Union[Dict, SofarCounterSetup], - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(SofarCounterSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: SofarCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_): + def update(self): # 0x0485 ActivePower_output_total Int16 in kW accuracy 0,01 discharge + charge - # 0x0488 ActivePower_PCC_total Int16 0,01 kW - power = client.read_input_registers(0x0488, ModbusDataType.INT_16, wordorder=Endian.Little, - unit=self.__modbus_id) * -1 + power = self.client.read_input_registers(0x0488, ModbusDataType.INT_16, wordorder=Endian.Little, + unit=self.__modbus_id) * -1 # 0x0484 Frequency_Grid UInt16 in Hz accuracy 0,01 - frequency = client.read_input_registers( + frequency = self.client.read_input_registers( 0x0484, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100 try: # 0x048F ActivePower_Output_R UInt16 in V accuracy 0,1 # 0x0493 ActivePower_PCC_R Int16 in kW accuracy 0,01 - powers = [-value for value in client.read_input_registers( + powers = [-value for value in self.client.read_input_registers( 0x0493, [ModbusDataType.INT_16] * 1, wordorder=Endian.Little, unit=self.__modbus_id )] except Exception: powers = None try: - voltages = [client.read_input_registers( + voltages = [self.client.read_input_registers( # 048D Voltage_Phase_R UInt16 in V accuracy 0,1 0x048D, ModbusDataType.UINT_16, unit=self.__modbus_id - ) / 10, client.read_input_registers( + ) / 10, self.client.read_input_registers( # 0498 Voltage_Phase_S UInt16 in V accuracy 0,1 0x0498, ModbusDataType.UINT_16, unit=self.__modbus_id - ) / 10, client.read_input_registers( + ) / 10, self.client.read_input_registers( # 04A3 Voltage_Phase_T UInt16 in V accuracy 0,1 0x04A3, ModbusDataType.UINT_16, unit=self.__modbus_id ) / 10] @@ -57,13 +63,13 @@ def update(self, client: ModbusTcpClient_): except Exception: voltages = [230, 230, 230] exported = [value * 10 - for value in client.read_input_registers( + for value in self.client.read_input_registers( # 0x0692 Energy_Selling_Total UInt32 in kwH accuracy 0,01 LSB # 0x0693 Energy_Selling_Total UInt32 in kwH accuracy 0,01 0x0692, [ModbusDataType.UINT_32] * 10, wordorder=Endian.Little, unit=self.__modbus_id)] imported = [value * 10 - for value in client.read_input_registers( + for value in self.client.read_input_registers( # 0x068E Energy_Purchase_Total UInt32 in kwH accuracy 0,01 LSB # 0x068F Energy_Purchase_Total UInt32 in kwH accuracy 0,01 0x068E, [ModbusDataType.UINT_32] * 10, diff --git a/packages/modules/devices/sofar/sofar/device.py b/packages/modules/devices/sofar/sofar/device.py index f1a9fb7746..2c91f0e8e6 100644 --- a/packages/modules/devices/sofar/sofar/device.py +++ b/packages/modules/devices/sofar/sofar/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.sofar.sofar.bat import SofarBat @@ -15,27 +14,33 @@ def create_device(device_config: Sofar): + client = None + def create_bat_component(component_config: SofarBatSetup): - return SofarBat(component_config, device_config.configuration.modbus_id) + nonlocal client + return SofarBat(component_config, modbus_id=device_config.configuration.modbus_id, client=client) def create_counter_component(component_config: SofarCounterSetup): - return SofarCounter(component_config, device_config.configuration.modbus_id) + nonlocal client + return SofarCounter(component_config, modbus_id=device_config.configuration.modbus_id, client=client) def create_inverter_component(component_config: SofarInverterSetup): - return SofarInverter(component_config, device_config.configuration.modbus_id) + nonlocal client + return SofarInverter(component_config, modbus_id=device_config.configuration.modbus_id, client=client) def update_components(components: Iterable[Union[SofarBat, SofarCounter, SofarInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/sofar/sofar/inverter.py b/packages/modules/devices/sofar/sofar/inverter.py index d73cdfb9f7..37fed243c3 100644 --- a/packages/modules/devices/sofar/sofar/inverter.py +++ b/packages/modules/devices/sofar/sofar/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,30 +11,37 @@ from modules.devices.sofar.sofar.config import SofarInverterSetup +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + modbus_id: int + + class SofarInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, SofarInverterSetup], - modbus_id: int) -> None: - self.component_config = dataclass_from_dict(SofarInverterSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: SofarInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['client'] + self.__modbus_id: int = self.kwargs['modbus_id'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: # 0x0586 Power_PV1 UInt16 in kW accuracy 0,01 # 0x0589 Power_PV2, 0x058C Power_PV3, 0x058F Power_PV4, 0x0592 Power_PV5, # 0x0595 Power_PV6, 0x0598 Power_PV7, 0x059B Power_PV8, 0x059E Power_PV9, 0x05A1 Power_PV10, # 0x05A4 Power_PV11, 0x05A7 Power_PV12, 0x05AA Power_PV13, # 0x05AD Power_PV14, 0x05B0 Power_PV15, 0x05B3 Power_PV16 - power = sum([client.read_input_registers(reg, ModbusDataType.UINT_16, + power = sum([self.client.read_input_registers(reg, ModbusDataType.UINT_16, unit=self.__modbus_id) for reg in [0x0586, 0x0589, 0x058C, 0x058F, 0x0592, 0x0595, 0x0598, 0x059B, 0x059E, 0x05A1, 0x05A4, 0x05A7, 0x05AA, 0x05AD, 0x05B0, 0x05B3]]) * -1 # 0x05C4 Power_PV_Total UInt16 in kW accuracy 0,1 # 0x0686 PV_Generation_Total UInt32 0,1 kW LSB # 0x0687 PV_Generation_Total UInt32 0,1 kW - exported = client.read_input_registers(0x0686, ModbusDataType.UINT_32, wordorder=Endian.Little, - unit=self.__modbus_id) * 100 + exported = self.client.read_input_registers(0x0686, ModbusDataType.UINT_32, wordorder=Endian.Little, + unit=self.__modbus_id) * 100 inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/solar_log/solar_log/counter.py b/packages/modules/devices/solar_log/solar_log/counter.py index a5267b2b68..82abc683cb 100644 --- a/packages/modules/devices/solar_log/solar_log/counter.py +++ b/packages/modules/devices/solar_log/solar_log/counter.py @@ -1,9 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Dict, TypedDict, Any - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -15,12 +13,18 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class SolarLogCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, SolarLogCounterSetup]) -> None: - self.component_config = dataclass_from_dict(SolarLogCounterSetup, component_config) - self.sim_counter = SimCounter(device_id, self.component_config.id, prefix="bezug") + def __init__(self, component_config: SolarLogCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) @@ -36,7 +40,7 @@ def store_values(self, power) -> None: power=power )) - def get_power(self, response: Dict) -> CounterState: + def get_power(self, response: Dict) -> int: return int(float(response["801"]["170"]["110"])) diff --git a/packages/modules/devices/solar_log/solar_log/device.py b/packages/modules/devices/solar_log/solar_log/device.py index 85b4639b63..c71bb20bd2 100644 --- a/packages/modules/devices/solar_log/solar_log/device.py +++ b/packages/modules/devices/solar_log/solar_log/device.py @@ -16,10 +16,10 @@ def create_device(device_config: SolarLog): def create_counter_component(component_config: SolarLogCounterSetup): - return SolarLogCounter(device_config.id, component_config) + return SolarLogCounter(component_config, device_id=device_config.id) def create_inverter_component(component_config: SolarLogInverterSetup): - return SolarLogInverter(device_config.id, component_config) + return SolarLogInverter(component_config) def update_components(components: Iterable[Union[SolarLogCounter, SolarLogInverter]]): response = req.get_http_session().post('http://'+device_config.configuration.ip_address+'/getjp', diff --git a/packages/modules/devices/solar_log/solar_log/inverter.py b/packages/modules/devices/solar_log/solar_log/inverter.py index fb70845a81..07b4698f1b 100644 --- a/packages/modules/devices/solar_log/solar_log/inverter.py +++ b/packages/modules/devices/solar_log/solar_log/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Dict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -15,9 +14,10 @@ class SolarLogInverter(AbstractInverter): def __init__(self, - device_id: int, - component_config: Union[Dict, SolarLogInverterSetup]) -> None: - self.component_config = dataclass_from_dict(SolarLogInverterSetup, component_config) + component_config: SolarLogInverterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solar_view/solar_view/counter.py b/packages/modules/devices/solar_view/solar_view/counter.py index db8ecf38d3..08e3e2a65d 100644 --- a/packages/modules/devices/solar_view/solar_view/counter.py +++ b/packages/modules/devices/solar_view/solar_view/counter.py @@ -1,9 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -16,8 +13,10 @@ class SolarViewCounter(AbstractCounter): - def __init__(self, component_config: Union[Dict, SolarViewCounterSetup]) -> None: - self.component_config = dataclass_from_dict(SolarViewCounterSetup, component_config) + def __init__(self, component_config: SolarViewCounterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solar_view/solar_view/inverter.py b/packages/modules/devices/solar_view/solar_view/inverter.py index 371d59d256..d57d4bc876 100644 --- a/packages/modules/devices/solar_view/solar_view/inverter.py +++ b/packages/modules/devices/solar_view/solar_view/inverter.py @@ -1,9 +1,6 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -16,8 +13,10 @@ class SolarViewInverter(AbstractInverter): - def __init__(self, component_config: Union[Dict, SolarViewInverterSetup]) -> None: - self.component_config = dataclass_from_dict(SolarViewInverterSetup, component_config) + def __init__(self, component_config: SolarViewInverterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solar_watt/solar_watt/bat.py b/packages/modules/devices/solar_watt/solar_watt/bat.py index e015e3c9c1..bfe1e8a4c1 100644 --- a/packages/modules/devices/solar_watt/solar_watt/bat.py +++ b/packages/modules/devices/solar_watt/solar_watt/bat.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Any, Dict, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -15,12 +14,17 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class SolarWattBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, SolarWattBatSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolarWattBatSetup, component_config) + def __init__(self, component_config: SolarWattBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/solar_watt/solar_watt/counter.py b/packages/modules/devices/solar_watt/solar_watt/counter.py index 381d10a568..6ca53ea90b 100644 --- a/packages/modules/devices/solar_watt/solar_watt/counter.py +++ b/packages/modules/devices/solar_watt/solar_watt/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Any, Dict, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -15,12 +14,17 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class SolarWattCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, SolarWattCounterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolarWattCounterSetup, component_config) + def __init__(self, component_config: SolarWattCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solar_watt/solar_watt/device.py b/packages/modules/devices/solar_watt/solar_watt/device.py index 7873afaa7d..aded618a55 100644 --- a/packages/modules/devices/solar_watt/solar_watt/device.py +++ b/packages/modules/devices/solar_watt/solar_watt/device.py @@ -46,13 +46,13 @@ def request(url: str) -> Dict: def create_device(device_config: SolarWatt): def create_bat_component(component_config: SolarWattBatSetup): - return SolarWattBat(device_config.id, component_config) + return SolarWattBat(component_config, device_id=device_config.id) def create_counter_component(component_config: SolarWattCounterSetup): - return SolarWattCounter(device_config.id, component_config) + return SolarWattCounter(component_config, device_id=device_config.id) def create_inverter_component(component_config: SolarWattInverterSetup): - return SolarWattInverter(device_config.id, component_config) + return SolarWattInverter(component_config, device_id=device_config.id) def update_components(components: Dict[str, Union[SolarWattBat, SolarWattCounter, SolarWattInverter]]): update(components, device_config.configuration.energy_manager, device_config.configuration.ip_address) diff --git a/packages/modules/devices/solar_watt/solar_watt/inverter.py b/packages/modules/devices/solar_watt/solar_watt/inverter.py index f4e403f51e..28c14ee47a 100644 --- a/packages/modules/devices/solar_watt/solar_watt/inverter.py +++ b/packages/modules/devices/solar_watt/solar_watt/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Any, Dict, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -15,12 +14,17 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + + class SolarWattInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, SolarWattInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolarWattInverterSetup, component_config) + def __init__(self, component_config: SolarWattInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solar_world/solar_world/counter.py b/packages/modules/devices/solar_world/solar_world/counter.py index 5b4437959a..b6885a1404 100644 --- a/packages/modules/devices/solar_world/solar_world/counter.py +++ b/packages/modules/devices/solar_world/solar_world/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -11,10 +10,17 @@ from modules.devices.solar_world.solar_world.config import SolarWorldCounterSetup +class KwargsDict(TypedDict): + device_id: int + + class SolarWorldCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: Union[Dict, SolarWorldCounterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolarWorldCounterSetup, component_config) + def __init__(self, component_config: SolarWorldCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solar_world/solar_world/device.py b/packages/modules/devices/solar_world/solar_world/device.py index 86469138b6..00501cb325 100644 --- a/packages/modules/devices/solar_world/solar_world/device.py +++ b/packages/modules/devices/solar_world/solar_world/device.py @@ -17,10 +17,10 @@ def create_device(device_config: SolarWorld): def create_counter_component(component_config: SolarWorldCounterSetup): - return SolarWorldCounter(device_config.id, component_config) + return SolarWorldCounter(component_config, device_id=device_config.id) def create_inverter_component(component_config: SolarWorldInverterSetup): - return SolarWorldInverter(device_config.id, component_config) + return SolarWorldInverter(component_config, device_id=device_config.id) def update_components(components: Iterable[Union[SolarWorldCounter, SolarWorldInverter]]): response = req.get_http_session().get("http://"+str(device_config.configuration.ip_address) + diff --git a/packages/modules/devices/solar_world/solar_world/inverter.py b/packages/modules/devices/solar_world/solar_world/inverter.py index 7d6519ada3..3eefa6f404 100644 --- a/packages/modules/devices/solar_world/solar_world/inverter.py +++ b/packages/modules/devices/solar_world/solar_world/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -11,10 +10,17 @@ from modules.devices.solar_world.solar_world.config import SolarWorldInverterSetup +class KwargsDict(TypedDict): + device_id: int + + class SolarWorldInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: Union[Dict, SolarWorldInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolarWorldInverterSetup, component_config) + def __init__(self, component_config: SolarWorldInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solaredge/solaredge/bat.py b/packages/modules/devices/solaredge/solaredge/bat.py index 59483aefa0..b1afe1ec47 100644 --- a/packages/modules/devices/solaredge/solaredge/bat.py +++ b/packages/modules/devices/solaredge/solaredge/bat.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Tuple, Union +from typing import Any, Tuple, TypedDict from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -20,14 +19,19 @@ FLOAT32_UNSUPPORTED = -0xffffff00000000000000000000000000 +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class SolaredgeBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, SolaredgeBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolaredgeBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SolaredgeBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/solaredge/solaredge/counter.py b/packages/modules/devices/solaredge/solaredge/counter.py index ee5be24628..e0a9bc09aa 100644 --- a/packages/modules/devices/solaredge/solaredge/counter.py +++ b/packages/modules/devices/solaredge/solaredge/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -17,13 +16,17 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + + class SolaredgeCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, SolaredgeCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(SolaredgeCounterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SolaredgeCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.registers = SolaredgeMeterRegisters() self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solaredge/solaredge/device.py b/packages/modules/devices/solaredge/solaredge/device.py index 3426bb3124..bf350aa6ab 100644 --- a/packages/modules/devices/solaredge/solaredge/device.py +++ b/packages/modules/devices/solaredge/solaredge/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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.solaredge.solaredge.bat import SolaredgeBat from modules.devices.solaredge.solaredge.counter import SolaredgeCounter @@ -45,13 +44,16 @@ def set_component_registers(components: Iterable[solaredge_component_classes], def create_device(device_config: Solaredge): + client = None + def create_bat_component(component_config: SolaredgeBatSetup): - return SolaredgeBat(device_config.id, component_config, client) + nonlocal client + return SolaredgeBat(component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: SolaredgeCounterSetup): - nonlocal device + nonlocal client, device synergy_units = get_synergy_units(component_config) - counter = SolaredgeCounter(device_config.id, component_config, client) + counter = SolaredgeCounter(component_config, client=client) # neue Komponente wird erst nach Instanziierung device.components hinzugefügt components = list(device.components.values()) components.append(counter) @@ -59,60 +61,61 @@ def create_counter_component(component_config: SolaredgeCounterSetup): return counter def create_inverter_component(component_config: SolaredgeInverterSetup): - return SolaredgeInverter(device_config.id, component_config, client) + nonlocal client + return SolaredgeInverter(component_config, client=client) def create_external_inverter_component(component_config: SolaredgeExternalInverterSetup): - nonlocal device + nonlocal client, device synergy_units = get_synergy_units(component_config) - external_inverter = SolaredgeExternalInverter(device_config.id, component_config, client) + external_inverter = SolaredgeExternalInverter(component_config, client=client) components = list(device.components.values()) components.append(external_inverter) set_component_registers(components, synergy_units, component_config.configuration.modbus_id) return external_inverter def update_components(components: Iterable[Union[SolaredgeBat, SolaredgeCounter, SolaredgeInverter]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() def get_synergy_units(component_config: Union[SolaredgeBatSetup, SolaredgeCounterSetup, SolaredgeInverterSetup, SolaredgeExternalInverterSetup]) -> None: - try: - if client.read_holding_registers(40121, modbus.ModbusDataType.UINT_16, - unit=component_config.configuration.modbus_id - ) == synergy_unit_identifier: - # Snyergy-Units vom Haupt-WR des angeschlossenen Meters ermitteln. Es kann mehrere Haupt-WR mit - # unterschiedlichen Modbus-IDs im Verbund geben. - log.debug("Synergy Units supported") - synergy_units = int(client.read_holding_registers( - 40129, modbus.ModbusDataType.UINT_16, - unit=component_config.configuration.modbus_id)) or 1 - log.debug( - f"Synergy Units detected for Modbus ID {component_config.configuration.modbus_id}: {synergy_units}") - else: - synergy_units = 1 - except Exception: + nonlocal client + if client.read_holding_registers(40121, modbus.ModbusDataType.UINT_16, + unit=component_config.configuration.modbus_id + ) == synergy_unit_identifier: + # Snyergy-Units vom Haupt-WR des angeschlossenen Meters ermitteln. Es kann mehrere Haupt-WR mit + # unterschiedlichen Modbus-IDs im Verbund geben. + log.debug("Synergy Units supported") + synergy_units = int(client.read_holding_registers( + 40129, modbus.ModbusDataType.UINT_16, + unit=component_config.configuration.modbus_id)) or 1 + log.debug( + f"Synergy Units detected for Modbus ID {component_config.configuration.modbus_id}: {synergy_units}") + else: synergy_units = 1 return synergy_units - try: + + def initializer(): + nonlocal client client = modbus.ModbusTcpClient_(device_config.configuration.ip_address, device_config.configuration.port, reconnect_delay=reconnect_delay) - device = ConfigurableDevice( - device_config=device_config, - component_factory=ComponentFactoryByType( - bat=create_bat_component, - counter=create_counter_component, - external_inverter=create_external_inverter_component, - inverter=create_inverter_component, - ), - component_updater=MultiComponentUpdater(update_components) - ) - except Exception: - log.exception("Fehler in create_device") + + device = ConfigurableDevice( + device_config=device_config, + initializer=initializer, + component_factory=ComponentFactoryByType( + bat=create_bat_component, + counter=create_counter_component, + external_inverter=create_external_inverter_component, + inverter=create_inverter_component, + ), + component_updater=MultiComponentUpdater(update_components) + ) return device diff --git a/packages/modules/devices/solaredge/solaredge/external_inverter.py b/packages/modules/devices/solaredge/solaredge/external_inverter.py index 44243cd208..97cc28689d 100644 --- a/packages/modules/devices/solaredge/solaredge/external_inverter.py +++ b/packages/modules/devices/solaredge/solaredge/external_inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -17,13 +16,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + + class SolaredgeExternalInverter(AbstractInverter): def __init__(self, - device_id: int, - component_config: Union[Dict, SolaredgeExternalInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(SolaredgeExternalInverterSetup, component_config) - self.__tcp_client = tcp_client + component_config: SolaredgeExternalInverterSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client = self.kwargs['client'] self.registers = SolaredgeMeterRegisters(self.component_config.configuration.meter_id) self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solaredge/solaredge/inverter.py b/packages/modules/devices/solaredge/solaredge/inverter.py index 948b782f85..e9ae35d943 100644 --- a/packages/modules/devices/solaredge/solaredge/inverter.py +++ b/packages/modules/devices/solaredge/solaredge/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -13,13 +12,19 @@ from modules.devices.solaredge.solaredge.scale import create_scaled_reader +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + + class SolaredgeInverter(AbstractInverter): def __init__(self, - device_id: int, - component_config: Union[Dict, SolaredgeInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(SolaredgeInverterSetup, component_config) - self.__tcp_client = tcp_client + component_config: SolaredgeInverterSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client = self.kwargs['client'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self._read_scaled_int16 = create_scaled_reader( diff --git a/packages/modules/devices/solaredge/solaredge/inverter_test.py b/packages/modules/devices/solaredge/solaredge/inverter_test.py index 6fc88254ec..4d2b8874b7 100644 --- a/packages/modules/devices/solaredge/solaredge/inverter_test.py +++ b/packages/modules/devices/solaredge/solaredge/inverter_test.py @@ -15,8 +15,9 @@ def test_read_state(): [616, 65535, 65535, -2], [14368, -1] ]) - inverter = SolaredgeInverter(0, SolaredgeInverterSetup(), Mock( + inverter = SolaredgeInverter(SolaredgeInverterSetup(), client=Mock( spec=ModbusTcpClient_, read_holding_registers=mock_read_holding_registers)) + inverter.initialize() # execution inverter_state = inverter.read_state() diff --git a/packages/modules/devices/solarmax/solarmax/bat.py b/packages/modules/devices/solarmax/solarmax/bat.py index 3d323c18e3..c15135050e 100644 --- a/packages/modules/devices/solarmax/solarmax/bat.py +++ b/packages/modules/devices/solarmax/solarmax/bat.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -10,18 +11,27 @@ from modules.devices.solarmax.solarmax.config import SolarmaxBatSetup +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class SolarmaxBat(AbstractBat): - def __init__(self, device_id: int, component_config: SolarmaxBatSetup) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolarmaxBatSetup, component_config) + def __init__(self, component_config: SolarmaxBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_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, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = client.read_holding_registers(114, ModbusDataType.INT_32, unit=unit) - soc = client.read_holding_registers(122, ModbusDataType.INT_16, unit=unit) + power = self.client.read_holding_registers(114, ModbusDataType.INT_32, unit=unit) + soc = self.client.read_holding_registers(122, ModbusDataType.INT_16, unit=unit) imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( diff --git a/packages/modules/devices/solarmax/solarmax/device.py b/packages/modules/devices/solarmax/solarmax/device.py index 2a71a6ba04..a30db146f4 100644 --- a/packages/modules/devices/solarmax/solarmax/device.py +++ b/packages/modules/devices/solarmax/solarmax/device.py @@ -5,7 +5,6 @@ from helpermodules.cli import run_using_positional_cli_args from modules.common import modbus 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.solarmax.solarmax import inverter from modules.devices.solarmax.solarmax.bat import SolarmaxBat @@ -16,24 +15,29 @@ def create_device(device_config: Solarmax): + client = None + def create_bat_component(component_config: SolarmaxBatSetup): - return SolarmaxBat(device_config.id, component_config) + nonlocal client + return SolarmaxBat(component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: SolarmaxInverterSetup): - return inverter.SolarmaxInverter(device_config.id, component_config) + nonlocal client + return inverter.SolarmaxInverter(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[Union[SolarmaxBat, inverter.SolarmaxInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, inverter=create_inverter_component, diff --git a/packages/modules/devices/solarmax/solarmax/inverter.py b/packages/modules/devices/solarmax/solarmax/inverter.py index 11d5bffe7d..b2ea19d55f 100644 --- a/packages/modules/devices/solarmax/solarmax/inverter.py +++ b/packages/modules/devices/solarmax/solarmax/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,19 +11,28 @@ from modules.devices.solarmax.solarmax.config import SolarmaxInverterSetup +class KwargsDict(TypedDict): + device_id: int + client: ModbusTcpClient_ + + class SolarmaxInverter(AbstractInverter): def __init__(self, - device_id: int, - component_config: Union[Dict, SolarmaxInverterSetup]) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(SolarmaxInverterSetup, component_config) + component_config: SolarmaxInverterSetup, + **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: - power = client.read_holding_registers(4151, ModbusDataType.UINT_32, - unit=self.component_config.configuration.modbus_id) * -1 + def update(self) -> None: + power = self.client.read_holding_registers(4151, ModbusDataType.UINT_32, + unit=self.component_config.configuration.modbus_id) * -1 power = power / 10 _, exported = self.sim_counter.sim_count(power) inverter_state = InverterState( diff --git a/packages/modules/devices/solax/solax/bat.py b/packages/modules/devices/solax/solax/bat.py index b6cb8aedd8..59b89cadb6 100644 --- a/packages/modules/devices/solax/solax/bat.py +++ b/packages/modules/devices/solax/solax/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,14 +12,19 @@ from modules.devices.solax.solax.config import SolaxBatSetup, Solax +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + device_config: Solax + + class SolaxBat(AbstractBat): - def __init__(self, - device_config: Solax, - component_config: Union[Dict, SolaxBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.device_config = device_config - self.component_config = dataclass_from_dict(SolaxBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SolaxBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client = self.kwargs['client'] + self.device_config = self.kwargs['device_config'] 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)) diff --git a/packages/modules/devices/solax/solax/counter.py b/packages/modules/devices/solax/solax/counter.py index 53f55788ff..f25f556e51 100644 --- a/packages/modules/devices/solax/solax/counter.py +++ b/packages/modules/devices/solax/solax/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -14,14 +13,19 @@ from modules.devices.solax.solax.version import SolaxVersion +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + device_config: Solax + + class SolaxCounter(AbstractCounter): - def __init__(self, - device_config: Solax, - component_config: Union[Dict, SolaxCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.device_config = device_config - self.component_config = dataclass_from_dict(SolaxCounterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SolaxCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client = self.kwargs['client'] + self.device_config = self.kwargs['device_config'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solax/solax/device.py b/packages/modules/devices/solax/solax/device.py index 711f0e0b60..081d64d90c 100644 --- a/packages/modules/devices/solax/solax/device.py +++ b/packages/modules/devices/solax/solax/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union 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.common.modbus import ModbusTcpClient_ from modules.devices.solax.solax.bat import SolaxBat @@ -15,27 +14,30 @@ def create_device(device_config: Solax): + client = None + def create_bat_component(component_config: SolaxBatSetup): - return SolaxBat(device_config, component_config, client) + return SolaxBat(component_config, device_config=device_config, client=client) def create_counter_component(component_config: SolaxCounterSetup): - return SolaxCounter(device_config, component_config, client) + return SolaxCounter(component_config, device_config=device_config, client=client) def create_inverter_component(component_config: SolaxInverterSetup): - return SolaxInverter(device_config, component_config, client) + return SolaxInverter(component_config, device_config=device_config, client=client) def update_components(components: Iterable[Union[SolaxBat, SolaxCounter, SolaxInverter]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/solax/solax/inverter.py b/packages/modules/devices/solax/solax/inverter.py index a65e4d15ea..eb3a7129e6 100644 --- a/packages/modules/devices/solax/solax/inverter.py +++ b/packages/modules/devices/solax/solax/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict from pymodbus.constants import Endian -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -14,14 +13,19 @@ from modules.devices.solax.solax.version import SolaxVersion +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + device_config: Solax + + class SolaxInverter(AbstractInverter): - def __init__(self, - device_config: Solax, - component_config: Union[Dict, SolaxInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.device_config = device_config - self.component_config = dataclass_from_dict(SolaxInverterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SolaxInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client = self.kwargs['client'] + self.device_config = self.kwargs['device_config'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/solis/solis/bat.py b/packages/modules/devices/solis/solis/bat.py index 3bc72335e2..06b1326466 100644 --- a/packages/modules/devices/solis/solis/bat.py +++ b/packages/modules/devices/solis/solis/bat.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import logging -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -12,21 +13,29 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + + class SolisBat(AbstractBat): - def __init__(self, component_config: SolisBatSetup) -> None: - self.component_config = dataclass_from_dict(SolisBatSetup, component_config) + def __init__(self, component_config: SolisBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id - power = client.read_input_registers(33149, ModbusDataType.INT_32, unit=unit) * -1 - soc = client.read_input_registers(33139, ModbusDataType.UINT_16, unit=unit) + power = self.client.read_input_registers(33149, ModbusDataType.INT_32, unit=unit) * -1 + soc = self.client.read_input_registers(33139, ModbusDataType.UINT_16, unit=unit) # Geladen in kWh - imported = client.read_input_registers(33161, ModbusDataType.UINT_32, unit=unit) * 1000 + imported = self.client.read_input_registers(33161, ModbusDataType.UINT_32, unit=unit) * 1000 # Entladen in kWh - exported = client.read_input_registers(33165, ModbusDataType.UINT_32, unit=unit) * 1000 + exported = self.client.read_input_registers(33165, ModbusDataType.UINT_32, unit=unit) * 1000 bat_state = BatState( power=power, diff --git a/packages/modules/devices/solis/solis/counter.py b/packages/modules/devices/solis/solis/counter.py index 346c5d4f02..e33b135556 100644 --- a/packages/modules/devices/solis/solis/counter.py +++ b/packages/modules/devices/solis/solis/counter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import Any, TypedDict from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState @@ -9,26 +9,36 @@ from modules.devices.solis.solis.version import SolisVersion +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + version: SolisVersion + + class SolisCounter: - def __init__(self, component_config: SolisCounterSetup, - version: SolisVersion) -> None: - self.component_config = dataclass_from_dict(SolisCounterSetup, component_config) + def __init__(self, component_config: SolisCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['client'] + self.version: SolisVersion = self.kwargs['version'] self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.version = version + self.version = self.kwargs['version'] + self.client = self.kwargs['client'] - def update(self, client: ModbusTcpClient_): + def update(self): unit = self.component_config.configuration.modbus_id register_offset = 30000 if self.version == SolisVersion.inverter: register_offset = -1 - power = client.read_input_registers(3263 + register_offset, ModbusDataType.INT_32, unit=unit) - powers = client.read_input_registers(3257 + register_offset, [ModbusDataType.INT_32]*3, unit=unit) - frequency = client.read_input_registers(3282 + register_offset, ModbusDataType.UINT_16, unit=unit) / 100 - imported = client.read_input_registers(3283 + register_offset, ModbusDataType.UINT_32, unit=unit) * 10 - exported = client.read_input_registers(3285 + register_offset, ModbusDataType.UINT_32, unit=unit) * 10 + power = self.client.read_input_registers(3263 + register_offset, ModbusDataType.INT_32, unit=unit) + powers = self.client.read_input_registers(3257 + register_offset, [ModbusDataType.INT_32]*3, unit=unit) + frequency = self.client.read_input_registers(3282 + register_offset, ModbusDataType.UINT_16, unit=unit) / 100 + imported = self.client.read_input_registers(3283 + register_offset, ModbusDataType.UINT_32, unit=unit) * 10 + exported = self.client.read_input_registers(3285 + register_offset, ModbusDataType.UINT_32, unit=unit) * 10 counter_state = CounterState( imported=imported, diff --git a/packages/modules/devices/solis/solis/device.py b/packages/modules/devices/solis/solis/device.py index 65cdaa4f60..ad8f676a5b 100644 --- a/packages/modules/devices/solis/solis/device.py +++ b/packages/modules/devices/solis/solis/device.py @@ -3,7 +3,6 @@ from typing import Iterable, Union from modules.common.abstract_device import DeviceDescriptor -from modules.common.component_context import SingleComponentUpdateContext from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.solis.solis.bat import SolisBat @@ -16,27 +15,35 @@ def create_device(device_config: Solis): + client = None + def create_bat_component(component_config: SolisBatSetup): - return SolisBat(component_config) + nonlocal client + return SolisBat(component_config, client=client) def create_counter_component(component_config: SolisCounterSetup): - return SolisCounter(component_config, SolisVersion(device_config.configuration.version)) + nonlocal client + return SolisCounter(component_config, version=SolisVersion(device_config.configuration.version), client=client) def create_inverter_component(component_config: SolisInverterSetup): - return SolisInverter(component_config, SolisVersion(device_config.configuration.version)) + nonlocal client + return SolisInverter(component_config, + version=SolisVersion(device_config.configuration.version), + client=client) def update_components(components: Iterable[Union[SolisBat, SolisCounter, SolisInverter]]): - with client as c: + nonlocal client + with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/solis/solis/inverter.py b/packages/modules/devices/solis/solis/inverter.py index b8fcb55887..9e18df42c6 100644 --- a/packages/modules/devices/solis/solis/inverter.py +++ b/packages/modules/devices/solis/solis/inverter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState @@ -11,23 +10,31 @@ from modules.devices.solis.solis.version import SolisVersion +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + version: SolisVersion + + class SolisInverter: - def __init__(self, component_config: Union[Dict, SolisInverterSetup], - version: SolisVersion) -> None: - self.component_config = dataclass_from_dict(SolisInverterSetup, component_config) + def __init__(self, component_config: SolisInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.client: ModbusTcpClient_ = self.kwargs['client'] + self.version: SolisVersion = self.kwargs['version'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - self.version = version - def update(self, client: ModbusTcpClient_) -> None: + def update(self) -> None: unit = self.component_config.configuration.modbus_id if self.version == SolisVersion.inverter: - power = client.read_input_registers(3004, ModbusDataType.UINT_32, unit=unit) * -1 - exported = client.read_input_registers(3008, ModbusDataType.UINT_32, unit=unit) * 1000 + power = self.client.read_input_registers(3004, ModbusDataType.UINT_32, unit=unit) * -1 + exported = self.client.read_input_registers(3008, ModbusDataType.UINT_32, unit=unit) * 1000 elif self.version == SolisVersion.hybrid: - power = client.read_input_registers(33057, ModbusDataType.UINT_32, unit=unit) * -1 - exported = client.read_input_registers(33029, ModbusDataType.UINT_32, unit=unit) * 1000 + power = self.client.read_input_registers(33057, ModbusDataType.UINT_32, unit=unit) * -1 + exported = self.client.read_input_registers(33029, ModbusDataType.UINT_32, unit=unit) * 1000 inverter_state = InverterState( power=power, diff --git a/packages/modules/devices/sonnen/sonnenbatterie/bat.py b/packages/modules/devices/sonnen/sonnenbatterie/bat.py index 5ac3cc8bbb..c22ce2dd4e 100644 --- a/packages/modules/devices/sonnen/sonnenbatterie/bat.py +++ b/packages/modules/devices/sonnen/sonnenbatterie/bat.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -15,16 +14,21 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + device_address: str + device_variant: int + + class SonnenbatterieBat(AbstractBat): - def __init__(self, - device_id: int, - device_address: str, - device_variant: int, - component_config: Union[Dict, SonnenbatterieBatSetup]) -> None: - self.__device_id = device_id - self.__device_address = device_address - self.__device_variant = device_variant - self.component_config = dataclass_from_dict(SonnenbatterieBatSetup, component_config) + def __init__(self, component_config: SonnenbatterieBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__device_address: str = self.kwargs['device_address'] + self.__device_variant: int = self.kwargs['device_variant'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/sonnen/sonnenbatterie/counter.py b/packages/modules/devices/sonnen/sonnenbatterie/counter.py index fa2a266a03..5a0180ca96 100644 --- a/packages/modules/devices/sonnen/sonnenbatterie/counter.py +++ b/packages/modules/devices/sonnen/sonnenbatterie/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -15,16 +14,21 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + device_address: str + device_variant: int + + class SonnenbatterieCounter(AbstractCounter): - def __init__(self, - device_id: int, - device_address: str, - device_variant: int, - component_config: Union[Dict, SonnenbatterieCounterSetup]) -> None: - self.__device_id = device_id - self.__device_address = device_address - self.__device_variant = device_variant - self.component_config = dataclass_from_dict(SonnenbatterieCounterSetup, component_config) + def __init__(self, component_config: SonnenbatterieCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__device_address: str = self.kwargs['device_address'] + self.__device_variant: int = self.kwargs['device_variant'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sonnen/sonnenbatterie/device.py b/packages/modules/devices/sonnen/sonnenbatterie/device.py index bfd73cdb81..34eab8948c 100644 --- a/packages/modules/devices/sonnen/sonnenbatterie/device.py +++ b/packages/modules/devices/sonnen/sonnenbatterie/device.py @@ -18,22 +18,22 @@ 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) + return SonnenbatterieBat(component_config, + device_id=device_config.id, + device_address=device_config.configuration.ip_address, + device_variant=device_config.configuration.variant) def create_counter_component(component_config: SonnenbatterieCounterSetup): - return SonnenbatterieCounter(device_config.id, - device_config.configuration.ip_address, - device_config.configuration.variant, - component_config) + return SonnenbatterieCounter(component_config, + device_id=device_config.id, + device_address=device_config.configuration.ip_address, + device_variant=device_config.configuration.variant) def create_inverter_component(component_config: SonnenbatterieInverterSetup): - return SonnenbatterieInverter(device_config.id, - device_config.configuration.ip_address, - device_config.configuration.variant, - component_config) + return SonnenbatterieInverter(component_config, + device_id=device_config.id, + device_address=device_config.configuration.ip_address, + device_variant=device_config.configuration.variant) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/sonnen/sonnenbatterie/inverter.py b/packages/modules/devices/sonnen/sonnenbatterie/inverter.py index a8b4122d0a..fdf71f4290 100644 --- a/packages/modules/devices/sonnen/sonnenbatterie/inverter.py +++ b/packages/modules/devices/sonnen/sonnenbatterie/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -15,16 +14,21 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + device_address: str + device_variant: int + + class SonnenbatterieInverter(AbstractInverter): - def __init__(self, - device_id: int, - device_address: str, - device_variant: int, - component_config: Union[Dict, SonnenbatterieInverterSetup]) -> None: - self.__device_id = device_id - self.__device_address = device_address - self.__device_variant = device_variant - self.component_config = dataclass_from_dict(SonnenbatterieInverterSetup, component_config) + def __init__(self, component_config: SonnenbatterieInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__device_address: str = self.kwargs['device_address'] + self.__device_variant: int = self.kwargs['device_variant'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/studer/studer/bat.py b/packages/modules/devices/studer/studer/bat.py index 8505f06761..707e7814fd 100644 --- a/packages/modules/devices/studer/studer/bat.py +++ b/packages/modules/devices/studer/studer/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -12,12 +11,17 @@ from modules.devices.studer.studer.config import StuderBatSetup +class KwargsDict(TypedDict): + client: modbus.ModbusTcpClient_ + + class StuderBat(AbstractBat): - def __init__(self, - component_config: Union[Dict, StuderBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(StuderBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: StuderBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.store = get_bat_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/studer/studer/device.py b/packages/modules/devices/studer/studer/device.py index dbbd51528a..13e0a35c58 100644 --- a/packages/modules/devices/studer/studer/device.py +++ b/packages/modules/devices/studer/studer/device.py @@ -1,12 +1,9 @@ #!/usr/bin/env python3 -""" Modul zum Auslesen von Alpha Ess Speichern, Zählern und Wechselrichtern. -""" import logging from typing import Iterable, Union from modules.common import modbus 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.studer.studer.bat import StuderBat from modules.devices.studer.studer.config import Studer, StuderBatSetup, StuderInverterSetup @@ -16,24 +13,29 @@ def create_device(device_config: Studer): + client = None + def create_bat_component(component_config: StuderBatSetup): - return StuderBat(component_config, client) + nonlocal client + return StuderBat(component_config, client=client) def create_inverter_component(component_config: StuderInverterSetup): - return StuderInverter(component_config, client) + nonlocal client + return StuderInverter(component_config, client=client) def update_components(components: Iterable[Union[StuderBat, StuderInverter]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, inverter=create_inverter_component, diff --git a/packages/modules/devices/studer/studer/inverter.py b/packages/modules/devices/studer/studer/inverter.py index 1384cbb4cc..ed267c57d3 100644 --- a/packages/modules/devices/studer/studer/inverter.py +++ b/packages/modules/devices/studer/studer/inverter.py @@ -1,23 +1,26 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict -from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState -from modules.common.modbus import ModbusDataType +from modules.common.modbus import ModbusDataType, ModbusTcpClient_ from modules.common.store import get_inverter_value_store from modules.devices.studer.studer.config import StuderInverterSetup +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + + class StuderInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, StuderInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.component_config = dataclass_from_dict(StuderInverterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: StuderInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__tcp_client: ModbusTcpClient_ = self.kwargs['client'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sungrow/sungrow/bat.py b/packages/modules/devices/sungrow/sungrow/bat.py index 9dbeeea25e..f4da93378d 100644 --- a/packages/modules/devices/sungrow/sungrow/bat.py +++ b/packages/modules/devices/sungrow/sungrow/bat.py @@ -1,13 +1,11 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict -from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState -from modules.common.modbus import ModbusDataType, Endian +from modules.common.modbus import ModbusDataType, Endian, ModbusTcpClient_ from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store from modules.devices.sungrow.sungrow.config import SungrowBatSetup, Sungrow @@ -15,14 +13,19 @@ from modules.devices.sungrow.sungrow.firmware import Firmware +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + device_config: Sungrow + + class SungrowBat(AbstractBat): - def __init__(self, - device_config: Union[Dict, Sungrow], - component_config: Union[Dict, SungrowBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.device_config = device_config - self.component_config = dataclass_from_dict(SungrowBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SungrowBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.device_config: Sungrow = self.kwargs['device_config'] + self.__tcp_client: ModbusTcpClient_ = self.kwargs['client'] 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)) diff --git a/packages/modules/devices/sungrow/sungrow/counter.py b/packages/modules/devices/sungrow/sungrow/counter.py index 03bf21cdf3..67e6cf849d 100644 --- a/packages/modules/devices/sungrow/sungrow/counter.py +++ b/packages/modules/devices/sungrow/sungrow/counter.py @@ -1,28 +1,31 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict -from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState -from modules.common.modbus import ModbusDataType, Endian -from modules.common.simcount import SimCounter +from modules.common.modbus import Endian, ModbusDataType, ModbusTcpClient_ +from modules.common.simcount._simcounter import SimCounter from modules.common.store import get_counter_value_store -from modules.devices.sungrow.sungrow.config import SungrowCounterSetup, Sungrow +from modules.devices.sungrow.sungrow.config import Sungrow, SungrowCounterSetup from modules.devices.sungrow.sungrow.version import Version +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + device_config: Sungrow + + class SungrowCounter(AbstractCounter): - def __init__(self, - device_config: Union[Dict, Sungrow], - component_config: Union[Dict, SungrowCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.device_config = device_config - self.component_config = dataclass_from_dict(SungrowCounterSetup, component_config) - self.__tcp_client = tcp_client - self.sim_counter = SimCounter(self.device_config.id, self.component_config.id, prefix="bezug") + def __init__(self, component_config: SungrowCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.device_config: Sungrow = self.kwargs['device_config'] + self.__tcp_client: ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter(self.device_config.id, self.component_config.id, prefix="evu") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.fault_text = "Dieser Sungrow Zähler liefert von Werk aus (entgegen der Dokumentation) "\ diff --git a/packages/modules/devices/sungrow/sungrow/device.py b/packages/modules/devices/sungrow/sungrow/device.py index 8de4c559c8..b9becf32a5 100644 --- a/packages/modules/devices/sungrow/sungrow/device.py +++ b/packages/modules/devices/sungrow/sungrow/device.py @@ -4,7 +4,6 @@ from modules.common import modbus 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 @@ -15,36 +14,40 @@ def create_device(device_config: Sungrow): + client = None + def create_bat_component(component_config: SungrowBatSetup): - return SungrowBat(device_config, component_config, client) + nonlocal client + return SungrowBat(component_config, device_config=device_config, client=client) def create_counter_component(component_config: SungrowCounterSetup): - return SungrowCounter(device_config, component_config, client) + nonlocal client + return SungrowCounter(component_config, device_config=device_config, client=client) def create_inverter_component(component_config: SungrowInverterSetup): - return SungrowInverter(device_config, component_config, client) + nonlocal client + return SungrowInverter(component_config, device_config=device_config, client=client) def update_components(components: Iterable[Union[SungrowBat, SungrowCounter, SungrowInverter]]): + nonlocal client with client: for component in components: if isinstance(component, SungrowInverter): - with SingleComponentUpdateContext(component.fault_state): - pv_power = component.update() + pv_power = component.update() for component in components: if isinstance(component, SungrowCounter): - with SingleComponentUpdateContext(component.fault_state): - component.update(pv_power) + component.update(pv_power) for component in components: if isinstance(component, SungrowBat): - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/sungrow/sungrow/inverter.py b/packages/modules/devices/sungrow/sungrow/inverter.py index 827e39c353..fe30c6f798 100644 --- a/packages/modules/devices/sungrow/sungrow/inverter.py +++ b/packages/modules/devices/sungrow/sungrow/inverter.py @@ -1,27 +1,30 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict -from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState -from modules.common.modbus import ModbusDataType, Endian +from modules.common.modbus import ModbusDataType, Endian, ModbusTcpClient_ from modules.common.simcount import SimCounter from modules.common.store import get_inverter_value_store from modules.devices.sungrow.sungrow.config import SungrowInverterSetup, Sungrow from modules.devices.sungrow.sungrow.version import Version +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + device_config: Sungrow + + class SungrowInverter(AbstractInverter): - def __init__(self, - device_config: Union[Dict, Sungrow], - component_config: Union[Dict, SungrowInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.device_config = device_config - self.component_config = dataclass_from_dict(SungrowInverterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: SungrowInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.device_config: Sungrow = self.kwargs['device_config'] + self.__tcp_client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.device_config.id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/sunways/sunways/device.py b/packages/modules/devices/sunways/sunways/device.py index 9844567d22..f4c1d1be0b 100644 --- a/packages/modules/devices/sunways/sunways/device.py +++ b/packages/modules/devices/sunways/sunways/device.py @@ -12,8 +12,8 @@ def create_device(device_config: Sunways): def create_inverter_component(component_config: SunwaysInverterSetup): return SunwaysInverter(component_config, - device_config.configuration.ip_address, - device_config.configuration.password) + ip_address=device_config.configuration.ip_address, + password=device_config.configuration.password) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/sunways/sunways/inverter.py b/packages/modules/devices/sunways/sunways/inverter.py index f1e3684d0e..5443b891cf 100644 --- a/packages/modules/devices/sunways/sunways/inverter.py +++ b/packages/modules/devices/sunways/sunways/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict from requests.auth import HTTPDigestAuth -from dataclass_utils import dataclass_from_dict from modules.common import req from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -18,15 +17,19 @@ """ +class KwargsDict(TypedDict): + ip_address: str + password: str + + class SunwaysInverter(AbstractInverter): - def __init__(self, - component_config: Union[Dict, SunwaysInverterSetup], - ip_address: str, - password: str) -> None: - - self.component_config = dataclass_from_dict(SunwaysInverterSetup, component_config) - self.ip_address = ip_address - self.password = password + def __init__(self, component_config: SunwaysInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.ip_address: str = self.kwargs['ip_address'] + self.password: str = self.kwargs['password'] self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/tasmota/tasmota/counter.py b/packages/modules/devices/tasmota/tasmota/counter.py index cff9f68d39..01c35f0d90 100644 --- a/packages/modules/devices/tasmota/tasmota/counter.py +++ b/packages/modules/devices/tasmota/tasmota/counter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict import logging -from dataclass_utils import dataclass_from_dict from modules.devices.tasmota.tasmota.config import TasmotaCounterSetup from modules.common.abstract_device import AbstractCounter from modules.common.tasmota import Tasmota @@ -13,23 +12,24 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + ip_address: str + phase: int + + class TasmotaCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, TasmotaCounterSetup], - ip_address: str, - phase: int) -> None: - self.__device_id = device_id - self.__ip_address = ip_address - if phase: - self.__phase = phase - else: - self.__phase = 1 - self.component_config = dataclass_from_dict(TasmotaCounterSetup, component_config) + def __init__(self, component_config: TasmotaCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__ip_address: str = self.kwargs['ip_address'] + self.__phase: int = self.kwargs['phase'] self.store = get_counter_value_store(self.component_config.id) - self.component_info = ComponentInfo.from_component_config(self.component_config) - self.__tasmota = Tasmota(self.__device_id, self.__ip_address, self.__phase) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) + self.__tasmota = Tasmota(self.__device_id, self.__ip_address, self.__phase) def update(self): log.debug("tasmota.counter.update: " + self.__ip_address) diff --git a/packages/modules/devices/tasmota/tasmota/device.py b/packages/modules/devices/tasmota/tasmota/device.py index d571ad3847..58d34f98de 100644 --- a/packages/modules/devices/tasmota/tasmota/device.py +++ b/packages/modules/devices/tasmota/tasmota/device.py @@ -11,10 +11,10 @@ def create_device(device_config: Tasmota): def create_counter_component(component_config: TasmotaCounterSetup): - return TasmotaCounter(device_config.id, - component_config, - device_config.configuration.ip_address, - int(device_config.configuration.phase)) + return TasmotaCounter(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address, + phase=int(device_config.configuration.phase)) return ConfigurableDevice( device_config=device_config, diff --git a/packages/modules/devices/tesla/tesla/bat.py b/packages/modules/devices/tesla/tesla/bat.py index 8383a4aaad..01f32b5153 100644 --- a/packages/modules/devices/tesla/tesla/bat.py +++ b/packages/modules/devices/tesla/tesla/bat.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -from typing import Dict, Union -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -12,8 +10,10 @@ class TeslaBat(AbstractBat): - def __init__(self, component_config: Union[Dict, TeslaBatSetup]) -> None: - self.component_config = dataclass_from_dict(TeslaBatSetup, component_config) + def __init__(self, component_config: TeslaBatSetup) -> None: + self.component_config = component_config + + 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)) diff --git a/packages/modules/devices/tesla/tesla/counter.py b/packages/modules/devices/tesla/tesla/counter.py index f135afe439..277048c5ca 100644 --- a/packages/modules/devices/tesla/tesla/counter.py +++ b/packages/modules/devices/tesla/tesla/counter.py @@ -1,9 +1,7 @@ #!/usr/bin/env python3 -from typing import Dict, Union import logging from requests import HTTPError -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -16,8 +14,10 @@ class TeslaCounter(AbstractCounter): - def __init__(self, component_config: Union[Dict, TeslaCounterSetup]) -> None: - self.component_config = dataclass_from_dict(TeslaCounterSetup, component_config) + def __init__(self, component_config: TeslaCounterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/tesla/tesla/device.py b/packages/modules/devices/tesla/tesla/device.py index 0d6bbd2d61..2494e0b0fa 100644 --- a/packages/modules/devices/tesla/tesla/device.py +++ b/packages/modules/devices/tesla/tesla/device.py @@ -38,6 +38,9 @@ def _authenticate(session: requests.Session, url: str, email: str, password: str def create_device(device_config: Tesla): + http_client = None + session = None + def create_bat_component(component_config: TeslaBatSetup): return TeslaBat(component_config) @@ -49,7 +52,7 @@ def create_inverter_component(component_config: TeslaInverterSetup): def update_components(components: Iterable[Union[TeslaBat, TeslaCounter, TeslaInverter]]): log.debug("Beginning update") - nonlocal http_client + nonlocal http_client, session address = device_config.configuration.ip_address email = device_config.configuration.email password = device_config.configuration.password @@ -69,10 +72,14 @@ def update_components(components: Iterable[Union[TeslaBat, TeslaCounter, TeslaIn __update_components(http_client, components) log.debug("Update completed successfully") - session = get_http_session() - http_client = PowerwallHttpClient(device_config.configuration.ip_address, session, None) + def initializer(): + nonlocal http_client, session + session = get_http_session() + http_client = PowerwallHttpClient(device_config.configuration.ip_address, session, None) + return ConfigurableDevice( device_config=device_config, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/tesla/tesla/inverter.py b/packages/modules/devices/tesla/tesla/inverter.py index 186cef65fa..7aea4b24b8 100644 --- a/packages/modules/devices/tesla/tesla/inverter.py +++ b/packages/modules/devices/tesla/tesla/inverter.py @@ -1,7 +1,4 @@ #!/usr/bin/env python3 -from typing import Dict, Union - -from dataclass_utils import dataclass_from_dict from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -12,8 +9,10 @@ class TeslaInverter(AbstractInverter): - def __init__(self, component_config: Union[Dict, TeslaInverterSetup]) -> None: - self.component_config = dataclass_from_dict(TeslaInverterSetup, component_config) + def __init__(self, component_config: TeslaInverterSetup) -> None: + self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/varta/varta/bat_api.py b/packages/modules/devices/varta/varta/bat_api.py index 021c250ded..a7475d8bf1 100644 --- a/packages/modules/devices/varta/varta/bat_api.py +++ b/packages/modules/devices/varta/varta/bat_api.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import xml.etree.ElementTree as ET -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any from modules.common import req from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -12,11 +12,19 @@ from modules.devices.varta.varta.config import VartaBatApiSetup +class KwargsDict(TypedDict): + device_id: int + ip_address: str + + class VartaBatApi(AbstractBat): - def __init__(self, device_id: int, component_config: VartaBatApiSetup, device_address: str) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VartaBatApiSetup, component_config) - self.__device_address = device_address + def __init__(self, component_config: VartaBatApiSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.ip_address: str = self.kwargs['ip_address'] self.sim_counter = SimCounter(self.__device_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)) @@ -33,7 +41,7 @@ def get_xml_text(attribute_value: str) -> float: # Wenn Speicher aus bzw. im Standby (keine Antwort), ersetze leeren Wert durch eine 0. return 0 - response = req.get_http_session().get('http://'+self.__device_address+'/cgi/ems_data.xml', + response = req.get_http_session().get('http://'+self.ip_address+'/cgi/ems_data.xml', timeout=5) response.encoding = 'utf-8' response = response.text.replace("\n", "") diff --git a/packages/modules/devices/varta/varta/bat_modbus.py b/packages/modules/devices/varta/varta/bat_modbus.py index 8267991145..f0ac3b5b31 100644 --- a/packages/modules/devices/varta/varta/bat_modbus.py +++ b/packages/modules/devices/varta/varta/bat_modbus.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState from modules.common.component_type import ComponentDescriptor @@ -10,23 +11,31 @@ from modules.devices.varta.varta.config import VartaBatModbusSetup +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: ModbusTcpClient_ + + class VartaBatModbus(AbstractBat): - def __init__(self, device_id: int, - component_config: VartaBatModbusSetup, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VartaBatModbusSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: VartaBatModbusSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_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, client: ModbusTcpClient_) -> None: - self.set_state(self.get_state(client)) + def update(self) -> None: + self.set_state(self.get_state()) - def get_state(self, client: ModbusTcpClient_) -> BatState: - soc = client.read_holding_registers(1068, ModbusDataType.INT_16, unit=self.__modbus_id) - power = client.read_holding_registers(1066, ModbusDataType.INT_16, unit=self.__modbus_id) + def get_state(self) -> BatState: + soc = self.client.read_holding_registers(1068, ModbusDataType.INT_16, unit=self.__modbus_id) + power = self.client.read_holding_registers(1066, ModbusDataType.INT_16, unit=self.__modbus_id) return BatState( power=power, soc=soc, diff --git a/packages/modules/devices/varta/varta/counter.py b/packages/modules/devices/varta/varta/counter.py index 244069ef0c..0f84a0fb23 100644 --- a/packages/modules/devices/varta/varta/counter.py +++ b/packages/modules/devices/varta/varta/counter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -10,19 +11,27 @@ from modules.devices.varta.varta.config import VartaCounterSetup +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: ModbusTcpClient_ + + class VartaCounter(AbstractCounter): - def __init__(self, device_id: int, - component_config: VartaCounterSetup, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VartaCounterSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: VartaCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_): - power = client.read_holding_registers(1078, ModbusDataType.INT_16, unit=self.__modbus_id) * -1 + def update(self): + power = self.client.read_holding_registers(1078, ModbusDataType.INT_16, unit=self.__modbus_id) * -1 imported, exported = self.sim_counter.sim_count(power) counter_state = CounterState( diff --git a/packages/modules/devices/varta/varta/device.py b/packages/modules/devices/varta/varta/device.py index 0e34ee40f4..19892093e6 100644 --- a/packages/modules/devices/varta/varta/device.py +++ b/packages/modules/devices/varta/varta/device.py @@ -21,35 +21,51 @@ def create_device(device_config: Varta): + client = None + def create_bat_api_component(component_config: VartaBatApiSetup): - return VartaBatApi(device_config.id, component_config, device_config.configuration.ip_address) + return VartaBatApi(component_config, + device_id=device_config.id, + ip_address=device_config.configuration.ip_address) def create_bat_modbus_component(component_config: VartaBatModbusSetup): - return VartaBatModbus(device_config.id, component_config, device_config.configuration.modbus_id) + nonlocal client + return VartaBatModbus(component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_counter_component(component_config: VartaCounterSetup): - return VartaCounter(device_config.id, component_config, device_config.configuration.modbus_id) + nonlocal client + return VartaCounter(component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def create_inverter_component(component_config: VartaInverterSetup): - return VartaInverter(device_config.id, component_config, device_config.configuration.modbus_id) + nonlocal client + return VartaInverter(component_config, + device_id=device_config.id, + modbus_id=device_config.configuration.modbus_id, + client=client) def update_components(components: Iterable[Union[VartaBatApi, VartaBatModbus, VartaCounter, VartaInverter]]): - with client as c: + nonlocal client + with client: for component in components: if isinstance(component, (VartaBatModbus, VartaCounter, VartaInverter)): - with SingleComponentUpdateContext(component.fault_state): - component.update(c) + component.update() for component in components: if isinstance(component, (VartaBatApi)): - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat_api=create_bat_api_component, bat_modbus=create_bat_modbus_component, diff --git a/packages/modules/devices/varta/varta/inverter.py b/packages/modules/devices/varta/varta/inverter.py index 6be1b430fd..5c7627a819 100644 --- a/packages/modules/devices/varta/varta/inverter.py +++ b/packages/modules/devices/varta/varta/inverter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor from modules.common.fault_state import ComponentInfo, FaultState @@ -9,19 +10,27 @@ from modules.devices.varta.varta.config import VartaInverterSetup +class KwargsDict(TypedDict): + device_id: int + modbus_id: int + client: ModbusTcpClient_ + + class VartaInverter: - def __init__(self, device_id: int, - component_config: VartaInverterSetup, - modbus_id: int) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VartaInverterSetup, component_config) - self.__modbus_id = modbus_id + def __init__(self, component_config: VartaInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__modbus_id: int = self.kwargs['modbus_id'] + self.client: ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) - def update(self, client: ModbusTcpClient_): - power = client.read_holding_registers(1102, ModbusDataType.UINT_16, unit=self.__modbus_id) * -1 + def update(self): + power = self.client.read_holding_registers(1102, ModbusDataType.UINT_16, unit=self.__modbus_id) * -1 _, exported = self.sim_counter.sim_count(power) inverter_state = InverterState( diff --git a/packages/modules/devices/victron/victron/bat.py b/packages/modules/devices/victron/victron/bat.py index 0e58b5fd7f..a6c1003caa 100644 --- a/packages/modules/devices/victron/victron/bat.py +++ b/packages/modules/devices/victron/victron/bat.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import Any, TypedDict -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractBat from modules.common.component_state import BatState @@ -13,14 +12,19 @@ from modules.devices.victron.victron.config import VictronBatSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class VictronBat(AbstractBat): - def __init__(self, - device_id: int, - component_config: Union[Dict, VictronBatSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VictronBatSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: VictronBatSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_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)) diff --git a/packages/modules/devices/victron/victron/counter.py b/packages/modules/devices/victron/victron/counter.py index 00a992cfd7..138fa638a4 100644 --- a/packages/modules/devices/victron/victron/counter.py +++ b/packages/modules/devices/victron/victron/counter.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState @@ -13,14 +12,19 @@ from modules.devices.victron.victron.config import VictronCounterSetup +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class VictronCounter(AbstractCounter): - def __init__(self, - device_id: int, - component_config: Union[Dict, VictronCounterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VictronCounterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: VictronCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/victron/victron/device.py b/packages/modules/devices/victron/victron/device.py index c74fdda0f8..e821a76412 100644 --- a/packages/modules/devices/victron/victron/device.py +++ b/packages/modules/devices/victron/victron/device.py @@ -3,8 +3,6 @@ from typing import Iterable, Union 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.common.modbus import ModbusTcpClient_ from modules.devices.victron.victron.bat import VictronBat @@ -16,27 +14,33 @@ def create_device(device_config: Victron): + client = None + def create_bat_component(component_config: VictronBatSetup): - return VictronBat(device_config.id, component_config, client) + nonlocal client + return VictronBat(component_config, device_id=device_config.id, client=client) def create_counter_component(component_config: VictronCounterSetup): - return VictronCounter(device_config.id, component_config, client) + nonlocal client + return VictronCounter(component_config, device_id=device_config.id, client=client) def create_inverter_component(component_config: VictronInverterSetup): - return VictronInverter(device_config.id, component_config, client) + nonlocal client + return VictronInverter(component_config, device_id=device_config.id, client=client) def update_components(components: Iterable[Union[VictronBat, VictronCounter, VictronInverter]]): + nonlocal client with client: for component in components: - with SingleComponentUpdateContext(component.fault_state): - component.update() + component.update() - try: + def initializer(): + nonlocal client 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, + initializer=initializer, component_factory=ComponentFactoryByType( bat=create_bat_component, counter=create_counter_component, diff --git a/packages/modules/devices/victron/victron/inverter.py b/packages/modules/devices/victron/victron/inverter.py index 91899b389b..84b677e13e 100644 --- a/packages/modules/devices/victron/victron/inverter.py +++ b/packages/modules/devices/victron/victron/inverter.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 import logging -from typing import Dict, Union +from typing import TypedDict, Any -from dataclass_utils import dataclass_from_dict from modules.common import modbus from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState @@ -16,14 +15,19 @@ log = logging.getLogger(__name__) +class KwargsDict(TypedDict): + device_id: int + client: modbus.ModbusTcpClient_ + + class VictronInverter(AbstractInverter): - def __init__(self, - device_id: int, - component_config: Union[Dict, VictronInverterSetup], - tcp_client: modbus.ModbusTcpClient_) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VictronInverterSetup, component_config) - self.__tcp_client = tcp_client + def __init__(self, component_config: VictronInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] + self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['client'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/vzlogger/vzlogger/counter.py b/packages/modules/devices/vzlogger/vzlogger/counter.py index 04f4cde876..0927af64e7 100644 --- a/packages/modules/devices/vzlogger/vzlogger/counter.py +++ b/packages/modules/devices/vzlogger/vzlogger/counter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractCounter from modules.common.component_state import CounterState from modules.common.component_type import ComponentDescriptor @@ -10,10 +11,17 @@ from modules.devices.vzlogger.vzlogger.utils import parse_line +class KwargsDict(TypedDict): + device_id: int + + class VZLoggerCounter(AbstractCounter): - def __init__(self, device_id: int, component_config: VZLoggerCounterSetup) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VZLoggerCounterSetup, component_config) + def __init__(self, component_config: VZLoggerCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug") self.store = get_counter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/vzlogger/vzlogger/device.py b/packages/modules/devices/vzlogger/vzlogger/device.py index 30a948d68c..fadfdcafc5 100644 --- a/packages/modules/devices/vzlogger/vzlogger/device.py +++ b/packages/modules/devices/vzlogger/vzlogger/device.py @@ -14,10 +14,10 @@ def create_device(device_config: VZLogger): def create_counter_component(component_config: VZLoggerCounterSetup): - return VZLoggerCounter(device_config.id, component_config) + return VZLoggerCounter(component_config, device_id=device_config.id) def create_inverter_component(component_config: VZLoggerInverterSetup): - return VZLoggerInverter(device_config.id, component_config) + return VZLoggerInverter(component_config, device_id=device_config.id) def update_components(components: Iterable[Union[VZLoggerCounter, VZLoggerInverter]]): response = req.get_http_session().get(device_config.configuration.ip_address, timeout=5).json() diff --git a/packages/modules/devices/vzlogger/vzlogger/inverter.py b/packages/modules/devices/vzlogger/vzlogger/inverter.py index ac953309b2..fda1d30dc2 100644 --- a/packages/modules/devices/vzlogger/vzlogger/inverter.py +++ b/packages/modules/devices/vzlogger/vzlogger/inverter.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -from dataclass_utils import dataclass_from_dict +from typing import TypedDict, Any + from modules.common.abstract_device import AbstractInverter from modules.common.component_state import InverterState from modules.common.component_type import ComponentDescriptor @@ -10,10 +11,17 @@ from modules.devices.vzlogger.vzlogger.utils import parse_line +class KwargsDict(TypedDict): + device_id: int + + class VZLoggerInverter(AbstractInverter): - def __init__(self, device_id: int, component_config: VZLoggerInverterSetup) -> None: - self.__device_id = device_id - self.component_config = dataclass_from_dict(VZLoggerInverterSetup, component_config) + def __init__(self, component_config: VZLoggerInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.__device_id: int = self.kwargs['device_id'] self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv") self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) diff --git a/packages/modules/devices/youless/youless/inverter.py b/packages/modules/devices/youless/youless/inverter.py index 63bdf3bda7..a26da3a205 100644 --- a/packages/modules/devices/youless/youless/inverter.py +++ b/packages/modules/devices/youless/youless/inverter.py @@ -10,6 +10,8 @@ class YoulessInverter(AbstractInverter): def __init__(self, component_config: YoulessInverterSetup) -> None: self.component_config = component_config + + def initialize(self) -> None: self.store = get_inverter_value_store(self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))