From baa1a34b8db2cb66b5b14e3d370913ee46b6e8ae Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Fri, 25 Sep 2026 10:03:37 +0200 Subject: [PATCH 1/2] =?UTF-8?q?Peak=20Filter:=20bei=20R=C3=BCckw=C3=A4rtss?= =?UTF-8?q?pr=C3=BCngen=20auf=20Wert=20gr=C3=B6=C3=9Fer/gleich=20H=C3=B6ch?= =?UTF-8?q?ststand=20warten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/modules/common/utils/peak_filter.py | 39 +++++++++++++------ .../modules/common/utils/test_peak_filter.py | 37 ++++++++++++++++++ 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/packages/modules/common/utils/peak_filter.py b/packages/modules/common/utils/peak_filter.py index 0ef0cc1af3..3fb562ce42 100644 --- a/packages/modules/common/utils/peak_filter.py +++ b/packages/modules/common/utils/peak_filter.py @@ -1,6 +1,6 @@ import logging from control import data -from typing import Optional +from typing import Optional, Tuple from modules.common.fault_state import FaultState from modules.common.component_type import ComponentType @@ -64,12 +64,12 @@ def check_imported_exported( control_interval = data.data.general_data.data.control_interval allowed_deviation = 2 * (control_interval / 3600) * max_power - imp = self.check_total_energy(imported, self.imported, allowed_deviation, max_energy) - self.imported = imported + checked_imp, prev_imp = self.check_total_energy(imported, self.imported, allowed_deviation, max_energy) + self.imported = prev_imp - exp = self.check_total_energy(exported, self.exported, allowed_deviation, max_energy) - self.exported = exported - return imp, exp + checked_exp, prev_exp = self.check_total_energy(exported, self.exported, allowed_deviation, max_energy) + self.exported = prev_exp + return checked_imp, checked_exp return imported, exported def check_total_energy( @@ -78,7 +78,7 @@ def check_total_energy( previous_total_energy: Optional[float], allowed_deviation: float, max_energy: float - ) -> Optional[float]: + ) -> Tuple[Optional[float], Optional[float]]: if total_energy is not None: if total_energy > max_energy: log.debug(f"PeakFilter: Unplausibler Zählerwert: {total_energy / 1000}kWh. " @@ -88,14 +88,29 @@ def check_total_energy( self.fault_state.warning("PeakFilter: Vorheriger Wert None (Startup), " f"aktueller Zählerwert: {total_energy / 1000 }kWh. " "Warte einen Regelintervall.") - elif (allowed_deviation > 0 and - ((total_energy - previous_total_energy) > allowed_deviation or - (total_energy - previous_total_energy) < 0)): + elif allowed_deviation > 0 and (total_energy - previous_total_energy) > allowed_deviation: log.debug(f"PeakFilter: Unplausibler Zählerwert: {total_energy / 1000}kWh. " f"Differenz zum vorherigen Wert: {total_energy - previous_total_energy}Wh. " f"erlaubte Differenz: {round(allowed_deviation, 2)}Wh.") + elif (total_energy - previous_total_energy) < 0: + log.debug(f"PeakFilter: Unplausibler Rückwärtssprung: {total_energy / 1000}kWh. " + f"Vorherigen Wert: {previous_total_energy / 1000}kWh. " + "Höchststand beibehalten.") + checked_energy = previous_total_energy + prev_energy = previous_total_energy + return checked_energy, prev_energy else: log.debug(f"PeakFilter: Zählerwert: {total_energy}Wh innerhalb der zulässigen Grenzen. " f"Differenz zum vorherigen Wert: {total_energy - previous_total_energy}Wh.") - return total_energy - return None + checked_energy = total_energy + prev_energy = total_energy + return checked_energy, prev_energy + # wenn der Peak-Filter greift, Zählerstand nicht aktualisieren (None). + # Zählerstand merken, damit immer nur die zwei letzten verglichen werden, um Vorwärtssprünge abzubilden. + checked_energy = None + prev_energy = total_energy + return checked_energy, prev_energy + else: + checked_energy = None + prev_energy = None + return checked_energy, prev_energy diff --git a/packages/modules/common/utils/test_peak_filter.py b/packages/modules/common/utils/test_peak_filter.py index b50d9eedd8..3a3b16d0ae 100644 --- a/packages/modules/common/utils/test_peak_filter.py +++ b/packages/modules/common/utils/test_peak_filter.py @@ -95,3 +95,40 @@ def test_check_values_valid(params): imp, exp = pf.check_values(params.power, params.imported, params.exported) assert imp == params.expected_imported assert exp == params.expected_exported + + +def test_check_total_energy_forward_jump_then_accept_second_high_and_wait_after_backward_jump(): + fs = DummyFaultState() + pf = PeakFilter(ComponentType.COUNTER, 1, fs) + + allowed_deviation = 10 + max_energy = 1_000_000_000 + + # Vorwaertssprung: erster Wert wird verworfen, aber als Vergleichsbasis gespeichert. + checked, previous = pf.check_total_energy(2000, 1000, allowed_deviation, max_energy) + assert checked is None + assert previous == 2000 + + # Zweiter hoher Wert mit kleiner Differenz wird uebernommen. + checked, previous = pf.check_total_energy(2005, previous, allowed_deviation, max_energy) + assert checked == 2005 + assert previous == 2005 + + # Rueckwaertssprung: letzter gueltiger Hoechststand bleibt erhalten. + checked, previous = pf.check_total_energy(1900, previous, allowed_deviation, max_energy) + assert checked == 2005 + assert previous == 2005 + + # Unterhalb des Hoechststands wird weiterhin gewartet. + checked, previous = pf.check_total_energy(1990, previous, allowed_deviation, max_energy) + assert checked == 2005 + assert previous == 2005 + + # Naechster gleicher oder hoeherer Wert wird wieder zugelassen. + checked, previous = pf.check_total_energy(2005, previous, allowed_deviation, max_energy) + assert checked == 2005 + assert previous == 2005 + + checked, previous = pf.check_total_energy(2010, previous, allowed_deviation, max_energy) + assert checked == 2010 + assert previous == 2010 From 0f35cbece1a3a142864eab81401c3916a669aaa7 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Fri, 25 Sep 2026 10:21:00 +0200 Subject: [PATCH 2/2] review --- packages/modules/common/utils/peak_filter.py | 8 ++++++++ .../modules/common/utils/test_peak_filter.py | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/packages/modules/common/utils/peak_filter.py b/packages/modules/common/utils/peak_filter.py index 3fb562ce42..bfb26cfbad 100644 --- a/packages/modules/common/utils/peak_filter.py +++ b/packages/modules/common/utils/peak_filter.py @@ -93,6 +93,14 @@ def check_total_energy( f"Differenz zum vorherigen Wert: {total_energy - previous_total_energy}Wh. " f"erlaubte Differenz: {round(allowed_deviation, 2)}Wh.") elif (total_energy - previous_total_energy) < 0: + if previous_total_energy > max_energy: + log.debug("PeakFilter: Erholung nach unplausibel hohem Zählerwert erkannt. " + f"Vorheriger Wert: {previous_total_energy / 1000}kWh über dem 50-Jahres-Limit " + f"({max_energy / 1000}kWh). Aktueller Wert {total_energy / 1000}kWh wird " + "verworfen und als neue Vergleichsbasis verwendet.") + checked_energy = None + prev_energy = total_energy + return checked_energy, prev_energy log.debug(f"PeakFilter: Unplausibler Rückwärtssprung: {total_energy / 1000}kWh. " f"Vorherigen Wert: {previous_total_energy / 1000}kWh. " "Höchststand beibehalten.") diff --git a/packages/modules/common/utils/test_peak_filter.py b/packages/modules/common/utils/test_peak_filter.py index 3a3b16d0ae..9af278ece9 100644 --- a/packages/modules/common/utils/test_peak_filter.py +++ b/packages/modules/common/utils/test_peak_filter.py @@ -132,3 +132,20 @@ def test_check_total_energy_forward_jump_then_accept_second_high_and_wait_after_ checked, previous = pf.check_total_energy(2010, previous, allowed_deviation, max_energy) assert checked == 2010 assert previous == 2010 + + # Der niedrigere Folgewert wird einmal verworfen und als neue Vergleichsbasis gesetzt. + allowed_deviation = 10 + max_energy = 3000 + + checked, previous = pf.check_total_energy(4000, 2900, allowed_deviation, max_energy) + assert checked is None + assert previous == 4000 + + checked, previous = pf.check_total_energy(2800, previous, allowed_deviation, max_energy) + assert checked is None + assert previous == 2800 + + # Danach wird ein plausibler Folgewert wieder zugelassen. + checked, previous = pf.check_total_energy(2805, previous, allowed_deviation, max_energy) + assert checked == 2805 + assert previous == 2805