From 8137a173c838404782b3c5e882ec39ec0d62b201 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Tue, 23 Jun 2026 10:48:26 +0200 Subject: [PATCH] chargepoint peaks: fix cp sum in case of error --- packages/control/bat_all.py | 34 +++----- .../control/chargepoint/chargepoint_all.py | 32 +++----- .../chargepoint/chargepoint_all_test.py | 77 +++++++++++++++++++ packages/control/pv_all.py | 38 ++++----- 4 files changed, 114 insertions(+), 67 deletions(-) create mode 100644 packages/control/chargepoint/chargepoint_all_test.py diff --git a/packages/control/bat_all.py b/packages/control/bat_all.py index 31511c9352..c123a5008c 100644 --- a/packages/control/bat_all.py +++ b/packages/control/bat_all.py @@ -153,31 +153,21 @@ def calc_power_for_all_components(self): fault_state = 0 for battery in data.data.bat_data.values(): try: - if battery.data.get.fault_state < 2: - try: - power += battery.data.get.power - except Exception: - log.exception(f"Fehler im Bat-Modul {battery.num}") - imported += battery.data.get.imported - exported += battery.data.get.exported - soc_sum += battery.data.get.soc - soc_count += 1 - else: - if fault_state < battery.data.get.fault_state: - fault_state = battery.data.get.fault_state + power += battery.data.get.power except Exception: log.exception(f"Fehler im Bat-Modul {battery.num}") - if fault_state == 0: - self.data.get.imported = imported - self.data.get.exported = exported - self.data.get.fault_state = 0 - self.data.get.fault_str = NO_ERROR - else: - self.data.get.fault_state = fault_state - self.data.get.fault_str = ("Bitte die Statusmeldungen der Speicher prüfen. Es konnte kein " - "aktueller Zählerstand ermittelt werden, da nicht alle Module Werte " - "liefern.") + imported += battery.data.get.imported + exported += battery.data.get.exported + soc_sum += battery.data.get.soc + soc_count += 1 + fault_state = max(fault_state, battery.data.get.fault_state) + self.data.get.fault_state = fault_state + self.data.get.fault_str = NO_ERROR if fault_state == 0 else ( + "Bitte die Statusmeldungen der Speicher prüfen. " + "Es haben nicht alle Module aktuelle Zählerstände geliefert.") self.data.get.power = power + self.data.get.imported = imported + self.data.get.exported = exported try: self.data.get.soc = int(soc_sum / soc_count) except ZeroDivisionError: diff --git a/packages/control/chargepoint/chargepoint_all.py b/packages/control/chargepoint/chargepoint_all.py index 381678fea1..a384681e17 100644 --- a/packages/control/chargepoint/chargepoint_all.py +++ b/packages/control/chargepoint/chargepoint_all.py @@ -73,30 +73,20 @@ def get_cp_sum(self): try: fault_state = 0 for cp in data.data.cp_data.values(): - if cp.data.get.fault_state < 2: - try: - imported = imported + cp.data.get.imported - exported = exported + cp.data.get.exported - except Exception: - log.exception(f"Fehler in der allgemeinen Ladepunkt-Klasse für Ladepunkt {cp.num}") - try: - power = power + cp.data.get.power - except Exception: - log.exception(f"Fehler in der allgemeinen Ladepunkt-Klasse für Ladepunkt {cp.num}") - else: - if fault_state < cp.data.get.fault_state: - fault_state = cp.data.get.fault_state + imported = imported + cp.data.get.imported + exported = exported + cp.data.get.exported + try: + power = power + cp.data.get.power + except Exception: + log.exception(f"Fehler in der allgemeinen Ladepunkt-Klasse für Ladepunkt {cp.num}") + fault_state = max(fault_state, cp.data.get.fault_state) # Ladepunkte setzen ihre Werte im Fehlerfall selbst zurück self.data.get.power = power self.data.get.imported = imported self.data.get.exported = exported - if fault_state == 0: - self.data.get.fault_state = 0 - self.data.get.fault_str = NO_ERROR - else: - self.data.get.fault_state = fault_state - self.data.get.fault_str = ("Bitte die Statusmeldungen der Ladepunkte prüfen. Es konnte kein " - "aktueller Zählerstand ermittelt werden, da nicht alle Ladepunkte Werte " - "liefern.") + self.data.get.fault_state = fault_state + self.data.get.fault_str = NO_ERROR if fault_state == 0 else ( + "Bitte die Statusmeldungen der Ladepunkte prüfen. " + "Es haben nicht alle Ladepunkte aktuelle Zählerstände geliefert.") except Exception: log.exception("Fehler in der allgemeinen Ladepunkt-Klasse") diff --git a/packages/control/chargepoint/chargepoint_all_test.py b/packages/control/chargepoint/chargepoint_all_test.py new file mode 100644 index 0000000000..a21f7c838c --- /dev/null +++ b/packages/control/chargepoint/chargepoint_all_test.py @@ -0,0 +1,77 @@ +from dataclasses import dataclass +from typing import List +from unittest.mock import Mock + +import pytest + +from control import data +from control.chargepoint.chargepoint import Chargepoint +from control.chargepoint.chargepoint_all import AllChargepoints +from helpermodules.constants import NO_ERROR + + +@dataclass +class Params: + name: str + cp_values: List[Chargepoint] + expected_power: float + expected_imported: float + expected_exported: float + expected_fault_state: int + expected_fault_str: str + + +def cp_mock(num: int, imported: float, exported: float, power: float, fault_state: int) -> Mock: + return Mock(spec=Chargepoint, num=num, data=Mock(get=Mock(imported=imported, + exported=exported, + power=power, + fault_state=fault_state))) + + +cases = [ + Params( + name="Alle Ladepunkte fehlerfrei", + cp_values=[ + cp_mock(1, 1000, 100, 1200, 0), + cp_mock(2, 2000, 200, 2400, 0), + ], + expected_power=3600, + expected_imported=3000, + expected_exported=300, + expected_fault_state=0, + expected_fault_str=NO_ERROR, + ), + Params( + name="Mindestens ein Ladepunkt mit Fehler", + cp_values=[ + cp_mock(1, 1000, 100, 1200, 0), + cp_mock(2, 2000, 200, 2400, 2), + ], + expected_power=3600, + expected_imported=3000, + expected_exported=300, + expected_fault_state=2, + expected_fault_str=( + "Bitte die Statusmeldungen der Ladepunkte prüfen. " + "Es haben nicht alle Ladepunkte aktuelle Zählerstände geliefert." + ), + ), +] + + +@pytest.mark.parametrize("params", cases, ids=[c.name for c in cases]) +def test_get_cp_sum(params: Params): + # setup + data.data_init(Mock()) + data.data.cp_data = {f"cp{index}": cp for index, cp in enumerate(params.cp_values)} + cp_all = AllChargepoints() + + # execution + cp_all.get_cp_sum() + + # evaluation + assert cp_all.data.get.power == params.expected_power + assert cp_all.data.get.imported == params.expected_imported + assert cp_all.data.get.exported == params.expected_exported + assert cp_all.data.get.fault_state == params.expected_fault_state + assert cp_all.data.get.fault_str == params.expected_fault_str diff --git a/packages/control/pv_all.py b/packages/control/pv_all.py index ccaf66f242..59cd0aec6c 100644 --- a/packages/control/pv_all.py +++ b/packages/control/pv_all.py @@ -60,34 +60,24 @@ def calc_power_for_all_components(self) -> None: fault_state = 0 for module in data.data.pv_data.values(): try: - if module.data.get.fault_state < 2: - try: - power += module.data.get.power - except Exception: - log.exception(f"Fehler im allgemeinen PV-Modul für pv{module.num}") - exported += module.data.get.exported - else: - if fault_state < module.data.get.fault_state: - fault_state = module.data.get.fault_state - limit = data.data.io_actions.stepwise_control(module.num)[1] - if module.data.get.fault_state == 0 and limit.message is not None: - # Fehlermeldung nicht überschreiben - module.data.get.fault_str = limit.message - Pub().pub(f"openWB/set/pv/{module.num}/get/fault_str", limit.message) + power += module.data.get.power except Exception: log.exception(f"Fehler im allgemeinen PV-Modul für pv{module.num}") - if fault_state == 0: - self.data.get.exported = exported - Pub().pub("openWB/set/pv/get/exported", self.data.get.exported) - self.data.get.fault_state = 0 - self.data.get.fault_str = NO_ERROR - else: - self.data.get.fault_state = fault_state - self.data.get.fault_str = ("Bitte die Statusmeldungen der Wechselrichter prüfen. Es konnte kein " - "aktueller Zählerstand ermittelt werden, da nicht alle Module Werte " - "liefern.") + exported += module.data.get.exported + fault_state = max(fault_state, module.data.get.fault_state) + limit = data.data.io_actions.stepwise_control(module.num)[1] + if module.data.get.fault_state == 0 and limit.message is not None: + # Fehlermeldung nicht überschreiben + module.data.get.fault_str = limit.message + Pub().pub(f"openWB/set/pv/{module.num}/get/fault_str", limit.message) + self.data.get.fault_state = fault_state + self.data.get.fault_str = NO_ERROR if fault_state == 0 else ( + "Bitte die Statusmeldungen der Wechselrichter prüfen. " + "Es haben nicht alle Module aktuelle Zählerstände geliefert.") self.data.get.power = power Pub().pub("openWB/set/pv/get/power", self.data.get.power) + self.data.get.exported = exported + Pub().pub("openWB/set/pv/get/exported", self.data.get.exported) Pub().pub("openWB/set/pv/get/fault_state", self.data.get.fault_state) Pub().pub("openWB/set/pv/get/fault_str", self.data.get.fault_str) self.data.config.configured = True