Skip to content

Commit

Permalink
Avoid refresh loops
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeBishop committed May 16, 2024
1 parent 47250df commit 79743cd
Showing 1 changed file with 35 additions and 29 deletions.
64 changes: 35 additions & 29 deletions lib/TWCManager/Vehicle/TeslaAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,45 +131,46 @@ def apiRefresh(self):
try:
req = requests.post(self.refreshURL, headers=headers, json=data)
logger.log(logging.INFO2, "Car API request" + str(req))
req.raise_for_status()
apiResponseDict = json.loads(req.text)
except requests.exceptions.RequestException:
logger.log(
logging.INFO2, "Request Exception parsing API Token Refresh Response"
)
pass
except ValueError:
pass
if req.status_code == 401:
logger.log(
logging.INFO2,
"TeslaAPI",
"ERROR: Can't access Tesla car via API. Please supply fresh tokens.",
)
self.setCarApiBearerToken("")
self.setCarApiRefreshToken("")
self.updateCarApiLastErrorTime()
# Instead of just setting carApiLastErrorTime, erase tokens to
# prevent further authorization attempts until user enters password
# on web interface. I feel this is safer than trying to log in every
# ten minutes with a bad token because Tesla might decide to block
# remote access to your car after too many authorization errors.
self.master.queue_background_task({"cmd": "saveSettings"})
return False
except json.decoder.JSONDecodeError:
logger.log(
logging.INFO2, "JSON Decode Error parsing API Token Refresh Response"
)
pass
except ValueError:
pass

try:
logger.log(logging.INFO4, "Car API auth response" + str(apiResponseDict))
self.setCarApiBearerToken(apiResponseDict["access_token"])
self.setCarApiRefreshToken(apiResponseDict["refresh_token"])
self.setCarApiTokenExpireTime(now + apiResponseDict["expires_in"])
self.master.queue_background_task({"cmd": "saveSettings"})
return True

except KeyError:
logger.log(
logging.INFO2,
"TeslaAPI",
"ERROR: Can't access Tesla car via API. Please log in again via web interface.",
)
self.updateCarApiLastErrorTime()
# Instead of just setting carApiLastErrorTime, erase tokens to
# prevent further authorization attempts until user enters password
# on web interface. I feel this is safer than trying to log in every
# ten minutes with a bad token because Tesla might decide to block
# remote access to your car after too many authorization errors.
self.setCarApiBearerToken("")
self.setCarApiRefreshToken("")
self.master.queue_background_task({"cmd": "saveSettings"})
except UnboundLocalError:
except:
pass

return False

def car_api_available(
self, email=None, password=None, charge=None, applyLimit=None
):
Expand Down Expand Up @@ -1149,7 +1150,7 @@ def setCarApiRefreshToken(self, token):
self.getCarApiBearerToken() == ""
or self.getCarApiTokenExpireTime() - time.time() < 60 * 60
):
self.apiRefresh()
return self.apiRefresh()
return True

def setCarApiTokenExpireTime(self, value):
Expand Down Expand Up @@ -1244,8 +1245,11 @@ def wakeVehicle(self, vehicle):
except requests.exceptions.RequestException:
if req.status_code == 401 and "expired" in req.text:
# If the token is expired, refresh it and try again
self.apiRefresh()
return self.wakeVehicle(vehicle)
if self.apiRefresh():
return self.wakeVehicle(vehicle)
elif req.status_code == 429:
# We're explicitly being told to back off
self.errorCount = max(30, self.errorCount)
return False
except json.decoder.JSONDecodeError:
return False
Expand Down Expand Up @@ -1411,10 +1415,12 @@ def get_car_api(self, url, checkReady=True, provesOnline=True):
except requests.exceptions.RequestException:
if req.status_code == 401 and "expired" in req.text:
# If the token is expired, refresh it and try again
self.apiRefresh()
continue
else:
pass
if self.apiRefresh():
continue
elif req.status_code == 429:
# We're explicitly being told to back off
self.errorCount = max(30, self.errorCount)
return False, None
except json.decoder.JSONDecodeError:
pass

Expand Down

0 comments on commit 79743cd

Please sign in to comment.