diff --git a/packages/modules/devices/kaco/kaco_nh/bat.py b/packages/modules/devices/kaco/kaco_nh/bat.py new file mode 100644 index 0000000000..01ca5c7159 --- /dev/null +++ b/packages/modules/devices/kaco/kaco_nh/bat.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +from typing import Any, TypedDict + +from modules.common import req +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.kaco.kaco_nh.config import KacoNHBatSetup +from modules.devices.kaco.kaco_nh.config import KacoNHConfiguration + + +class KwargsDict(TypedDict): + device_config: KacoNHConfiguration + device_id: int + + +class KacoNHBat(AbstractBat): + def __init__(self, component_config: KacoNHBatSetup, **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: KacoNHConfiguration = self.kwargs['device_config'] + 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: + response = req.get_http_session().get( + 'http://' + self.device_config.ip_address + ':' + str(self.device_config.port) + '/getdevdata.cgi?device=' + + str(self.component_config.configuration.id) + '&sn=' + self.device_config.serial_number, + timeout=5).json() + power = int(response["pb"]) * -1 + soc = float(response["soc"]) + + imported, exported = self.sim_counter.sim_count(power) + bat_state = BatState( + power=power, + soc=soc, + imported=imported, + exported=exported + ) + self.store.set(bat_state) + + +component_descriptor = ComponentDescriptor(configuration_factory=KacoNHBatSetup) diff --git a/packages/modules/devices/kaco/kaco_nh/config.py b/packages/modules/devices/kaco/kaco_nh/config.py new file mode 100644 index 0000000000..75a2010a36 --- /dev/null +++ b/packages/modules/devices/kaco/kaco_nh/config.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +from typing import Optional + +from modules.common.component_setup import ComponentSetup +from ..vendor import vendor_descriptor + + +class KacoNHConfiguration: + def __init__(self, ip_address: Optional[str] = None, + port: Optional[int] = None, + serial_number: Optional[str] = None): + self.ip_address = ip_address + self.port = port + self.serial_number = serial_number + + +class KacoNH: + def __init__(self, + name: str = "Kaco NH", + type: str = "kaco_nh", + id: int = 0, + configuration: KacoNHConfiguration = None) -> None: + self.name = name + self.type = type + self.vendor = vendor_descriptor.configuration_factory().type + self.id = id + self.configuration = configuration or KacoNHConfiguration() + + +class KacoNHBatConfiguration: + def __init__(self, id: int = 0): + self.id = id + + +class KacoNHBatSetup(ComponentSetup[KacoNHBatConfiguration]): + def __init__(self, + name: str = "Kaco NH Speicher", + type: str = "bat", + id: int = 0, + configuration: KacoNHBatConfiguration = None) -> None: + super().__init__(name, type, id, configuration or KacoNHBatConfiguration()) + + +class KacoNHCounterConfiguration: + def __init__(self, id: int = 0): + self.id = id + + +class KacoNHCounterSetup(ComponentSetup[KacoNHCounterConfiguration]): + def __init__(self, + name: str = "Kaco NH Zähler", + type: str = "counter", + id: int = 0, + configuration: KacoNHCounterConfiguration = None) -> None: + super().__init__(name, type, id, configuration or KacoNHCounterConfiguration()) + + +class KacoNHInverterConfiguration: + def __init__(self, id: int = 0): + self.id = id + + +class KacoNHInverterSetup(ComponentSetup[KacoNHInverterConfiguration]): + def __init__(self, + name: str = "KacoNH Wechselrichter", + type: str = "inverter", + id: int = 0, + configuration: KacoNHInverterConfiguration = None) -> None: + super().__init__(name, type, id, configuration or KacoNHInverterConfiguration()) diff --git a/packages/modules/devices/kaco/kaco_nh/counter.py b/packages/modules/devices/kaco/kaco_nh/counter.py new file mode 100644 index 0000000000..f52a6e75b4 --- /dev/null +++ b/packages/modules/devices/kaco/kaco_nh/counter.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +from typing import TypedDict, Any + +from modules.common import req +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.store import get_counter_value_store +from modules.devices.kaco.kaco_nh.config import KacoNHConfiguration, KacoNHCounterSetup + + +class KwargsDict(TypedDict): + device_config: KacoNHConfiguration + + +class KacoNHCounter(AbstractCounter): + def __init__(self, component_config: KacoNHCounterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.device_config: KacoNHConfiguration = 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)) + + def update(self) -> None: + response = req.get_http_session().get( + 'http://' + self.device_config.ip_address + ':' + str(self.device_config.port) + '/getdevdata.cgi?device=' + + str(self.component_config.configuration.id) + '&sn=' + self.device_config.serial_number, + timeout=5).json() + power = float(response["pac"]) + imported = float(response["iet"]) * 100 + exported = float(response["oet"]) * 100 + + counter_state = CounterState( + imported=imported, + exported=exported, + power=power + ) + self.store.set(counter_state) + + +component_descriptor = ComponentDescriptor(configuration_factory=KacoNHCounterSetup) diff --git a/packages/modules/devices/kaco/kaco_nh/device.py b/packages/modules/devices/kaco/kaco_nh/device.py new file mode 100644 index 0000000000..243fa864e6 --- /dev/null +++ b/packages/modules/devices/kaco/kaco_nh/device.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import logging +from typing import Iterable, Union + +from modules.common.abstract_device import DeviceDescriptor +from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater +from modules.devices.kaco.kaco_nh.bat import KacoNHBat +from modules.devices.kaco.kaco_nh.config import (KacoNH, KacoNHBatSetup, + KacoNHCounterSetup, KacoNHInverterSetup) +from modules.devices.kaco.kaco_nh.counter import KacoNHCounter +from modules.devices.kaco.kaco_nh.inverter import KacoNHInverter + +log = logging.getLogger(__name__) + + +def create_device(device_config: KacoNH): + def create_bat_component(component_config: KacoNHBatSetup): + return KacoNHBat(component_config=component_config, + device_config=device_config.configuration, + device_id=device_config.id) + + def create_counter_component(component_config: KacoNHCounterSetup): + return KacoNHCounter(component_config=component_config, + device_config=device_config.configuration) + + def create_inverter_component(component_config: KacoNHInverterSetup): + return KacoNHInverter(component_config=component_config, + device_config=device_config.configuration) + + def update_components(components: Iterable[Union[KacoNHBat, KacoNHCounter, KacoNHInverter]]): + for component in components: + component.update() + + 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=KacoNH) diff --git a/packages/modules/devices/kaco/kaco_nh/inverter.py b/packages/modules/devices/kaco/kaco_nh/inverter.py new file mode 100644 index 0000000000..7b9eebebd7 --- /dev/null +++ b/packages/modules/devices/kaco/kaco_nh/inverter.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +from typing import Dict, TypedDict, Any + +from modules.common import req +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.store import get_inverter_value_store +from modules.devices.kaco.kaco_nh.config import KacoNHInverterSetup +from modules.devices.kaco.kaco_nh.config import KacoNHConfiguration + + +class KwargsDict(TypedDict): + device_config: KacoNHConfiguration + + +class KacoNHInverter(AbstractInverter): + def __init__(self, component_config: KacoNHInverterSetup, **kwargs: Any) -> None: + self.component_config = component_config + self.kwargs: KwargsDict = kwargs + + def initialize(self) -> None: + self.device_config: KacoNHConfiguration = 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)) + + def update(self, response: Dict) -> None: + response = req.get_http_session().get( + 'http://' + self.device_config.ip_address + ':' + str(self.device_config.port) + '/getdevdata.cgi?device=' + + str(self.component_config.configuration.id) + '&sn=' + self.device_config.serial_number, + timeout=5).json() + + power = float(response["pac"]) * -1 + exported = float(response["eto"]) * 100 + + self.store.set(InverterState( + power=power, + exported=exported + )) + + +component_descriptor = ComponentDescriptor(configuration_factory=KacoNHInverterSetup)