@@ -33,7 +33,7 @@ def apply_offset(date_time: datetime, offset: str, inverse = False):
3333
3434 return date_time + timedelta (hours = hours , minutes = minutes , seconds = seconds )
3535
36- def is_target_timeframe_complete_in_period (current_date : datetime , start_time : datetime , end_time : datetime , target_timeframes : list | None ):
36+ def is_target_timeframe_complete_in_period (current_date : datetime , start_time : datetime , end_time : datetime , target_timeframes : list | None , context : str = None ):
3737 if target_timeframes is None or len (target_timeframes ) < 1 :
3838 return False
3939
@@ -43,7 +43,7 @@ def is_target_timeframe_complete_in_period(current_date: datetime, start_time: d
4343 target_timeframes [- 1 ]["end" ] <= current_date
4444 )
4545
46- def get_start_and_end_times (current_date : datetime , target_start_time : str , target_end_time : str , start_time_not_in_past = True ):
46+ def get_start_and_end_times (current_date : datetime , target_start_time : str , target_end_time : str , start_time_not_in_past = True , context : str = None ):
4747 if (target_start_time is not None ):
4848 target_start = parse_datetime (current_date .strftime (f"%Y-%m-%dT{ target_start_time } :00%z" ))
4949 else :
@@ -58,15 +58,15 @@ def get_start_and_end_times(current_date: datetime, target_start_time: str, targ
5858 target_end = as_utc (target_end )
5959
6060 if (target_start >= target_end ):
61- _LOGGER .debug (f'{ target_start } is after { target_end } , so setting target end to tomorrow' )
61+ _LOGGER .debug (f'{ context } - { target_start } is after { target_end } , so setting target end to tomorrow' )
6262 if target_start > current_date :
6363 target_start = target_start - timedelta (days = 1 )
6464 else :
6565 target_end = target_end + timedelta (days = 1 )
6666
6767 # If our start date has passed, reset it to current_date to avoid picking a slot in the past
6868 if (start_time_not_in_past == True and target_start < current_date and current_date < target_end ):
69- _LOGGER .debug (f'Rolling target and { target_start } is in the past. Setting start to { current_date } ' )
69+ _LOGGER .debug (f'{ context } - Rolling target and { target_start } is in the past. Setting start to { current_date } ' )
7070 target_start = current_date
7171
7272 # If our start and end are both in the past, then look to the next day
@@ -76,8 +76,8 @@ def get_start_and_end_times(current_date: datetime, target_start_time: str, targ
7676
7777 return (target_start , target_end )
7878
79- def get_fixed_applicable_time_periods (target_start : datetime , target_end : datetime , time_period_values : list ):
80- _LOGGER .debug (f'Finding rates between { target_start } and { target_end } ' )
79+ def get_fixed_applicable_time_periods (target_start : datetime , target_end : datetime , time_period_values : list , context : str = None ):
80+ _LOGGER .debug (f'{ context } - Finding rates between { target_start } and { target_end } ' )
8181
8282 # Retrieve the rates that are applicable for our target rate
8383 applicable_rates = []
@@ -93,12 +93,12 @@ def get_fixed_applicable_time_periods(target_start: datetime, target_end: dateti
9393 hours = (date_diff .days * 24 ) + (date_diff .seconds // 3600 )
9494 periods = hours * 2
9595 if len (applicable_rates ) < periods :
96- _LOGGER .debug (f'Incorrect number of periods discovered. Require { periods } , but only have { len (applicable_rates )} ' )
96+ _LOGGER .debug (f'{ context } - Incorrect number of periods discovered. Require { periods } , but only have { len (applicable_rates )} ' )
9797 return None
9898
9999 return applicable_rates
100100
101- def get_rolling_applicable_time_periods (current_date : datetime , time_period_values : list , target_hours : float ):
101+ def get_rolling_applicable_time_periods (current_date : datetime , time_period_values : list , target_hours : float , context : str = None ):
102102 # Retrieve the rates that are applicable for our target rate
103103 applicable_time_periods = []
104104 periods = target_hours * 2
@@ -114,12 +114,12 @@ def get_rolling_applicable_time_periods(current_date: datetime, time_period_valu
114114
115115 # Make sure that we have enough rates that meet our target period
116116 if len (applicable_time_periods ) < periods :
117- _LOGGER .debug (f'Incorrect number of periods discovered. Require { periods } , but only have { len (applicable_time_periods )} ' )
117+ _LOGGER .debug (f'{ context } - Incorrect number of periods discovered. Require { periods } , but only have { len (applicable_time_periods )} ' )
118118 return None
119119
120120 return applicable_time_periods
121121
122- def __get_valid_to (rate ):
122+ def __get_end (rate ):
123123 return (rate ["end" ].timestamp (), rate ["end" ].fold )
124124
125125def calculate_continuous_times (
@@ -130,7 +130,8 @@ def calculate_continuous_times(
130130 min_value = None ,
131131 max_value = None ,
132132 weighting : list = None ,
133- hours_mode = CONFIG_TARGET_HOURS_MODE_EXACT
133+ hours_mode = CONFIG_TARGET_HOURS_MODE_EXACT ,
134+ context : str = None
134135 ):
135136 if (applicable_time_periods is None or target_hours <= 0 ):
136137 return []
@@ -139,12 +140,12 @@ def calculate_continuous_times(
139140 total_required_time_periods = math .ceil (target_hours * 2 )
140141
141142 if weighting is not None and len (weighting ) != total_required_time_periods :
142- raise ValueError (" Weighting does not match target hours" )
143+ raise ValueError (f" { context } - Weighting does not match target hours" )
143144
144145 best_continuous_time_periods = None
145146 best_continuous_time_periods_total = None
146147
147- _LOGGER .debug (f'{ applicable_time_periods_count } applicable time periods found' )
148+ _LOGGER .debug (f'{ context } - { applicable_time_periods_count } applicable time periods found' )
148149
149150 # Loop through our rates and try and find the block of time that meets our desired
150151 # hours and has the lowest combined rates
@@ -196,15 +197,14 @@ def calculate_continuous_times(
196197 if ((best_continuous_time_periods is None or is_best_continuous_rates ) and has_required_hours ):
197198 best_continuous_time_periods = continuous_time_periods
198199 best_continuous_time_periods_total = continuous_rates_total
199- _LOGGER .debug (f'New best block discovered { continuous_rates_total } ({ continuous_time_periods [0 ]["start" ] if len (continuous_time_periods ) > 0 else None } - { continuous_time_periods [- 1 ]["end" ] if len (continuous_time_periods ) > 0 else None } )' )
200+ _LOGGER .debug (f'{ context } - New best block discovered { continuous_rates_total } ({ continuous_time_periods [0 ]["start" ] if len (continuous_time_periods ) > 0 else None } - { continuous_time_periods [- 1 ]["end" ] if len (continuous_time_periods ) > 0 else None } )' )
200201 else :
201- _LOGGER .debug (f'Total rates for current block { continuous_rates_total } ({ continuous_time_periods [0 ]["start" ] if len (continuous_time_periods ) > 0 else None } - { continuous_time_periods [- 1 ]["end" ] if len (continuous_time_periods ) > 0 else None } ). Total rates for best block { best_continuous_time_periods_total } ' )
202+ _LOGGER .debug (f'{ context } - Total rates for current block { continuous_rates_total } ({ continuous_time_periods [0 ]["start" ] if len (continuous_time_periods ) > 0 else None } - { continuous_time_periods [- 1 ]["end" ] if len (continuous_time_periods ) > 0 else None } ). Total rates for best block { best_continuous_time_periods_total } ' )
202203
203204 if best_continuous_time_periods is not None :
204205 # Make sure our rates are in ascending order before returning
205- best_continuous_time_periods .sort (key = __get_valid_to )
206+ best_continuous_time_periods .sort (key = __get_end )
206207 return best_continuous_time_periods
207-
208208 return []
209209
210210def highest_last_time_period (time_period ):
@@ -230,7 +230,8 @@ def calculate_intermittent_times(
230230 find_latest_time_periods = False ,
231231 min_value = None ,
232232 max_value = None ,
233- hours_mode = CONFIG_TARGET_HOURS_MODE_EXACT
233+ hours_mode = CONFIG_TARGET_HOURS_MODE_EXACT ,
234+ context : str = None
234235 ):
235236 if (applicable_time_periods is None ):
236237 return []
@@ -250,29 +251,29 @@ def calculate_intermittent_times(
250251
251252 applicable_time_periods = list (filter (lambda rate : (min_value is None or rate ["value" ] >= min_value ) and (max_value is None or rate ["value" ] <= max_value ), applicable_time_periods ))
252253
253- _LOGGER .debug (f'{ len (applicable_time_periods )} applicable time periods found' )
254+ _LOGGER .debug (f'{ context } - { len (applicable_time_periods )} applicable time periods found' )
254255
255256 if ((hours_mode == CONFIG_TARGET_HOURS_MODE_EXACT and len (applicable_time_periods ) >= total_required_time_periods ) or hours_mode == CONFIG_TARGET_HOURS_MODE_MAXIMUM ):
256257 applicable_time_periods = applicable_time_periods [:total_required_time_periods ]
257258
258259 # Make sure our rates are in ascending order before returning
259- applicable_time_periods .sort (key = __get_valid_to )
260+ applicable_time_periods .sort (key = __get_end )
260261
261262 return applicable_time_periods
262263 elif len (applicable_time_periods ) >= total_required_time_periods :
263264 # Make sure our rates are in ascending order before returning
264- applicable_time_periods .sort (key = __get_valid_to )
265+ applicable_time_periods .sort (key = __get_end )
265266
266267 return applicable_time_periods
267268
268269 return []
269270
270- def get_target_time_period_info (current_date : datetime , applicable_rates , offset : str = None ):
271+ def get_target_time_period_info (current_date : datetime , applicable_time_periods , offset : str = None , context : str = None ):
271272 is_active = False
272273 next_time = None
273274 current_duration_in_hours = 0
274275 next_duration_in_hours = 0
275- total_applicable_rates = len (applicable_rates ) if applicable_rates is not None else 0
276+ total_applicable_time_periods = len (applicable_time_periods ) if applicable_time_periods is not None else 0
276277
277278 overall_total_value = 0
278279 overall_min_value = None
@@ -286,30 +287,30 @@ def get_target_time_period_info(current_date: datetime, applicable_rates, offset
286287 next_min_value = None
287288 next_max_value = None
288289
289- if (total_applicable_rates > 0 ):
290+ if (total_applicable_time_periods > 0 ):
290291
291292 # Find the applicable rates that when combine become a continuous block. This is more for
292293 # intermittent rates.
293- applicable_rates .sort (key = __get_valid_to )
294+ applicable_time_periods .sort (key = __get_end )
294295 applicable_rate_blocks = list ()
295- block_valid_from = applicable_rates [0 ]["start" ]
296+ block_valid_from = applicable_time_periods [0 ]["start" ]
296297
297298 total_value = 0
298299 min_value = None
299300 max_value = None
300301
301- for index , rate in enumerate (applicable_rates ):
302- if (index > 0 and applicable_rates [index - 1 ]["end" ] != rate ["start" ]):
303- diff = applicable_rates [index - 1 ]["end" ] - block_valid_from
302+ for index , rate in enumerate (applicable_time_periods ):
303+ if (index > 0 and applicable_time_periods [index - 1 ]["end" ] != rate ["start" ]):
304+ diff = applicable_time_periods [index - 1 ]["end" ] - block_valid_from
304305 minutes = diff .total_seconds () / 60
305306 periods = minutes / 30
306307 if periods < 1 :
307- _LOGGER .error (f"Less than 1 period discovered. Defaulting to 1 period. Rate start: { rate ["start" ]} ; Applicable rates: { applicable_rates } " )
308+ _LOGGER .error (f"{ context } - Less than 1 period discovered. Defaulting to 1 period. Rate start: { rate ["start" ]} ; Applicable rates: { applicable_time_periods } " )
308309 periods = 1
309310
310311 applicable_rate_blocks .append ({
311312 "start" : block_valid_from ,
312- "end" : applicable_rates [index - 1 ]["end" ],
313+ "end" : applicable_time_periods [index - 1 ]["end" ],
313314 "duration_in_hours" : minutes / 60 ,
314315 "average_value" : total_value / periods ,
315316 "min_value" : min_value ,
@@ -336,11 +337,11 @@ def get_target_time_period_info(current_date: datetime, applicable_rates, offset
336337 overall_max_value = rate ["value" ]
337338
338339 # Make sure our final block is added
339- diff = applicable_rates [- 1 ]["end" ] - block_valid_from
340+ diff = applicable_time_periods [- 1 ]["end" ] - block_valid_from
340341 minutes = diff .total_seconds () / 60
341342 applicable_rate_blocks .append ({
342343 "start" : block_valid_from ,
343- "end" : applicable_rates [- 1 ]["end" ],
344+ "end" : applicable_time_periods [- 1 ]["end" ],
344345 "duration_in_hours" : minutes / 60 ,
345346 "average_value" : total_value / (minutes / 30 ),
346347 "min_value" : min_value ,
@@ -372,7 +373,7 @@ def get_target_time_period_info(current_date: datetime, applicable_rates, offset
372373
373374 return {
374375 "is_active" : is_active ,
375- "overall_average_value" : round (overall_total_value / total_applicable_rates , 5 ) if total_applicable_rates > 0 else 0 ,
376+ "overall_average_value" : round (overall_total_value / total_applicable_time_periods , 5 ) if total_applicable_time_periods > 0 else 0 ,
376377 "overall_min_value" : overall_min_value ,
377378 "overall_max_value" : overall_max_value ,
378379 "current_duration_in_hours" : current_duration_in_hours ,
0 commit comments