diff --git a/packages/modules/devices/solis/solis/bat.py b/packages/modules/devices/solis/solis/bat.py index 490fc6a8f5..be88ab4059 100644 --- a/packages/modules/devices/solis/solis/bat.py +++ b/packages/modules/devices/solis/solis/bat.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 import logging -from typing import TypedDict, Any +from typing import TypedDict, Any, Optional 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, ModbusTcpClient_ +from modules.common.simcount import SimCounter from modules.common.store import get_bat_value_store from modules.devices.solis.solis.config import SolisBatSetup +from modules.devices.solis.solis.version import SolisVersion from modules.common.utils.peak_filter import PeakFilter from modules.common.component_type import ComponentType @@ -17,6 +19,8 @@ class KwargsDict(TypedDict): client: ModbusTcpClient_ + device_id: int + version: SolisVersion class SolisBat(AbstractBat): @@ -26,6 +30,8 @@ def __init__(self, component_config: SolisBatSetup, **kwargs: Any) -> None: def initialize(self) -> None: self.client: ModbusTcpClient_ = self.kwargs['client'] + self.version: SolisVersion = self.kwargs['version'] + 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)) self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state) @@ -35,19 +41,45 @@ def update(self) -> None: power = self.client.read_input_registers(33149, ModbusDataType.INT_32, unit=unit) soc = self.client.read_input_registers(33139, ModbusDataType.UINT_16, unit=unit) - # Geladen in kWh - imported = self.client.read_input_registers(33161, ModbusDataType.UINT_32, unit=unit) * 1000 - # Entladen in kWh - exported = self.client.read_input_registers(33165, ModbusDataType.UINT_32, unit=unit) * 1000 + bat_current = self.client.read_input_registers(33134, ModbusDataType.INT_16, unit=unit) * -0.1 - imported, exported = self.peak_filter.check_values(power, imported, exported) + currents = [bat_current / 3] * 3 + + self.peak_filter.check_values(power) + imported, exported = self.sim_counter.sim_count(power) bat_state = BatState( power=power, soc=soc, + currents=currents, imported=imported, exported=exported ) self.store.set(bat_state) + def set_power_limit(self, power_limit: Optional[int]) -> None: + unit = self.component_config.configuration.modbus_id + + if power_limit is None: + self.client.write_register(43135, 0, data_type=ModbusDataType.UINT_16, unit=unit) + log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter") + elif power_limit == 0: + self.client.write_register(43135, 1, data_type=ModbusDataType.UINT_16, unit=unit) + self.client.write_register(43136, 0, data_type=ModbusDataType.UINT_16, unit=unit) + log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht geladen/entladen") + elif power_limit < 0: + self.client.write_register(43135, 2, data_type=ModbusDataType.UINT_16, unit=unit) + power_value = int(abs(power_limit) / 10) + self.client.write_register(43129, power_value, data_type=ModbusDataType.UINT_16, unit=unit) + log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch") + elif power_limit > 0: + self.client.write_register(43135, 1, data_type=ModbusDataType.UINT_16, unit=unit) + power_value = int(power_limit / 10) + self.client.write_register(43136, power_value, data_type=ModbusDataType.UINT_16, unit=unit) + log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W geladen") + + def power_limit_controllable(self) -> bool: + # Nur die S-Serie sollte die Speichersteuerung können + return self.version == SolisVersion.hybrid_s + component_descriptor = ComponentDescriptor(configuration_factory=SolisBatSetup) diff --git a/packages/modules/devices/solis/solis/counter.py b/packages/modules/devices/solis/solis/counter.py index e5a17bf559..a33feff386 100644 --- a/packages/modules/devices/solis/solis/counter.py +++ b/packages/modules/devices/solis/solis/counter.py @@ -26,8 +26,6 @@ def initialize(self) -> None: 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 = self.kwargs['version'] - self.client = self.kwargs['client'] self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state) def update(self): diff --git a/packages/modules/devices/solis/solis/device.py b/packages/modules/devices/solis/solis/device.py index 6b52c6a3cc..969c325b58 100644 --- a/packages/modules/devices/solis/solis/device.py +++ b/packages/modules/devices/solis/solis/device.py @@ -10,7 +10,6 @@ from modules.devices.solis.solis.counter import SolisCounter from modules.devices.solis.solis.inverter import SolisInverter from modules.devices.solis.solis.config import Solis, SolisBatSetup, SolisCounterSetup, SolisInverterSetup -from modules.devices.solis.solis.version import SolisVersion log = logging.getLogger(__name__) @@ -20,17 +19,21 @@ def create_device(device_config: Solis): def create_bat_component(component_config: SolisBatSetup): nonlocal client - return SolisBat(component_config, client=client) + return SolisBat(component_config, + client=client, + device_id=device_config.id, + version=device_config.configuration.version) def create_counter_component(component_config: SolisCounterSetup): nonlocal client - return SolisCounter(component_config, version=SolisVersion(device_config.configuration.version), client=client) + return SolisCounter(component_config, client=client, version=device_config.configuration.version) def create_inverter_component(component_config: SolisInverterSetup): nonlocal client return SolisInverter(component_config, - version=SolisVersion(device_config.configuration.version), - client=client) + client=client, + device_id=device_config.id, + version=device_config.configuration.version) def update_components(components: Iterable[Union[SolisBat, SolisCounter, SolisInverter]]): nonlocal client diff --git a/packages/modules/devices/solis/solis/inverter.py b/packages/modules/devices/solis/solis/inverter.py index 749829a57f..078e9a9903 100644 --- a/packages/modules/devices/solis/solis/inverter.py +++ b/packages/modules/devices/solis/solis/inverter.py @@ -5,6 +5,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_inverter_value_store from modules.devices.solis.solis.config import SolisInverterSetup from modules.devices.solis.solis.version import SolisVersion @@ -14,6 +15,7 @@ class KwargsDict(TypedDict): client: ModbusTcpClient_ + device_id: int version: SolisVersion @@ -25,6 +27,7 @@ def __init__(self, component_config: SolisInverterSetup, **kwargs: Any) -> None: def initialize(self) -> None: self.client: ModbusTcpClient_ = self.kwargs['client'] self.version: SolisVersion = self.kwargs['version'] + self.sim_counter = SimCounter(self.kwargs['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.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state) @@ -33,15 +36,24 @@ def update(self) -> None: unit = self.component_config.configuration.modbus_id if self.version == SolisVersion.inverter: - 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 = 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 - - _, exported = self.peak_filter.check_values(power, None, exported) + # Für Stringwechselrichter -1 bei Modbus Registers + power = self.client.read_input_registers(3004, ModbusDataType.INT_32, unit=unit) * -1 + dc_power = self.client.read_input_registers(3006, ModbusDataType.UINT_32, unit=unit) * -1 + currents = self.client.read_input_registers(3036, [ModbusDataType.UINT_16]*3, unit=unit) + elif self.version in (SolisVersion.hybrid, SolisVersion.hybrid_s): + power = self.client.read_input_registers(33079, ModbusDataType.INT_32, unit=unit) * -1 + dc_power = self.client.read_input_registers(33057, ModbusDataType.UINT_32, unit=unit) * -1 + currents = self.client.read_input_registers(33076, [ModbusDataType.UINT_16]*3, unit=unit) + + currents = [value * -0.1 for value in currents] + + self.peak_filter.check_values(power) + imported, exported = self.sim_counter.sim_count(power) inverter_state = InverterState( power=power, + dc_power=dc_power, + currents=currents, + imported=imported, exported=exported ) self.store.set(inverter_state) diff --git a/packages/modules/devices/solis/solis/version.py b/packages/modules/devices/solis/solis/version.py index f1a0fe5854..31517a4ce4 100644 --- a/packages/modules/devices/solis/solis/version.py +++ b/packages/modules/devices/solis/solis/version.py @@ -4,3 +4,4 @@ class SolisVersion(Enum): inverter = "inverter" hybrid = "hybrid" + hybrid_s = "hybrid_s"