-
Notifications
You must be signed in to change notification settings - Fork 115
Feature extended filter #3246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature extended filter #3246
Changes from all commits
0441698
3301400
5dee2a9
5b47c40
2223791
fec4386
8841d89
b9bb195
af281cf
6732231
8214261
eabcf30
fe14ef5
da8ee2e
8029f48
72b7997
13bc6a0
31ded0e
384cf5a
8ea2614
bbf335a
65347ff
3920397
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,93 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import logging | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from control import data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Optional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from modules.common.fault_state import FaultState | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log = logging.getLogger(__name__) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class PeakFilter: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, type: str, component_id: int, fault_state: FaultState): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.type = type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.component_id = component_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.fault_state = fault_state | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.imported = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.exported = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def check_values( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| power: float, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imported: Optional[float] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exported: Optional[float] = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> tuple[Optional[float], Optional[float]]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # setze maximale Leistung je nach Komponente | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.type == "counter": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| counter = data.data.counter_data[f"counter{self.component_id}"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_power = counter.data.config.max_total_power | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif self.type == "inverter": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inverter = data.data.pv_data[f"pv{self.component_id}"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_power = inverter.data.config.max_ac_out | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif self.type == "bat": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bat = data.data.bat_data[f"bat{self.component_id}"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_power = bat.data.config.max_power | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError(f"Unsupported component type {self.type!r} in PeakFilter") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # prüfe Leistung und importierte/exportierte Energie auf Plausibilität | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.check_power(max_power, power) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.check_imported_exported(max_power, imported, exported) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def check_power(self, max_power: float, power: float) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Wenn die Leistung mehr als doppelt so hoch ist wie die | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # konfigurierte maximale Leistung, ist sie unplausibel. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if max_power > 0 and abs(power) > 2 * max_power: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise Exception(f"Peakfilter: Die Leistung von {power / 1000}kW überschreitet die konfigurierte max. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Gesamtleistung von {max_power / 1000}kW um mehr als das Doppelte. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Werte werden noch nicht berücksichtigt.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def check_imported_exported( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_power: float, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imported: Optional[float] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exported: Optional[float] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> tuple[Optional[float], Optional[float]]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if max_power > 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Die erlaubte Abweichung ist doppelt so groß wie die mögliche | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Energiemenge pro Intervall bei maximaler Leistung | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.imported = imported | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exp = self.check_total_energy(exported, self.exported, allowed_deviation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.exported = exported | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return imp, exp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return imported, exported | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def check_total_energy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| total_energy: Optional[float], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| previous_total_energy: Optional[float], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| allowed_deviation: float | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Optional[float]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if total_energy is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if previous_total_energy is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if allowed_deviation > 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.debug(f"PeakFilter: Vorheriger Wert None, aktueller Zählerwert: {total_energy / 1000 }kWh. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Warte einen Regelintervall.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.fault_state.warning(f"Peakfilter: {total_energy / 1000}kWh. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Die PV-Produktion erscheint höher, als laut Anlagenkonfiguration " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "plausibel ist. Erneute Prüfung im nächsten Regelintervall.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.fault_state.warning(f"Peakfilter: {total_energy / 1000}kWh. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Die PV-Produktion erscheint höher, als laut Anlagenkonfiguration plausibel " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ist. Erneute Prüfung im nächsten Regelintervall.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+74
to
+93
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if total_energy is not None: | |
| if allowed_deviation > 0 and previous_total_energy is None: | |
| log.debug(f"PeakFilter: Vorheriger Wert None, aktueller Zählerwert: {total_energy / 1000 }kWh. " | |
| "Warte einen Regelintervall.") | |
| self.fault_state.warning(f"Peakfilter: {total_energy / 1000}kWh. " | |
| "Die PV-Produktion erscheint höher, als laut Anlagenkonfiguration plausibel " | |
| "ist. Erneute Prüfung im nächsten Regelintervall.") | |
| 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.") | |
| self.fault_state.warning(f"Peakfilter: {total_energy / 1000}kWh. " | |
| "Die PV-Produktion erscheint höher, als laut Anlagenkonfiguration plausibel " | |
| "ist. Erneute Prüfung im nächsten Regelintervall.") | |
| 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 | |
| if total_energy is None: | |
| return None | |
| # Wenn keine sinnvolle erlaubte Abweichung berechnet werden konnte, | |
| # akzeptiere den Wert ohne Plausibilitätsprüfung. | |
| if allowed_deviation <= 0: | |
| if previous_total_energy is not None: | |
| log.debug( | |
| f"PeakFilter: Zählerwert: {total_energy}Wh (keine Plausibilitätsprüfung). " | |
| f"Differenz zum vorherigen Wert: {total_energy - previous_total_energy}Wh." | |
| ) | |
| else: | |
| log.debug( | |
| f"PeakFilter: Zählerwert: {total_energy}Wh (keine Plausibilitätsprüfung, " | |
| "kein vorheriger Wert vorhanden)." | |
| ) | |
| return total_energy | |
| if previous_total_energy is None: | |
| log.debug( | |
| f"PeakFilter: Vorheriger Wert None, aktueller Zählerwert: {total_energy / 1000}kWh. " | |
| "Warte einen Regelintervall." | |
| ) | |
| self.fault_state.warning( | |
| f"Peakfilter: {total_energy / 1000}kWh. " | |
| "Die PV-Produktion erscheint höher, als laut Anlagenkonfiguration plausibel " | |
| "ist. Erneute Prüfung im nächsten Regelintervall." | |
| ) | |
| return None | |
| if (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." | |
| ) | |
| self.fault_state.warning( | |
| f"Peakfilter: {total_energy / 1000}kWh. " | |
| "Die PV-Produktion erscheint höher, als laut Anlagenkonfiguration plausibel " | |
| "ist. Erneute Prüfung im nächsten Regelintervall." | |
| ) | |
| return None | |
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| from dataclasses import dataclass | ||
| import pytest | ||
| from unittest.mock import MagicMock | ||
| from modules.common.utils.peak_filter import PeakFilter | ||
| from modules.common.fault_state import FaultState | ||
|
|
||
|
|
||
| class DummyFaultState(FaultState): | ||
| def __init__(self): | ||
| self.warnings = [] | ||
|
|
||
| def warning(self, msg): | ||
| self.warnings.append(msg) | ||
|
|
||
|
|
||
| class DummyConfig: | ||
| def __init__(self, max_power): | ||
| self.max_power = max_power | ||
| self.max_total_power = max_power | ||
| self.max_ac_out = max_power | ||
|
|
||
|
|
||
| class DummyData: | ||
| def __init__(self, max_power): | ||
| self.data = MagicMock() | ||
| self.data.config = DummyConfig(max_power) | ||
|
|
||
|
|
||
| @pytest.fixture(autouse=True) | ||
| def patch_data(monkeypatch): | ||
| import modules.common.utils.peak_filter as pf | ||
| pf.data = MagicMock() | ||
| pf.data.data = MagicMock() | ||
| pf.data.data.counter_data = {"counter1": DummyData(3000)} | ||
| pf.data.data.pv_data = {"pv1": DummyData(2000)} | ||
| pf.data.data.bat_data = {"bat1": DummyData(1000)} | ||
| pf.data.data.general_data = MagicMock() | ||
| pf.data.data.general_data.data = MagicMock() | ||
| pf.data.data.general_data.data.control_interval = 10 | ||
| yield | ||
|
|
||
|
|
||
| @dataclass | ||
| class Params: | ||
| name: str | ||
| type: str | ||
| previous_imported: float | ||
| previous_exported: float | ||
| power: float | ||
| imported: float | ||
| exported: float | ||
| expected_imported: float | ||
| expected_exported: float | ||
| expect_exception: bool = False | ||
|
|
||
|
|
||
| cases = [ | ||
| Params("Power Peak Zähler positiv", "counter", 1000, 500, 11000, 1300, 800, None, None, True), | ||
| Params("Power Peak Zähler negativ", "counter", 1000, 500, -11000, 1300, 800, None, None, True), | ||
| Params("Power Peak Wechselrichter", "inverter", 1000, 500, 11000, 1005, 505, 1005, 505, True), | ||
| Params("Power Peak Speicher positiv", "bat", 1000, 500, 11000, 1005, 505, 1005, 505, True), | ||
| Params("Power Peak Speicher negativ", "bat", 1000, 500, -11000, 1005, 505, 1005, 505, True), | ||
| Params("Imp/ Exp Zähler - Werte valide", "counter", 1000, 500, 900, 1005, 505, 1005, 505), | ||
| Params("Imp/ Exp Wechselrichter - Werte valide", "inverter", 1000, 500, 1500, 1005, 505, 1005, 505), | ||
| Params("Imp/ Exp Speicher - Werte valide", "bat", 1000, 500, 400, 1005, 505, 1005, 505), | ||
| Params("Imp/ Exp Zähler - Werte invalide", "counter", 1000, 500, 1000, 1300, 800, None, None), | ||
| Params("Imp/ Exp Zähler - Import invalide", "counter", 1000, 500, 1000, 1300, 505, None, 505), | ||
| Params("Imp/ Exp Zähler - Export invalide", "counter", 1000, 500, 1000, 1005, 800, 1005, None), | ||
| Params("Imp/ Exp Wechselrichter - Werte invalide", "inverter", 1000, 500, 1500, 1300, 800, None, None), | ||
| Params("Imp/ Exp Wechselrichter - Import invalide", "inverter", 1000, 500, 1500, 1300, 505, None, 505), | ||
| Params("Imp/ Exp Wechselrichter - Export invalide", "inverter", 1000, 500, 1500, 1005, 800, 1005, None), | ||
| Params("Imp/ Exp Speicher - Werte invalide", "bat", 1000, 500, 400, 1300, 800, None, None), | ||
| Params("Imp/ Exp Speicher - Import invalide", "bat", 1000, 500, 400, 1300, 505, None, 505), | ||
| Params("Imp/ Exp Speicher - Export invalide", "bat", 1000, 500, 400, 1005, 800, 1005, None), | ||
| ] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("params", cases, ids=[c.name for c in cases]) | ||
| def test_check_values_valid(params): | ||
| fs = DummyFaultState() | ||
| pf = PeakFilter(params.type, 1, fs) | ||
| pf.imported = params.previous_imported | ||
| pf.exported = params.previous_exported | ||
| if params.expect_exception: | ||
| with pytest.raises(Exception): | ||
| imp, exp = pf.check_values(params.power, params.imported, params.exported) | ||
| else: | ||
| imp, exp = pf.check_values(params.power, params.imported, params.exported) | ||
| assert imp == params.expected_imported | ||
| assert exp == params.expected_exported |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |||||
| from modules.common.modbus import ModbusDataType | ||||||
| from modules.common.simcount import SimCounter | ||||||
| from modules.common.store import get_bat_value_store | ||||||
| from modules.common.utils.peak_filter import PeakFilter | ||||||
|
|
||||||
|
|
||||||
| class KwargsDict(TypedDict): | ||||||
|
|
@@ -30,13 +31,15 @@ def initialize(self) -> None: | |||||
| self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher") | ||||||
| self.store = get_bat_value_store(self.component_config.id) | ||||||
| self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) | ||||||
| self.peak_filter = PeakFilter("bat", self.component_config.id, self.fault_state) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| def update(self): | ||||||
| currents = self.__tcp_client.read_input_registers( | ||||||
| 0x100E, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) | ||||||
| powers = self.__tcp_client.read_input_registers(0x1020, [ModbusDataType.FLOAT_32]*3, unit=self.__modbus_id) | ||||||
| power = sum(powers) | ||||||
|
|
||||||
| self.peak_filter.check_values(power) | ||||||
| imported, exported = self.sim_counter.sim_count(power) | ||||||
|
|
||||||
| bat_state = BatState( | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bitte das Enum für die Typen benutzen.