From ffefdaa3375187e21c309654374541477b14ab36 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Tue, 8 Jul 2025 17:13:13 +0200 Subject: [PATCH 1/6] EZA --- packages/control/io_device.py | 12 +++- packages/control/pv_all.py | 4 ++ packages/modules/io_actions/groups.py | 2 + .../stepwise_control/__init__.py | 0 .../production_plants/stepwise_control/api.py | 68 +++++++++++++++++++ .../stepwise_control/config.py | 25 +++++++ 6 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 packages/modules/io_actions/production_plants/stepwise_control/__init__.py create mode 100644 packages/modules/io_actions/production_plants/stepwise_control/api.py create mode 100644 packages/modules/io_actions/production_plants/stepwise_control/config.py diff --git a/packages/control/io_device.py b/packages/control/io_device.py index e64c5aba8e..6c349b2091 100644 --- a/packages/control/io_device.py +++ b/packages/control/io_device.py @@ -7,6 +7,7 @@ from modules.io_actions.controllable_consumers.dimming.api import Dimming from modules.io_actions.controllable_consumers.dimming_direct_control.api import DimmingDirectControl from modules.io_actions.controllable_consumers.ripple_control_receiver.api import RippleControlReceiver +from modules.io_actions.production_plants.stepwise_control.api import StepwiseControl @dataclass @@ -47,7 +48,7 @@ def __init__(self, num: Union[int, str]): class IoActions: def __init__(self): - self.actions: Dict[int, Union[Dimming, DimmingDirectControl, RippleControlReceiver]] = {} + self.actions: Dict[int, Union[Dimming, DimmingDirectControl, RippleControlReceiver, StepwiseControl]] = {} def setup(self): for action in self.actions.values(): @@ -93,3 +94,12 @@ def ripple_control_receiver(self, device: Dict) -> float: return action.ripple_control_receiver() else: return 1 + + def stepwise_control(self, device_id: int) -> Optional[str]: + for action in self.actions.values(): + if isinstance(action, StepwiseControl): + if device_id == action.config.configuration.pv_id: + #self._check_fault_state_io_device(action.config.configuration.io_device) + return action.control_stepwise() + else: + return None diff --git a/packages/control/pv_all.py b/packages/control/pv_all.py index abe2f50225..01f7833411 100644 --- a/packages/control/pv_all.py +++ b/packages/control/pv_all.py @@ -68,6 +68,10 @@ def calc_power_for_all_components(self) -> None: else: if fault_state < module_data.get.fault_state: fault_state = module_data.get.fault_state + msg = data.data.io_actions.stepwise_control(data.data.pv_data[module].num) + if msg is not None and data.data.pv_data[module].data.get.fault_state == 0: + data.data.pv_data[module].data.get.fault_str = msg + Pub().pub(f"openWB/set/pv/{data.data.pv_data[module].num}/get/fault_str", msg) except Exception: log.exception("Fehler im allgemeinen PV-Modul für "+str(module)) if fault_state == 0: diff --git a/packages/modules/io_actions/groups.py b/packages/modules/io_actions/groups.py index 538025f563..1015e67a3e 100644 --- a/packages/modules/io_actions/groups.py +++ b/packages/modules/io_actions/groups.py @@ -3,8 +3,10 @@ class ActionGroup(Enum): CONTROLLABLE_CONSUMERS = "controllable_consumers" + PRODUCTION_PLANTS = "production_plants" READABLE_GROUP_NAME = { ActionGroup.CONTROLLABLE_CONSUMERS: "Steuerbare Verbrauchseinrichtungen (§14a)", + ActionGroup.PRODUCTION_PLANTS: "Erzeugungsanlagen (§9)", } diff --git a/packages/modules/io_actions/production_plants/stepwise_control/__init__.py b/packages/modules/io_actions/production_plants/stepwise_control/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/modules/io_actions/production_plants/stepwise_control/api.py b/packages/modules/io_actions/production_plants/stepwise_control/api.py new file mode 100644 index 0000000000..430f361147 --- /dev/null +++ b/packages/modules/io_actions/production_plants/stepwise_control/api.py @@ -0,0 +1,68 @@ +import logging +from control import data +from typing import Optional +from helpermodules.logger import ModifyLoglevelContext +from modules.common.abstract_device import DeviceDescriptor +from modules.common.abstract_io import AbstractIoAction +from modules.common.utils.component_parser import get_component_name_by_id +from modules.io_actions.production_plants.stepwise_control.config import StepwiseControlSetup + +control_command_log = logging.getLogger("steuve_control_command") + + +class StepwiseControl(AbstractIoAction): + def __init__(self, config: StepwiseControlSetup): + self.config = config + control_command_log.info(f"Stufenweise Steuerung einer EZA: Eingang {self.config.configuration.s1} für S1, " + f"Eingang {self.config.configuration.s2} für S2, und Eingang " + f"{self.config.configuration.w3} für W3 wird überwacht. Die Beschränkung musss im WR" + " vorgenommen werden.") + self.s1_prev = False + self.s2_prev = False + self.w3_prev = False + super().__init__() + + def setup(self) -> None: + pass + + def control_stepwise(self) -> Optional[str]: + text = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist auf " + "{} % beschränkt. Die Beschränkung musss im WR vorgenommen werden.") + msg = None + log_msg = None + digital_input = data.data.io_states[f"io_states{self.config.configuration.io_device}"].data.get.digital_input + if digital_input[self.config.configuration.s1] is True: + msg = text.format(60) + if self.s1_prev is False: + log_msg = msg + elif digital_input[self.config.configuration.s2] is True: + msg = text.format(30) + if self.s1_prev is False: + log_msg = msg + elif digital_input[self.config.configuration.w3] is True: + msg = text.format(0) + if self.s1_prev is False: + log_msg = msg + if (digital_input[self.config.configuration.s1] is False and + digital_input[self.config.configuration.s2] is False and + digital_input[self.config.configuration.w3] is False and + self.s1_prev is False and + self.s2_prev is False and + self.w3_prev is False): + # Keine Beschränkung soll nicht dauerhaft im WR angezeigt werden. + log_msg = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist " + "nicht beschränkt. Die Beschränkung musss im WR vorgenommen werden.") + self.s1_prev = digital_input[self.config.configuration.s1] + self.s2_prev = digital_input[self.config.configuration.s2] + self.w3_prev = digital_input[self.config.configuration.w3] + if log_msg is not None: + with ModifyLoglevelContext(control_command_log, logging.DEBUG): + control_command_log.info(log_msg) + return msg + + +def create_action(config: StepwiseControlSetup): + return StepwiseControl(config=config) + + +device_descriptor = DeviceDescriptor(configuration_factory=StepwiseControlSetup) diff --git a/packages/modules/io_actions/production_plants/stepwise_control/config.py b/packages/modules/io_actions/production_plants/stepwise_control/config.py new file mode 100644 index 0000000000..3ac772e1f3 --- /dev/null +++ b/packages/modules/io_actions/production_plants/stepwise_control/config.py @@ -0,0 +1,25 @@ +from dataclasses import dataclass +from typing import Optional +from modules.io_actions.groups import ActionGroup + + +@dataclass +class StepwiseControlConfig: + io_device: Optional[int] = None + s1: str = None + s2: str = None + w3: str = None + pv_id: int = None + + +class StepwiseControlSetup: + def __init__(self, + name: str = "Stufenweise Steuerung einer EZA", + type: str = "stepwise_control", + id: int = 0, + configuration: StepwiseControlConfig = None): + self.name = name + self.type = type + self.id = id + self.configuration = configuration or StepwiseControlConfig() + self.group = ActionGroup.PRODUCTION_PLANTS.value From 00b48c5cc0e824fb2ab5760e973ba0a163d0bea8 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Wed, 9 Jul 2025 07:35:19 +0200 Subject: [PATCH 2/6] fix --- .../production_plants/stepwise_control/api.py | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/packages/modules/io_actions/production_plants/stepwise_control/api.py b/packages/modules/io_actions/production_plants/stepwise_control/api.py index 430f361147..a47117cc6b 100644 --- a/packages/modules/io_actions/production_plants/stepwise_control/api.py +++ b/packages/modules/io_actions/production_plants/stepwise_control/api.py @@ -17,9 +17,6 @@ def __init__(self, config: StepwiseControlSetup): f"Eingang {self.config.configuration.s2} für S2, und Eingang " f"{self.config.configuration.w3} für W3 wird überwacht. Die Beschränkung musss im WR" " vorgenommen werden.") - self.s1_prev = False - self.s2_prev = False - self.w3_prev = False super().__init__() def setup(self) -> None: @@ -29,36 +26,32 @@ def control_stepwise(self) -> Optional[str]: text = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist auf " "{} % beschränkt. Die Beschränkung musss im WR vorgenommen werden.") msg = None - log_msg = None digital_input = data.data.io_states[f"io_states{self.config.configuration.io_device}"].data.get.digital_input if digital_input[self.config.configuration.s1] is True: msg = text.format(60) - if self.s1_prev is False: - log_msg = msg elif digital_input[self.config.configuration.s2] is True: msg = text.format(30) - if self.s1_prev is False: - log_msg = msg elif digital_input[self.config.configuration.w3] is True: msg = text.format(0) - if self.s1_prev is False: - log_msg = msg + if msg is not None: + with ModifyLoglevelContext(control_command_log, logging.DEBUG): + control_command_log.info(msg) + return msg if (digital_input[self.config.configuration.s1] is False and digital_input[self.config.configuration.s2] is False and - digital_input[self.config.configuration.w3] is False and - self.s1_prev is False and - self.s2_prev is False and - self.w3_prev is False): + digital_input[self.config.configuration.w3] is False): # Keine Beschränkung soll nicht dauerhaft im WR angezeigt werden. - log_msg = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist " + msg = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist " "nicht beschränkt. Die Beschränkung musss im WR vorgenommen werden.") - self.s1_prev = digital_input[self.config.configuration.s1] - self.s2_prev = digital_input[self.config.configuration.s2] - self.w3_prev = digital_input[self.config.configuration.w3] - if log_msg is not None: with ModifyLoglevelContext(control_command_log, logging.DEBUG): - control_command_log.info(log_msg) - return msg + control_command_log.info(msg) + return None + else: + raise ValueError( + f"Unbekannter Zustand der Stufenweise Steuerung {self.config.name}: " + f"{digital_input[self.config.configuration.s1]}, " + f"{digital_input[self.config.configuration.s2]}, {digital_input[self.config.configuration.w3]}." + ) def create_action(config: StepwiseControlSetup): From 22d1565dfb9e5ea3473f5199dd6b0cda2f8d4f6e Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Wed, 9 Jul 2025 08:20:04 +0200 Subject: [PATCH 3/6] EZA --- packages/control/io_device.py | 8 +++- packages/modules/common/store/_io.py | 13 +++++ .../production_plants/stepwise_control/api.py | 48 ++++++++++++------- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/packages/control/io_device.py b/packages/control/io_device.py index 6c349b2091..387d9004bf 100644 --- a/packages/control/io_device.py +++ b/packages/control/io_device.py @@ -16,6 +16,10 @@ class Get: analog_output: Dict[int, float] = None digital_input: Dict[int, bool] = None digital_output: Dict[int, bool] = None + analog_input_prev: Dict[int, float] = None + analog_output_prev: Dict[int, float] = None + digital_input_prev: Dict[int, bool] = None + digital_output_prev: Dict[int, bool] = None fault_str: str = NO_ERROR fault_state: int = 0 @@ -27,7 +31,9 @@ def get_factory(): @dataclass class Set: analog_output: Dict[int, float] = None + analog_output_prev: Dict[int, float] = None digital_output: Dict[int, bool] = None + digital_output_prev: Dict[int, bool] = None def set_factory(): @@ -99,7 +105,7 @@ def stepwise_control(self, device_id: int) -> Optional[str]: for action in self.actions.values(): if isinstance(action, StepwiseControl): if device_id == action.config.configuration.pv_id: - #self._check_fault_state_io_device(action.config.configuration.io_device) + self._check_fault_state_io_device(action.config.configuration.io_device) return action.control_stepwise() else: return None diff --git a/packages/modules/common/store/_io.py b/packages/modules/common/store/_io.py index cba0fcccc9..f083c4d46f 100644 --- a/packages/modules/common/store/_io.py +++ b/packages/modules/common/store/_io.py @@ -1,3 +1,4 @@ +from control import data from modules.common.component_state import IoState from modules.common.fault_state import FaultState from modules.common.store import ValueStore @@ -16,14 +17,26 @@ def set(self, state: IoState) -> None: def update(self): try: if self.state.digital_input: + pub_to_broker(f"openWB/set/io/states/{self.num}/get/digital_input_prev", + data.data.io_states[f"io_states{self.num}"].data.get.digital_input) pub_to_broker(f"openWB/set/io/states/{self.num}/get/digital_input", self.state.digital_input) if self.state.analog_input: + pub_to_broker(f"openWB/set/io/states/{self.num}/get/analog_input_prev", + data.data.io_states[f"io_states{self.num}"].data.get.analog_input) pub_to_broker(f"openWB/set/io/states/{self.num}/get/analog_input", self.state.analog_input) if self.state.digital_output: + pub_to_broker(f"openWB/set/io/states/{self.num}/get/digital_output_prev", + data.data.io_states[f"io_states{self.num}"].data.get.digital_output) pub_to_broker(f"openWB/set/io/states/{self.num}/get/digital_output", self.state.digital_output) + pub_to_broker(f"openWB/set/io/states/{self.num}/set/digital_output_prev", + data.data.io_states[f"io_states{self.num}"].data.set.digital_output) pub_to_broker(f"openWB/set/io/states/{self.num}/set/digital_output", self.state.digital_output) if self.state.analog_output: + pub_to_broker(f"openWB/set/io/states/{self.num}/get/analog_output_prev", + data.data.io_states[f"io_states{self.num}"].data.get.analog_output) pub_to_broker(f"openWB/set/io/states/{self.num}/get/analog_output", self.state.analog_output) + pub_to_broker(f"openWB/set/io/states/{self.num}/set/analog_output_prev", + data.data.io_states[f"io_states{self.num}"].data.set.analog_output) pub_to_broker(f"openWB/set/io/states/{self.num}/set/analog_output", self.state.analog_output) except Exception as e: raise FaultState.from_exception(e) diff --git a/packages/modules/io_actions/production_plants/stepwise_control/api.py b/packages/modules/io_actions/production_plants/stepwise_control/api.py index a47117cc6b..77dd746f19 100644 --- a/packages/modules/io_actions/production_plants/stepwise_control/api.py +++ b/packages/modules/io_actions/production_plants/stepwise_control/api.py @@ -27,31 +27,43 @@ def control_stepwise(self) -> Optional[str]: "{} % beschränkt. Die Beschränkung musss im WR vorgenommen werden.") msg = None digital_input = data.data.io_states[f"io_states{self.config.configuration.io_device}"].data.get.digital_input - if digital_input[self.config.configuration.s1] is True: + digital_input_prev = data.data.io_states[ + f"io_states{self.config.configuration.io_device}"].data.get.digital_input_prev + + active_inputs = [ + digital_input[self.config.configuration.s1], + digital_input[self.config.configuration.s2], + digital_input[self.config.configuration.w3] + ] + num_active = sum(1 for v in active_inputs if v) + + if num_active > 1: + error_msg = (f"Fehler: Mehr als ein Eingang ist aktiv für die stufenweise Steuerung der EZA! " + f"S1: {digital_input[self.config.configuration.s1]}, " + f"S2: {digital_input[self.config.configuration.s2]}, " + f"W3: {digital_input[self.config.configuration.w3]}") + with ModifyLoglevelContext(control_command_log, logging.ERROR): + control_command_log.error(error_msg) + raise ValueError(error_msg) + + if digital_input[self.config.configuration.s1]: msg = text.format(60) - elif digital_input[self.config.configuration.s2] is True: + elif digital_input[self.config.configuration.s2]: msg = text.format(30) - elif digital_input[self.config.configuration.w3] is True: + elif digital_input[self.config.configuration.w3]: msg = text.format(0) - if msg is not None: - with ModifyLoglevelContext(control_command_log, logging.DEBUG): - control_command_log.info(msg) - return msg - if (digital_input[self.config.configuration.s1] is False and - digital_input[self.config.configuration.s2] is False and - digital_input[self.config.configuration.w3] is False): + else: # Keine Beschränkung soll nicht dauerhaft im WR angezeigt werden. msg = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist " - "nicht beschränkt. Die Beschränkung musss im WR vorgenommen werden.") + "nicht beschränkt. Die Beschränkung musss im WR vorgenommen werden.") + + if not (digital_input[self.config.configuration.s1] == digital_input_prev[self.config.configuration.s1] and + digital_input[self.config.configuration.s2] == digital_input_prev[self.config.configuration.s2] and + digital_input[self.config.configuration.w3] == digital_input_prev[self.config.configuration.w3]): + # Wenn sich was geändet hat, loggen with ModifyLoglevelContext(control_command_log, logging.DEBUG): control_command_log.info(msg) - return None - else: - raise ValueError( - f"Unbekannter Zustand der Stufenweise Steuerung {self.config.name}: " - f"{digital_input[self.config.configuration.s1]}, " - f"{digital_input[self.config.configuration.s2]}, {digital_input[self.config.configuration.w3]}." - ) + return msg def create_action(config: StepwiseControlSetup): From 95c44dcaecc549c70b6bd544be86e58542b07a2d Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Wed, 9 Jul 2025 08:34:43 +0200 Subject: [PATCH 4/6] Wiki --- "docs/IO-Ger\303\244te & -Aktionen.md" | 6 +++++- ...bare Verbrauchseinrichtungen nach \302\24714a.md" | 12 ++++++++++++ .../production_plants/stepwise_control/api.py | 6 +++--- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git "a/docs/IO-Ger\303\244te & -Aktionen.md" "b/docs/IO-Ger\303\244te & -Aktionen.md" index bac6bd4be8..cd16d3e177 100644 --- "a/docs/IO-Ger\303\244te & -Aktionen.md" +++ "b/docs/IO-Ger\303\244te & -Aktionen.md" @@ -27,7 +27,11 @@ Die AddOn-Platine stellt 7 Eingänge und 3 Ausgänge zur Verfügung. WICHTIG: In ### Steuerbare Verbrauchseinrichtungen: Dimmen per EMS, Dimmung per Direkt-Steuerung, RSE -Ausführliche Informationen findest Du im gesonderten Wiki-Beitrag [Steuerbare Verbrauchseinrichtungen](https://github.com/openWB/core/wiki/Steuerbare-Verbrauchseinrichtungen-nach-§14a) +Ausführliche Informationen findest Du im gesonderten Wiki-Beitrag [Steuerbare Einrichtungen nach § 14a EnGW und § 9 EEG](https://github.com/openWB/core/wiki/Steuerbare-Verbrauchseinrichtungen-nach-§14a) + +### Steuerbare Erzeugungseinrichtungen: Stufenweise Steuerung +Bitte beachten: Die openWB steuert keinen Wechselrichter an. Sie zeigt lediglich den aktuellen Zustand der Beschränkung ein. +Ausführliche Informationen findest Du im gesonderten Wiki-Beitrag [Steuerbare Einrichtungen nach § 14a EnGW und § 9 EEG](https://github.com/openWB/core/wiki/Steuerbare-Verbrauchseinrichtungen-nach-§14a) ## Manuelles Setzen der Ausgänge Die Ausgänge aller IO-Geräte können per MQTT gesetzt werden. Die Topics findet Ihr in den Einstellungen des jeweiligen Geräts als Copy-to-Clipboard-Link. Das manuelle Setzen des Ausgangs überschreibt den Wert, den zB die openWB bei einer IO-Aktion gesetzt hat. \ No newline at end of file diff --git "a/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" "b/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" index d4cbb44c5b..b9a19e7754 100644 --- "a/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" +++ "b/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" @@ -1,3 +1,4 @@ +## Stuerbare Verbrauchseinrichtungen (SteuVE) nach § 14a EnGW Der Gesetzgeber sieht verschiedene Möglichkeiten für steuerbare Verbrauchseinrichtungen vor. Für jede steuerbare Verbrauchseinrichtung kann eine andere Option angemeldet werden. Bei der Konfiguration muss deshalb auch immer der/die Ladepunkte angegeben werden, für die die IO-Aktion angewendet werden soll. ### Dimmen per EMS @@ -13,3 +14,14 @@ Pro steuerbarer Verbrauchseinrichtung muss eine IO-Aktion konfiguriert werden un ### Rundsteuer-Empfänger-Kontakt (RSE) Für den RSE-Kontakt kann ein Muster aus verschiedenen Eingängen und ein Prozentwert, auf den die Anschlussleistung begrenzt wird, angegeben werden. + +## Steuerbare Erzeugungsanlagen (EZA) nach § 9 EEG + +Bitte beachten: Die openWB steuert keinen Wechselrichter an. Sie zeigt lediglich den aktuellen Zustand der Beschränkung ein. + +Die Einspeiseleistung des Wechselrichters wird über drei Signalkontakte der FNN-Steuerbox geregelt. Die openWB übernimmt dabei keine direkte Steuerung des Wechselrichters, sondern visualisiert lediglich den aktuellen Steuerzustand. Das Signalkabel der FNN-Steuerbox muss daher beispielsweise über eine Doppelklemme mit dem I/O-Modul der openWB verbunden und anschließend zum Wechselrichter weitergeführt (durchgeschleift) werden. +Die Signalkontakte bilden folgende Zustände ab: +S1 -> 60% der EZA +S2 -> 30% der EZA +W3 -> 0% der EZA +alle Kontakte offen -> 100% der EZA \ No newline at end of file diff --git a/packages/modules/io_actions/production_plants/stepwise_control/api.py b/packages/modules/io_actions/production_plants/stepwise_control/api.py index 77dd746f19..592951a2a1 100644 --- a/packages/modules/io_actions/production_plants/stepwise_control/api.py +++ b/packages/modules/io_actions/production_plants/stepwise_control/api.py @@ -15,7 +15,7 @@ def __init__(self, config: StepwiseControlSetup): self.config = config control_command_log.info(f"Stufenweise Steuerung einer EZA: Eingang {self.config.configuration.s1} für S1, " f"Eingang {self.config.configuration.s2} für S2, und Eingang " - f"{self.config.configuration.w3} für W3 wird überwacht. Die Beschränkung musss im WR" + f"{self.config.configuration.w3} für W3 wird überwacht. Die Beschränkung musss in der EZA" " vorgenommen werden.") super().__init__() @@ -24,7 +24,7 @@ def setup(self) -> None: def control_stepwise(self) -> Optional[str]: text = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist auf " - "{} % beschränkt. Die Beschränkung musss im WR vorgenommen werden.") + "{} % beschränkt. Die Beschränkung musss in der EZA vorgenommen werden.") msg = None digital_input = data.data.io_states[f"io_states{self.config.configuration.io_device}"].data.get.digital_input digital_input_prev = data.data.io_states[ @@ -55,7 +55,7 @@ def control_stepwise(self) -> Optional[str]: else: # Keine Beschränkung soll nicht dauerhaft im WR angezeigt werden. msg = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist " - "nicht beschränkt. Die Beschränkung musss im WR vorgenommen werden.") + "nicht beschränkt. Die Beschränkung musss in der EZA vorgenommen werden.") if not (digital_input[self.config.configuration.s1] == digital_input_prev[self.config.configuration.s1] and digital_input[self.config.configuration.s2] == digital_input_prev[self.config.configuration.s2] and From f4fc38ba8163d9a12cea7ae1660356792c3b8049 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Wed, 9 Jul 2025 08:36:36 +0200 Subject: [PATCH 5/6] flake8 --- .../io_actions/production_plants/stepwise_control/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/modules/io_actions/production_plants/stepwise_control/api.py b/packages/modules/io_actions/production_plants/stepwise_control/api.py index 592951a2a1..8dfa0b4110 100644 --- a/packages/modules/io_actions/production_plants/stepwise_control/api.py +++ b/packages/modules/io_actions/production_plants/stepwise_control/api.py @@ -15,8 +15,8 @@ def __init__(self, config: StepwiseControlSetup): self.config = config control_command_log.info(f"Stufenweise Steuerung einer EZA: Eingang {self.config.configuration.s1} für S1, " f"Eingang {self.config.configuration.s2} für S2, und Eingang " - f"{self.config.configuration.w3} für W3 wird überwacht. Die Beschränkung musss in der EZA" - " vorgenommen werden.") + f"{self.config.configuration.w3} für W3 wird überwacht. Die Beschränkung musss in " + "der EZA vorgenommen werden.") super().__init__() def setup(self) -> None: From 19b32b9444c0cd344355120a6973b7796678bbd5 Mon Sep 17 00:00:00 2001 From: benderl Date: Thu, 17 Jul 2025 07:46:49 +0200 Subject: [PATCH 6/6] Apply suggestions from code review --- "docs/IO-Ger\303\244te & -Aktionen.md" | 2 +- ...Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git "a/docs/IO-Ger\303\244te & -Aktionen.md" "b/docs/IO-Ger\303\244te & -Aktionen.md" index cd16d3e177..07f34179a8 100644 --- "a/docs/IO-Ger\303\244te & -Aktionen.md" +++ "b/docs/IO-Ger\303\244te & -Aktionen.md" @@ -30,7 +30,7 @@ Die AddOn-Platine stellt 7 Eingänge und 3 Ausgänge zur Verfügung. WICHTIG: In Ausführliche Informationen findest Du im gesonderten Wiki-Beitrag [Steuerbare Einrichtungen nach § 14a EnGW und § 9 EEG](https://github.com/openWB/core/wiki/Steuerbare-Verbrauchseinrichtungen-nach-§14a) ### Steuerbare Erzeugungseinrichtungen: Stufenweise Steuerung -Bitte beachten: Die openWB steuert keinen Wechselrichter an. Sie zeigt lediglich den aktuellen Zustand der Beschränkung ein. +Bitte beachten: Die openWB steuert keinen Wechselrichter an. Sie zeigt lediglich den aktuellen Zustand der Beschränkung an. Ausführliche Informationen findest Du im gesonderten Wiki-Beitrag [Steuerbare Einrichtungen nach § 14a EnGW und § 9 EEG](https://github.com/openWB/core/wiki/Steuerbare-Verbrauchseinrichtungen-nach-§14a) ## Manuelles Setzen der Ausgänge diff --git "a/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" "b/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" index b9a19e7754..0b5b54a611 100644 --- "a/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" +++ "b/docs/Steuerbare Verbrauchseinrichtungen nach \302\24714a.md" @@ -17,11 +17,12 @@ Für den RSE-Kontakt kann ein Muster aus verschiedenen Eingängen und ein Prozen ## Steuerbare Erzeugungsanlagen (EZA) nach § 9 EEG -Bitte beachten: Die openWB steuert keinen Wechselrichter an. Sie zeigt lediglich den aktuellen Zustand der Beschränkung ein. +Bitte beachten: Die openWB steuert keinen Wechselrichter an. Sie zeigt lediglich den aktuellen Zustand der Beschränkung an. -Die Einspeiseleistung des Wechselrichters wird über drei Signalkontakte der FNN-Steuerbox geregelt. Die openWB übernimmt dabei keine direkte Steuerung des Wechselrichters, sondern visualisiert lediglich den aktuellen Steuerzustand. Das Signalkabel der FNN-Steuerbox muss daher beispielsweise über eine Doppelklemme mit dem I/O-Modul der openWB verbunden und anschließend zum Wechselrichter weitergeführt (durchgeschleift) werden. +Die Einspeiseleistung des Wechselrichters wird über drei Signalkontakte der FNN-Steuerbox geregelt. Die openWB übernimmt dabei keine direkte Steuerung des Wechselrichters, sondern visualisiert lediglich den aktuellen Steuerzustand. Das Signalkabel der FNN-Steuerbox muss daher beispielsweise über eine Doppelklemme mit dem I/O-Modul der openWB verbunden und anschließend zum Wechselrichter weitergeführt (durchgeschliffen) werden. Die Signalkontakte bilden folgende Zustände ab: S1 -> 60% der EZA S2 -> 30% der EZA W3 -> 0% der EZA -alle Kontakte offen -> 100% der EZA \ No newline at end of file +alle Kontakte offen -> 100% der EZA +Sollten mehrere Kontakte geschlossen sein, so wird die geringste Leistungsstufe ausgewählt (z. B. S2 und W3 -> 0%). \ No newline at end of file