1+ from datetime import datetime , timedelta
2+ import random
13from typing import TypeVar , Generic , Callable
24from helpermodules import timecheck
35import logging
6+ from helpermodules .pub import Pub
47from modules .common import store
58from modules .common .component_context import SingleComponentUpdateContext
69from modules .common .component_state import TariffState
710from modules .common .component_type import ComponentType
811from modules .common .fault_state import ComponentInfo , FaultState
912
1013
14+ # Stunden für tägliche Tarifaktualisierung, manche Anbieter aktualisieren mehrfach täglich
15+ TARIFF_UPDATE_HOURS = [2 , 8 , 14 , 20 ]
1116T_TARIFF_CONFIG = TypeVar ("T_TARIFF_CONFIG" )
1217TARIFF_UPDATE_HOUR = 14 # latest expected time for daily tariff update
1318ONE_HOUR_SECONDS : int = 3600
19+
1420log = logging .getLogger (__name__ )
1521
1622
@@ -28,17 +34,36 @@ def __init__(self,
2834
2935 def update (self ) -> None :
3036 if hasattr (self , "_component_updater" ):
31- with SingleComponentUpdateContext (self .fault_state ):
32- tariff_state , timeslot_length_seconds = self .__update_et_provider_data ()
33- self .__store_and_publish_updated_data (tariff_state )
34- self .__log_and_publish_progress (timeslot_length_seconds , tariff_state )
37+ try :
38+ with SingleComponentUpdateContext (self .fault_state ):
39+ tariff_state , timeslot_length_seconds = self .__update_et_provider_data ()
40+ self .__store_and_publish_updated_data (tariff_state )
41+ self .__log_and_publish_progress (timeslot_length_seconds , tariff_state )
42+ except Exception as e :
43+ log .exception (f"Fehler beim Aktualisieren der Tarifdaten { e } " )
44+ self .fault_state .warning ("Error updating tariff data, retry in 5 minutes" )
3545
3646 def __update_et_provider_data (self ) -> tuple [TariffState , int ]:
37- tariff_state = self ._component_updater ()
47+ tariff_state = self .__call_component_updater ()
3848 timeslot_length_seconds = self .__calculate_price_timeslot_length (tariff_state )
3949 tariff_state = self ._remove_outdated_prices (tariff_state , timeslot_length_seconds )
4050 return tariff_state , timeslot_length_seconds
4151
52+ def __calculate_next_query_time (self ) -> float :
53+ now = datetime .now ()
54+ current_hour = now .hour
55+ next_hour = min ([hour for hour in TARIFF_UPDATE_HOURS
56+ if hour > current_hour ], default = TARIFF_UPDATE_HOURS [0 ])
57+ # reduce serverload on their site by trying early and randomizing query time minutes and seconds
58+ next_query_time = (now .replace (hour = next_hour , minute = 0 , second = 0 , microsecond = 0 ) +
59+ timedelta (days = 1 , minutes = random .randint (1 , 35 ) * - 1 , seconds = random .randint (0 , 5 ) * 10 ))
60+ Pub ().pub ("openWB/set/optional/ep/get/next_query_time" , int (next_query_time .timestamp ()))
61+
62+ def __call_component_updater (self ) -> TariffState :
63+ tariff_state = self ._component_updater ()
64+ self .__calculate_next_query_time ()
65+ return tariff_state
66+
4267 def __log_and_publish_progress (self , timeslot_length_seconds , tariff_state ):
4368 def publish_info (message_extension : str ) -> None :
4469 self .fault_state .no_error (
0 commit comments