mlowijs / tesla_api

Lightweight Python API client for the Tesla API.
MIT License
80 stars 31 forks source link

Cope with tesla API errors #40

Open one4many opened 3 years ago

one4many commented 3 years ago

From time to time Tesla-API servers return text/html instead of application/json. Which results in a rather nasty Exception (Some information is obfuscated):

File "/home/....../tesla_api/__init__.py", line 154, in get
    response_json = await resp.json()
  File "/home/....../lib/python3.8/site-packages/aiohttp/client_reqrep.py", line 1026, in json
    raise ContentTypeError(
aiohttp.client_exceptions.ContentTypeError: 0, message='Attempt to decode JSON with unexpected mimetype: text/html', url=URL('https://owner-api.teslamotors.com/api/1/vehicles/21212121212121/data_request/charge_state')
    raise ContentTypeError(

Handling this is the app seems too complicated, as this error could occur at any point the app code (and api call) and just generate a lot of copy & paste code for exception handling. Or a 2nd api layer around the lib just to handle those rare hick-ups.

The lib could retry to send the command for a defined number of times or raise a CommunicationError Exception of some sort.

Dreamsorcerer commented 3 years ago

That must be another recent change, I've not seen these before.

I'll try and reproduce soon, but if you could debug and get the resp.text() that would help figure out exactly what is happening.

one4many commented 3 years ago

I will add a resp.text() and log the output. I happens very rarely though. I hope I can catch it in the future.

fkhera commented 3 years ago

Tesla changed to v3 oauth api about last Friday so all their auth basically broke I have a work around in my python code 👍 https://github.com/fkhera/powerwallCloud/blob/abd0daa069888e68b346201464ec5dfcda771144/powerwallBackup.py#L132

one4many commented 3 years ago

Just found another Tesla Server oddity. I get an response with the correct header (and mimetype) but no body data at all. This causes a None response in await resp.json() and finally results in an exception like this:

Traceback (most recent call last):
  File "pcase.py", line 32, in <module>
    asyncio.run(main())
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 587, in run_until_complete
    return future.result()
  File "pcase.py", line 10, in main
    energy_sites = await client.list_energy_sites()
  File "/Users/......../tesla_api/__init__.py", line 183, in list_energy_sites
    for product in await self.get("products") if "energy_site_id" in product]
  File "/Users/......./tesla_api/__init__.py", line 157, in get
    if "error" in response_json:
TypeError: argument of type 'NoneType' is not iterable
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x10eabf390>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x10eadaa60>, 0.923982764)]']
connector: <aiohttp.connector.TCPConnector object at 0x10eabf3d0>

The Tesla servers don't respond to this account/token with any valid response. No data or not even a authentication error. So I'm not sure if we can assume the account is intact and we just don't get any data at the moment or the account is blocked/disabled/temporarily disabled for now.

Maybe raising a 'No data' exception is ok for now and if it turns out to be a authentication problem changing it into a 'Authentication Error' exception.

Dreamsorcerer commented 3 years ago

Thanks Tesla... :P

Dreamsorcerer commented 3 years ago

OK, sounds like the latter issue may be a WAF? https://github.com/timdorr/tesla-api/issues/260#issuecomment-772424029

one4many commented 3 years ago

Hmmm, not sure if it is a WAF. WAFs typically block IP addresses and not single sessions. All other connections my servers hold (talking to the API-Servers) work without a problem. In theory it is possible to block a single session because it is identifiable via the auth-header but WAFs can't do that (at least none of the ones I know).

I just retried the account in question with the same result, just no data from the Tesla API servers. This account had no requests for at least 4 hrs.

Just to be clear: This is just a request to retrieve data from the API and not a request to authenticate via user/pass/MFA token.