Skip to content

io action: error of io device use remaining energy, show message#3080

Merged
LKuemmel merged 3 commits intoopenWB:masterfrom
LKuemmel:dimm_kit
Mar 11, 2026
Merged

io action: error of io device use remaining energy, show message#3080
LKuemmel merged 3 commits intoopenWB:masterfrom
LKuemmel:dimm_kit

Conversation

@LKuemmel
Copy link
Contributor

@LKuemmel LKuemmel commented Jan 6, 2026

https://forum.openwb.de/viewtopic.php?p=138295#p138295
Bei der Dimmung wird im Failsafe-Mode die Leistung zur Verfügung gestellt, die auch bei Aktivierung durch den Netzbetreiber zur Verfügung stehen würde.
Der Nutzer bekommt eine Meldung am Ladepunkt, dass seine Ladung gestoppt/reduziert wurde, weil das IO-Gerät im Fehlerzustand ist.

Dimmen per EMS

  • Aktion aktiv
  • Aktion inaktiv
  • Aktion gelöscht, Aktion vorher aktiv
  • Gerät Fehler, Aktion vorher aktiv
  • Gerät Fehler, Aktion vorher inaktiv

Dimmen per Direktsteuerung

  • Aktion aktiv
  • Aktion inaktiv
  • Gerät Fehler

RSE

  • Aktion aktiv
  • Aktion inaktiv
  • Gerät Fehler
  • undefined Pattern

Erzeuger

  • Aktion aktiv
  • Aktion inaktiv
  • Gerät Fehler
  • undefined Pattern

@LKuemmel LKuemmel added this to the 2.2.0 milestone Jan 8, 2026
@LKuemmel LKuemmel marked this pull request as ready for review March 11, 2026 13:49
@LKuemmel LKuemmel requested a review from Copilot March 11, 2026 13:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Diese PR erweitert die IO-Actions um ein Failsafe-Verhalten bei IO-Gerätefehlern und liefert zusätzlich strukturierte Limit-Informationen (Message + LimitingValue), damit im System/Frontend aussagekräftige Meldungen angezeigt werden können (z.B. bei Dimmung/RSE/Stufensteuerung).

Changes:

  • IO-Actions geben nun i.d.R. ein Tuple (value, LoadmanagementLimit) zurück und berücksichtigen den IO-Fehlerzustand als Failsafe-Trigger.
  • Loadmanagement und PV-All verwenden die neuen Limit-Metadaten für Anzeige/Weiterverarbeitung.
  • Gemeinsame Helper-Funktion zur Erkennung des IO-Fault-States eingeführt und LimitingValue-Enum erweitert.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
packages/modules/io_actions/generator_systems/stepwise_control/api_io.py Stepwise-Control liefert Limit-Metadaten + Failsafe bei IO-Fehler.
packages/modules/io_actions/generator_systems/stepwise_control/api_eebus.py Stepwise-Control (EEBus) um Limit-Metadaten/Failsafe erweitert.
packages/modules/io_actions/controllable_consumers/ripple_control_receiver/api.py RSE liefert Limit-Metadaten/Failsafe und erweitert Logging/Timestamp-Handling.
packages/modules/io_actions/controllable_consumers/dimming_direct_control/api.py Direktsteuerungs-Dimmung liefert Limit-Metadaten/Failsafe.
packages/modules/io_actions/controllable_consumers/dimming/api_io.py IO-Dimmung liefert Limit-Metadaten/Failsafe und Logging-Erweiterungen.
packages/modules/io_actions/controllable_consumers/dimming/api_eebus.py EEBus-Dimmung liefert Limit-Metadaten/Failsafe und Logging-Erweiterungen.
packages/modules/io_actions/common.py Neuer Helper check_fault_state_io_device() für wiederverwendbare Fault-Erkennung.
packages/control/pv_all.py PV-Fault-String basiert nun auf Stepwise-Control-Limit-Metadaten.
packages/control/loadmanagement.py Loadmanagement nutzt Tuple-Returns der IO-Actions und propagiert Limits.
packages/control/limiting_value.py Neue/angepasste LimitingValue-Texte + CONTROL_STEPWISE + Missing-Config-Text.
packages/control/io_device.py IoActions-API auf Tuple-Return umgestellt (Value + LoadmanagementLimit).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +66 to +75
def dimming_via_direct_control(self) -> Tuple[Optional[float], LoadmanagementLimit]:
if check_fault_state_io_device(self.config.configuration.io_device):
return (4200, LoadmanagementLimit(
LimitingValue.CONTROLLABLE_CONSUMERS_ERROR.value.format(get_io_name_by_id(
self.config.configuration.io_device)),
LimitingValue.CONTROLLABLE_CONSUMERS_ERROR))
elif data.data.io_states[f"io_states{self.config.configuration.io_device}"].data.get.digital_input[
self.dimming_input] == self.dimming_value:
return 4200
return (4200, LoadmanagementLimit(LimitingValue.DIMMING_VIA_DIRECT_CONTROL.value,
LimitingValue.DIMMING_VIA_DIRECT_CONTROL))
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die Methode dimming_via_direct_control() liefert jetzt ein (value, LoadmanagementLimit)-Tuple. Es gibt jedoch direkte Call-Sites, die weiterhin None/float erwarten (z.B. packages/control/process.py prüft action.dimming_via_direct_control() is None). Bitte diese Call-Sites auf das neue Return-Format umstellen (z.B. erstes Element auspacken).

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +50
if check_fault_state_io_device(self.config.configuration.io_device):
log_active_ripple_control_receiver()
for pattern in self.config.configuration.input_pattern:
for digital_input, value in pattern["matrix"].items():
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Der Aufruf log_active_ripple_control_receiver() passiert hier, bevor in der folgenden Schleife überhaupt ein pattern bestimmt wurde. Dadurch wird im Fehlerfall die Logging-Funktion mit nicht initialisierten Kontextdaten ausgeführt. Entweder den ersten Aufruf entfernen oder erst nach Auswahl eines passenden Patterns loggen.

Copilot uses AI. Check for mistakes.
# Alle digitalen Eingänge entsprechen dem Pattern
return pattern["value"] if pattern["value"] is not None else 0
if pattern["value"] is None:
return 0, LoadmanagementLimit(LimitingValue.MISSING_CONFIFGURATION,
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadmanagementLimit.message ist als Optional[str] definiert, hier wird aber LimitingValue.MISSING_CONFIFGURATION (Enum) übergeben. Das führt später zu ungewollten Strings wie LimitingValue.MISSING_CONFIFGURATION in der UI. Verwende für die Message LimitingValue.MISSING_CONFIFGURATION.value und als limiting_value nur das Enum (nicht .value).

Suggested change
return 0, LoadmanagementLimit(LimitingValue.MISSING_CONFIFGURATION,
return 0, LoadmanagementLimit(LimitingValue.MISSING_CONFIFGURATION.value,

Copilot uses AI. Check for mistakes.
break
else:
if pattern["value"] is None:
return 0, LoadmanagementLimit(LimitingValue.MISSING_CONFIFGURATION,
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadmanagementLimit.message ist Optional[str], hier wird aber LimitingValue.MISSING_CONFIFGURATION (Enum) übergeben. Dadurch landet später der Enum-Name statt der eigentlichen Meldung im fault_str. Bitte .value für die Message verwenden und limiting_value=LimitingValue.MISSING_CONFIFGURATION setzen.

Suggested change
return 0, LoadmanagementLimit(LimitingValue.MISSING_CONFIFGURATION,
return 0, LoadmanagementLimit(LimitingValue.MISSING_CONFIFGURATION.value,

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +5


def check_fault_state_io_device(io_device: int) -> bool:
return data.data.io_states[f"io_states{io_device}"].data.get.fault_state == 2
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In check_fault_state_io_device() wird der Fehlerzustand mit der Magic Number 2 geprüft. Für bessere Lesbarkeit/Wartbarkeit könnte hier FaultStateLevel.ERROR (siehe modules/common/fault_state_level.py) verwendet werden.

Suggested change
def check_fault_state_io_device(io_device: int) -> bool:
return data.data.io_states[f"io_states{io_device}"].data.get.fault_state == 2
from modules.common.fault_state_level import FaultStateLevel
def check_fault_state_io_device(io_device: int) -> bool:
return (
data.data.io_states[f"io_states{io_device}"].data.get.fault_state
== FaultStateLevel.ERROR
)

Copilot uses AI. Check for mistakes.
@@ -177,9 +175,4 @@ def _limit_by_ripple_control_receiver(self,
available_currents = [min(max_current*value - cp.data.set.target_current, c)
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hier können bei value=0 (z.B. Fehler-/Failsafe-Fall) negative Ströme entstehen, weil max_current*value - cp.data.set.target_current negativ wird und per min() übernommen werden kann. Bitte den berechneten Strom auf mindestens 0A clampen, bevor er in available_currents übernommen wird.

Suggested change
available_currents = [min(max_current*value - cp.data.set.target_current, c)
available_currents = [max(min(max_current*value - cp.data.set.target_current, c), 0)

Copilot uses AI. Check for mistakes.
Comment on lines +140 to +141
value, limit = data.data.io_actions.dimming_via_direct_control({"type": "cp", "id": cp.num})
if value is not None:
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die geänderte IO-Action-Integration (Tuple-Return mit LoadmanagementLimit) in _limit_by_dimming_via_direct_control, _limit_by_dimming und _limit_by_ripple_control_receiver ist aktuell nicht durch Unit-Tests abgedeckt (in loadmanagement_test.py werden nur _limit_by_power und _limit_by_current getestet). Bitte Tests ergänzen, die die neue Limit-Auswahl und die Fehler-/Failsafe-Pfade verifizieren.

Copilot uses AI. Check for mistakes.
Comment on lines +103 to +104
limit = LoadmanagementLimit(
LimitingValue.CONTROL_STEPWISE.value.format(pattern["value"]*100),
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In der Meldung wird pattern["value"]*100 direkt formatiert. Da pattern["value"] i.d.R. ein Float ist (z.B. 0.5), ergibt das user-facing Werte wie 50.0%. Bitte vor dem Formatieren sinnvoll runden/als int ausgeben, um konsistente Prozentangaben zu erhalten.

Suggested change
limit = LoadmanagementLimit(
LimitingValue.CONTROL_STEPWISE.value.format(pattern["value"]*100),
percentage = int(round(pattern["value"] * 100))
limit = LoadmanagementLimit(
LimitingValue.CONTROL_STEPWISE.value.format(percentage),

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +109
limit = LoadmanagementLimit(
LimitingValue.CONTROL_STEPWISE.value.format(pattern["value"]*100),
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die Prozentangabe nutzt pattern["value"]*100 ohne Rundung/Konvertierung. Das führt bei Float-Werten zu Ausgaben wie 50.0%. Bitte die Prozentwerte für die Nutzeranzeige runden (z.B. int/round).

Suggested change
limit = LoadmanagementLimit(
LimitingValue.CONTROL_STEPWISE.value.format(pattern["value"]*100),
percent_value = round(pattern["value"] * 100)
limit = LoadmanagementLimit(
LimitingValue.CONTROL_STEPWISE.value.format(int(percent_value)),

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +50
with ModifyLoglevelContext(control_command_log, logging.DEBUG):
if check_fault_state_io_device(self.config.configuration.io_device):
log_active_ripple_control_receiver()
for pattern in self.config.configuration.input_pattern:
for digital_input, value in pattern["matrix"].items():
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In setup() werden die Input-Patterns nur noch ausgewertet, wenn das IO-Gerät im Fehlerzustand ist. Im Normalfall (fault_state != 2) wird dadurch nie aktiviert bzw. kein Timestamp gesetzt, obwohl die Pattern evtl. aktiv sind. Bitte die Pattern-Auswertung wieder auch im Normalfall durchführen (Fault-State nur als zusätzlicher Aktivierungsgrund behandeln).

Copilot uses AI. Check for mistakes.
@LKuemmel LKuemmel merged commit cfdbc1b into openWB:master Mar 11, 2026
1 check passed
@LKuemmel LKuemmel deleted the dimm_kit branch March 11, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants