Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/control/bat.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def get_factory() -> Get:
@dataclass
class Set:
power_limit: Optional[int] = field(default=None, metadata={"topic": "set/power_limit"})
evu_power: Optional[int] = field(default=None, metadata={"topic": "set/evu_power"})


def set_factory() -> Set:
Expand Down
3 changes: 2 additions & 1 deletion packages/control/bat_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ def _set_bat_power_active_control(self, power):
log.debug(("Aktive Speichersteuerung: Ladung - "
f"Speicher (ID: {bat_component.component_config.id}) "
f"laden mit {power_limit} ({factor} x {bat_component_data.get.max_charge_power}) W"))
data.data.bat_data[f"bat{bat_component.component_config.id}"].data.set.power_limit = power_limit
bat_component_data.set.power_limit = power_limit
bat_component_data.set.evu_power = data.data.counter_all_data.get_evu_counter().data.get.power

def setup_bat(self):
""" prüft, ob mind ein Speicher vorhanden ist und berechnet die Summen-Topics.
Expand Down
2 changes: 1 addition & 1 deletion packages/control/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def process_algorithm_results(self) -> None:
Thread(
target=set_power_limit_wrapper,
args=(bat_component,
data.data.bat_data[f"bat{bat_component.component_config.id}"].data.set.power_limit),
data.data.bat_data[f"bat{bat_component.component_config.id}"].data.set),
name=f"set power limit {bat_component.component_config.id}"))
for action in data.data.io_actions.actions.values():
if isinstance(action, DimmingDirectControl):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def _get_data_path() -> Path:
INTERNAL_TOPICS = ['openWB/bat/set/charging_power_left',
'openWB/bat/set/regulate_up',
'openWB/bat/+/set/power_limit',
'openWB/bat/+/set/evu_power',
'openWB/command/max_id/autolock_plan',
'openWB/command/max_id/charge_template',
'openWB/command/max_id/charge_template_scheduled_plan',
Expand Down
2 changes: 2 additions & 0 deletions packages/helpermodules/setdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,8 @@ def process_bat_topic(self, msg: mqtt.MQTTMessage):
self._validate_value(msg, bool)
elif "/set/power_limit" in msg.topic:
self._validate_value(msg, float)
elif "/set/evu_power" in msg.topic:
self._validate_value(msg, float)
else:
self.__unknown_topic(msg)
else:
Expand Down
1 change: 1 addition & 0 deletions packages/helpermodules/update_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class UpdateConfig:
"^openWB/bat/[0-9]+/get/fault_str$",
"^openWB/bat/[0-9]+/get/power_limit_controllable$",
"^openWB/bat/[0-9]+/set/power_limit$",
"^openWB/bat/[0-9]+/set/evu_power$",

"^openWB/chargepoint/get/power$",
"^openWB/chargepoint/get/exported$",
Expand Down
5 changes: 3 additions & 2 deletions packages/modules/common/configurable_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from modules.common.abstract_device import AbstractBat, AbstractDevice
from modules.common.component_context import SingleComponentUpdateContext, MultiComponentUpdateContext
from modules.common.fault_state import ComponentInfo, FaultState
from control.bat import Set as SetPoint

T_DEVICE_CONFIG = TypeVar("T_DEVICE_CONFIG")
T_COMPONENT = TypeVar("T_COMPONENT")
Expand Down Expand Up @@ -130,9 +131,9 @@ def update(self):
self.__component_updater(initialized_components, self.error_handler)


def set_power_limit_wrapper(bat_component: AbstractBat, power_limit: Optional[int]):
def set_power_limit_wrapper(bat_component: AbstractBat, setpoint: Optional[SetPoint]):
"""set_power_limit innerhalb des SingleComponentUpdateContext aufrufen,
damit Fehler im fault_state-Handler behandelt werden
"""
with SingleComponentUpdateContext(bat_component.fault_state, update_always=False):
bat_component.set_power_limit(power_limit)
bat_component.set_power_limit(setpoint)
9 changes: 5 additions & 4 deletions packages/modules/devices/alpha_ess/alpha_ess/bat.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import time
from typing import TypedDict, Any, Optional
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
Expand All @@ -11,6 +11,7 @@
from modules.devices.alpha_ess.alpha_ess.config import AlphaEssBatSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from control.bat import Set as SetPoint

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -62,16 +63,16 @@ def update(self) -> None:
)
self.store.set(bat_state)

def set_power_limit(self, power_limit: Optional[int]) -> None:
def set_power_limit(self, setpoint: SetPoint) -> None:
unit = self.__modbus_id

if power_limit is None:
if setpoint.power_limit is None:
# Kein Powerlimit gefordert, externe Steuerung deaktivieren
log.debug("Keine Batteriesteuerung gefordert, deaktiviere externe Steuerung.")
if self.last_mode is not None:
self.__tcp_client.write_register(2127, 0, data_type=ModbusDataType.UINT_16, unit=unit)
self.last_mode = None
elif power_limit <= 0:
elif setpoint.power_limit <= 0:
# AlphaESS kann die Entladung nur über den SoC verhindern (komplette Entladesperre)
# Netzladung mit geringen Ziel SoC verhindert auch Entladung (Default 10%)
# Zeiten für Netzladung müssen im Wechselrichter aktiviert werden
Expand Down
11 changes: 6 additions & 5 deletions packages/modules/devices/anker/solarbank/bat.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
import logging
from typing import Any, Optional, TypedDict
from typing import Any, TypedDict

from modules.common.abstract_device import AbstractBat
from modules.common.component_state import BatState
Expand All @@ -12,6 +12,7 @@
from modules.devices.anker.solarbank.config import Anker, AnkerBatSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from control.bat import Set as SetPoint

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -52,10 +53,10 @@ def update(self) -> None:
)
self.store.set(bat_state)

def set_power_limit(self, power_limit: Optional[int]) -> None:
def set_power_limit(self, setpoint: SetPoint) -> None:
unit = self.device_config.configuration.modbus_id

if power_limit is None:
if setpoint.power_limit is None:
log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter")
if self.last_mode is not None:
self.client.write_register(10064, 0, data_type=ModbusDataType.UINT_16, unit=unit)
Expand All @@ -65,9 +66,9 @@ def set_power_limit(self, power_limit: Optional[int]) -> None:
self.client.write_register(10064, 3, data_type=ModbusDataType.UINT_16, unit=unit)
self.last_mode = 'limited'

power_value = 0 if power_limit == 0 else int(power_limit) * -1
power_value = 0 if setpoint.power_limit == 0 else int(setpoint.power_limit) * -1
self.client.write_register(10071, power_value, data_type=ModbusDataType.INT_32, unit=unit)
log.debug("Aktive Batteriesteuerung angefordert, angeforderte Leistung: {power_value} W")
log.debug(f"Aktive Batteriesteuerung angefordert, angeforderte Leistung: {power_value} W")

def power_limit_controllable(self) -> bool:
return True
Expand Down
9 changes: 5 additions & 4 deletions packages/modules/devices/batterx/batterx/bat.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
import logging
from typing import Dict, TypedDict, Any, Optional
from typing import Dict, TypedDict, Any

from modules.devices.batterx.batterx.config import BatterXBatSetup
from modules.common.abstract_device import AbstractBat
Expand All @@ -12,6 +12,7 @@
from modules.common import req
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from control.bat import Set as SetPoint

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -49,10 +50,10 @@ def update(self, resp: Dict) -> None:
)
self.store.set(bat_state)

def set_power_limit(self, power_limit: Optional[int]) -> None:
def set_power_limit(self, setpoint: SetPoint) -> None:
log.debug(f'last_mode: {self.last_mode}')

if power_limit is None:
if setpoint.power_limit is None:
# Kein Powerlimit gefordert, externe Steuerung deaktivieren
log.debug("Keine Batteriesteuerung gefordert, deaktiviere externe Steuerung.")
if self.last_mode is not None:
Expand All @@ -67,7 +68,7 @@ def set_power_limit(self, power_limit: Optional[int]) -> None:
timeout=5
)
self.last_mode = None
elif power_limit <= 0:
elif setpoint.power_limit <= 0:
# BatterX kann Entladung nur komplett sperren
log.debug("Aktive Batteriesteuerung angestoßen. Setze Entladesperre.")
if self.last_mode != 'stop':
Expand Down
7 changes: 4 additions & 3 deletions packages/modules/devices/generic/mqtt/bat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
from typing import Any, Dict, Optional, TypedDict
from typing import Any, Dict, TypedDict

from helpermodules.pub import Pub
from helpermodules.utils._get_default import get_default
Expand All @@ -12,6 +12,7 @@
from modules.devices.generic.mqtt.config import MqttBatSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from control.bat import Set as SetPoint


class KwargsDict(TypedDict):
Expand Down Expand Up @@ -55,8 +56,8 @@ def parse_received_topics(value: str):
)
self.store.set(bat_state)

def set_power_limit(self, power_limit: Optional[int]) -> None:
Pub().pub(f"openWB/set/mqtt/bat/{self.component_config.id}/set/power_limit", power_limit)
def set_power_limit(self, setpoint: SetPoint) -> None:
Pub().pub(f"openWB/set/mqtt/bat/{self.component_config.id}/set/power_limit", setpoint.power_limit)

def power_limit_controllable(self) -> bool:
return self.component_config.configuration.power_limit_controllable
Expand Down
22 changes: 12 additions & 10 deletions packages/modules/devices/good_we/good_we/bat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
from typing import TypedDict, Any, Optional
from typing import TypedDict, Any
import logging

from modules.common import modbus
Expand All @@ -14,6 +14,7 @@
from modules.devices.good_we.good_we.version import GoodWeVersion
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from control.bat import Set as SetPoint

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -73,37 +74,38 @@ def update(self) -> None:
)
self.store.set(bat_state)

def set_power_limit(self, power_limit: Optional[int]) -> None:
def set_power_limit(self, setpoint: SetPoint) -> None:
unit = self.__modbus_id
log.debug(f'last_mode: {self.last_mode}')

if power_limit is None:
if setpoint.power_limit is None:
log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter")
if self.last_mode is not None:
self.__tcp_client.write_register(47511, 1, data_type=ModbusDataType.UINT_16, unit=unit)
self.__tcp_client.write_register(47512, 0, data_type=ModbusDataType.UINT_16, unit=unit)
self.last_mode = None
elif power_limit == 0:
elif setpoint.power_limit == 0:
log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen")
if self.last_mode != 'stop':
self.__tcp_client.write_register(47511, 2, data_type=ModbusDataType.UINT_16, unit=unit)
self.__tcp_client.write_register(47512, 0, data_type=ModbusDataType.UINT_16, unit=unit)
self.last_mode = 'stop'
elif power_limit < 0:
log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_limit} W entladen für den Hausverbrauch")
elif setpoint.power_limit < 0:
log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {setpoint.power_limit} W "
"entladen für den Hausverbrauch")
if self.last_mode != 'discharge':
self.__tcp_client.write_register(47511, 3, data_type=ModbusDataType.UINT_16, unit=unit)
self.last_mode = 'discharge'
# Die maximale Entladeleistung begrenzen auf 5000W, maximaler Wertebereich Modbusregister.
power_value = int(min(abs(power_limit), 10000))
power_value = int(min(abs(setpoint.power_limit), 10000))
log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch")
self.__tcp_client.write_register(47512, power_value, data_type=ModbusDataType.UINT_16, unit=unit)
elif power_limit > 0:
elif setpoint.power_limit > 0:
if self.last_mode != 'charge':
self.__tcp_client.write_register(47511, 2, data_type=ModbusDataType.UINT_16, unit=unit)
self.last_mode = 'charge'
power_value = int(min(abs(power_limit), 10000))
log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch")
power_value = int(min(abs(setpoint.power_limit), 10000))
log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W geladen.")
self.__tcp_client.write_register(47512, power_value, data_type=ModbusDataType.UINT_16, unit=unit)

def power_limit_controllable(self) -> bool:
Expand Down
17 changes: 9 additions & 8 deletions packages/modules/devices/kostal/kostal_plenticore/bat.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
import logging
from typing import TypedDict, Any, Optional
from typing import TypedDict, Any
from pymodbus.constants import Endian

from modules.common.abstract_device import AbstractBat
Expand All @@ -13,6 +13,7 @@
from modules.devices.kostal.kostal_plenticore.config import KostalPlenticoreBatSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from control.bat import Set as SetPoint

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -67,24 +68,24 @@ def update(self) -> None:
# Kostal setzt das Register autmatisch nach Timeout zurück auf Eigensteuerung.
# Timeout kann im Kostal UI geändert werden. Standardwert 30s

def set_power_limit(self, power_limit: Optional[int]) -> None:
def set_power_limit(self, setpoint: SetPoint) -> None:
unit = self.modbus_id

if power_limit is None:
if setpoint.power_limit is None:
# Keine Registeränderung damit nach Timeout eigenständig zurückgesetzt wird
log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter")
elif power_limit == 0:
elif setpoint.power_limit == 0:
# wiederholt auf Stop setzen damit sich Register nicht zurücksetzt
log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen")
self.client.write_register(1034, 0.0, data_type=ModbusDataType.FLOAT_32,
wordorder=self.endianess, unit=unit)
elif power_limit < 0:
power_value = float(abs(power_limit))
elif setpoint.power_limit < 0:
power_value = float(abs(setpoint.power_limit))
log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W entladen für den Hausverbrauch")
self.client.write_register(1034, power_value, data_type=ModbusDataType.FLOAT_32,
wordorder=self.endianess, unit=unit)
elif power_limit > 0:
power_value = float(abs(power_limit)) * -1
elif setpoint.power_limit > 0:
power_value = float(abs(setpoint.power_limit)) * -1
log.debug(f"Aktive Batteriesteuerung. Batterie wird mit {power_value} W geladen")
self.client.write_register(1034, power_value, data_type=ModbusDataType.FLOAT_32,
wordorder=self.endianess, unit=unit)
Expand Down
15 changes: 8 additions & 7 deletions packages/modules/devices/marstek/venus_c_e/bat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
from typing import Optional, TypedDict, Any, Union
from typing import TypedDict, Any, Union
from modules.common.abstract_device import AbstractBat
from modules.common.component_state import BatState
from modules.common.component_type import ComponentDescriptor
Expand All @@ -10,6 +10,7 @@
from modules.devices.marstek.venus_c_e.config import VenusCEBatSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from control.bat import Set as SetPoint


class KwargsDict(TypedDict):
Expand Down Expand Up @@ -53,20 +54,20 @@ def update(self) -> None:
)
self.store.set(bat_state)

def set_power_limit(self, power_limit: Optional[int]) -> None:
def set_power_limit(self, setpoint: SetPoint) -> None:
# Wenn der Speicher die Steuerung der Ladeleistung unterstützt, muss bei Übergabe einer Zahl auf aktive
# Speichersteurung umgeschaltet werden, sodass der Speicher mit der übergebenen Leistung lädt/entlädt. Wird
# None übergeben, muss der Speicher die Null-Punkt-Ausregelung selbst übernehmen.
if (power_limit is None):
if (setpoint.power_limit is None):
self._write_reg(42000, 0x55bb)
else:
self._write_reg(42000, 0x55aa)
if power_limit < 0:
if setpoint.power_limit < 0:
self._write_reg(42010, 2)
self._write_reg(42021, int(min(-power_limit, 2500)))
elif power_limit > 0:
self._write_reg(42021, int(min(-setpoint.power_limit, 2500)))
elif setpoint.power_limit > 0:
self._write_reg(42010, 1)
self._write_reg(42020, int(min(power_limit, 2500)))
self._write_reg(42020, int(min(setpoint.power_limit, 2500)))
else:
self._write_reg(42010, 0)

Expand Down
Loading