11import asyncio
2- import backoff
32import logging
43import settings
54
65from datetime import datetime , timedelta
76from evohomeasync2 import EvohomeClientOld as EvohomeClient , ControlSystem , Location , Zone
87from evohomeasync2 .schemas import SystemMode , ZoneMode
98from evohome_helper import weather
9+ from tenacity import retry , retry_if_exception_type , stop_after_attempt , wait_exponential
1010from typing import Generator
1111
1212logger = logging .getLogger (__name__ )
1313_evohome_client = None
14- _retry = backoff .on_exception (wait_gen = backoff .expo , exception = Exception , max_tries = 6 )
14+ _retry = retry (
15+ retry = retry_if_exception_type (Exception ),
16+ wait = wait_exponential (),
17+ stop = stop_after_attempt (6 ),
18+ reraise = True ,
19+ )
1520
1621_AWAY_MODE_MAP = {
1722 "auto" : SystemMode .AUTO ,
@@ -102,20 +107,24 @@ def _get_zone_switch_points(zone: Zone, now: datetime) -> list[tuple[datetime, f
102107 return result
103108
104109
105- def _get_last_heating_switchpoint (zone : Zone , now : datetime ) -> tuple [datetime , float ]:
106- last_heating_datetime = now - timedelta ( weeks = 52 )
107- last_heating_temperature = - 99.0
110+ def _get_last_heating_switchpoint (zone : Zone , now : datetime ) -> tuple [datetime , float ] | None :
111+ last_heating_datetime = None
112+ last_heating_temperature = None
108113 for switchpoint_datetime , switchpoint_temperature in _get_zone_switch_points (zone , now ):
109114 if not _is_considered_off (switchpoint_temperature ):
110115 last_heating_datetime = switchpoint_datetime
111116 last_heating_temperature = switchpoint_temperature
117+
118+ if last_heating_datetime is None or last_heating_temperature is None :
119+ return None
120+
112121 return last_heating_datetime , last_heating_temperature
113122
114123
115- def _get_active_setpoint (zone : Zone , now : datetime ) -> float :
124+ def _get_active_setpoint (zone : Zone , now : datetime ) -> float | None :
116125 switch_points = _get_zone_switch_points (zone , now )
117126 if not switch_points :
118- return - 99.0
127+ return None
119128 return switch_points [- 1 ][1 ]
120129
121130
@@ -124,7 +133,12 @@ def is_in_schedule_grace_period(location: Location) -> bool:
124133
125134 zones = get_zones (location )
126135 for zone in zones :
127- switch_point_start , switch_point_temperature = _get_last_heating_switchpoint (zone , now )
136+ switch_point = _get_last_heating_switchpoint (zone , now )
137+ if switch_point is None :
138+ logger .debug ("no scheduled heating switch point found for %s" , zone .name )
139+ continue
140+
141+ switch_point_start , switch_point_temperature = switch_point
128142 logger .debug (
129143 "last scheduled switch point for %s was at: %s (%s degrees celsius)" ,
130144 zone .name ,
@@ -177,8 +191,8 @@ async def _is_normal_heating_needed(location: Location) -> bool:
177191 inside_temp_diff = settings .AUTO_ECO_INSIDE_TEMP_DIFF
178192 highest_set_point_temp = _get_highest_set_point_temp (location )
179193
180- # all zones are off?
181- if _is_considered_off (highest_set_point_temp ):
194+ # no valid active setpoint, or all zones are off?
195+ if highest_set_point_temp is None or _is_considered_off (highest_set_point_temp ):
182196 return True
183197
184198 # can we fetch a valid temperature?
@@ -198,12 +212,14 @@ async def _is_normal_heating_needed(location: Location) -> bool:
198212 return outside_current_temp + inside_temp_diff < highest_set_point_temp
199213
200214
201- def _get_highest_set_point_temp (location : Location ) -> float :
215+ def _get_highest_set_point_temp (location : Location ) -> float | None :
202216 zones = list (get_zones (location ))
203217 if not zones :
204- return - 99
218+ return None
205219 now = get_current_time (location )
206- return max (_get_active_setpoint (zone , now ) for zone in zones )
220+ active_setpoints = (_get_active_setpoint (zone , now ) for zone in zones )
221+ valid_setpoints = filter (lambda setpoint : setpoint is not None , active_setpoints )
222+ return max (valid_setpoints , default = None )
207223
208224
209225@_retry
0 commit comments