Skip to content

Commit cf13beb

Browse files
committed
Implement Strict typing
1 parent 4f4c639 commit cf13beb

File tree

22 files changed

+1720
-53
lines changed

22 files changed

+1720
-53
lines changed

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,6 @@ tesla_fleet_api = ["py.typed"]
3838
exclude = ["tesla_fleet_api/tesla/vehicle/proto/*"]
3939

4040
[tool.pyright]
41+
include = ["tesla_fleet_api"]
42+
typeCheckingMode = "strict"
4143
exclude = ["tesla_fleet_api/tesla/vehicle/proto/*"]

tesla_fleet_api.egg-info/PKG-INFO

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
Metadata-Version: 2.4
2+
Name: tesla_fleet_api
3+
Version: 1.3.2
4+
Summary: Tesla Fleet API library for Python
5+
Author-email: Brett Adams <[email protected]>
6+
License-Expression: Apache-2.0
7+
Project-URL: Homepage, https://github.com/Teslemetry/python-tesla-fleet-api
8+
Classifier: Development Status :: 5 - Production/Stable
9+
Classifier: Programming Language :: Python :: 3
10+
Classifier: Operating System :: OS Independent
11+
Requires-Python: >=3.10
12+
Description-Content-Type: text/markdown
13+
License-File: LICENSE
14+
Requires-Dist: aiohttp
15+
Requires-Dist: aiofiles
16+
Requires-Dist: aiolimiter
17+
Requires-Dist: cryptography
18+
Requires-Dist: protobuf
19+
Requires-Dist: bleak
20+
Requires-Dist: bleak-retry-connector
21+
Dynamic: license-file
22+
23+
# Tesla Fleet API
24+
25+
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.
26+
27+
## Features
28+
29+
- Fleet API for vehicles
30+
- Fleet API for energy sites
31+
- Fleet API with signed vehicle commands
32+
- Bluetooth for vehicles
33+
- Teslemetry integration
34+
- Tessie integration
35+
36+
## Installation
37+
38+
You can install the library using pip:
39+
40+
```bash
41+
pip install tesla-fleet-api
42+
```
43+
44+
## Usage
45+
46+
### Authentication
47+
48+
The `TeslaFleetOAuth` class provides methods that help with authenticating to the Tesla Fleet API. Here's a basic example:
49+
50+
```python
51+
import asyncio
52+
import aiohttp
53+
from tesla_fleet_api import TeslaFleetOAuth
54+
55+
async def main():
56+
async with aiohttp.ClientSession() as session:
57+
oauth = TeslaFleetOAuth(
58+
session=session,
59+
client_id="<client_id>",
60+
client_secret="<client_secret>",
61+
redirect_uri="<redirect_uri>",
62+
)
63+
64+
# Get the login URL and navigate the user to it
65+
login_url = oauth.get_login_url(scopes=["openid", "email", "offline_access"])
66+
print(f"Please go to {login_url} and authorize access.")
67+
68+
# After the user authorizes access, they will be redirected to the redirect_uri with a code
69+
code = input("Enter the code you received: ")
70+
71+
# Exchange the code for a refresh token
72+
await oauth.get_refresh_token(code)
73+
print(f"Access token: {oauth.access_token}")
74+
print(f"Refresh token: {oauth.refresh_token}")
75+
# Dont forget to store the refresh token so you can use it again later
76+
77+
asyncio.run(main())
78+
```
79+
80+
### Fleet API for Vehicles
81+
82+
The `TeslaFleetApi` class provides methods to interact with the Fleet API for vehicles. Here's a basic example:
83+
84+
```python
85+
import asyncio
86+
import aiohttp
87+
from tesla_fleet_api import TeslaFleetApi
88+
from tesla_fleet_api.exceptions import TeslaFleetError
89+
90+
async def main():
91+
async with aiohttp.ClientSession() as session:
92+
api = TeslaFleetApi(
93+
access_token="<access_token>",
94+
session=session,
95+
region="na",
96+
)
97+
98+
try:
99+
data = await api.vehicles.list()
100+
print(data)
101+
except TeslaFleetError as e:
102+
print(e)
103+
104+
asyncio.run(main())
105+
```
106+
107+
For more detailed examples, see [Fleet API for Vehicles](docs/fleet_api_vehicles.md).
108+
109+
### Fleet API for Energy Sites
110+
111+
The `EnergySites` class provides methods to interact with the Fleet API for energy sites. Here's a basic example:
112+
113+
```python
114+
import asyncio
115+
import aiohttp
116+
from tesla_fleet_api import TeslaFleetApi
117+
from tesla_fleet_api.exceptions import TeslaFleetError
118+
119+
async def main():
120+
async with aiohttp.ClientSession() as session:
121+
api = TeslaFleetApi(
122+
access_token="<access_token>",
123+
session=session,
124+
region="na",
125+
)
126+
127+
try:
128+
energy_sites = await api.energySites.list()
129+
print(energy_sites)
130+
except TeslaFleetError as e:
131+
print(e)
132+
133+
asyncio.run(main())
134+
```
135+
136+
For more detailed examples, see [Fleet API for Energy Sites](docs/fleet_api_energy_sites.md).
137+
138+
### Fleet API with Signed Vehicle Commands
139+
140+
The `VehicleSigned` class provides methods to interact with the Fleet API using signed vehicle commands. Here's a basic example:
141+
142+
```python
143+
import asyncio
144+
import aiohttp
145+
from tesla_fleet_api import TeslaFleetApi
146+
from tesla_fleet_api.tesla.vehicle.signed import VehicleSigned
147+
from tesla_fleet_api.exceptions import TeslaFleetError
148+
149+
async def main():
150+
async with aiohttp.ClientSession() as session:
151+
api = TeslaFleetApi(
152+
access_token="<access_token>",
153+
session=session,
154+
region="na",
155+
)
156+
157+
try:
158+
vehicle = VehicleSigned(api, "<vin>")
159+
data = await vehicle.wake_up()
160+
print(data)
161+
except TeslaFleetError as e:
162+
print(e)
163+
164+
asyncio.run(main())
165+
```
166+
167+
For more detailed examples, see [Fleet API with Signed Vehicle Commands](docs/fleet_api_signed_commands.md).
168+
169+
### Bluetooth for Vehicles
170+
171+
The `TeslaBluetooth` class provides methods to interact with Tesla vehicles using Bluetooth. Here's a basic example:
172+
173+
```python
174+
import asyncio
175+
from bleak import BleakScanner
176+
from tesla_fleet_api import TeslaBluetooth
177+
178+
async def main():
179+
scanner = BleakScanner()
180+
devices = await scanner.discover()
181+
for device in devices:
182+
if TeslaBluetooth().valid_name(device.name):
183+
print(f"Found Tesla vehicle: {device.name}")
184+
185+
asyncio.run(main())
186+
```
187+
188+
For more detailed examples, see [Bluetooth for Vehicles](docs/bluetooth_vehicles.md).
189+
190+
### Teslemetry
191+
192+
The `Teslemetry` class provides methods to interact with the Teslemetry service. Here's a basic example:
193+
194+
```python
195+
import asyncio
196+
import aiohttp
197+
from tesla_fleet_api import Teslemetry
198+
from tesla_fleet_api.exceptions import TeslaFleetError
199+
200+
async def main():
201+
async with aiohttp.ClientSession() as session:
202+
api = Teslemetry(
203+
access_token="<access_token>",
204+
session=session,
205+
)
206+
207+
try:
208+
data = await api.vehicles.list()
209+
print(data)
210+
except TeslaFleetError as e:
211+
print(e)
212+
213+
asyncio.run(main())
214+
```
215+
216+
For more detailed examples, see [Teslemetry](docs/teslemetry.md).
217+
218+
### Tessie
219+
220+
The `Tessie` class provides methods to interact with the Tessie service. Here's a basic example:
221+
222+
```python
223+
import asyncio
224+
import aiohttp
225+
from tesla_fleet_api import Tessie
226+
from tesla_fleet_api.exceptions import TeslaFleetError
227+
228+
async def main():
229+
async with aiohttp.ClientSession() as session:
230+
api = Tessie(
231+
access_token="<access_token>",
232+
session=session,
233+
)
234+
235+
try:
236+
data = await api.vehicles.list()
237+
print(data)
238+
except TeslaFleetError as e:
239+
print(e)
240+
241+
asyncio.run(main())
242+
```
243+
244+
For more detailed examples, see [Tessie](docs/tessie.md).
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
LICENSE
2+
README.md
3+
pyproject.toml
4+
tesla_fleet_api/__init__.py
5+
tesla_fleet_api/const.py
6+
tesla_fleet_api/exceptions.py
7+
tesla_fleet_api/py.typed
8+
tesla_fleet_api.egg-info/PKG-INFO
9+
tesla_fleet_api.egg-info/SOURCES.txt
10+
tesla_fleet_api.egg-info/dependency_links.txt
11+
tesla_fleet_api.egg-info/requires.txt
12+
tesla_fleet_api.egg-info/top_level.txt
13+
tesla_fleet_api/tesla/__init__.py
14+
tesla_fleet_api/tesla/bluetooth.py
15+
tesla_fleet_api/tesla/charging.py
16+
tesla_fleet_api/tesla/energysite.py
17+
tesla_fleet_api/tesla/fleet.py
18+
tesla_fleet_api/tesla/oauth.py
19+
tesla_fleet_api/tesla/partner.py
20+
tesla_fleet_api/tesla/tesla.py
21+
tesla_fleet_api/tesla/user.py
22+
tesla_fleet_api/tesla/vehicle/__init__.py
23+
tesla_fleet_api/tesla/vehicle/bluetooth.py
24+
tesla_fleet_api/tesla/vehicle/commands.py
25+
tesla_fleet_api/tesla/vehicle/fleet.py
26+
tesla_fleet_api/tesla/vehicle/signed.py
27+
tesla_fleet_api/tesla/vehicle/vehicle.py
28+
tesla_fleet_api/tesla/vehicle/vehicles.py
29+
tesla_fleet_api/tesla/vehicle/proto/__init__.py
30+
tesla_fleet_api/tesla/vehicle/proto/__init__.pyi
31+
tesla_fleet_api/tesla/vehicle/proto/car_server_pb2.py
32+
tesla_fleet_api/tesla/vehicle/proto/car_server_pb2.pyi
33+
tesla_fleet_api/tesla/vehicle/proto/common_pb2.py
34+
tesla_fleet_api/tesla/vehicle/proto/common_pb2.pyi
35+
tesla_fleet_api/tesla/vehicle/proto/errors_pb2.py
36+
tesla_fleet_api/tesla/vehicle/proto/errors_pb2.pyi
37+
tesla_fleet_api/tesla/vehicle/proto/keys_pb2.py
38+
tesla_fleet_api/tesla/vehicle/proto/keys_pb2.pyi
39+
tesla_fleet_api/tesla/vehicle/proto/managed_charging_pb2.py
40+
tesla_fleet_api/tesla/vehicle/proto/managed_charging_pb2.pyi
41+
tesla_fleet_api/tesla/vehicle/proto/signatures_pb2.py
42+
tesla_fleet_api/tesla/vehicle/proto/signatures_pb2.pyi
43+
tesla_fleet_api/tesla/vehicle/proto/universal_message_pb2.py
44+
tesla_fleet_api/tesla/vehicle/proto/universal_message_pb2.pyi
45+
tesla_fleet_api/tesla/vehicle/proto/vcsec_pb2.py
46+
tesla_fleet_api/tesla/vehicle/proto/vcsec_pb2.pyi
47+
tesla_fleet_api/tesla/vehicle/proto/vehicle_pb2.py
48+
tesla_fleet_api/tesla/vehicle/proto/vehicle_pb2.pyi
49+
tesla_fleet_api/teslemetry/__init__.py
50+
tesla_fleet_api/teslemetry/teslemetry.py
51+
tesla_fleet_api/teslemetry/vehicles.py
52+
tesla_fleet_api/tessie/__init__.py
53+
tesla_fleet_api/tessie/tessie.py
54+
tesla_fleet_api/tessie/vehicles.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
aiohttp
2+
aiofiles
3+
aiolimiter
4+
cryptography
5+
protobuf
6+
bleak
7+
bleak-retry-connector
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tesla_fleet_api

tesla_fleet_api/exceptions.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import aiohttp
2+
from typing import Any
23
from tesla_fleet_api.const import LOGGER
34

45

@@ -7,10 +8,10 @@ class TeslaFleetError(BaseException):
78

89
message: str = "An unknown error has occurred."
910
status: int | None = None
10-
data: dict | str | None = None
11+
data: dict[str, Any] | str | None = None
1112
key: str | None = None
1213

13-
def __init__(self, data: dict | str | None = None, status: int | None = None):
14+
def __init__(self, data: dict[str, Any] | str | None = None, status: int | None = None):
1415
LOGGER.debug(self.message)
1516
self.data = data
1617
self.status = status or self.status
@@ -1028,11 +1029,11 @@ async def raise_for_status(resp: aiohttp.ClientResponse) -> None:
10281029
if resp.status < 400:
10291030
return
10301031

1031-
data = None
1032+
data: dict[str, Any] | None = None
10321033
error = None
10331034
if resp.content_type == "application/json":
10341035
data = await resp.json()
1035-
error = data.get("error")
1036+
error = data.get("error") if data else None
10361037

10371038
if resp.status == 400:
10381039
if error:

tesla_fleet_api/tesla/bluetooth.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import asyncio
44
import hashlib
55
import re
6+
from typing import Any
67
from bleak import BleakClient
78
from bleak.backends.device import BLEDevice
89
from bleak_retry_connector import establish_connection
910
from google.protobuf.json_format import MessageToJson, MessageToDict
11+
from google.protobuf.message import Message
1012

1113
from tesla_fleet_api.const import LOGGER
1214
from tesla_fleet_api.tesla.tesla import Tesla
@@ -33,7 +35,7 @@ def get_name(self, vin: str) -> str:
3335
"""Get the name of a vehicle."""
3436
return "S" + hashlib.sha1(vin.encode('utf-8')).hexdigest()[:16] + "C"
3537

36-
async def query_display_name(self, device: BLEDevice, max_attempts=5) -> str | None:
38+
async def query_display_name(self, device: BLEDevice, max_attempts: int = 5) -> str | None:
3739
"""Queries the name of a bluetooth vehicle."""
3840
client = await establish_connection(
3941
BleakClient,
@@ -60,10 +62,10 @@ async def query_display_name(self, device: BLEDevice, max_attempts=5) -> str | N
6062

6163
# Helpers
6264

63-
def toJson(message) -> str:
65+
def toJson(message: Message) -> str:
6466
"""Convert a protobuf message to JSON."""
6567
return MessageToJson(message, preserving_proto_field_name=True)
6668

67-
def toDict(message) -> dict:
69+
def toDict(message: Message) -> dict[str, Any]:
6870
"""Convert a protobuf message to a dictionary."""
6971
return MessageToDict(message, preserving_proto_field_name=True)

0 commit comments

Comments
 (0)