diff --git a/packages/modules/devices/elgris/__init__.py b/packages/modules/devices/elgris/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/modules/devices/elgris/elgris/__init__.py b/packages/modules/devices/elgris/elgris/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/modules/devices/elgris/elgris/bat.py b/packages/modules/devices/elgris/elgris/bat.py new file mode 100644 index 0000000000..6d45e76c4d --- /dev/null +++ b/packages/modules/devices/elgris/elgris/bat.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +from typing import Any, TypedDict + +from modules.common.component_state import BatState +from modules.devices.elgris.elgris.elgris import Elgris +from modules.devices.elgris.elgris.config import ElgrisBatSetup +from modules.common import modbus +from modules.common.abstract_device import AbstractBat +from modules.common.component_type import ComponentDescriptor +from modules.common.fault_state import ComponentInfo, FaultState +from modules.common.store import get_bat_value_store + + +class KwargsDict(TypedDict): + tcp_client: modbus.ModbusTcpClient_ + modbus_id: int + + +class ElgrisBat(AbstractBat): + def __init__(self, component_config: ElgrisBatSetup, **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.__modbus_id: int = self.kwargs['modbus_id'] + self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) + self.elgris = Elgris(self.__modbus_id, self.__tcp_client, self.fault_state) + self.store = get_bat_value_store(self.component_config.id) + + def update(self): + with self.__tcp_client: + counter_state = self.elgris.get_counter_state() + bat_state = BatState( + exported=counter_state.exported, + imported=counter_state.imported, + power=counter_state.power, + currents=counter_state.currents, + ) + self.store.set(bat_state) + + +component_descriptor = ComponentDescriptor(configuration_factory=ElgrisBatSetup) diff --git a/packages/modules/devices/elgris/elgris/config.py b/packages/modules/devices/elgris/elgris/config.py new file mode 100644 index 0000000000..cccf6e5c02 --- /dev/null +++ b/packages/modules/devices/elgris/elgris/config.py @@ -0,0 +1,66 @@ +from typing import Optional + +from modules.common.component_setup import ComponentSetup +from ..vendor import vendor_descriptor + + +class ElgrisConfiguration: + def __init__(self, modbus_id: int = 1, ip_address: Optional[str] = None, port: int = 502): + self.modbus_id = modbus_id + self.ip_address = ip_address + self.port = port + + +class Elgris: + def __init__(self, + name: str = "Elgris", + type: str = "elgris", + id: int = 0, + configuration: ElgrisConfiguration = None) -> None: + self.name = name + self.type = type + self.vendor = vendor_descriptor.configuration_factory().type + self.id = id + self.configuration = configuration or ElgrisConfiguration() + + +class ElgrisBatConfiguration: + def __init__(self): + pass + + +class ElgrisBatSetup(ComponentSetup[ElgrisBatConfiguration]): + def __init__(self, + name: str = "Elgris Smart Meter Speicher", + type: str = "bat", + id: int = 0, + configuration: ElgrisBatConfiguration = None) -> None: + super().__init__(name, type, id, configuration or ElgrisBatConfiguration()) + + +class ElgrisCounterConfiguration: + def __init__(self): + pass + + +class ElgrisCounterSetup(ComponentSetup[ElgrisCounterConfiguration]): + def __init__(self, + name: str = "Elgris Smart Meter", + type: str = "counter", + id: int = 0, + configuration: ElgrisCounterConfiguration = None) -> None: + super().__init__(name, type, id, configuration or ElgrisCounterConfiguration()) + + +class ElgrisInverterConfiguration: + def __init__(self): + pass + + +class ElgrisInverterSetup(ComponentSetup[ElgrisInverterConfiguration]): + def __init__(self, + name: str = "Elgris Smart Meter Welchselrichter", + type: str = "inverter", + id: int = 0, + configuration: ElgrisInverterConfiguration = None) -> None: + super().__init__(name, type, id, configuration or ElgrisInverterConfiguration()) diff --git a/packages/modules/devices/elgris/elgris/counter.py b/packages/modules/devices/elgris/elgris/counter.py new file mode 100644 index 0000000000..8456e3a134 --- /dev/null +++ b/packages/modules/devices/elgris/elgris/counter.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +from typing import Any, TypedDict + +from modules.devices.elgris.elgris.elgris import Elgris +from modules.devices.elgris.elgris.config import ElgrisCounterSetup +from modules.common import modbus +from modules.common.abstract_device import AbstractCounter +from modules.common.component_type import ComponentDescriptor +from modules.common.fault_state import ComponentInfo, FaultState +from modules.common.store import get_counter_value_store + + +class KwargsDict(TypedDict): + tcp_client: modbus.ModbusTcpClient_ + modbus_id: int + + +class ElgrisCounter(AbstractCounter): + def __init__(self, component_config: ElgrisCounterSetup, **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.__modbus_id: int = self.kwargs['modbus_id'] + self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) + self.elgris = Elgris(self.__modbus_id, self.__tcp_client, self.fault_state) + self.store = get_counter_value_store(self.component_config.id) + + def update(self): + with self.__tcp_client: + counter_state = self.elgris.get_counter_state() + self.store.set(counter_state) + + +component_descriptor = ComponentDescriptor(configuration_factory=ElgrisCounterSetup) diff --git a/packages/modules/devices/elgris/elgris/device.py b/packages/modules/devices/elgris/elgris/device.py new file mode 100644 index 0000000000..2c8a93c3cc --- /dev/null +++ b/packages/modules/devices/elgris/elgris/device.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +import logging +from typing import Iterable, Union + +from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater +from modules.devices.elgris.elgris import bat, counter, inverter +from modules.devices.elgris.elgris.config import Elgris, ElgrisBatSetup, ElgrisCounterSetup +from modules.common import modbus +from modules.common.abstract_device import DeviceDescriptor +from modules.common.component_context import SingleComponentUpdateContext +from modules.devices.elgris.elgris.config import ElgrisInverterSetup + +log = logging.getLogger(__name__) + + +def create_device(device_config: Elgris): + client = None + + def create_bat_component(component_config: ElgrisBatSetup): + nonlocal client + return bat.ElgrisBat(component_config=component_config, tcp_client=client, + modbus_id=device_config.configuration.modbus_id) + + def create_counter_component(component_config: ElgrisCounterSetup): + nonlocal client + return counter.ElgrisCounter(component_config=component_config, tcp_client=client, + modbus_id=device_config.configuration.modbus_id) + + def create_inverter_component(component_config: ElgrisInverterSetup): + nonlocal client + return inverter.ElgrisInverter(component_config=component_config, tcp_client=client, + modbus_id=device_config.configuration.modbus_id) + + def update_components(components: Iterable[Union[bat.ElgrisBat, counter.ElgrisCounter, inverter.ElgrisInverter]]): + with client: + for component in components: + with SingleComponentUpdateContext(component.fault_state): + component.update() + + def initializer(): + nonlocal client + client = modbus.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=Elgris) diff --git a/packages/modules/devices/elgris/elgris/elgris.py b/packages/modules/devices/elgris/elgris/elgris.py new file mode 100644 index 0000000000..74d5e8272c --- /dev/null +++ b/packages/modules/devices/elgris/elgris/elgris.py @@ -0,0 +1,13 @@ +from modules.common import modbus +from modules.common.fault_state import FaultState +from modules.common.sdm import Sdm630_72 + + +class Elgris(Sdm630_72): + def __init__(self, modbus_id: int, client: modbus.ModbusTcpClient_, fault_state: FaultState) -> None: + self.client = client + self.id = modbus_id + self.last_query = self._get_time_ms() + self.WAIT_MS_BETWEEN_QUERIES = 100 + self.serial_number = "" + self.fault_state = fault_state diff --git a/packages/modules/devices/elgris/elgris/inverter.py b/packages/modules/devices/elgris/elgris/inverter.py new file mode 100644 index 0000000000..c85d133582 --- /dev/null +++ b/packages/modules/devices/elgris/elgris/inverter.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +from typing import Any, TypedDict + +from modules.common.component_state import InverterState +from modules.devices.elgris.elgris.elgris import Elgris +from modules.common.store._inverter import get_inverter_value_store +from modules.devices.elgris.elgris.config import ElgrisInverterSetup +from modules.common import modbus +from modules.common.abstract_device import AbstractInverter +from modules.common.component_type import ComponentDescriptor +from modules.common.fault_state import ComponentInfo, FaultState + + +class KwargsDict(TypedDict): + tcp_client: modbus.ModbusTcpClient_ + modbus_id: int + + +class ElgrisInverter(AbstractInverter): + def __init__(self, component_config: ElgrisInverterSetup, **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.__modbus_id: int = self.kwargs['modbus_id'] + self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) + self.elgris = Elgris(self.__modbus_id, self.__tcp_client, self.fault_state) + self.store = get_inverter_value_store(self.component_config.id) + + def update(self): + with self.__tcp_client: + counter_state = self.elgris.get_counter_state() + inverter_state = InverterState( + exported=counter_state.exported, + imported=counter_state.imported, + power=counter_state.power, + currents=counter_state.currents, + ) + self.store.set(inverter_state) + + +component_descriptor = ComponentDescriptor(configuration_factory=ElgrisInverterSetup) diff --git a/packages/modules/devices/elgris/vendor.py b/packages/modules/devices/elgris/vendor.py new file mode 100644 index 0000000000..33ce570be5 --- /dev/null +++ b/packages/modules/devices/elgris/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 = "Elgris" + self.group = VendorGroup.VENDORS.value + + +vendor_descriptor = DeviceDescriptor(configuration_factory=Vendor) diff --git a/packages/smarthome/smartbase.py b/packages/smarthome/smartbase.py index e5afc1e5d3..b3c233fce2 100644 --- a/packages/smarthome/smartbase.py +++ b/packages/smarthome/smartbase.py @@ -3,7 +3,7 @@ import os from typing import Dict, Tuple from smarthome.smartbase0 import Sbase0 -from smarthome.smartmeas import Slsdm630, Sllovato, Slsdm120, Slwe514, Slfronius +from smarthome.smartmeas import SlElgris, Slsdm630, Sllovato, Slsdm120, Slwe514, Slfronius from smarthome.smartmeas import Sljson, Slsmaem, Slshelly, Sltasmota, Slmqtt from smarthome.smartmeas import Slhttp, Slavm, Slmystrom, Slb23 from smarthome.smartbut import Sbshelly @@ -396,7 +396,9 @@ def updatepar(self, input_param: Dict[str, str]) -> None: ") Separate Messung. Altes Measure" + "device gelöscht " + self._oldmeasuretype1) del self._mydevicemeasure - if (self._device_measuretype == 'sdm630'): + if (self._device_measuretype == 'elgris'): + self._mydevicemeasure = SlElgris() + elif (self._device_measuretype == 'sdm630'): self._mydevicemeasure = Slsdm630() elif (self._device_measuretype == 'lovato'): self._mydevicemeasure = Sllovato() diff --git a/packages/smarthome/smartmeas.py b/packages/smarthome/smartmeas.py index 2d0e49839c..5ff1daa525 100644 --- a/packages/smarthome/smartmeas.py +++ b/packages/smarthome/smartmeas.py @@ -1,3 +1,4 @@ +from modules.devices.elgris.elgris import elgris from smarthome.smartbase0 import Sbase0 from typing import Dict, Tuple from modules.common import modbus @@ -524,6 +525,25 @@ def sepwattread(self) -> Tuple[int, int]: return self.newwatt, self.newwattk +class SlElgris(Slbase): + def __init__(self) -> None: + # setting + super().__init__() + + def sepwattread(self) -> Tuple[int, int]: + try: + with modbus.ModbusTcpClient_(self._device_measureip, self._device_measureportsdm) as tcp_client: + elg = elgris.Elgris(self._device_measureid, tcp_client, None) + _, newwatt = elg.get_power() + self.newwatt = int(newwatt) + self.newwattk = int(elg.get_imported()) + except Exception: + log.exception("Leistungsmessung %s %d %s " + % ('Elgris ', self.device_nummer, + str(self._device_measureip))) + return self.newwatt, self.newwattk + + class Slsdm120(Slbase): def __init__(self) -> None: # setting diff --git a/web/settings/modules/legacy_smart_home/smarthomeconfig.php b/web/settings/modules/legacy_smart_home/smarthomeconfig.php index d0a8b94490..63c721a559 100644 --- a/web/settings/modules/legacy_smart_home/smarthomeconfig.php +++ b/web/settings/modules/legacy_smart_home/smarthomeconfig.php @@ -905,6 +905,7 @@
-
+
@@ -976,13 +977,13 @@
-
+
-
+