From b63a1c80274d4a35cd344a31e33f650a54621ce9 Mon Sep 17 00:00:00 2001 From: Mike Bishop Date: Thu, 9 May 2024 09:53:28 -0400 Subject: [PATCH] Better token expiration handling --- lib/TWCManager/Control/HTTPControl.py | 3 --- lib/TWCManager/Vehicle/TeslaAPI.py | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/TWCManager/Control/HTTPControl.py b/lib/TWCManager/Control/HTTPControl.py index f1515c93..4f51d990 100644 --- a/lib/TWCManager/Control/HTTPControl.py +++ b/lib/TWCManager/Control/HTTPControl.py @@ -1265,11 +1265,8 @@ def process_save_settings(self, page="settings"): carapi = master.getModuleByName("TeslaAPI") if key == "carApiBearerToken": carapi.setCarApiBearerToken(self.getFieldValue(key)) - # New tokens expire after 8 hours - carapi.setCarApiTokenExpireTime(time.time() + 8 * 60 * 60) elif key == "carApiRefreshToken": carapi.setCarApiRefreshToken(self.getFieldValue(key)) - carapi.setCarApiTokenExpireTime(time.time() + 45 * 24 * 60 * 60) else: # Write setting to dictionary diff --git a/lib/TWCManager/Vehicle/TeslaAPI.py b/lib/TWCManager/Vehicle/TeslaAPI.py index 25a57d24..cf141bf4 100644 --- a/lib/TWCManager/Vehicle/TeslaAPI.py +++ b/lib/TWCManager/Vehicle/TeslaAPI.py @@ -1129,9 +1129,16 @@ def setCarApiBearerToken(self, token=None): self.baseURL = self.regionURL["OwnerAPI"] elif decoded.get("ou_code", "") in self.regionURL: self.baseURL = self.regionURL[decoded["ou_code"]] + + if "exp" in decoded: + self.setCarApiTokenExpireTime(int(decoded["exp"])) + else: + self.setCarApiTokenExpireTime(time.time() + 8 * 60 * 60) + except jwt.exceptions.DecodeError: # Fallback to owner-api if we get an exception decoding jwt token self.baseURL = self.regionURL["OwnerAPI"] + self.setCarApiTokenExpireTime(time.time() + 8 * 60 * 60) return True else: return False @@ -1230,6 +1237,10 @@ def wakeVehicle(self, vehicle): logger.log(logging.INFO8, "Car API cmd wake_up" + str(req)) apiResponseDict = json.loads(req.text) 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) return False except json.decoder.JSONDecodeError: return False @@ -1393,7 +1404,12 @@ def get_car_api(self, url, checkReady=True, provesOnline=True): # This one is somewhat common: # {'response': None, 'error': 'vehicle unavailable: {:error=>"vehicle unavailable:"}', 'error_description': ''} except requests.exceptions.RequestException: - pass + 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 except json.decoder.JSONDecodeError: pass