diff --git a/packages/control/counter.py b/packages/control/counter.py index 4e8b832e93..8736fc0150 100644 --- a/packages/control/counter.py +++ b/packages/control/counter.py @@ -628,6 +628,12 @@ def reset_pv_data(self): """ setzt die Daten zurück, die über mehrere Regelzyklen genutzt werden. """ try: + if self.data.set.reserved_surplus != 0 or self.data.set.released_surplus != 0: + log.info( + f"PV-Algorithmus-Werte werden zurückgesetzt: reservierter Überschuss " + f"{self.data.set.reserved_surplus}W, freigegebener Überschuss " + f"{self.data.set.released_surplus}W." + ) self.data.set.reserved_surplus = 0 self.data.set.released_surplus = 0 except Exception: diff --git a/packages/control/load.py b/packages/control/load.py index abd9bb666a..48dfa99fb3 100644 --- a/packages/control/load.py +++ b/packages/control/load.py @@ -10,7 +10,7 @@ log = logging.getLogger(__name__) -def no_charge() -> None: +def reset_pv_data_if_no_active_delays() -> None: """ Wenn keine EV angesteckt sind oder keine Verzögerungen aktiv sind, werden die Algorithmus-Werte zurückgesetzt. (dient der Robustheit) @@ -19,18 +19,24 @@ def no_charge() -> None: for load in list(data.data.cp_data.values()) + list(data.data.consumer_data.values()): try: control_parameter = load.data.control_parameter - # Kein EV, das Laden soll - # Kein EV, das auf das Ablaufen der Einschalt- oder Phasenumschaltverzögerung wartet - if (control_parameter.state != ChargepointState.PERFORMING_PHASE_SWITCH and - control_parameter.state != ChargepointState.PHASE_SWITCH_DELAY and - control_parameter.state != ChargepointState.SWITCH_OFF_DELAY and - control_parameter.state != ChargepointState.SWITCH_ON_DELAY and - control_parameter.state != ChargepointState.NO_CHARGING_ALLOWED): - continue + if isinstance(load, Chargepoint): + if (not load.data.get.plug_state or + (control_parameter.state != ChargepointState.PERFORMING_PHASE_SWITCH and + control_parameter.state != ChargepointState.PHASE_SWITCH_DELAY and + control_parameter.state != ChargepointState.SWITCH_OFF_DELAY and + control_parameter.state != ChargepointState.SWITCH_ON_DELAY and + control_parameter.state != ChargepointState.NO_CHARGING_ALLOWED)): + continue + break else: + # Verbraucher haben keinen Plug-Status. + # Nur laufende Ein-/Ausschaltverzögerungen müssen den Reset verhindern. + if (control_parameter.state != ChargepointState.SWITCH_OFF_DELAY and + control_parameter.state != ChargepointState.SWITCH_ON_DELAY): + continue break except Exception: - log.exception("Fehler beim Bereinigen der Werte für Ladepunkt/Verbraucher "+load.num) + log.exception(f"Fehler beim Bereinigen der Werte für Ladepunkt/Verbraucher {load.num}") else: data.data.counter_all_data.get_evu_counter().reset_pv_data() except Exception: diff --git a/packages/control/load_test.py b/packages/control/load_test.py new file mode 100644 index 0000000000..c9aa4d7e18 --- /dev/null +++ b/packages/control/load_test.py @@ -0,0 +1,64 @@ +from typing import Dict +from unittest.mock import Mock + +from control import data, load +from control.chargepoint.chargepoint import Chargepoint +from control.chargepoint.chargepoint_state import ChargepointState +from control.consumer.consumer import Consumer + + +def _setup_control_data(cp_data: Dict[str, Chargepoint], consumer_data: Dict[str, Consumer]): + data.data_init(Mock()) + data.data.cp_data = cp_data + data.data.consumer_data = consumer_data + + evu_counter = Mock() + evu_counter.reset_pv_data = Mock() + data.data.counter_all_data = Mock(get_evu_counter=Mock(return_value=evu_counter)) + return evu_counter + + +def test_reset_pv_data_when_only_consumer_is_no_charging_allowed(): + consumer = Mock(spec=Consumer, num="1") + consumer.data = Mock(control_parameter=Mock(state=ChargepointState.NO_CHARGING_ALLOWED)) + evu_counter = _setup_control_data({}, {"consumer1": consumer}) + + load.reset_pv_data_if_no_active_delays() + + evu_counter.reset_pv_data.assert_called_once() + + +def test_do_not_reset_pv_data_when_consumer_switch_off_delay_active(): + consumer = Mock(spec=Consumer, num="1") + consumer.data = Mock(control_parameter=Mock(state=ChargepointState.SWITCH_OFF_DELAY)) + evu_counter = _setup_control_data({}, {"consumer1": consumer}) + + load.reset_pv_data_if_no_active_delays() + + evu_counter.reset_pv_data.assert_not_called() + + +def test_do_not_reset_pv_data_with_plugged_chargepoint_no_charging_allowed(): + cp = Mock(spec=Chargepoint, num="1") + cp.data = Mock( + control_parameter=Mock(state=ChargepointState.NO_CHARGING_ALLOWED), + get=Mock(plug_state=True), + ) + evu_counter = _setup_control_data({"cp1": cp}, {}) + + load.reset_pv_data_if_no_active_delays() + + evu_counter.reset_pv_data.assert_not_called() + + +def test_reset_pv_data_with_unplugged_chargepoint_no_charging_allowed(): + cp = Mock(spec=Chargepoint, num="1") + cp.data = Mock( + control_parameter=Mock(state=ChargepointState.NO_CHARGING_ALLOWED), + get=Mock(plug_state=False), + ) + evu_counter = _setup_control_data({"cp1": cp}, {}) + + load.reset_pv_data_if_no_active_delays() + + evu_counter.reset_pv_data.assert_called_once() diff --git a/packages/control/prepare.py b/packages/control/prepare.py index e72620d8e6..86dc39966a 100644 --- a/packages/control/prepare.py +++ b/packages/control/prepare.py @@ -38,7 +38,7 @@ def setup_algorithm(self) -> None: data.data.bat_all_data.setup_bat() data.data.consumer_all_data.get_consumer_sum() data.data.cp_all_data.get_cp_sum() - load.no_charge() + load.reset_pv_data_if_no_active_delays() data.data.counter_all_data.set_home_consumption() except Exception: log.exception("Fehler im Prepare-Modul")