Tesla Fleet API library for Python
Project description
Tesla Fleet API
Tesla Fleet API is a Python library that provides an interface to interact with Tesla's Fleet API, including signed commands and encrypted local Bluetooth (BLE) communication. It also supports interactions with Teslemetry and Tessie services.
Features
- Fleet API for vehicles
- Fleet API for energy sites
- Fleet API with signed vehicle commands
- Bluetooth for vehicles
- Routing and failover across backends for vehicles and energy sites (e.g. Bluetooth/local primary, cloud fallback)
- Teslemetry integration
- Tessie integration
Installation
You can install the library using pip:
pip install tesla-fleet-api
Usage
Authentication
The TeslaFleetOAuth class provides methods that help with authenticating to the Tesla Fleet API. Here's a basic example:
import asyncio
import aiohttp
from tesla_fleet_api import TeslaFleetOAuth
async def main():
async with aiohttp.ClientSession() as session:
oauth = TeslaFleetOAuth(
session=session,
client_id="<client_id>",
client_secret="<client_secret>",
redirect_uri="<redirect_uri>",
)
# Get the login URL and navigate the user to it
login_url = oauth.get_login_url(scopes=["openid", "email", "offline_access"])
print(f"Please go to {login_url} and authorize access.")
# After the user authorizes access, they will be redirected to the redirect_uri with a code
code = input("Enter the code you received: ")
# Exchange the code for a refresh token
await oauth.get_refresh_token(code)
print(f"Access token: {oauth.access_token}")
print(f"Refresh token: {oauth.refresh_token}")
# Dont forget to store the refresh token so you can use it again later
asyncio.run(main())
Fleet API for Vehicles
The TeslaFleetApi class provides methods to interact with the Fleet API for vehicles. Here's a basic example:
import asyncio
import aiohttp
from tesla_fleet_api import TeslaFleetApi
from tesla_fleet_api.exceptions import TeslaFleetError
async def main():
async with aiohttp.ClientSession() as session:
api = TeslaFleetApi(
access_token="<access_token>",
session=session,
region="na",
)
try:
data = await api.vehicles.list()
print(data)
except TeslaFleetError as e:
print(e)
asyncio.run(main())
For more detailed examples, see Fleet API for Vehicles.
Fleet API for Energy Sites
The EnergySites class provides methods to interact with the Fleet API for energy sites. Here's a basic example:
import asyncio
import aiohttp
from tesla_fleet_api import TeslaFleetApi
from tesla_fleet_api.exceptions import TeslaFleetError
async def main():
async with aiohttp.ClientSession() as session:
api = TeslaFleetApi(
access_token="<access_token>",
session=session,
region="na",
)
try:
energy_sites = await api.energySites.list()
print(energy_sites)
except TeslaFleetError as e:
print(e)
asyncio.run(main())
For more detailed examples, see Fleet API for Energy Sites.
Fleet API with Signed Vehicle Commands
The VehicleSigned class provides methods to interact with the Fleet API using signed vehicle commands. Here's a basic example:
import asyncio
import aiohttp
from tesla_fleet_api import TeslaFleetApi
from tesla_fleet_api.tesla.vehicle.signed import VehicleSigned
from tesla_fleet_api.exceptions import TeslaFleetError
async def main():
async with aiohttp.ClientSession() as session:
api = TeslaFleetApi(
access_token="<access_token>",
session=session,
region="na",
)
try:
vehicle = VehicleSigned(api, "<vin>")
data = await vehicle.wake_up()
print(data)
except TeslaFleetError as e:
print(e)
asyncio.run(main())
For more detailed examples, see Fleet API with Signed Vehicle Commands.
Bluetooth for Vehicles
The TeslaBluetooth class provides methods to interact with Tesla vehicles using Bluetooth. Here's a basic example:
import asyncio
from bleak import BleakScanner
from tesla_fleet_api import TeslaBluetooth
async def main():
scanner = BleakScanner()
devices = await scanner.discover()
for device in devices:
if TeslaBluetooth().valid_name(device.name):
print(f"Found Tesla vehicle: {device.name}")
asyncio.run(main())
For more detailed examples, see Bluetooth for Vehicles.
VehicleBluetooth keeps a held BLE connection alive during idle periods by
default with a passive GATT read about every 20 seconds. Pass
keepalive_interval=None (or 0) when creating the vehicle to disable it;
leaving it enabled can keep an already-awake car awake longer, so disconnect or
disable keepalive when vehicle sleep is preferred.
BLE connect/notify failures, and GATT writes rejected before backend I/O, raise
BluetoothTransportError, a TeslaFleetError subclass, with the original
transport exception chained as __cause__ when available. A GATT write that
entered backend I/O and then failed or timed out is delivery-ambiguous and
raises BluetoothTimeout/BluetoothUnconfirmedCommand instead. Mutating BLE
commands use a confirmation ladder controlled by confirmation ("ack" by
default) and raise_unconfirmed (False by default): an inconclusive lost
acknowledgement resolves as best-effort success unless you opt in to
BluetoothUnconfirmedCommand, while a command proven not to have applied raises
BluetoothCommandFailed. See Bluetooth for Vehicles
for the full ladder. Catch TeslaFleetError to handle Bluetooth transport
failures (including bleak.exc.BleakError and builtin TimeoutError from
ESPHome proxies) and response-wait timeouts through the same library error
hierarchy.
Routing and Failover
The Router class composes an ordered list of two-or-more backends that share a common method surface and dispatches each method call down the chain, automatically failing over on most errors. VehicleRouter and EnergySiteRouter are thin entity-specific subclasses. A common setup is a local VehicleBluetooth primary with a cloud fallback (e.g. a TeslemetryVehicle), so commands go over Bluetooth when the vehicle is reachable and route to the cloud otherwise:
import asyncio
import aiohttp
from tesla_fleet_api import TeslaBluetooth, Teslemetry
from tesla_fleet_api.router import VehicleRouter
from tesla_fleet_api.exceptions import TeslaFleetError
async def main():
async with aiohttp.ClientSession() as session:
# Primary: local Bluetooth
tesla_bluetooth = TeslaBluetooth()
await tesla_bluetooth.get_private_key("path/to/private_key.pem")
primary = tesla_bluetooth.vehicles.create("<vin>", confirmation="verify")
# Secondary (fallback): Teslemetry cloud
teslemetry = Teslemetry(access_token="<access_token>", session=session)
secondary = teslemetry.vehicles.create("<vin>")
vehicle = VehicleRouter(primary, secondary)
try:
await vehicle.wake_up()
except TeslaFleetError as e:
print(e)
asyncio.run(main())
The constructor is Router(primary, secondary, *more_backends, health=None); the two-argument form shown above is fully backward compatible, and any number of extra backends may follow to extend the chain. Each call is tried on the first backend that has the method and, on any exception except BluetoothUnconfirmedCommand, retried on the next backend that has it, returning the first success (raising the last error only if every applicable backend fails). Non-callable attributes (e.g. vin) resolve to the first backend that has them.
By default the router attempts the primary and fails over on any error, with no up-front probe. You can also pass an explicit health check — a bool, a sync callable, or an async callable returning bool — to decide up front whether to route to the primary or skip straight to the rest of the chain. The health check gates only the primary (the first backend); later backends are reached purely through per-command failover.
EnergySiteRouter follows the same pattern for energy sites, pairing a duck-typed local EnergySite-shaped object (e.g. aiopowerwall's PowerwallEnergySite, no dependency added) with a cloud TeslemetryEnergySite fallback:
from tesla_fleet_api.router import EnergySiteRouter
router = EnergySiteRouter(local_energysite, teslemetry_energysite)
await router.set_operation(...) # local first, cloud on failure
Router, VehicleRouter, and EnergySiteRouter are all importable from tesla_fleet_api.router (and, for backward compatibility, from tesla_fleet_api.tesla).
Enable DEBUG logging for tesla_fleet_api to see which backend served a routed call and why failover happened.
Warning: Because a failed call is replayed on the next backend, a non-idempotent command (e.g.
honk_horn,actuate_trunk,door_unlock,charge_start) that fails mid-flight — after a backend may have already partially applied it — can be double-executed (or executed more than once across a longer chain) when it is retried on the next backend. This is a deliberate tradeoff of per-command failover.BluetoothUnconfirmedCommandis the exception: it propagates without failover because the BLE command may already have executed. When the primary isVehicleBluetooth, passconfirmation="verify"to resolve supported mutating command timeouts by state before they reach the router, and setraise_unconfirmed=Truewhen callers must see still-ambiguous outcomes instead of the default best-effort success; callers needing exactly-once semantics for other commands should gate dispatch with an explicithealthcheck or call the underlying backends directly.Dispatch is implemented via
__getattr__, which does not proxy dunder methods, soasync with Router(...)does not manage a backend's BLE connection lifecycle (__aenter__/__aexit__). Commands still auto-connect on send; for explicit connect/disconnect reach throughrouter.primary(orrouter.backends).
Debug Logging
Enable the tesla_fleet_api logger at DEBUG to see each command's command
name, transport/backend, and result. In standalone scripts, configure a handler
first:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("tesla_fleet_api").setLevel(logging.DEBUG)
Command log lines use transport=bluetooth, fleet, teslemetry, or tessie.
Routers also emit backend=<ClassName> lines for each backend tried. See
Bluetooth for Vehicles
for examples and the signed-command naming details.
Teslemetry
The Teslemetry class provides methods to interact with the Teslemetry service. Here's a basic example:
import asyncio
import aiohttp
from tesla_fleet_api import Teslemetry
from tesla_fleet_api.exceptions import TeslaFleetError
async def main():
async with aiohttp.ClientSession() as session:
api = Teslemetry(
access_token="<access_token>",
session=session,
)
try:
data = await api.vehicles.list()
print(data)
except TeslaFleetError as e:
print(e)
asyncio.run(main())
For more detailed examples, see Teslemetry.
Tessie
The Tessie class provides methods to interact with the Tessie service. Here's a basic example:
import asyncio
import aiohttp
from tesla_fleet_api import Tessie
from tesla_fleet_api.exceptions import TeslaFleetError
async def main():
async with aiohttp.ClientSession() as session:
api = Tessie(
access_token="<access_token>",
session=session,
)
try:
data = await api.vehicles.list()
print(data)
except TeslaFleetError as e:
print(e)
asyncio.run(main())
For more detailed examples, see Tessie.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tesla_fleet_api-1.7.1.tar.gz.
File metadata
- Download URL: tesla_fleet_api-1.7.1.tar.gz
- Upload date:
- Size: 186.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cd4f873e1541e5a8eeb8bbb0bc53ff1c825601a81e324799a378d8ef3bcb3fe
|
|
| MD5 |
f5aba9879304475f680dea134bd85f1e
|
|
| BLAKE2b-256 |
e1e95c9b67a3937d8f66de31d38ce559db350b04314be7c79607662281a3575d
|
Provenance
The following attestation bundles were made for tesla_fleet_api-1.7.1.tar.gz:
Publisher:
python-publish.yml on Teslemetry/python-tesla-fleet-api
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tesla_fleet_api-1.7.1.tar.gz -
Subject digest:
9cd4f873e1541e5a8eeb8bbb0bc53ff1c825601a81e324799a378d8ef3bcb3fe - Sigstore transparency entry: 2149026425
- Sigstore integration time:
-
Permalink:
Teslemetry/python-tesla-fleet-api@68f79c5b95d1ad5394fae1ec4247bca99d341af3 -
Branch / Tag:
refs/tags/v1.7.1 - Owner: https://github.com/Teslemetry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@68f79c5b95d1ad5394fae1ec4247bca99d341af3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tesla_fleet_api-1.7.1-py3-none-any.whl.
File metadata
- Download URL: tesla_fleet_api-1.7.1-py3-none-any.whl
- Upload date:
- Size: 166.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b87cb2d28c5d5d8643353c8acd05075865bc7181a5c895fb861d4cd33ed1dfb
|
|
| MD5 |
a17d34b0340bc098f2347a9c9b511a1e
|
|
| BLAKE2b-256 |
0a72d6e3db2b870364915f716b362e11bbe6f1f91167df1d53e2a68aefcb697f
|
Provenance
The following attestation bundles were made for tesla_fleet_api-1.7.1-py3-none-any.whl:
Publisher:
python-publish.yml on Teslemetry/python-tesla-fleet-api
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tesla_fleet_api-1.7.1-py3-none-any.whl -
Subject digest:
9b87cb2d28c5d5d8643353c8acd05075865bc7181a5c895fb861d4cd33ed1dfb - Sigstore transparency entry: 2149026458
- Sigstore integration time:
-
Permalink:
Teslemetry/python-tesla-fleet-api@68f79c5b95d1ad5394fae1ec4247bca99d341af3 -
Branch / Tag:
refs/tags/v1.7.1 - Owner: https://github.com/Teslemetry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@68f79c5b95d1ad5394fae1ec4247bca99d341af3 -
Trigger Event:
push
-
Statement type: