Skip to content

Commit 79ffe58

Browse files
authored
soc_bmwbc: improve error handling; set timestamp 0 after new captcha (#2478)
1 parent 2beb0f1 commit 79ffe58

1 file changed

Lines changed: 52 additions & 10 deletions

File tree

  • packages/modules/vehicles/bmwbc

packages/modules/vehicles/bmwbc/api.py

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
from datetime import datetime
1212
from copy import deepcopy
1313
from threading import Lock
14+
# from uuid import uuid4
1415
import os.path
1516
import shutil
17+
import time
1618

1719
from helpermodules.utils.error_handling import ImportErrorContext
1820
with ImportErrorContext():
@@ -21,6 +23,7 @@
2123
from bimmer_connected.account import MyBMWAccount
2224
from bimmer_connected.api.regions import Regions
2325
from bimmer_connected.utils import MyBMWJSONEncoder
26+
from bimmer_connected.models import MyBMWAPIError
2427

2528
from modules.common.component_state import CarState
2629
from modules.common.store import RAMDISK_PATH
@@ -205,13 +208,15 @@ async def _fetch_soc(self,
205208
if self._store[user_id]['captcha_token'] != captcha_token:
206209
# invalidate current refresh and access token to force new login
207210
log.debug("new captcha token configured - invalidate stored token set")
211+
self._new_captcha = True
208212
self._store[user_id]['expires_at'] = None
209213
self._store[user_id]['access_token'] = None
210214
self._store[user_id]['refresh_token'] = None
211215
self._store[user_id]['session_id'] = None
212216
self._store[user_id]['gcid'] = None
213217
else:
214218
log.debug("captcha token unchanged")
219+
self._new_captcha = False
215220

216221
if user_id not in self._auth:
217222
if self._store[user_id]['expires_at'] is not None and \
@@ -227,7 +232,8 @@ async def _fetch_soc(self,
227232
Regions.REST_OF_WORLD,
228233
refresh_token=self._store[user_id]['refresh_token'],
229234
access_token=self._store[user_id]['access_token'],
230-
expires_at=expires_at)
235+
expires_at=expires_at,
236+
hcaptcha_token=captcha_token)
231237
else:
232238
# no token, authenticate via user_id, password and captcha_token
233239
log.info("authenticate via userid, password, captcha token")
@@ -252,7 +258,7 @@ async def _fetch_soc(self,
252258
else:
253259
log.debug("# Reuse _clconf instance")
254260

255-
# instantiate account object of not existent yet
261+
# instantiate account object if not existent yet
256262
if user_id not in self._account:
257263
log.debug("# Create _account instance")
258264
# user, password and region already set in BMWAuthentication/ClientConfiguration!
@@ -273,6 +279,7 @@ async def _fetch_soc(self,
273279
if user_id not in self._last_reload:
274280
self._last_reload[user_id] = 0
275281
if self._now > self._last_reload[user_id] + 5 * 60:
282+
# self._auth[user_id].session_id = str(uuid4()) # experimental to avoid error 408: reset session_id
276283
# experimental: login when expires_at is reached to force token refresh
277284
if self._store[user_id]['expires_at'] is not None:
278285
expires_at = datetime.fromisoformat(self._store[user_id]['expires_at'])
@@ -287,9 +294,36 @@ async def _fetch_soc(self,
287294
"/" + self._auth[user_id].refresh_token)
288295

289296
# get vehicle list - needs to be called async
290-
log.info(self._mode + ": reload vehicles data")
291-
await self._account[user_id].get_vehicles()
292-
self._last_reload[user_id] = datetime.timestamp(datetime.now())
297+
_loop = 5 # 5 retries
298+
while _loop > 0:
299+
log.info(self._mode + ": reload vehicles data/" + str(_loop))
300+
try:
301+
await self._account[user_id].get_vehicles()
302+
except MyBMWAPIError as err:
303+
log.info(self._mode + ": get_vehicles err= " + str(err.__class__) + ": " + str(err))
304+
_err = -1
305+
if 'Internal Server Error' in str(err):
306+
log.info(self._mode + ": get_vehicles : Internal Server Error")
307+
_err = 500
308+
if 'Request Timeout' in str(err):
309+
log.info(self._mode + ": get_vehicles : Request Timeout")
310+
_err = 408
311+
log.info(self._mode + ": get_vehicles : _err=" + str(_err))
312+
time.sleep(10) # experimental: sleep for 10 secs
313+
# log.info(self._mode + ": get_vehicles exception " + str(err))
314+
log.info("# before except login:" + str(self._auth[user_id].expires_at) +
315+
"/" + self._auth[user_id].refresh_token)
316+
await self._auth[user_id].login()
317+
log.info("# after except login:" + str(self._auth[user_id].expires_at) +
318+
"/" + self._auth[user_id].refresh_token)
319+
await self._account[user_id].get_vehicles()
320+
_loop = _loop - 1
321+
except Exception as err:
322+
log.error("bmwbc.fetch_soc: get_vehicles Error, vehicle_id: " +
323+
vehicle_id + f" {err=}, {type(err)=}")
324+
raise err
325+
self._last_reload[user_id] = datetime.timestamp(datetime.now())
326+
_loop = 0
293327

294328
# get vehicle data for vin
295329
vehicle = self._account[user_id].get_vehicle(vin)
@@ -305,9 +339,15 @@ async def _fetch_soc(self,
305339
soc = int(state['electricChargingState']['chargingLevelPercent'])
306340
range = float(state['electricChargingState']['range'])
307341
lastUpdatedAt = state['lastUpdatedAt']
308-
# convert lastUpdatedAt to soc_timestamp
309-
soc_tsdtZ = datetime.strptime(lastUpdatedAt, ts_fmt + "Z")
310-
soc_tsX = datetime.timestamp(soc_tsdtZ)
342+
if self._new_captcha:
343+
# after new captcha use system timestamp
344+
# soc_tsX = datetime.timestamp(datetime.now())
345+
# after new captcha use timestamp 0 (19700101)
346+
soc_tsX = 0
347+
else:
348+
# convert lastUpdatedAt to soc_timestamp
349+
soc_tsdtZ = datetime.strptime(lastUpdatedAt, ts_fmt + "Z")
350+
soc_tsX = datetime.timestamp(soc_tsdtZ)
311351

312352
# save the vehicle data for further analysis if required
313353
dump_json(respd, replyFilePrefix + vehicle_id)
@@ -333,15 +373,17 @@ async def _fetch_soc(self,
333373
"/" + self._auth[user_id].refresh_token)
334374

335375
except Exception as err:
336-
log.error("bmwbc.fetch_soc: requestData Error, vehicle_id: " + vehicle_id + f" {err=}, {type(err)=}")
376+
# log.error("bmwbc.fetch_soc: requestData Error, vehicle_id: " + vehicle_id + f" {err=}, {type(err)=}")
377+
log.error("bmwbc.fetch_soc: requestData Error, vehicle_id: " + str(vehicle_id))
337378
# self._auth = None
338379
self._auth.pop(user_id, None)
339380
self._clconf.pop(user_id, None)
340381
self._account.pop(user_id, None)
341382
soc = 0
342383
range = 0.0
343384
soc_tsX = datetime.timestamp(datetime.now())
344-
raise RequestFailed("SoC Request failed:\n" + str(err))
385+
# raise RequestFailed("SoC Request failed:\n" + str(err))
386+
raise Exception("SoC Request failed") from err
345387
return soc, range, soc_tsX
346388

347389

0 commit comments

Comments
 (0)