Giter Site home page Giter Site logo

tdorssers / teslapy Goto Github PK

View Code? Open in Web Editor NEW
358.0 46.0 78.0 775 KB

A Python module to use the Tesla Motors Owner API

License: MIT License

Python 99.13% Dockerfile 0.38% Shell 0.49%
python requests geopy tkinter tesla teslamotors tesla-api json requests-oauthlib selenium

teslapy's Introduction

TeslaPy

A Python implementation based on unofficial documentation of the client side interface to the Tesla Motors Owner API, which provides functionality to monitor and control Tesla products remotely.

The Owner API will stop working as vehicles begin requiring end-to-end command authentication using the Tesla Vehicle Command Protocol. Pre-2021 Model S and X vehicles do not support this new protocol and remain controllable using TeslaPy.

Version Downloads

Overview

This module depends on Python requests, requests_oauthlib and websocket-client. It requires Python 3.10+ when using urllib3 2.0, which comes with requests 2.30.0+, or you can pin urllib3 to 1.26.x by installing urllib3<2.

The Tesla class extends requests_oauthlib.OAuth2Session which extends requests.Session and therefore inherits methods like get() and post() that can be used to perform API calls. Module characteristics:

  • It implements Tesla's new OAuth 2 Single Sign-On service.
  • Acquired tokens are stored in current working directory in cache.json file for persistence by default.
  • The cache stores tokens of each authorized identity (email).
  • Authentication is only needed when a new token is requested (usually once).
  • The token is automatically refreshed when expired without the need to reauthenticate.
  • An email registered in another region (e.g. auth.tesla.cn) is also supported.
  • Streaming API support using a WebSocket.
  • Pluggable cache and authenticator methods.

TeslaPy 2.0.0+ no longer implements headless authentication. The constructor differs and takes these arguments:

Argument Description
email SSO identity
verify (optional) verify SSL certificate
proxy (optional) URL of proxy server
retry (optional) number of connection retries or Retry instance
timeout (optional) Connect/read timeout
user_agent (optional) the User-Agent string
authenticator (optional) Function with one argument, the authorization URL, that returns the redirected URL
cache_file (optional) path to cache file used by default loader and dumper
cache_loader (optional) function that returns the cache dict
cache_dumper (optional) function with one argument, the cache dict
sso_base_url (optional) URL of SSO service, set to https://auth.tesla.cn/ if your email is registered in another region
state (optional) state string for CSRF protection
code_verifier (optional) PKCE code verifier string
app_user_agent (optional) X-Tesla-User-Agent string

TeslaPy 2.1.0+ no longer implements RFC 7523 and uses the SSO token for all API requests.

The class will open Tesla's SSO page in the system's default web browser to authenticate. After successful authentication, a Page not found will be displayed and the URL should start with https://auth.tesla.com/void/callback, which is the redirected URL. The class will use stdio to get the full redirected URL from the web browser by default. You need to copy and paste the full URL from the web browser to the console to continue aquirering API tokens. You can use a pluggable authenticator method to automate this, for example using pywebview or selenium. It is also possible to use an SSO refresh token obtained by a 3rd party authentication app.

The convenience method api() uses named endpoints listed in endpoints.json to perform calls, so the module does not require changes if the API is updated. api() substitutes path variables in the URI and calls fetch_token() when needed. Any error message returned by the API is raised as an HTTPError exception. Additionally, the class implements the following methods:

Call Description
request() performs API call using relative or absolute URL, serialization and error message handling
new_code_verifier() generates code verifier for PKCE
authorization_url() forms authorization URL with PKCE extension and tries to detect the accounts registered region
fetch_token() requests an SSO token using Authorization Code grant with PKCE extension
refresh_token() requests an SSO token using Refresh Token grant
close() remove all requests adapter instances
logout() removes token from cache, returns logout URL and optionally signs out using system's default web browser
vehicle_list() returns a list of Vehicle objects
battery_list() returns a list of Battery objects
solar_list() returns a list of SolarPanel objects

The Vehicle class extends dict and stores vehicle data returned by the Owner API, which is a pull API. The get_vehicle_summary() and get_vehicle_data() calls update the Vehicle instance, merging data. The streaming API pushes vehicle data on-change after subscription. The stream() method takes an optional argument, a callback function that is called with one argument, a dict holding the changed data. The Vehicle object is always updated with the pushed data. If there are no changes within 10 seconds, the vehicle stops streaming data. The stream() method has two more optional arguments to control restarting. Additionally, the class implements the following methods:

Call Online Description
api() Yes performs an API call to named endpoint requiring vehicle_id with optional arguments
get_vehicle_summary() No gets the state of the vehicle (online, asleep, offline)
available() No checks if the vehicle is online based on cached data or refreshed status when aged out
sync_wake_up() No wakes up and waits for the vehicle to come online
decode_option() No lookup option code description (read from option_codes.json)
option_code_list() 1 No lists known descriptions of the vehicle option codes
get_vehicle_data() Yes get vehicle data for selected endpoints, defaults to all endpoints
get_vehicle_location_data() Yes gets the basic and location data for the vehicle
get_nearby_charging_sites() Yes lists nearby Tesla-operated charging stations
get_service_scheduling_data() No retrieves next service appointment for this vehicle
get_charge_history() 2 No lists vehicle charging history data points
mobile_enabled() Yes checks if the Mobile Access setting is enabled in the car
compose_image() 3 No composes a vehicle image based on vehicle option codes
dist_units() No converts distance or speed units to GUI setting of the vehicle
temp_units() No converts temperature units to GUI setting of the vehicle
gui_time() No returns timestamp or current time formatted to GUI setting
last_seen() No returns vehicle last seen natural time
decode_vin() No decodes the vehicle identification number to a dict
command() Yes wrapper around api() for vehicle command response error handling

1 Option codes appear to be deprecated.

2 Car software version 2021.44.25 or higher required, Data Sharing must be enabled and you must be the primary vehicle owner.

3 Pass vehicle option codes to this method now options codes are deprecated.

Only methods with No in the Online column are available when the vehicle is asleep or offline. These methods will not prevent your vehicle from sleeping. Other methods and API calls require the vehicle to be brought online by using sync_wake_up() and can prevent your vehicle from sleeping if called within too short a period.

The Product class extends dict and is initialized with product data of Powerwalls and solar panels returned by the API. Additionally, the class implements the following methods:

Call Description
api() performs an API call to named endpoint requiring battery_id or site_id with optional arguments
get_history_data() Retrieve live status of product
get_calendar_history_data() Retrieve live status of product
command() wrapper around api() for battery command response error handling

The Battery class extends Product and stores Powerwall data returned by the API, updated by get_battery_data(). Additionally, the class implements the following methods:

Call Description
get_battery_data() Retrieve detailed state and configuration of the battery
set_operation() Set battery operation to self_consumption, backup or autonomous
set_backup_reserve_percent() Set the minimum backup reserve percent for that battery
set_import_export() Sets the battery grid import and export settings
get_tariff() Get the tariff rate data
set_tariff() Set the tariff rate data. The data can be created manually, or generated by create_tariff
create_tariff() Creates a correctly formatted dictionary of tariff data

The SolarPanel class extends Product and stores solar panel data returned by the API, updated by get_site_data(). Additionally, the class implements the following methods:

Call Description
get_site_data() Retrieve current site generation data

Usage

Basic usage of the module:

import teslapy
with teslapy.Tesla('[email protected]') as tesla:
    vehicles = tesla.vehicle_list()
    vehicles[0].sync_wake_up()
    vehicles[0].command('ACTUATE_TRUNK', which_trunk='front')
    vehicles[0].get_vehicle_data()
    print(vehicles[0]['vehicle_state']['car_version'])

TeslaPy 2.4.0 and 2.5.0 automatically calls get_vehicle_data() and TeslaPy 2.6.0+ automatically calls get_latest_vehicle_data() when a key is not found. This example works for TeslaPy 2.6.0+:

import teslapy
with teslapy.Tesla('[email protected]') as tesla:
    vehicles = tesla.vehicle_list()
    print(vehicles[0]['display_name'] + ' last seen ' + vehicles[0].last_seen() +
          ' at ' + str(vehicles[0]['charge_state']['battery_level']) + '% SoC')

Example output:

Tim's Tesla last seen 6 hours ago at 87% SoC

Authentication

The Tesla class implements a pluggable authentication method. If you want to implement your own method to handle the SSO page and retrieve the redirected URL after authentication, you can pass a function as an argument to the constructor, that takes the authentication URL as an argument and returns the redirected URL. The authenticator argument is accessible as an attribute as well.

pywebview

Example using a webview component that displays the SSO page in its own native GUI window.

import teslapy
import webview

def custom_auth(url):
    result = ['']
    window = webview.create_window('Login', url)
    def on_loaded():
        result[0] = window.get_current_url()
        if 'void/callback' in result[0].split('?')[0]:
            window.destroy()
    window.loaded += on_loaded
    webview.start()
    return result[0]

with teslapy.Tesla('[email protected]', authenticator=custom_auth) as tesla:
    tesla.fetch_token()

selenium

Example using selenium to automate web browser interaction. The SSO page returns a 403 when navigator.webdriver is set and currently only Chrome, Opera and Edge Chromium can prevent this.

import teslapy
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

def custom_auth(url):
    options = webdriver.ChromeOptions()
    options.add_argument("--disable-blink-features=AutomationControlled")
    with webdriver.Chrome(chrome_options=options) as browser:
        browser.get(url)
        WebDriverWait(browser, 300).until(EC.url_contains('void/callback'))
        return browser.current_url

with teslapy.Tesla('[email protected]', authenticator=custom_auth) as tesla:
    tesla.fetch_token()

Alternative

TeslaPy 2.2.0 introduced the authorization_url() method to get the SSO page URL and the option to supply the redirected URL as keyword argument authorization_response to fetch_token() after authentication.

import teslapy
tesla = teslapy.Tesla('[email protected]')
if not tesla.authorized:
    print('Use browser to login. Page Not Found will be shown at success.')
    print('Open this URL: ' + tesla.authorization_url())
    tesla.fetch_token(authorization_response=input('Enter URL after authentication: '))
vehicles = tesla.vehicle_list()
print(vehicles[0])
tesla.close()

Alternative staged

Support for staged authorization has been added to TeslaPy 2.5.0. The keyword arguments state and code_verifier are accepted by the Tesla class constructor, the authorization_url() method and the fetch_token() method.

import teslapy
# First stage
tesla = teslapy.Tesla('[email protected]')
if not tesla.authorized:
    state = tesla.new_state()
    code_verifier = tesla.new_code_verifier()
    print('Use browser to login. Page Not Found will be shown at success.')
    print('Open: ' + tesla.authorization_url(state=state, code_verifier=code_verifier))
tesla.close()
# Second stage
tesla = teslapy.Tesla('[email protected]', state=state, code_verifier=code_verifier)
if not tesla.authorized:
    tesla.fetch_token(authorization_response=input('Enter URL after authentication: '))
vehicles = tesla.vehicle_list()
print(vehicles[0])
tesla.close()

3rd party authentication apps

TeslaPy 2.4.0+ supports usage of a refresh token obtained by 3rd party authentication apps. The refresh token is used to obtain an access token and both are cached for persistence, so you only need to supply the refresh token only once.

import teslapy
with teslapy.Tesla('[email protected]') as tesla:
    if not tesla.authorized:
        tesla.refresh_token(refresh_token=input('Enter SSO refresh token: '))
    vehicles = tesla.vehicle_list()
    print(vehicles[0])

Logout

To use your systems's default web browser to sign out of the SSO page and clear the token from cache:

tesla.logout(sign_out=True)

If using pywebview, you can clear the token from cache and get the logout URL to display a sign out window:

window = webview.create_window('Logout', tesla.logout())
window.start()

Selenium does not store cookies, just clear the token from cache:

tesla.logout()

Cache

The Tesla class implements a pluggable cache method. If you don't want to use the default disk caching, you can pass a function to load and return the cache dict, and a function that takes a dict as an argument to dump the cache dict, as arguments to the constructor. The cache_loader and cache_dumper arguments are accessible as attributes as well.

import json
import sqlite3
import teslapy

def db_load():
    con = sqlite3.connect('cache.db')
    cur = con.cursor()
    cache = {}
    try:
        for row in cur.execute('select * from teslapy'):
            cache[row[0]] = json.loads(row[1])
    except sqlite3.OperationalError:
        pass
    con.close()
    return cache

def db_dump(cache):
    con = sqlite3.connect('cache.db')
    con.execute('create table if not exists teslapy (email text primary key, data json)')
    for email, data in cache.items():
        con.execute('replace into teslapy values (?, ?)', [email, json.dumps(data)])
    con.commit()
    con.close()

with teslapy.Tesla('[email protected]', cache_loader=db_load, cache_dumper=db_dump) as tesla:
    tesla.fetch_token()

Absolute URL

The Safety Scores are obtained though another API. TeslaPy 2.1.0 introduced absolute URL support for accessing non-Owner API endpoints.

from teslapy import Tesla

with Tesla('[email protected]') as tesla:
    vehicles = tesla.vehicle_list()
    url = 'https://akamai-apigateway-vfx.tesla.com/safety-rating/daily-metrics'
    print(tesla.get(url, params={'vin': vehicles[0]['vin'], 'deviceLanguage': 'en',
                                 'deviceCountry': 'US', 'timezone': 'UTC'}))

Robustness

TeslaPy uses an adjustable connect and read timeout of 10 seconds by default. Refer to the timeouts section for more details. TeslaPy does not retry failed or timed out connections by default, which can be enabled with the retry parameter.

tesla = teslapy.Tesla('[email protected]', retry=2, timeout=15)

A robust program accounting for network failures has a retry strategy, that includes the total number of retry attempts to make, the HTTP response codes to retry on and optionally a backoff factor. Refer to the retry module for more details.

Be aware that Tesla may temporarily block your account if you are hammering the servers too much.

import teslapy
retry = teslapy.Retry(total=2, status_forcelist=(500, 502, 503, 504))
with teslapy.Tesla('[email protected]', retry=retry) as tesla:
    vehicles = tesla.vehicle_list()
    print(vehicles[0])
vehicles[0].command('FLASH_LIGHTS')  # Raises exception

The line after the context manager will raise an exception when using TeslaPy 2.5.0+ because it explicitly closes the requests connection handler when the context manager exits. Earlier versions would not raise an exception and retries would not work.

Take a look at cli.py, menu.py or gui.py for more code examples.

Commands

These are the major commands:

Endpoint Parameters Value
UNLOCK
LOCK
HONK_HORN
FLASH_LIGHTS
CLIMATE_ON
CLIMATE_OFF
MAX_DEFROST on true or false
CHANGE_CLIMATE_TEMPERATURE_SETTING driver_temp, passenger_temp temperature in celcius
SET_CLIMATE_KEEPER_MODE climate_keeper_mode 0=off, 1=on, 2=dog, 3=camp
HVAC_BIOWEAPON_MODE on true or false
SCHEDULED_DEPARTURE 1 enable, departure_time, preconditioning_enabled, preconditioning_weekdays_only, off_peak_charging_enabled, off_peak_charging_weekdays_only, end_off_peak_time true or false, minutes past midnight
SCHEDULED_CHARGING 1 enable, time true or false, minutes past midnight
CHARGING_AMPS 1 charging_amps between 0-32
SET_CABIN_OVERHEAT_PROTECTION on, fan_only true or false
CHANGE_CHARGE_LIMIT percent percentage
SET_VEHICLE_NAME vehicle_name name
CHANGE_SUNROOF_STATE state vent or close
WINDOW_CONTROL 2 command, lat, lon vent or close, 0, 0
ACTUATE_TRUNK which_trunk rear or front
REMOTE_START
TRIGGER_HOMELINK lat, lon current lattitude and logitude
CHARGE_PORT_DOOR_OPEN
CHARGE_PORT_DOOR_CLOSE
START_CHARGE
STOP_CHARGE
SET_COP_TEMP temp temperature in celcius
MEDIA_TOGGLE_PLAYBACK
MEDIA_NEXT_TRACK
MEDIA_PREVIOUS_TRACK
MEDIA_NEXT_FAVORITE
MEDIA_PREVIOUS_FAVORITE
MEDIA_VOLUME_UP
MEDIA_VOLUME_DOWN
SET_VALET_MODE on, password true or false, 4 digit PIN
RESET_VALET_PIN
SPEED_LIMIT_ACTIVATE pin 4 digit PIN
SPEED_LIMIT_DEACTIVATE pin 4 digit PIN
SPEED_LIMIT_SET_LIMIT limit_mph between 50-90
SPEED_LIMIT_CLEAR_PIN pin 4 digit PIN
SCHEDULE_SOFTWARE_UPDATE offset_sec seconds
CANCEL_SOFTWARE_UPDATE
SET_SENTRY_MODE on true or false
REMOTE_SEAT_HEATER_REQUEST heater, level seat 0-5, level 0-3
REMOTE_AUTO_SEAT_CLIMATE_REQUEST auto_seat_position, auto_climate_on 1-2, true or false
REMOTE_SEAT_COOLING_REQUEST seat_position, seat_cooler_level
REMOTE_STEERING_WHEEL_HEATER_REQUEST on true or false

1 requires car version 2021.36 or higher. Setting charging_amps to 2 or 3 results in 3A and setting to 0 or 1 results in 2A.

2 close requires lat and lon values to be near the current location of the car.

Exceptions

Basic exception handling:

try:
    vehicles[0].command('HONK_HORN')
except teslapy.HTTPError as e:
    print(e)

All requests.exceptions and oauthlib.oauth2.rfc6749.errors classes are imported by the module. When the vehicle is asleep or offline and the vehicle needs to be online for the API endpoint to be executed, the following exception is raised: requests.exceptions.HTTPError: 408 Client Error: vehicle unavailable. The exception can be caught as teslapy.HTTPError.

Additionally, sync_wake_up() raises teslapy.VehicleError when the vehicle does not come online within the specified timeout. And command() also raises teslapy.VehicleError when the vehicle command response result is False. For instance, if one of the media endpoints is called and there is no user present in the vehicle, the following exception is raised: VehicleError: user_not_present.

As of January 29, 2021, Tesla updated this endpoint to follow RFC 7523 and requires the use of the SSO service (auth.tesla.com) for authentication. If you get a requests.exceptions.HTTPError: 400 Client Error: endpoint_deprecated:_please_update_your_app for url: https://owner-api.teslamotors.com/oauth/token then you are probably using an old version of this module.

As of September 3, 2021, Tesla has added ReCaptcha to the login form. This caused the headless login implemented by TeslaPy to break. If you get a ValueError: Credentials rejected. Recaptcha is required and you are using correct credentials then you are probably using an old version of this module.

As of January 12, 2022, Tesla has deprecated the use of RFC 7523 tokens and requires the SSO tokens to be used for API access. If you get a requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://owner-api.teslamotors.com/api/1/vehicles and you are using correct credentials then you are probably using an old version of this module.

As of January 7, 2024, Tesla has removed the VEHICLE_LIST endpoint. If you get a requests.exceptions.HTTPError: 412 Client Error: Endpoint is only available on fleetapi. Visit https://developer.tesla.com/docs for more info then you are probably using an old version of this module.

Demo applications

The source repository contains three demo applications that optionally use pywebview version 3.0 or higher or selenium version 3.13.0 or higher to automate weblogin. Selenium 4.0.0 or higher is required for Edge Chromium.

cli.py is a simple CLI application that can use almost all functionality of the TeslaPy module. The filter option allows you to select a product if more than one product is linked to your account. API output is JSON formatted:

usage: cli.py [-h] -e EMAIL [-f FILTER] [-a API [KEYVALUE ...]] [-k KEYVALUE]
              [-c COMMAND] [-t TIMEOUT] [-p PROXY] [-R REFRESH] [-U URL] [-l]
              [-o] [-v] [-w] [-g] [-b] [-n] [-m] [-s] [-d] [-r] [-S] [-H] [-V]
              [-L] [-u] [--chrome] [--edge]

Tesla Owner API CLI

optional arguments:
  -h, --help            show this help message and exit
  -e EMAIL              login email
  -f FILTER             filter on id, vin, etc.
  -a API [KEYVALUE ...]
                        API call endpoint name
  -k KEYVALUE           API parameter (key=value)
  -c COMMAND            product command endpoint
  -t TIMEOUT            connect/read timeout
  -p PROXY              proxy server URL
  -R REFRESH            use this refresh token
  -U URL                SSO service base URL
  -l, --list            list all selected vehicles/batteries
  -o, --option          list vehicle option codes
  -v, --vin             vehicle identification number decode
  -w, --wake            wake up selected vehicle(s)
  -g, --get             get rollup of all vehicle data
  -b, --battery         get detailed battery state and config
  -n, --nearby          list nearby charging sites
  -m, --mobile          get mobile enabled state
  -s, --site            get current site generation data
  -d, --debug           set logging level to debug
  -r, --stream          receive streaming vehicle data on-change
  -S, --service         get service self scheduling eligibility
  -H, --history         get charging history data
  -B, --basic           get basic vehicle data only
  -G, --location        get location (GPS) data, wake as needed
  -V, --verify          disable verify SSL certificate
  -L, --logout          clear token from cache and logout
  -u, --user            get user account details
  --chrome              use Chrome WebDriver
  --edge                use Edge WebDriver

Example usage of cli.py:

python cli.py -e [email protected] -w -a ACTUATE_TRUNK -k which_trunk=front

menu.py is a menu-based console application that displays vehicle data in a tabular format. The application depends on geopy to convert GPS coordinates to a human readable address:

gui.py is a graphical user interface using tkinter. API calls are performed asynchronously using threading. The GUI supports auto refreshing of the vehicle data and displays a composed vehicle image. Note that the vehicle will not go to sleep, if auto refresh is enabled. The application depends on geopy to convert GPS coordinates to a human readable address. If Tcl/Tk GUI toolkit version of your Python installation is lower than 8.6 then pillow is required to display the vehicle image. User preferences, such as which web browser to use for authentication, persist upon application restart.

The vehicle charging history can be displayed in a graph as well.

The demo applications can be containerized using the provided Dockerfile. A bind volume is used to store cache.json and gui.ini in the current directory on the host machine:

sudo docker build -t teslapy .
xhost +local:*
sudo docker run -ti --net=host --privileged -v "$(pwd)":/home/tsla teslapy

Vehicle data

Example output of get_vehicle_data() or python cli.py -e [email protected] -w -g below:

{
    "id": 12345678901234567,
    "vehicle_id": 1234567890,
    "vin": "5YJ3E111111111111",
    "display_name": "Tim's Tesla",
    "option_codes": null,
    "color": null,
    "tokens": [
        "1234567890abcdef",
        "abcdef1234567890"
    ],
    "state": "online",
    "in_service": false,
    "id_s": "12345678901234567",
    "calendar_enabled": true,
    "api_version": 6,
    "backseat_token": null,
    "backseat_token_updated_at": null,
    "user_id": 123456,
    "charge_state": {
        "battery_heater_on": false,
        "battery_level": 44,
        "battery_range": 99.84,
        "charge_current_request": 16,
        "charge_current_request_max": 16,
        "charge_enable_request": true,
        "charge_energy_added": 14.54,
        "charge_limit_soc": 90,
        "charge_limit_soc_max": 100,
        "charge_limit_soc_min": 50,
        "charge_limit_soc_std": 90,
        "charge_miles_added_ideal": 66.5,
        "charge_miles_added_rated": 66.5,
        "charge_port_cold_weather_mode": false,
        "charge_port_door_open": true,
        "charge_port_latch": "Engaged",
        "charge_rate": 455.7,
        "charge_to_max_range": false,
        "charger_actual_current": 0,
        "charger_phases": null,
        "charger_pilot_current": 16,
        "charger_power": 100,
        "charger_voltage": 2,
        "charging_state": "Charging",
        "conn_charge_cable": "IEC",
        "est_battery_range": 78.13,
        "fast_charger_brand": "Tesla",
        "fast_charger_present": true,
        "fast_charger_type": "Combo",
        "ideal_battery_range": 99.84,
        "managed_charging_active": false,
        "managed_charging_start_time": null,
        "managed_charging_user_canceled": false,
        "max_range_charge_counter": 1,
        "minutes_to_full_charge": 15,
        "not_enough_power_to_heat": null,
        "scheduled_charging_pending": false,
        "scheduled_charging_start_time": null,
        "time_to_full_charge": 0.25,
        "timestamp": 1569952097456,
        "trip_charging": true,
        "usable_battery_level": 44,
        "user_charge_enable_request": null
    },
    "climate_state": {
        "battery_heater": false,
        "battery_heater_no_power": null,
        "climate_keeper_mode": "off",
        "driver_temp_setting": 21.0,
        "fan_status": 3,
        "inside_temp": 21.0,
        "is_auto_conditioning_on": true,
        "is_climate_on": true,
        "is_front_defroster_on": false,
        "is_preconditioning": false,
        "is_rear_defroster_on": false,
        "left_temp_direction": 54,
        "max_avail_temp": 28.0,
        "min_avail_temp": 15.0,
        "outside_temp": 13.5,
        "passenger_temp_setting": 21.0,
        "remote_heater_control_enabled": true,
        "right_temp_direction": 54,
        "seat_heater_left": 0,
        "seat_heater_right": 0,
        "side_mirror_heaters": false,
        "smart_preconditioning": false,
        "timestamp": 1569952097456,
        "wiper_blade_heater": false
    },
    "drive_state": {
        "gps_as_of": 1569952096,
        "heading": 240,
        "latitude": 52.531951,
        "longitude": 6.156999,
        "native_latitude": 52.531951,
        "native_location_supported": 1,
        "native_longitude": 6.156999,
        "native_type": "wgs",
        "power": -100,
        "shift_state": null,
        "speed": null,
        "timestamp": 1569952097456
    },
    "gui_settings": {
        "gui_24_hour_time": true,
        "gui_charge_rate_units": "km/hr",
        "gui_distance_units": "km/hr",
        "gui_range_display": "Rated",
        "gui_temperature_units": "C",
        "show_range_units": false,
        "timestamp": 1569952097456
    },
    "vehicle_config": {
        "can_accept_navigation_requests": true,
        "can_actuate_trunks": true,
        "car_special_type": "base",
        "car_type": "model3",
        "charge_port_type": "CCS",
        "eu_vehicle": true,
        "exterior_color": "SolidBlack",
        "has_air_suspension": false,
        "has_ludicrous_mode": false,
        "key_version": 2,
        "motorized_charge_port": true,
        "plg": false,
        "rear_seat_heaters": 0,
        "rear_seat_type": null,
        "rhd": false,
        "roof_color": "Glass",
        "seat_type": null,
        "spoiler_type": "None",
        "sun_roof_installed": null,
        "third_row_seats": "<invalid>",
        "timestamp": 1569952097456,
        "use_range_badging": true,
        "wheel_type": "Pinwheel18"
    },
    "vehicle_state": {
        "api_version": 6,
        "autopark_state_v2": "unavailable",
        "calendar_supported": true,
        "car_version": "2019.32.11.1 d39e85a",
        "center_display_state": 2,
        "df": 0,
        "dr": 0,
        "fd_window": 0,
        "fp_window": 0,
        "ft": 0,
        "is_user_present": true,
        "locked": false,
        "media_state": {
            "remote_control_enabled": true
        },
        "notifications_supported": true,
        "odometer": 6963.081561,
        "parsed_calendar_supported": true,
        "pf": 0,
        "pr": 0,
        "rd_window": 0,
        "remote_start": false,
        "remote_start_enabled": true,
        "remote_start_supported": true,
        "rp_window": 0,
        "rt": 0,
        "sentry_mode": false,
        "sentry_mode_available": true,
        "software_update": {
            "expected_duration_sec": 2700,
            "status": ""
        },
        "speed_limit_mode": {
            "active": false,
            "current_limit_mph": 85.0,
            "max_limit_mph": 90,
            "min_limit_mph": 50,
            "pin_code_set": false
        },
        "sun_roof_percent_open": null,
        "sun_roof_state": "unknown",
        "timestamp": 1569952097456,
        "valet_mode": false,
        "valet_pin_needed": true,
        "vehicle_name": "Tim's Tesla"
    }
}

Example output of get_service_scheduling_data() or python cli.py -e [email protected] --service below:

{
    "vin": "5YJ3E111111111111",
    "next_appt_timestamp": "2021-06-08T13:15:00",
    "next_appt_end_timestamp": null,
    "show_badge": false
}

Powerwall data

Example output of get_battery_data() or python cli.py -e [email protected] -b below:

{
    "energy_site_id": 111110110110,
    "resource_type": "battery",
    "site_name": "Elon's House",
    "id": "STE10110111-00101",
    "gateway_id": "1111100-11-A--AAA11110A1A111",
    "asset_site_id": "a1100111-1a11-1aaa-a111-1a0011aa1111",
    "energy_left": 0,
    "total_pack_energy": 13746,
    "percentage_charged": 0,
    "battery_type": "ac_powerwall",
    "backup_capable": true,
    "battery_power": 0,
    "sync_grid_alert_enabled": false,
    "breaker_alert_enabled": false,
    "components": {
        "solar": true,
        "solar_type": "pv_panel",
        "battery": true,
        "grid": true,
        "backup": true,
        "gateway": "teg",
        "load_meter": true,
        "tou_capable": true,
        "storm_mode_capable": true,
        "flex_energy_request_capable": false,
        "car_charging_data_supported": false,
        "off_grid_vehicle_charging_reserve_supported": false,
        "vehicle_charging_performance_view_enabled": false,
        "vehicle_charging_solar_offset_view_enabled": false,
        "battery_solar_offset_view_enabled": true,
        "show_grid_import_battery_source_cards": true,
        "battery_type": "ac_powerwall",
        "configurable": false,
        "grid_services_enabled": false
    },
    "grid_status": "Active",
    "backup": {
        "backup_reserve_percent": 0,
        "events": null
    },
    "user_settings": {
        "storm_mode_enabled": false,
        "sync_grid_alert_enabled": false,
        "breaker_alert_enabled": false
    },
    "default_real_mode": "self_consumption",
    "operation": "self_consumption",
    "installation_date": "2020-01-01T10:10:00+08:00",
    "power_reading": [
        {
            "timestamp": "2021-02-24T04:25:39+08:00",
            "load_power": 5275,
            "solar_power": 3,
            "grid_power": 5262,
            "battery_power": 10,
            "generator_power": 0
        }
    ],
    "battery_count": 1
}

Energy site data

Example output of get_site_data() or python cli.py -e [email protected] -s below:

{
    "energy_site_id": 111110110110,
    "resource_type": "solar",
    "id": "111aaa00-111a-11a1-00aa-00a1aa1aa0aa",
    "asset_site_id": "a1100111-1a11-1aaa-a111-1a0011aa1111",
    "solar_power": 11892.01953125,
    "solar_type": "pv_panel",
    "storm_mode_enabled": null,
    "powerwall_onboarding_settings_set": null,
    "sync_grid_alert_enabled": false,
    "breaker_alert_enabled": false,
    "components": {
        "battery": false,
        "solar": true,
        "solar_type": "pv_panel",
        "grid": true,
        "load_meter": true,
        "market_type": "residential"
    },
    "energy_left": 0,
    "total_pack_energy": 1,
    "percentage_charged": 0,
    "battery_power": 0,
    "load_power": 0,
    "grid_status": "Unknown",
    "grid_services_active": false,
    "grid_power": -11892.01953125,
    "grid_services_power": 0,
    "generator_power": 0,
    "island_status": "island_status_unknown",
    "storm_mode_active": false,
    "timestamp": "2022-08-15T17:12:26Z",
    "wall_connectors": null
}

Installation

TeslaPy is available on PyPI:

python -m pip install teslapy 'urllib3<2'

Make sure you have Python 2.7+ or 3.5+ installed on your system. Alternatively, clone the repository to your machine and run demo application cli.py, menu.py or gui.py to get started, after installing requests_oauthlib 0.8.0+, geopy 1.14.0+, pywebview 3.0+ (optional), selenium 3.13.0+ (optional) and websocket-client 0.59+ using PIP as follows:

python -m pip install requests_oauthlib geopy pywebview selenium websocket-client

and install ChromeDriver to use Selenium or on Ubuntu as follows:

sudo apt-get install python3-requests-oauthlib python3-geopy python3-webview python3-selenium python3-websocket

teslapy's People

Contributors

696grocuttt avatar alandtse avatar bhusang avatar billyburly avatar carrotcn avatar danielwoz avatar dev-dull avatar justmedude avatar kdvlr avatar mababio avatar marcone avatar otw avatar purcell-lab avatar robharman avatar shred86 avatar tdorssers avatar twischer avatar xenomorpheus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

teslapy's Issues

Unauthorized Access

Two days ago, I noticed one of my devices which uses your software was failing to retrieve data from Tesla about my vehicle. I checked my official Tesla phone app, and for the first time since installing it, was requesting I re-enter my username and password.

I dug a little deeper, and both my custom script which uses the library, as well as the included gui.py script fail with the following error:

401 Client Error: Unauthorized for url: https://owner-api.teslamotors.com/api/1/vehicles

Is anyone else noticing such problems?

Credentials rejected

I seem to be getting ValueError: Credentials rejected. It might be due to Tesla adding a captcha lately.

Redirect URL doesn't work

I was able to successfully use TeslaPy and cli.py to generate a token earlier this week. Using the same Raspberry Pi platform I tried to use it again just now but the URL I was redirected to after logging in was generic - https://auth.tesla.com/static/404.html - not the long URL that can be pasted back into the script to generate the token. I looked like the longer URL flashed on the screen for a split second, but I can't figure out any way to find it in Chrome. It isn't in the browser history. Did Tesla make a change to the auth site that has broken the TeslaPy login process?

Battery percentage_charged is wrong

I'm not exactly sure what percentage_charged means, but dividing 4731 Wh / 13774 Wh gives me 34% charge state, which is also displayed in the app. The 3.868... is wrong in my opinion.

{
    ...
    "energy_left": 4731.894736842106,
    "total_pack_energy": 13774,
    "percentage_charged": 3.8685643327920523,
    ...
}

Using refresh token to authenticate does not work

I generate a specific refresh token like this:

import teslapy
import sys

with teslapy.Tesla(input('Enter Tesla login email: '), cache_loader=lambda: {}, cache_dumper=lambda x: None) as tesla:
    if not tesla.authorized:
        print('Use browser to login. Page Not Found will be shown at success.')
        print('Open this URL: ' + tesla.authorization_url())
        try:
            token = tesla.fetch_token(authorization_response=input('Enter URL after authentication: '))
            print(f"Refresh Token: {token['refresh_token']}")
        except Exception as e:
            print(f"Authorisation failed: {e}")
            sys.exit(1)
    else:
        print(f"Refresh Token: {tesla.token['refresh_token']}")

Note how I disable cache_loader and cache_dumper here, so TeslaPy does not cache a successful authentication in between.

Now I use the returned refresh_token in another script to authenticate:

import teslapy

with teslapy.Tesla(input('Enter Tesla login email: ')) as tesla:
    if not tesla.authorized:
        try:
            tesla.refresh_token(refresh_token = input('Your refresh token: '))
        except Exception as e:
            raise Exception("Refreshing the access token failed; is the refresh_token still valid?") from e

and this gives me the following error:

  File "/usr/local/lib/python3.9/site-packages/teslapy/__init__.py", line 209, in refresh_token
    super(Tesla, self).refresh_token(token_url, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests_oauthlib/oauth2_session.py", line 452, in refresh_token
    self.token = self._client.parse_request_body_response(r.text, scope=self.scope)
  File "/usr/local/lib/python3.9/site-packages/oauthlib/oauth2/rfc6749/clients/base.py", line 448, in parse_request_body_response
    self.token = parse_token_response(body, scope=scope)
  File "/usr/local/lib/python3.9/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 441, in parse_token_response
    validate_token_parameters(params)
  File "/usr/local/lib/python3.9/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 448, in validate_token_parameters
    raise_from_error(params.get('error'), params)
  File "/usr/local/lib/python3.9/site-packages/oauthlib/oauth2/rfc6749/errors.py", line 399, in raise_from_error
    raise cls(**kwargs)
oauthlib.oauth2.rfc6749.errors.ServerError: (server_error) Internal server error

What am I doing wrong?

New SSO Token Method did not work for non-Desktop Clients

Hi,
since the SSO Token query opens a Webbrowser on the same machine to get the Access-Token after a successful login, it was no longer possible to do this on my Linux Terminal-only Device to obtain a new Token via this method.

I am unsure if I might did not get everything right, maybe there is still the old method available, but I could not find it at least.
I helped myself by just add "print(url)" to init.py where TeslaPy is waiting for the Users response with the URL. Then I could just copy the request-URL to my Desktop Machine and did the Token-Query Process there and copy the response back into the stdin.

So it would be great to get this easy response URL output to the current version, might be others with Terminal only Linux Servers out there :-)

passing boolean value to API endpoint

I am trying to use the API endpoint STORM_MODE_SETTINGS and it is expecting bool value.

Running cli.py ... -a STORM_MODE_SETTINGS -k enabled=True
gets this error
requests.exceptions.HTTPError: 400 Client Error: https://powergate.prd.sn.tesla.services:443/api/v2/energy_site/storm_mode => Unable to read user settings payload --(Error)--> [[ json: cannot unmarshal string into Go struct field StormModeSettings.enabled of type bool ]] for url: https://owner-api.teslamotors.com/api/1/energy_sites/XXX/storm_mode

Is there way to pass a boolean value?

Thanks

requests.exceptions.HTTPError: 500 Server Error: Internal Server Error for url: https://auth.tesla.com/oauth2/v3/authorize?

I disabled MFA on my tesla account yet I still can't run menu.py

Here is the error I get:

Enter email: MY_TESLA_EMAIL
Traceback (most recent call last):
File "menu.py", line 336, in
main()
File "menu.py", line 306, in main
vehicles = tesla.vehicle_list()
File "C:\Users\aviad\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\teslapy_init_.py", line 327, in vehicle_list
return [Vehicle(v, self) for v in self.api('VEHICLE_LIST')['response']]
File "C:\Users\aviad\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\teslapy_init_.py", line 312, in api
self.fetch_token()
File "C:\Users\aviad\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\teslapy_init_.py", line 183, in fetch_token
url = self.authorization_url()
File "C:\Users\aviad\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\teslapy_init_.py", line 162, in authorization_url
response.raise_for_status() # Raise HTTPError, if one occurred
File "C:\Users\aviad\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\requests\models.py", line 960, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 500 Server Error: Internal Server Error for url: https://auth.tesla.com/oauth2/v3/authorize?response_type=code&client_id=ownerapi&redirect_uri=https%3A%2F%2Fauth.tesla.com%2Fvoid%2Fcallback&scope=openid+email+offline_access&state=X2yy3x9XLOKcGwS3WQzW7aSRRUh9CL&code_challenge=sHsqezDB3WXgqipH5Cx8jDcx1YTwEQtV3hjHVEj7k3I&code_challenge_method=S256&login_hint=MY_TESLA_EMAIL

Can't Use Refresh Token

Hey! I'd like to use this library with a refresh token I supply.

I saw this example in the README, but it still brings up the browser auth. Do you have any idea why?

import teslapy
with teslapy.Tesla('[email protected]') as tesla:
    if not tesla.authorized:
        tesla.refresh_token(refresh_token='my-refresh-token')

Custom cache load/save via ruamel.yaml is failing

I'm trying to implement a cache_loader and cache_dumper with ruamel.yaml, but while I can use my functions directly, using them with the Tesla class fails.

(I realize that doing this in YAML vs the normal JSON doesn't add any value, I'm just doing it for experimentation and fun!)

My code:

from teslapy import Tesla
from ruamel.yaml import YAML

def load_cache():
    yaml = YAML(typ="safe", pure=True)  # ensure we return a real dict()
    with open("cache.yml") as f:
        return yaml.load(f)

def save_cache(cache):
    yaml = YAML(typ="safe", pure=True)
    yaml.default_flow_style = False
    with open("cache.yml", "w") as f:
        yaml.dump(cache, f)

with Tesla(
    email="[email protected]", cache_loader=load_cache, cache_dumper=save_cache
) as tesla:
    tesla.fetch_token()

When I run this, I get this:

File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts-5VgpqDjT-py3.10/lib/python3.10/site-packages/requests_oauthlib/oauth2_session.py", line 502, in request
    token = self.refresh_token(
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/teslapy/__init__.py", line 210, in refresh_token
    self._token_updater()  # Save new token
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/teslapy/__init__.py", line 274, in _token_updater
    self.cache_dumper(cache)
  File "/home/philipsd6/devel/teslapy/./tesla_test.py", line 46, in save_cache
    yaml.dump(cache, f)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/main.py", line 574, in dump
    return self.dump_all([data], stream, transform=transform)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/main.py", line 583, in dump_all
    self._context_manager.dump(data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/main.py", line 915, in dump
    self._yaml.representer.represent(data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 80, in represent
    node = self.represent_data(data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 103, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 321, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 214, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 103, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 321, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 214, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 113, in represent_data
    node = self.yaml_representers[None](self, data)
  File "/home/philipsd6/.cache/pypoetry/virtualenvs/tesla-scripts/lib/python3.10/site-packages/ruamel/yaml/representer.py", line 354, in represent_undefined
    raise RepresenterError(_F('cannot represent an object: {data!s}', data=data))
ruamel.yaml.representer.RepresenterError: cannot represent an object: {'access_token': '...redacted', 'refresh_token': '...redacted'}

But calling the functions manually works fine with no errors:

In [3]: cache = load_cache()

In [4]: cache.keys()
Out[4]: dict_keys(['[email protected]'])

In [5]: save_cache(cache)

Cannot login

I'm trying to run the menu.py and get this error after I enter my email address

Enter email: [email protected]
[pywebview] loaded event is deprecated and will be removed in 4.0. Use events.loaded instead
2022-04-30 15:41:20,351 - pywebview - WARNING - loaded event is deprecated and will be removed in 4.0. Use events.loaded instead
Traceback (most recent call last):
File "c:\SourceVector\TeslaPy-master\TeslaPy-master\menu.py", line 345, in
main()
File "c:\SourceVector\TeslaPy-master\TeslaPy-master\menu.py", line 311, in main
vehicles = tesla.vehicle_list()
File "c:\SourceVector\TeslaPy-master\TeslaPy-master\teslapy_init_.py", line 369, in vehicle_list
return [Vehicle(v, self) for v in self.api('VEHICLE_LIST')['response']]
File "c:\SourceVector\TeslaPy-master\TeslaPy-master\teslapy_init_.py", line 354, in api
self.fetch_token()
File "c:\SourceVector\TeslaPy-master\TeslaPy-master\teslapy_init_.py", line 221, in fetch_token
kwargs['authorization_response'] = self.authenticator(url)
File "c:\SourceVector\TeslaPy-master\TeslaPy-master\menu.py", line 280, in custom_auth
window.loaded += on_loaded
AttributeError: can't set attribute
PS C:\SourceVector>

Any ideas?

I'm using Python 3.8.8

If I run this in debug mode, I have this error

Exception has occurred: TypeError
vars() argument must have dict attribute
File "C:\SourceVector\TeslaPy-master\TeslaPy-master\menu.py", line 25, in
raw_input = vars(builtins).get('raw_input', input) # Py2/3 compatibility

Thanks

crash when vehicle is in service

The code fails when vehicle is in service and awake.

For example, selecting 3 at the menu.py prompt to wake up the vehicle produces
this:

Choice (0 to quit): 3

Please wait...
2022-01-21 21:42:54,913 - teslapy - INFO - Corbimobile is asleep
2022-01-21 21:43:12,121 - teslapy - INFO - Corbimobile is online

Traceback (most recent call last):
File "TeslaPy/./menu.py", line 332, in
main()
File "TeslaPy/./menu.py", line 315, in main
menu(vehicles[idx])
File "TeslaPy/./menu.py", line 173, in menu
if not vehicle.mobile_enabled():
File "TeslaPy/teslapy/init.py", line 479, in mobile_enabled
return self.tesla.get(uri)['response']
File "/usr/lib/python3.9/site-packages/requests/sessions.py", line 555, in get
return self.request('GET', url, **kwargs)
File "TeslaPy/teslapy/init.py", line 121, in request
response.raise_for_status() # Raise HTTPError, if one occurred
File "/usr/lib/python3.9/site-packages/requests/models.py", line 943, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 405 Client Error: vehicle is currently in service for url: https://owner-api.teslamotors.com/api/1/vehicles/1492************/mobile_enabled

Restarting menu.py crashes right away until the vehicle goes back to sleep.

Script asks for captcha on every login attempt

As far as I understand it shouldn't do it, but even after a successful login, the next time it asks for the captcha:

import teslapy

def solve_captcha(svg):
    import webbrowser
    import tempfile
    # Use web browser to display SVG image
    with tempfile.NamedTemporaryFile(suffix='.svg', delete=False) as f:
        f.write(svg)
    webbrowser.open('file://' + f.name)
    indigo.server.log('#### Tesla: Login Captcha required')
    indigo.actionGroup.execute(932264821) # notification
    import time
    time.sleep(10)
    return str(indigo.variables[373373398].value)

try:
    with teslapy.Tesla(tesla_mail, tesla_pass) as tesla:
        tesla.captcha_solver = solve_captcha
        tesla.fetch_token()
        vehicles = tesla.vehicle_list()
except: 
    indigo.server.log('#### Tesla: Login failed')

ValueError: Credentials rejected. Recaptcha is required

Hi,

recently I'm getting this error :

Traceback (most recent call last):
File "/home/gettoken.py", line 29, in
main(sys.argv[1],sys.argv[2])
File "/home/gettoken.py", line 24, in main
s = tesla.fetch_token()
File "/opt/rh/rh-python36/root/usr/lib64/python3.6/site-packages/teslapy/init.py", line 227, in fetch_token
raise ValueError('. '.join(msgs))
ValueError: Credentials rejected. Recaptcha is required

It seems that this error is raised before asking for the captcha solver? I'm using this code to solve captchas online via 2captcha, tit worked perfectlly until yesterday, and now seems that solve_captcha it's not executing

def solve_captcha(svg):
    #print("solver")
    with open('captcha.svg', 'wb') as f:
        f.write(svg)
    solver = CaptchaSolver('2captcha', api_key='xxxx')
    cairosvg.svg2png(url='captcha.svg', write_to='captcha.png')
    raw_data = open('captcha.png', 'rb').read()
    solv = solver.solve_captcha(raw_data)
    #print(solv)
    return solv

def main(user, pwd):
     with teslapy.Tesla(user, pwd) as tesla:
          tesla.captcha_solver = solve_captcha   
          s = tesla.fetch_token()
          print(tesla.token)
          return tesla.token

thanks!

HTTPError: 401 Client Error: Unauthorized for url: https://owner-api.teslamotors.com/api/1/vehicles

I've had a data collection program running for many months now without issue and has picked up successfully with the cached tokens after every restart. Today it failed with the following:

Traceback (most recent call last):
File "/mnt/seagate/private/Python/tesla/Julia.py", line 393, in
vehicles = tesla.vehicle_list()
File "/usr/local/lib/python2.7/dist-packages/teslapy/init.py", line 384, in vehicle_list
return [Vehicle(v, self) for v in self.api('VEHICLE_LIST')['response']]
File "/usr/local/lib/python2.7/dist-packages/teslapy/init.py", line 379, in api
return self.request('GET', uri, params=kwargs)
File "/usr/local/lib/python2.7/dist-packages/teslapy/init.py", line 148, in request
response.raise_for_status() # Raise HTTPError, if one occurred
File "/home/pi/.local/lib/python2.7/site-packages/requests/models.py", line 940, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://owner-api.teslamotors.com/api/1/vehicles

I also tried using another program which is closely based on one of your sample programs and it fails with same error.

I updated to the very latest TeslaPy (2.3.0) but no change.

The token was refreshed on 2022-01-07 19:54:58 and has an expiry of 2022-02-21 19:54:58 (dates are in UK format).

As this has just started to fail I'm not sure if this is a temporary fault with the Tesla infrastructure or if there has been a significant change again.

The official Tesla App is still working correctly at the moment.

Would appreciate any advice on how to further diagnose this problem.

HTTP Error during Authenticate

Just found this repo. Seems very well put together. I tried using the cli.py as well as importing the teslapy in my own python script. It fails with the following error.

Traceback (most recent call last):
  File "./test.py", line 3, in <module>
    tesla.fetch_token()
  File "/docker/homeassistant/config/python_scripts/TeslaPy/teslapy.py", line 69, in fetch_token
    response = self.api('AUTHENTICATE', data=data)
  File "/docker/homeassistant/config/python_scripts/TeslaPy/teslapy.py", line 162, in api
    return self.request(endpoint['TYPE'], uri, data=kwargs)
  File "/docker/homeassistant/config/python_scripts/TeslaPy/teslapy.py", line 55, in request
    response.raise_for_status()  # Raise HTTPError, if one occurred
  File "/usr/lib/python3/dist-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: invalid_request. The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed for url: https://owner-api.teslamotors.com/oauth/token

I tried to recreate the cache.json with a valid token, but that did not seem to work either.

why SSLError๏ผŸ

HTTPSConnectionPool(host='auth.tesla.com', port=443): Max retries exceeded with url: /oauth2/v3/authorize?
Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available."

Issues running on Raspberry pi

Hello,

I have a simple script that runs fine on my PC, but when I copy it across to my raspberry pi, I get the following error:

File "TeslaDisplay.py", line 19, in <module> tesla.fetch_token() File "/home/pi/Scripts/TeslaDisplay/teslapy/teslapy.py", line 71, in fetch_token email=self.email, password=self.password) File "/home/pi/Scripts/TeslaDisplay/teslapy/teslapy.py", line 165, in api return self.request(endpoint['TYPE'], uri, data=kwargs) File "/home/pi/Scripts/TeslaDisplay/teslapy/teslapy.py", line 58, in request response.raise_for_status() # Raise HTTPError, if one occurred File "/home/pi/.local/lib/python3.7/site-packages/requests/models.py", line 943, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 400 Client Error: endpoint_deprecated:_please_update_your_app for url: https://owner-api.teslamotors.com/oauth/token

Any ideas what I might be missing?

Unicode issue

Hi,
I'll get a traceback, as the GPS information of my car seems to resolve to a location which contains an Umlaut (in this case 'รผ').

Happy to provide further details and thanks for this fairly cool tool!

Traceback (most recent call last):
  File "menu.py", line 259, in <module>
    main()
  File "menu.py", line 256, in main
    menu(vehicles[idx])
  File "menu.py", line 151, in menu
    show_vehicle_data(vehicle.get_vehicle_data())
  File "menu.py", line 87, in show_vehicle_data
    print('GPS: {:.75}'.format(str(location)))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xdf' in position 10: ordinal not in range(128)

Help

Hi,

I'm interested in using the telsapy for accessing more information about the Tesla Powerwall battery but having a bit of trouble.

I'm new to Python, and api, so it's all a bit of jumble for me at the moment.

So, I've download Python (on Windows) and did the following
python -m pip install teslapy
python -m pip install requests_oauthlib geopy

No problem with doing that, all successful.

I've copied the cli.py file (actually I copied the text into Notepad and saved it as cli.py in the c:\python directory.

But when I execute the following command (where myemailaddress and mypassword is what I used to get access to the Tesla app on Android)

python cli.py -e myemailaddress -p mypassword -b

I get the following reply:-

Traceback (most recent call last):
File "C:\Python\cli.py", line 90, in
main()
File "C:\Python\cli.py", line 59, in main
selected = prod = tesla.vehicle_list() + tesla.battery_list()
AttributeError: 'Tesla' object has no attribute 'battery_list'

Is there something I'm supposed to put in the cli.py? What is wrong with line 59 and 90?

So, I don't know where the problem is or what I should be expecting (hoping it was something like the Powerwall data section posted)

Be much appreciated if someone can point me with troubleshooting as this is my first attempt at Python programming.

Thanks,
Graham

Authenication issue "ValueError: Timestamp is in the future"

Hello!

trying to run a basic getting started script as shown in the examples:

import teslapy
with teslapy.Tesla('[email protected]') as tesla:
    vehicles = tesla.vehicle_list()
    print(vehicles[0]['display_name'] + ' last seen ' + vehicles[0].last_seen() +
          ' at ' + str(vehicles[0]['charge_state']['battery_level']) + '% SoC')

After I login, I copy/paste the URL from the web browser and I get this error:

Use browser to login. Page Not Found will be shown at success.
Enter URL after authentication: https://auth.tesla.com/void/callback?code=blah&state=blah&issuer=https%3A%2F%2Fauth.tesla.com%2Foauth2%2Fv3
Traceback (most recent call last):
  File "/Users/me/myprojects/tesla/./test.py", line 6, in <module>
    print(vehicles[0]['display_name'] + ' last seen ' + vehicles[0].last_seen() +
  File "/opt/homebrew/lib/python3.9/site-packages/teslapy/__init__.py", line 639, in last_seen
    raise ValueError('Timestamp is in the future')
ValueError: Timestamp is in the future

Using:

python 3.9.13
macOS 12.4
M1 Pro

cache.json portability?

Hey, first, I would like to thank you for this great piece of software! I really enjoyed it until Tesla broke our ability to simply connect to their API using a Python script. Scheduling my climate control and heated seats to be hot when I get into my car in the winter morning of northern Canada was a great addition.

More of a question here but, now that we have to live with the reCaptcha and a real browser to get a valid token, I was asking myself if there's some way of reusing the cache.json file generated on my laptop inside a docker container. Basically, from what I've tested, I can't reuse it.

Am I doing something wrong or is there something store inside the token that prevent it from being reused on another computer?

Thanks for your help!

Issues with credentials : Credentials rejected

hey all, wanted to give this a shot, got everything installed but i'm having issues with logging in. i didnt have MFA enabled, using cli.py was still requesting a captcha. i logged into tesla, configured MFA anyhow and verified the captcha works using an authenticator app. no matter what i try, the cli.py script is returning invalid credentials. i've waited multiple iterations of credentials to verify too. thanks!

Captcha: 364833
Traceback (most recent call last):
  File "cli.py", line 100, in <module>
    main()
  File "cli.py", line 61, in main
    tesla.fetch_token()
  File "/var/www/scripts/TeslaPy/teslapy/__init__.py", line 203, in fetch_token
    raise ValueError('Credentials rejected')
ValueError: Credentials rejected

How to login with captcha

Since this is not really an issue of the code - rather a missing part in the manual - I open a new one.

How do I pass the captcha to the login as seen below?

captcha = 'btBg'

This part worked before:

with teslapy.Tesla(tesla_mail, tesla_pass) as tesla:
    tesla.fetch_token()
    vehicles = tesla.vehicle_list()

Thanks, I really didn't find any documentation for this.

Additionally, how often do I have to do this when using the code above. Will it remember the login or not?

Get Safety Score endpoints data

Anyone managed to get Safety Score data? I see the end points in endpoints.json, but they don't seem to work with e.g. the cli.py example.

How to solve Captcha?

The docs refer to support for captcha, and sure enough I get a prompt for captcha...
But how do I solve it?
I'm using a raspberry pi with no GUI...

can't find docs on how to handle the captcha. Is an image saved somewhere for me to download and go view?

My looping app will run for hours but never a day

My code is published as: https://github.com/israndy/SuperchargerLog

I continue to receive this error, and because it happens daily I am not sure how to track it down, I just see this output after the last successful step the program did run:

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/urllib3/connectionpool.py", line 703, in urlopen
httplib_response = self._make_request(
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/urllib3/connectionpool.py", line 449, in _make_request
six.raise_from(e, None)
File "", line 3, in raise_from
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/urllib3/connectionpool.py", line 444, in _make_request
httplib_response = conn.getresponse()

And it goes on for page after page of errors.

ChargerPhases odd behaviour

I am finding an odd result with the ChargerPhases value.

If the charger is single phase, such as my home charger, it returns the correct value of 1

If the charger is 3 phase (and I believe it is, as it shows 16A 3 phase in the car and is charging at 11kw which is what it would if it was 3 phase, it returns a value of 2. I have this at 2 different locations.

The code I am using is

        ChargerPhases = int(car.get_vehicle_data()['charge_state']['charger_phases'])

444 Client Error: Custom for URL

I have been using this module for a while with no issues until recently, I have made no changes to previously working code and now I am getting a 444 Client Error: CUSTOM for url: https://owner-api.teslamotors.com/oauth/token when calling fetch_token() at first I thought that it was an issue with the tesla server, but the tesla app and another third party app I use are both connecting fine. any ideas what I can try to get a token?

Can't get values

import teslapy
with teslapy.Tesla(tesla_mail, tesla_pass) as tesla:
    tesla.fetch_token()
    vehicles = tesla.vehicle_list()
    vehicles[0].sync_wake_up()
    test = vehicles[0]['charge_state']['charging_state']

This should give me the charging state, but it doesn't. It doesn't work for any value. Commands work though and state returns "online":

vehicles[0].command('STOP_CHARGE')
vehicles[0]['state']

No login possible

import teslapy

def solve_captcha(svg):
    import webbrowser
    import tempfile
    # Use web browser to display SVG image
    with tempfile.NamedTemporaryFile(suffix='.svg', delete=False) as f:
        f.write(svg)
    webbrowser.open('file://' + f.name)
    indigo.server.log('#### Tesla: Login Captcha required')
    indigo.actionGroup.execute(932264821) # notification
    import time
    time.sleep(10)
    return str(indigo.variables[64356346].value)

try:
    with teslapy.Tesla(tesla_mail, tesla_pass, cache_file='/Users/server/Skripte/TeslaPy/cache.json') as tesla:
        tesla.captcha_solver = solve_captcha
        tesla.fetch_token()
        vehicles = tesla.vehicle_list()
except: 
    indigo.server.log('#### Tesla: Login failed')

This code worked, but since yesterday it fails to login. No browser is opened for the captcha though. Any ideas?
Car is online and accessible through the app.

The error appears instantly.
If I delete the cache file there is no difference.

menu.py: TypeError: unsupported format string passed to NoneType.__format__

With the git version, menu.py starts displaying data, and then encounters an error:

...
...
Driver Seat Heater: 0                  Passenger Seat Heater: 0
Is Front Defroster On: False           Is Rear Defroster On: False
--------------------------------------------------------------------------------
Traceback (most recent call last):
  File "./menu.py", line 329, in <module>
    main()
  File "./menu.py", line 312, in main
    menu(vehicles[idx])
  File "./menu.py", line 176, in menu
    show_vehicle_data(vehicle.get_vehicle_data())
  File "./menu.py", line 61, in show_vehicle_data
    print(fmt.format(ve['vehicle_name'], vehicle.dist_units(ve['odometer'])))
TypeError: unsupported format string passed to NoneType.__format__

$ python3 --version
Python 3.7.3

list index out of range

2021-04-08 20:53:56,123 - teslapy - WARNING - compose_image requires options for the image to be accurate
Exception in Tkinter callback
Traceback (most recent call last):
File "/Users/arvin/opt/anaconda3/lib/python3.8/tkinter/init.py", line 1883, in call
return self.func(*args)
File "/Users/arvin/opt/anaconda3/lib/python3.8/tkinter/init.py", line 804, in callit
func(*args)
File "gui.py", line 644, in process_update_dashboard
self.dashboard.update_widgets()
File "gui.py", line 316, in update_widgets
self.ft.text(door[ve['ft']])
IndexError: list index out of range

Crash in vehicle_list()

Got the following crash this morning. I've 'bolded' the line that I think in my source code generated the crash. I'm using a refresh token to connect. It runs without issue for several hours. Not sure if it's about the access token expiring. The next expiration is today at 11:02:00 PM local time. I'll see if it does it then.

The source is at https://github.com/SylvainGa/TeslaRainCheck


Apr 15 11:31:06 weewx python3[20670]: Traceback (most recent call last):
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 600, in urlopen
Apr 15 11:31:06 weewx python3[20670]:     chunked=chunked)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 384, in _make_request
Apr 15 11:31:06 weewx python3[20670]:     six.raise_from(e, None)
Apr 15 11:31:06 weewx python3[20670]:   File "<string>", line 3, in raise_from
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 380, in _make_request
Apr 15 11:31:06 weewx python3[20670]:     httplib_response = conn.getresponse()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3.7/http/client.py", line 1352, in getresponse
Apr 15 11:31:06 weewx python3[20670]:     response.begin()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3.7/http/client.py", line 310, in begin
Apr 15 11:31:06 weewx python3[20670]:     version, status, reason = self._read_status()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3.7/http/client.py", line 279, in _read_status
Apr 15 11:31:06 weewx python3[20670]:     raise RemoteDisconnected("Remote end closed connection without"
Apr 15 11:31:06 weewx python3[20670]: http.client.RemoteDisconnected: Remote end closed connection without response
Apr 15 11:31:06 weewx python3[20670]: During handling of the above exception, another exception occurred:
Apr 15 11:31:06 weewx python3[20670]: Traceback (most recent call last):
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/requests/adapters.py", line 449, in send
Apr 15 11:31:06 weewx python3[20670]:     timeout=timeout
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 638, in urlopen
Apr 15 11:31:06 weewx python3[20670]:     _stacktrace=sys.exc_info()[2])
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 367, in increment
Apr 15 11:31:06 weewx python3[20670]:     raise six.reraise(type(error), error, _stacktrace)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/six.py", line 692, in reraise
Apr 15 11:31:06 weewx python3[20670]:     raise value.with_traceback(tb)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 600, in urlopen
Apr 15 11:31:06 weewx python3[20670]:     chunked=chunked)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 384, in _make_request
Apr 15 11:31:06 weewx python3[20670]:     six.raise_from(e, None)
Apr 15 11:31:06 weewx python3[20670]:   File "<string>", line 3, in raise_from
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 380, in _make_request
Apr 15 11:31:06 weewx python3[20670]:     httplib_response = conn.getresponse()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3.7/http/client.py", line 1352, in getresponse
Apr 15 11:31:06 weewx python3[20670]:     response.begin()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3.7/http/client.py", line 310, in begin
Apr 15 11:31:06 weewx python3[20670]:     version, status, reason = self._read_status()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3.7/http/client.py", line 279, in _read_status
Apr 15 11:31:06 weewx python3[20670]:     raise RemoteDisconnected("Remote end closed connection without"
Apr 15 11:31:06 weewx python3[20670]: urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
Apr 15 11:31:06 weewx python3[20670]: During handling of the above exception, another exception occurred:
Apr 15 11:31:06 weewx python3[20670]: Traceback (most recent call last):
Apr 15 11:31:06 weewx python3[20670]:   File "/home/pi/tesla/check_tesla_windows_mqtt.py", line 216, in <module>
Apr 15 11:31:06 weewx python3[20670]:     client.loop_forever()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 1756, in loop_forever
Apr 15 11:31:06 weewx python3[20670]:     rc = self._loop(timeout)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 1164, in _loop
Apr 15 11:31:06 weewx python3[20670]:     rc = self.loop_read()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 1556, in loop_read
Apr 15 11:31:06 weewx python3[20670]:     rc = self._packet_read()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 2439, in _packet_read
Apr 15 11:31:06 weewx python3[20670]:     rc = self._packet_handle()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 3033, in _packet_handle
Apr 15 11:31:06 weewx python3[20670]:     return self._handle_publish()
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 3327, in _handle_publish
Apr 15 11:31:06 weewx python3[20670]:     self._handle_on_message(message)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/local/lib/python3.7/dist-packages/paho/mqtt/client.py", line 3570, in _handle_on_message
Apr 15 11:31:06 weewx python3[20670]:     on_message(self, self._userdata, message)
Apr 15 11:31:06 weewx python3[20670]:   File "/home/pi/tesla/check_tesla_windows_mqtt.py", line 87, in on_message
**Apr 15 11:31:06 weewx python3[20670]:     vehicles = tesla.vehicle_list()**
Apr 15 11:31:06 weewx python3[20670]:   File "./TeslaPy/teslapy/__init__.py", line 351, in vehicle_list
Apr 15 11:31:06 weewx python3[20670]:     return [Vehicle(v, self) for v in self.api('VEHICLE_LIST')['response']]
Apr 15 11:31:06 weewx python3[20670]:   File "./TeslaPy/teslapy/__init__.py", line 347, in api
Apr 15 11:31:06 weewx python3[20670]:     **{arg_name: kwargs})
Apr 15 11:31:06 weewx python3[20670]:   File "./TeslaPy/teslapy/__init__.py", line 141, in request
Apr 15 11:31:06 weewx python3[20670]:     response = super(Tesla, self).request(method, url, **kwargs)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/requests_oauthlib/oauth2_session.py", line 360, in request
Apr 15 11:31:06 weewx python3[20670]:     headers=headers, data=data, **kwargs)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/requests/sessions.py", line 533, in request
Apr 15 11:31:06 weewx python3[20670]:     resp = self.send(prep, **send_kwargs)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/requests/sessions.py", line 646, in send
Apr 15 11:31:06 weewx python3[20670]:     r = adapter.send(request, **kwargs)
Apr 15 11:31:06 weewx python3[20670]:   File "/usr/lib/python3/dist-packages/requests/adapters.py", line 498, in send
Apr 15 11:31:06 weewx python3[20670]:     raise ConnectionError(err, request=request)
Apr 15 11:31:06 weewx python3[20670]: requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
Apr 15 11:31:07 weewx systemd[1]: check_tesla_windows_mqtt.service: Main process exited, code=exited, status=1/FAILURE
Apr 15 11:31:07 weewx systemd[1]: check_tesla_windows_mqtt.service: Failed with result 'exit-code'.

BadStatusLine error

Hi,

First of all, thanks for all this good work, it's really interesting to follow this kind of community projects.

I did not find a let's say "end user" documented way to use this set of scripts so I may be wrong by handling it the way I am.
I'm simply using the cli.py script to try to authenticate myself and to get vehicles info but it's not working and I'm getting the follwing error:

python cli.py -e <email> -w -g --chrome
requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine('No status line received - the server has closed the connection',))

What would I miss? Again, maybe I'm handling that the wrong way but the idea is just to be able to use the cli Python script to retrieve interactively infos from my vehicle. I don't intend to use those scripts in my own code or whatsoever.

Thanks a lot for your feedback.

Pluggable cache method

Would be useful to be able to override the default file based cache with your own implementation (DB, Redis, memcached etc.)

Setting passenger temperature results in lowest setting.

I'd like to thank you for this body of work. Very well crafted!

Setting the drivers temperature works as expected. Newest version 2.5.0

{"name":"change_climate_temperature_setting","data":{"driver_temp":20.555555555555554},"result":true}

{"name":"change_climate_temperature_setting","data":{"passenger_temp":20.555555555555554},"result":true}

image

CHARGING_HISTORY returns 404

I use the endpoint CHARGING_HISTORY in my project but it stopped working since march. It returns an 404 error. However, other endpoints like vehicle.get_charge_history() work great. Did I do anything wrong?
I tried:
vehicle.api('CHARGING_HISTORY')['response']
tesla.api('CHARGING_HISTORY')['response']
return:
404 Client Error: 404. Not Found 1c646759c29905f76e5ab5f24874ad13 for url: https://owner-api.teslamotors.com/bff/v2/mobile-app/charging/history

HTTP Status 400 when querying historic battery data

I have a powerwall and try to get historic data via tesla.battery_list()[0].get_history_data().

The built request for this however seems to be invalid. I get the following reported:

HTTPError: 400 Client Error: kind `savings` is not supported for url: https://owner-api.teslamotors.com/api/1/energy_sites/2653779/history?kind=savings&period=day&end_date=2022-04-14T00%3A13%3A08.000Z

Can only auth successfully in TeslaPy directory

hey all, seeing a very weird failure here. i had to change my pw and re-auth, updated to 2.0 via pip3, also pulled down the repo locally.

Name: TeslaPy
Version: 2.0.0
Summary: A Python module to use the Tesla Motors Owner API
Home-page: https://github.com/tdorssers/TeslaPy
Author: Tim Dorssers
Author-email: [email protected]
License: UNKNOWN
Location: /usr/local/lib/python3.6/site-packages
Requires: requests-oauthlib, requests, websocket-client

unfortunately after updating, i can only get my scripts to work if in the current directory.

sample script

root@pigts:/var/www/scripts/notify/TeslaPy# cat teslakev.py 
import teslapy

with teslapy.Tesla('XXXXX') as tesla:
        tesla.fetch_token()
        vehicles = tesla.vehicle_list()
        vehicles[1].sync_wake_up()
        print(vehicles[1].get_vehicle_data()['drive_state'])

command output :

root@pigts:~# python3 /var/www/scripts/notify/TeslaPy/teslakev.py
Traceback (most recent call last):
  File "/var/www/scripts/notify/TeslaPy/teslakev.py", line 5, in <module>
    vehicles = tesla.vehicle_list()
  File "/var/www/scripts/notify/TeslaPy/teslapy/__init__.py", line 281, in vehicle_list
    return [Vehicle(v, self) for v in self.api('VEHICLE_LIST')['response']]
  File "/var/www/scripts/notify/TeslaPy/teslapy/__init__.py", line 276, in api
    return self.request('GET', uri, params=kwargs)
  File "/var/www/scripts/notify/TeslaPy/teslapy/__init__.py", line 119, in request
    response.raise_for_status()  # Raise HTTPError, if one occurred
  File "/usr/local/lib/python3.6/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://owner-api.teslamotors.com/api/1/vehicles


root@pigts:~# cd /var/www/scripts/notify/TeslaPy/
root@pigts:/var/www/scripts/notify/TeslaPy# python3 teslakev.py 
{
    "gps_as_of": XXX,
    "heading": 258,
    "latitude": XXX,
    "longitude": -XXX,
    "native_latitude": XXX,
    "native_location_supported": 1,
    "native_longitude": -XXX,
    "native_type": "wgs",
    "power": 0,
    "shift_state": null,
    "speed": null,
    "timestamp": 1632799082968
}

Asynchronous authenticator?

It would be nice to be able in a web application to show the auth url then wait for the user to provide the url including the code through a form submission. Any idea how I could achieve that?

Commands Hanging On New Ubuntu Installation

I've been using Teslapy for about 6 months. Awesome. I use it to adjust charging based on solar panel output.

I recently built up an Ubuntu machine. The code hangs when executing a command. See the attached output when I stop the code. This code runs on other machines (e.g. Windows) but won't run on this Ubuntu machine.

All the packages identified in requirements.txt seem to be up to minimum versions required.

Any guidance on what I need to do to rectify this?

Thanks.

Jim Haselmaier
Suncatcher

No module named 'teslapy'

Hi,

Running py file with SSH works perfectly.
Running the same py file from HA using shell_command results with : No module named 'teslapy' - fails on the import command

My config:
shell_command:
enable_sentry: cd /config/scripts && python3 enable_sentry.py

enable_sentry.py file
try:
import teslapy
except Exception as Argument:
with open('logerror.txt', 'w') as f:
f.write(str(Argument))

System Health
version: core-2022.2.3
installation_type: Home Assistant OS
dev: false
hassio: true
docker: true
user: root
virtualenv: false
python_version: 3.9.7
os_name: Linux
os_version: 5.10.63-v8
arch: aarch64

host_os: Home Assistant OS 7.2
update_channel: stable
supervisor_version: supervisor-2022.01.1
docker_version: 20.10.9
disk_total: 109.3 GB
disk_used: 34.1 GB
healthy: true
supported: true
board: rpi4-64
supervisor_api: ok
version_api: ok
installed_addons: Samba share (9.5.1), Mosquitto broker (6.0.1), Terminal & SSH (9.3.0), File editor (5.3.3), Duck DNS (1.14.0), Frigate NVR (2.3), PostgreSQL (1.0.0), Grafana (7.4.1), TeslaMate (0.17.1)

Image renderer not working

Captcha issue

Hello,

Looks like tesla changed something.

Traceback (most recent call last):
  File "/usr/local/scripts/teslacli/teslacli.py", line 40, in <module>
    main()
  File "/usr/local/scripts/teslacli/teslacli.py", line 31, in main
    tesla = fetch_tesla()
  File "/usr/local/scripts/teslacli/teslacli.py", line 16, in fetch_tesla
    tesla.fetch_token()
  File "/usr/local/scripts/teslacli/venv/lib/python3.9/site-packages/teslapy/__init__.py", line 210, in fetch_token
    raise ValueError('. '.join(msgs))
ValueError: Credentials rejected. Captcha is required. Captcha does not match

The first GET to oauth2/v3/authorize does not ask for a captcha, but after POST'ing username / password it rejects the login, and a new form is presented. Looks identical to the previous, but now a captcha is requested. teslapy doesn't handle this correctly.

Had to copy this in (__init__.py after line 198) to check for it:

        form = HTMLForm(response.text)
        # Retrieve captcha image if required
        if 'captcha' in form:
            response = oauth.get(self.sso_base + 'captcha')
            response.raise_for_status()  # Raise HTTPError, if one occurred
            form['captcha'] = self.captcha_solver(response.content)
            if not form['captcha']:
                raise ValueError('Missing captcha response')
            # Submit login credentials to get authorization code through redirect
            form.update({'identity': self.email, 'credential': self.password})
            response = oauth.post(self.sso_base + 'oauth2/v3/authorize',
                                  data=form, allow_redirects=False)

Authentication error - ValueError: `passcode_getter` callback is not set

import teslapy
with teslapy.Tesla('{my_email}, '{my_password}') as tesla:
        tesla.fetch_token()
        vehicles = tesla.vehicle_list()
        print(vehicles)

Traceback (most recent call last):
File "", line 2, in
File "/Users/jas/github/TeslaPy/teslapy/teslapy.py", line 139, in fetch_token
response = self._check_mfa(oauth, transaction_id)
File "/Users/jas/github/TeslaPy/teslapy/teslapy.py", line 158, in _check_mfa
raise ValueError('passcode_getter callback is not set')
ValueError: passcode_getter callback is not set

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.