diff --git a/packages/control/ev/charge_template.py b/packages/control/ev/charge_template.py index 887cc68fd3..308a0ad843 100644 --- a/packages/control/ev/charge_template.py +++ b/packages/control/ev/charge_template.py @@ -322,23 +322,26 @@ def scheduled_charging_recent_plan(self, raise ValueError("Um Zielladen mit SoC-Ziel nutzen zu können, bitte ein SoC-Modul konfigurieren " f"oder im Plan {p.name} als Begrenzung Energie einstellen.") try: - if ((p.limit.selected == "amount" and used_amount >= p.limit.amount) or - ((p.limit.selected == "soc" and soc >= p.limit.soc_scheduled) and - (p.limit.selected == "soc" and soc >= p.limit.soc_limit))): - plan_fulfilled = True - else: - plan_fulfilled = False plans_diff_end_date.append( - {p.id: timecheck.check_end_time(p, chargemode_switch_timestamp, plan_fulfilled)}) - log.debug(f"Verbleibende Zeit bis zum Zieltermin [s]: {plans_diff_end_date}, " - f"Plan erfüllt: {plan_fulfilled}") + {p.id: timecheck.check_end_time(p, chargemode_switch_timestamp)}) + log.debug(f"Verbleibende Zeit bis zum Zieltermin [s]: {plans_diff_end_date}") except Exception: log.exception("Fehler im ev-Modul "+str(self.data.id)) if plans_diff_end_date: # ermittle den Key vom kleinsten value in plans_diff_end_date filtered_plans = [d for d in plans_diff_end_date if list(d.values())[0] is not None] if filtered_plans: - plan_dict = min(filtered_plans, key=lambda x: list(x.values())[0]) + sorted_plans = sorted(filtered_plans, key=lambda x: list(x.values())[0]) + if len(sorted_plans) == 1: + plan_dict = sorted_plans[0] + elif (len(sorted_plans) > 1 and + list(sorted_plans[0].values())[0] < 0 and + list(sorted_plans[1].values())[0] < 43200): + # wenn der erste Plan in der Liste in der Vergangenheit liegt, dann den zweiten nehmen, wenn dessen + # Zielzeit weniger als 12 h entfernt ist. + plan_dict = sorted_plans[1] + else: + plan_dict = sorted_plans[0] if plan_dict: plan_id = list(plan_dict.keys())[0] plan_end_time = list(plan_dict.values())[0] diff --git a/packages/control/ev/charge_template_test.py b/packages/control/ev/charge_template_test.py index c9ba2ef6b6..8512597652 100644 --- a/packages/control/ev/charge_template_test.py +++ b/packages/control/ev/charge_template_test.py @@ -182,10 +182,11 @@ def test_calculate_duration(selected: str, phases: int, expected_duration: float @pytest.mark.parametrize( "end_time_mock, expected_plan_num", [ - pytest.param([1000, 1500, 2000], 0, id="1st plan"), - pytest.param([1500, 1000, 2000], 1, id="2nd plan"), - pytest.param([1500, 2000, 1000], 2, id="3rd plan"), - pytest.param([None]*3, 0, id="no plan"), + pytest.param([1000, 1500, 2000], 0, id="nächster Zieltermin Plan 0"), + pytest.param([-100, 1000, 2000], 1, id="Plan 0 abgelaufen, Plan 1 innerhalb der nächsten 12h"), + pytest.param([-100, 45000, 50000], 0, id="Plan 0 abgelaufen, Plan 1 nicht innerhalb der nächsten 12h"), + pytest.param([1500, 2000, 1000], 2, id="nächster Zieltermin Plan 2"), + pytest.param([None]*3, 0, id="kein Plan"), ]) def test_scheduled_charging_recent_plan(end_time_mock, expected_plan_num: Optional[int], @@ -212,37 +213,6 @@ def test_scheduled_charging_recent_plan(end_time_mock, assert selected_plan is None -@pytest.mark.parametrize("end_time_mock, expected_plan_num", - [ - pytest.param([-10000, 1500, 2000], 0, id="1st plan"), - pytest.param([None, -100, 2000], 1, id="1st plan fulfilled, 2nd plan"), - pytest.param([None, -50, -100], 2, id="1st plan fulfilled, 3rd plan"), - pytest.param([None]*3, None, id="no plan"), - ]) -def test_scheduled_charging_recent_plan_fulfilled(end_time_mock, expected_plan_num, monkeypatch): - # setup - # der erste PLan ist erfüllt, der zweite wird ausgewählt - calculate_duration_mock = Mock(return_value=(100, 3000, 3, 500)) - monkeypatch.setattr(ChargeTemplate, "_calc_remaining_time", calculate_duration_mock) - check_end_time_mock = Mock(side_effect=end_time_mock) - monkeypatch.setattr(timecheck, "check_end_time", check_end_time_mock) - ct = ChargeTemplate() - plan_mock_0 = Mock(spec=ScheduledChargingPlan, active=True, current=14, id=0, limit=Limit(selected="amount")) - plan_mock_1 = Mock(spec=ScheduledChargingPlan, active=True, current=14, id=1, limit=Limit(selected="amount")) - plan_mock_2 = Mock(spec=ScheduledChargingPlan, active=True, current=14, id=2, limit=Limit(selected="amount")) - ct.data.chargemode.scheduled_charging.plans = [plan_mock_0, plan_mock_1, plan_mock_2] - - # execution - selected_plan = ct.scheduled_charging_recent_plan( - 60, EvTemplate(), 3, 1200, 3, True, ChargingType.AC.value, 1652688000, Mock(spec=ControlParameter), 0) - - # evaluation - if selected_plan: - assert selected_plan.plan.id == expected_plan_num - else: - assert selected_plan is expected_plan_num - - @pytest.mark.parametrize( "plan_data, soc, used_amount, selected, expected", [ diff --git a/packages/helpermodules/timecheck.py b/packages/helpermodules/timecheck.py index b144d45b3d..8b42a97d8e 100644 --- a/packages/helpermodules/timecheck.py +++ b/packages/helpermodules/timecheck.py @@ -113,11 +113,8 @@ def is_timeframe_valid(now: datetime.datetime, begin: datetime.datetime, end: da def check_end_time(plan: ScheduledChargingPlan, - chargemode_switch_timestamp: Optional[float], - plan_fulfilled: bool) -> Optional[float]: + chargemode_switch_timestamp: Optional[float]) -> Optional[float]: """ prüft, ob der in angegebene Zeitpunkt abzüglich der Dauer jetzt ist. - Um etwas Puffer zu haben, werden bei Überschreiten des Zeitpunkts die nachfolgenden 20 Min auch noch als Ladezeit - zurückgegeben. Return ------ @@ -154,7 +151,7 @@ def missed_date_still_active(remaining_time: float) -> bool: remaining_time = end - now else: raise TypeError(f'Unbekannte Häufigkeit {plan.frequency.selected}') - if chargemode_switch_timestamp and (end.timestamp() < chargemode_switch_timestamp or plan_fulfilled): + if chargemode_switch_timestamp and end.timestamp() < chargemode_switch_timestamp: # Als auf Zielladen umgeschaltet wurde, war der Termin schon vorbei return None else: diff --git a/packages/helpermodules/timecheck_test.py b/packages/helpermodules/timecheck_test.py index e22afce0ac..d45f0b8227 100644 --- a/packages/helpermodules/timecheck_test.py +++ b/packages/helpermodules/timecheck_test.py @@ -20,28 +20,24 @@ def __init__(self, name: str, self.second_time = second_time -@pytest.mark.parametrize("time, selected, date, plan_fulfilled, expected_remaining_time", - [pytest.param("9:00", "once", "2022-05-16", False, 1148, id="once"), - pytest.param("7:55", "once", "2022-05-16", False, None, id="missed date, plugged before"), - pytest.param("8:05", "once", "2022-05-16", False, - +@pytest.mark.parametrize("time, selected, date, expected_remaining_time", + [pytest.param("9:00", "once", "2022-05-16", 1148, id="once"), + pytest.param("7:55", "once", "2022-05-16", None, id="missed date, plugged before"), + pytest.param("8:05", "once", "2022-05-16", - 2152, id="once missed date, plugged after"), - pytest.param("12:00", "daily", [], False, 11948, id="daily today"), - pytest.param("2:00", "daily", [], False, 62348, id="daily missed today, use next day"), + pytest.param("12:00", "daily", [], 11948, id="daily today"), + pytest.param("2:00", "daily", [], 62348, id="daily missed today, use next day"), pytest.param("7:55", "weekly", [True, False, False, False, - False, False, False], False, 602048, id="weekly missed today"), + False, False, False], 602048, id="weekly missed today"), pytest.param("2:00", "weekly", [False, False, True, False, False, False, False], - False, 148748, - id="weekly missed today's date, no date on next day"), + 148748, id="weekly missed today's date, no date on next day"), pytest.param("2:00", "weekly", [True, True, False, False, False, False, False], - False, 62348, - id="weekly missed today's date, date on next day"), - pytest.param("8:05", "once", "2022-05-16", True, None, id="once missed date, plugged after"), + 62348, id="weekly missed today's date, date on next day"), ] ) def test_check_end_time(time: str, selected: str, date: List, - plan_fulfilled: bool, expected_remaining_time: float): # setup plan = Mock(spec=ScheduledChargingPlan, time=time, frequency=Mock(spec=FrequencyDate, selected=selected,)) @@ -51,8 +47,7 @@ def test_check_end_time(time: str, # execution remaining_time = timecheck.check_end_time( plan, - chargemode_switch_timestamp=datetime.datetime.strptime("5/16/2022 8:00", "%m/%d/%Y %H:%M").timestamp(), - plan_fulfilled=plan_fulfilled) + chargemode_switch_timestamp=datetime.datetime.strptime("5/16/2022 8:00", "%m/%d/%Y %H:%M").timestamp()) # evaluation assert remaining_time == expected_remaining_time