Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions packages/control/ev/charge_template.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from dataclasses import asdict, dataclass, field
import datetime
import logging
import traceback
from typing import Dict, Optional, Tuple
Expand Down Expand Up @@ -381,17 +382,17 @@ def _calculate_duration(self,
"für Zielladen bereits erreicht wurde.")
SCHEDULED_CHARGING_NO_PLANS_CONFIGURED = "Keine Ladung, da keine Ziel-Termine konfiguriert sind."
SCHEDULED_CHARGING_NO_DATE_PENDING = "Kein Zielladen, da kein Ziel-Termin ansteht."
SCHEDULED_CHARGING_USE_PV = ("Kein Zielladen, da noch Zeit bis zum Zieltermin ist. Falls vorhanden, "
SCHEDULED_CHARGING_USE_PV = ("Laden startet {}. Falls vorhanden, "
"wird mit Überschuss geladen.")
SCHEDULED_CHARGING_MAX_CURRENT = ("Zielladen mit {}A. Der Ladestrom wurde erhöht, um den Zieltermin zu erreichen. "
"Es wird bis max. 20 Minuten nach dem angegebenen Zieltermin geladen.")
SCHEDULED_CHARGING_LIMITED_BY_SOC = 'einen SoC von {}%'
SCHEDULED_CHARGING_LIMITED_BY_AMOUNT = '{}kWh geladene Energie'
SCHEDULED_CHARGING_IN_TIME = ('Zielladen mit mindestens {}A, um {} um {} zu erreichen. Falls vorhanden wird '
'zusätzlich EVU-Überschuss geladen.')
SCHEDULED_CHARGING_CHEAP_HOUR = "Zielladen, da ein günstiger Zeitpunkt zum preisbasierten Laden ist."
SCHEDULED_CHARGING_CHEAP_HOUR = "Zielladen, da ein günstiger Zeitpunkt zum preisbasierten Laden ist. {}"
SCHEDULED_CHARGING_EXPENSIVE_HOUR = ("Zielladen ausstehend, da jetzt kein günstiger Zeitpunkt zum preisbasierten "
"Laden ist. Falls vorhanden, wird mit Überschuss geladen.")
"Laden ist. {} Falls vorhanden, wird mit Überschuss geladen.")

def scheduled_charging_calc_current(self,
plan_data: Optional[SelectedPlan],
Expand Down Expand Up @@ -447,14 +448,17 @@ def scheduled_charging_calc_current(self,
# ist.
if self.data.et.active and data.data.optional_data.et_provider_available():
hour_list = data.data.optional_data.et_get_loading_hours(plan_data.duration, plan_data.remaining_time)
log.debug(f"Günstige Ladezeiten: {hour_list}")
hours_message = ("Geladen wird zu folgenden Uhrzeiten: " +
", ".join([datetime.datetime.fromtimestamp(hour).strftime('%-H:%M')
for hour in sorted(hour_list)])
+ ".")
if timecheck.is_list_valid(hour_list):
message = self.SCHEDULED_CHARGING_CHEAP_HOUR
message = self.SCHEDULED_CHARGING_CHEAP_HOUR.format(hours_message)
current = plan_data.available_current
submode = "instant_charging"
elif ((limit.selected == "soc" and soc <= limit.soc_limit) or
(limit.selected == "amount" and used_amount < limit.amount)):
message = self.SCHEDULED_CHARGING_EXPENSIVE_HOUR
message = self.SCHEDULED_CHARGING_EXPENSIVE_HOUR.format(hours_message)
current = min_current
submode = "pv_charging"
phases = control_parameter_phases
Expand All @@ -465,7 +469,14 @@ def scheduled_charging_calc_current(self,
if limit.selected == "soc" and soc >= limit.soc_limit:
message = self.SCHEDULED_REACHED_LIMIT_SOC
else:
message = self.SCHEDULED_CHARGING_USE_PV
now = datetime.datetime.today()
start_time = now + datetime.timedelta(seconds=plan_data.remaining_time)
if start_time.year == now.year and start_time.month == now.month and start_time.day == now.day:
message = self.SCHEDULED_CHARGING_USE_PV.format(
f"um {start_time.strftime('%-H:%M')} Uhr")
else:
message = self.SCHEDULED_CHARGING_USE_PV.format(
f"am {start_time.strftime('%d.%m')} um {start_time.strftime('%-H:%M')} Uhr")
current = min_current
submode = "pv_charging"
phases = control_parameter_phases
Expand Down
14 changes: 10 additions & 4 deletions packages/control/ev/charge_template_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
from typing import Dict, NamedTuple, Optional, Tuple
from unittest.mock import Mock

Expand Down Expand Up @@ -244,7 +245,8 @@ def test_search_plan(check_duration_return1: Tuple[Optional[float], bool],
ChargeTemplate.SCHEDULED_CHARGING_MAX_CURRENT.format(16), 3),
id="few minutes too late, but didn't miss for today"),
pytest.param(SelectedPlan(remaining_time=301, duration=3600), 79, 0, "soc",
(6, "pv_charging", ChargeTemplate.SCHEDULED_CHARGING_USE_PV, 3), id="too early, use pv"),
(6, "pv_charging", ChargeTemplate.SCHEDULED_CHARGING_USE_PV.format("um 8:45 Uhr"), 3),
id="too early, use pv"),
])
def test_scheduled_charging_calc_current(plan_data: SelectedPlan,
soc: int,
Expand Down Expand Up @@ -279,8 +281,10 @@ def test_scheduled_charging_calc_current_no_plans():
@pytest.mark.parametrize(
"loading_hour, expected",
[
pytest.param(True, (14, "instant_charging", ChargeTemplate.SCHEDULED_CHARGING_CHEAP_HOUR, 3)),
pytest.param(False, (6, "pv_charging", ChargeTemplate.SCHEDULED_CHARGING_EXPENSIVE_HOUR, 3)),
pytest.param(True, (14, "instant_charging", ChargeTemplate.SCHEDULED_CHARGING_CHEAP_HOUR.format(
"Geladen wird zu folgenden Uhrzeiten: 8:00."), 3)),
pytest.param(False, (6, "pv_charging", ChargeTemplate.SCHEDULED_CHARGING_EXPENSIVE_HOUR.format(
"Geladen wird zu folgenden Uhrzeiten: 8:00."), 3)),
])
def test_scheduled_charging_calc_current_electricity_tariff(loading_hour, expected, monkeypatch):
# setup
Expand All @@ -289,7 +293,9 @@ def test_scheduled_charging_calc_current_electricity_tariff(loading_hour, expect
plan.limit.selected = "soc"
ct.data.chargemode.scheduled_charging.plans = {"0": plan}
ct.data.et.active = True
mock_et_get_loading_hours = Mock(return_value=[])
# für Github-Test keinen Zeitstempel verwenden
mock_et_get_loading_hours = Mock(return_value=[datetime.datetime(
year=2022, month=5, day=16, hour=8, minute=0).timestamp()])
monkeypatch.setattr(data.data.optional_data, "et_get_loading_hours", mock_et_get_loading_hours)
mock_et_provider_available = Mock(return_value=True)
monkeypatch.setattr(data.data.optional_data, "et_provider_available", mock_et_provider_available)
Expand Down