@@ -226,6 +226,7 @@ def __init__(self, hass: HomeAssistant, session: OAuth2Session, config_entry: Co
226226 self .last_update_success = False
227227 self ._vin = config_entry .data ["vin" ]
228228 self ._last_update_time = 0
229+ self ._rate_limit_hit = False
229230
230231 # just copied over must check later...
231232 self ._config_entry = config_entry
@@ -476,15 +477,23 @@ def _check_if_veh_capability_supported(self, a_capability: str, capabilities: di
476477 async def _async_update_data (self ):
477478 _LOGGER .debug (f"{ self .vli } _async_update_data(): Updating data for VIN: { self ._vin } " )
478479 now = time .monotonic ()
479- if now - self ._last_update_time < 15 :
480+ if self . _rate_limit_hit and now - self ._last_update_time < 60 :
480481 _LOGGER .debug (f"{ self .vli } Rate limit: Returning cached data (last update { now - self ._last_update_time :.1f} s ago)" )
481- return self .data
482+ if self .data is not None :
483+ return self .data
482484
483485 # IMHO this is not required for an OAuth2Session
484486 await self ._session .async_ensure_token_valid ()
485487 telemetry_data = await self .request_telemetry ()
486- if telemetry_data is None or telemetry_data == RATE_LIMIT_INDICATOR :
488+ if telemetry_data is None :
487489 raise UpdateFailed ("No data received from Ford API (or exception/error)" )
490+ elif RATE_LIMIT_INDICATOR in telemetry_data :
491+ if self .data is None :
492+ # we are in the initial startup phase of the integration... since we have no self.data yet (that
493+ # we could return)
494+ raise UpdateFailed ("API not ready yet - please retry later" , retry_after = float (telemetry_data .get (RATE_LIMIT_INDICATOR , 62 )))
495+ else :
496+ return self .data
488497 else :
489498 pass
490499 # health_data = await self.request_health()
@@ -499,6 +508,7 @@ async def _async_update_data(self):
499508
500509 if telemetry_data is not None :
501510 self ._last_update_time = time .monotonic ()
511+ self ._rate_limit_hit = False
502512 return telemetry_data
503513 # result = {}
504514 # if ROOT_METRICS in telemetry_data:
@@ -542,9 +552,18 @@ async def __request_data(self, url_template:str, logging_type:str):
542552
543553 except BaseException as exc :
544554 if res .status == 429 :
545- _LOGGER .debug (f"{ self .vli } request_{ logging_type } ():{ url } caused { res .status } - rate limit exceeded - sleeping for 15 seconds" )
555+ try :
556+ val = res .headers .get ("Retry-After" )
557+ if val is not None and val .isdigit ():
558+ retry_after = int (val )
559+ else :
560+ retry_after = 62
561+ except (ValueError , TypeError ):
562+ retry_after = 62
563+ _LOGGER .debug (f"{ self .vli } request_{ logging_type } ():{ url } caused { res .status } - rate limit exceeded - sleeping for { retry_after } seconds" )
546564 self ._last_update_time = time .monotonic ()
547- return RATE_LIMIT_INDICATOR
565+ self ._rate_limit_hit = True
566+ return {RATE_LIMIT_INDICATOR : retry_after }
548567 else :
549568 _LOGGER .info (f"{ self .vli } request_{ logging_type } ():{ url } caused { type (exc ).__name__ } { exc } " )
550569 stack_trace = traceback .format_stack ()
0 commit comments