diff --git a/packages/modules/devices/solakon/solakon_one/bat.py b/packages/modules/devices/solakon/solakon_one/bat.py index 2896e75f37..e4e8fc1e9f 100644 --- a/packages/modules/devices/solakon/solakon_one/bat.py +++ b/packages/modules/devices/solakon/solakon_one/bat.py @@ -32,10 +32,8 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - # Reg 39134 AC Leistung am Stecker, Batterie aus dem Netz aufladen hat positive Werte, - # Leistung aus der Batterie und/oder aus PV ins Netz abgeben hat negative Werte - # Reg 39237 Battery Combined Power - power = self.client.read_holding_registers(39237, ModbusDataType.INT_32, unit=unit) + # Reg 39230 Battery Power, laut Hersteller-Doku positiv beim Laden, negativ beim Entladen + power = self.client.read_holding_registers(39230, ModbusDataType.INT_32, unit=unit) # SoC Ladezustand der Batterie in % soc = self.client.read_holding_registers(39424, ModbusDataType.INT_16, unit=unit) # gesamte DC Ladung der Batterie in Wh diff --git a/packages/modules/devices/solakon/solakon_one/config.py b/packages/modules/devices/solakon/solakon_one/config.py index 98807b2580..741e016155 100644 --- a/packages/modules/devices/solakon/solakon_one/config.py +++ b/packages/modules/devices/solakon/solakon_one/config.py @@ -58,3 +58,20 @@ def __init__(self, configuration: SolakonOneInverterConfiguration = None, **kwargs) -> None: super().__init__(name, type, id, configuration or SolakonOneInverterConfiguration(), **kwargs) + + +@auto_str +class SolakonOneCounterConfiguration: + def __init__(self, modbus_id: int = 1): + self.modbus_id = modbus_id + + +@auto_str +class SolakonOneCounterSetup(ComponentSetup[SolakonOneCounterConfiguration]): + def __init__(self, + name: str = "Solakon One Zähler", + type: str = "counter", + id: int = 0, + configuration: SolakonOneCounterConfiguration = None, + **kwargs) -> None: + super().__init__(name, type, id, configuration or SolakonOneCounterConfiguration(), **kwargs) diff --git a/packages/modules/devices/solakon/solakon_one/counter.py b/packages/modules/devices/solakon/solakon_one/counter.py new file mode 100644 index 0000000000..9b9107edc7 --- /dev/null +++ b/packages/modules/devices/solakon/solakon_one/counter.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +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.modbus import ModbusDataType, ModbusTcpClient_ +from modules.common.store import get_component_value_store +from modules.devices.solakon.solakon_one.config import SolakonOneCounterSetup +from modules.common.utils.peak_filter import PeakFilter +from modules.common.component_type import ComponentType + + +class KwargsDict(TypedDict): + client: ModbusTcpClient_ + + +class SolakonOneCounter(AbstractCounter): + def __init__(self, component_config: SolakonOneCounterSetup, **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_component_value_store(self.component_config.type, self.component_config.id) + self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) + self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) + + def update(self) -> None: + unit = self.component_config.configuration.modbus_id + + # Reg 39134 AC Leistung am Stecker (Grid Information laut Hersteller-Doku), Bezug hat positive Werte, + # Einspeisung hat negative Werte + power = self.client.read_holding_registers(39134, ModbusDataType.INT_32, unit=unit) * -1 + + # Gesamte Netzeinspeisung/-bezug in Wh + exported = self.client.read_holding_registers(39621, ModbusDataType.UINT_32, unit=unit) * 10 + imported = self.client.read_holding_registers(39625, ModbusDataType.UINT_32, unit=unit) * 10 + + imported, exported = self.peak_filter.check_values(power, imported, exported) + counter_state = CounterState( + power=power, + imported=imported, + exported=exported + ) + self.store.set(counter_state) + + +component_descriptor = ComponentDescriptor(configuration_factory=SolakonOneCounterSetup) diff --git a/packages/modules/devices/solakon/solakon_one/device.py b/packages/modules/devices/solakon/solakon_one/device.py index 3a92b5e420..0d893f51c3 100644 --- a/packages/modules/devices/solakon/solakon_one/device.py +++ b/packages/modules/devices/solakon/solakon_one/device.py @@ -7,8 +7,10 @@ from modules.common.configurable_device import ConfigurableDevice, ComponentFactoryByType, MultiComponentUpdater from modules.common.modbus import ModbusTcpClient_ from modules.devices.solakon.solakon_one.bat import SolakonOneBat +from modules.devices.solakon.solakon_one.counter import SolakonOneCounter from modules.devices.solakon.solakon_one.inverter import SolakonOneInverter -from modules.devices.solakon.solakon_one.config import SolakonOne, SolakonOneBatSetup, SolakonOneInverterSetup +from modules.devices.solakon.solakon_one.config import (SolakonOne, SolakonOneBatSetup, SolakonOneCounterSetup, + SolakonOneInverterSetup) log = logging.getLogger(__name__) @@ -20,9 +22,12 @@ def create_bat_component(component_config: SolakonOneBatSetup): return SolakonOneBat(component_config=component_config, client=client) def create_inverter_component(component_config: SolakonOneInverterSetup): - return SolakonOneInverter(component_config=component_config, client=client) + return SolakonOneInverter(component_config=component_config, client=client, device_id=device_config.id) - def update_components(components: Iterable[Union[SolakonOneBat, SolakonOneInverter]]): + def create_counter_component(component_config: SolakonOneCounterSetup): + return SolakonOneCounter(component_config=component_config, client=client) + + def update_components(components: Iterable[Union[SolakonOneBat, SolakonOneInverter, SolakonOneCounter]]): with client: for component in components: with SingleComponentUpdateContext(component.fault_state): @@ -38,6 +43,7 @@ def initializer(): component_factory=ComponentFactoryByType( bat=create_bat_component, inverter=create_inverter_component, + counter=create_counter_component, ), component_updater=MultiComponentUpdater(update_components) ) diff --git a/packages/modules/devices/solakon/solakon_one/inverter.py b/packages/modules/devices/solakon/solakon_one/inverter.py index d8bd5784cf..ffa1c186b7 100644 --- a/packages/modules/devices/solakon/solakon_one/inverter.py +++ b/packages/modules/devices/solakon/solakon_one/inverter.py @@ -6,6 +6,7 @@ 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.simcount import SimCounter from modules.common.store import get_component_value_store from modules.devices.solakon.solakon_one.config import SolakonOneInverterSetup from modules.common.utils.peak_filter import PeakFilter @@ -14,6 +15,7 @@ class KwargsDict(TypedDict): client: ModbusTcpClient_ + device_id: int class SolakonOneInverter(AbstractInverter): @@ -23,6 +25,8 @@ def __init__(self, component_config: SolakonOneInverterSetup, **kwargs: Any) -> def initialize(self) -> None: self.client: ModbusTcpClient_ = self.kwargs['client'] + self.sim_counter = SimCounter( + self.kwargs['device_id'], self.component_config.id, self.component_config.type) self.store = get_component_value_store(self.component_config.type, self.component_config.id) self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) @@ -30,13 +34,11 @@ def initialize(self) -> None: def update(self) -> None: unit = self.component_config.configuration.modbus_id - # Reg 39134 AC Leistung am Stecker, Batterie aus dem Heimnetz aufladen hat positive Werte, - # Leistung aus der Batterie und/oder aus PV ins Heimnetz abgeben hat negative Werte - power = self.client.read_holding_registers(39134, ModbusDataType.INT_32, unit=unit) * -1 - - # Gesamte Energie am Wechselrichter in Wh - exported = self.client.read_holding_registers(39621, ModbusDataType.UINT_32, unit=unit) * 10 - imported = self.client.read_holding_registers(39625, ModbusDataType.UINT_32, unit=unit) * 10 + # Gesamte DC PV Leistung aller vier MPPT in W + power = self.client.read_holding_registers(39118, ModbusDataType.INT_32, unit=unit) * -1 + # Gesamte DC PV Produktion in Wh + exported = self.client.read_holding_registers(39601, ModbusDataType.UINT_32, unit=unit) * 10 + imported, _ = self.sim_counter.sim_count(power) imported, exported = self.peak_filter.check_values(power, imported, exported) inverter_state = InverterState(