tesla-fleet-api 1.0.4__py3-none-any.whl → 1.0.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tesla_fleet_api/const.py +1 -1
- tesla_fleet_api/exceptions.py +0 -1
- tesla_fleet_api/tesla/energysite.py +2 -1
- tesla_fleet_api/tesla/vehicle/bluetooth.py +43 -24
- tesla_fleet_api/tesla/vehicle/signed.py +0 -11
- tesla_fleet_api/tesla/vehicle/vehicle.py +17 -3
- tesla_fleet_api/tesla/vehicle/vehicles.py +6 -3
- tesla_fleet_api/teslemetry/teslemetry.py +2 -2
- tesla_fleet_api/teslemetry/{vehicle.py → vehicles.py} +3 -1
- tesla_fleet_api/tessie/tessie.py +2 -2
- tesla_fleet_api/tessie/{vehicle.py → vehicles.py} +3 -1
- {tesla_fleet_api-1.0.4.dist-info → tesla_fleet_api-1.0.6.dist-info}/METADATA +1 -1
- {tesla_fleet_api-1.0.4.dist-info → tesla_fleet_api-1.0.6.dist-info}/RECORD +16 -16
- {tesla_fleet_api-1.0.4.dist-info → tesla_fleet_api-1.0.6.dist-info}/WHEEL +1 -1
- {tesla_fleet_api-1.0.4.dist-info → tesla_fleet_api-1.0.6.dist-info}/LICENSE +0 -0
- {tesla_fleet_api-1.0.4.dist-info → tesla_fleet_api-1.0.6.dist-info}/top_level.txt +0 -0
tesla_fleet_api/const.py
CHANGED
tesla_fleet_api/exceptions.py
CHANGED
@@ -159,11 +159,12 @@ class EnergySites(dict[int, EnergySite]):
|
|
159
159
|
"""Class describing the Tesla Fleet API partner endpoints"""
|
160
160
|
|
161
161
|
_parent: TeslaFleetApi
|
162
|
+
Site = EnergySite
|
162
163
|
|
163
164
|
def __init__(self, parent: TeslaFleetApi):
|
164
165
|
self._parent = parent
|
165
166
|
|
166
167
|
def create(self, energy_site_id: int) -> EnergySite:
|
167
168
|
"""Create a specific energy site."""
|
168
|
-
self[energy_site_id] =
|
169
|
+
self[energy_site_id] = self.Site(self._parent, energy_site_id)
|
169
170
|
return self[energy_site_id]
|
@@ -118,7 +118,17 @@ class VehicleBluetooth(Commands):
|
|
118
118
|
|
119
119
|
async def connect(self, device: BLEDevice | None = None, max_attempts: int = MAX_CONNECT_ATTEMPTS) -> None:
|
120
120
|
"""Connect to the Tesla BLE device."""
|
121
|
-
|
121
|
+
if device:
|
122
|
+
self.device = device
|
123
|
+
if not self.device:
|
124
|
+
raise ValueError(f"Device {self.ble_name} not found")
|
125
|
+
self.client = await establish_connection(
|
126
|
+
BleakClient,
|
127
|
+
self.device,
|
128
|
+
self.vin,
|
129
|
+
max_attempts=max_attempts,
|
130
|
+
ble_device_callback=self.get_device
|
131
|
+
)
|
122
132
|
await self.client.start_notify(READ_UUID, self._on_notify)
|
123
133
|
|
124
134
|
async def disconnect(self) -> bool:
|
@@ -140,34 +150,43 @@ class VehicleBluetooth(Commands):
|
|
140
150
|
self._recv += data
|
141
151
|
else:
|
142
152
|
self._recv_len = int.from_bytes(data[:2], 'big')
|
153
|
+
if self._recv_len > 1024:
|
154
|
+
LOGGER.error("Parsed very large message length")
|
155
|
+
self._recv = bytearray()
|
156
|
+
self._recv_len = 0
|
157
|
+
return
|
143
158
|
self._recv = data[2:]
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
if len(self._recv)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
159
|
+
#while len(self._recv) > self._recv_len:
|
160
|
+
#
|
161
|
+
# # Maybe this needs to trigger a reset
|
162
|
+
# await self._on_message(bytes(self._recv[:self._recv_len]))
|
163
|
+
# self._recv_len = int.from_bytes(self._recv[self._recv_len:self._recv_len+2], 'big')
|
164
|
+
# self._recv = self._recv[self._recv_len+2:]
|
165
|
+
# continue
|
166
|
+
if len(self._recv) >= self._recv_len:
|
167
|
+
if len(self._recv) > self._recv_len:
|
168
|
+
LOGGER.debug(f"Received more data than expected: {len(self._recv)} > {self._recv_len}")
|
169
|
+
try:
|
170
|
+
msg = RoutableMessage.FromString(bytes(self._recv[:self._recv_len]))
|
171
|
+
await self._on_message(msg)
|
172
|
+
self._recv = bytearray()
|
173
|
+
self._recv_len = 0
|
174
|
+
except DecodeError:
|
175
|
+
# Attempt parsing the whole payload
|
176
|
+
msg = RoutableMessage.FromString(bytes(self._recv))
|
177
|
+
LOGGER.warn(f"Parsed more data than length: {len(self._recv)} > {self._recv_len}")
|
178
|
+
await self._on_message(msg)
|
179
|
+
self._recv = bytearray()
|
180
|
+
self._recv_len = 0
|
181
|
+
|
182
|
+
async def _on_message(self, msg: RoutableMessage) -> None:
|
157
183
|
"""Receive messages from the Tesla BLE data."""
|
158
|
-
try:
|
159
|
-
msg = RoutableMessage.FromString(data)
|
160
|
-
except DecodeError as e:
|
161
|
-
LOGGER.error(f"Error parsing message: {e}")
|
162
|
-
self._recv = bytearray()
|
163
|
-
self._recv_len = 0
|
164
|
-
return
|
165
184
|
|
166
185
|
if(msg.to_destination.routing_address != self._from_destination):
|
167
186
|
# Ignore ephemeral key broadcasts
|
168
187
|
return
|
169
188
|
|
170
|
-
LOGGER.
|
189
|
+
LOGGER.debug(f"Received response: {msg}")
|
171
190
|
await self._queues[msg.from_destination.domain].put(msg)
|
172
191
|
|
173
192
|
async def _send(self, msg: RoutableMessage, requires: str) -> RoutableMessage:
|
@@ -184,7 +203,7 @@ class VehicleBluetooth(Commands):
|
|
184
203
|
await self.client.write_gatt_char(WRITE_UUID, payload, True)
|
185
204
|
|
186
205
|
# Process the response
|
187
|
-
async with asyncio.timeout(
|
206
|
+
async with asyncio.timeout(2):
|
188
207
|
while True:
|
189
208
|
resp = await self._queues[domain].get()
|
190
209
|
LOGGER.debug(f"Received message {resp}")
|
@@ -217,7 +236,7 @@ class VehicleBluetooth(Commands):
|
|
217
236
|
),
|
218
237
|
protobuf_message_as_bytes=request.SerializeToString(),
|
219
238
|
)
|
220
|
-
resp = await self._send(msg)
|
239
|
+
resp = await self._send(msg, "protobuf_message_as_bytes")
|
221
240
|
respMsg = FromVCSECMessage.FromString(resp.protobuf_message_as_bytes)
|
222
241
|
if(respMsg.commandStatus.whitelistOperationStatus.whitelistOperationInformation):
|
223
242
|
if(respMsg.commandStatus.whitelistOperationStatus.whitelistOperationInformation < len(WHITELIST_OPERATION_STATUS)):
|
@@ -5,14 +5,6 @@ from typing import TYPE_CHECKING
|
|
5
5
|
|
6
6
|
from tesla_fleet_api.tesla.vehicle.fleet import VehicleFleet
|
7
7
|
from tesla_fleet_api.tesla.vehicle.commands import Commands
|
8
|
-
from tesla_fleet_api.exceptions import (
|
9
|
-
MESSAGE_FAULTS,
|
10
|
-
NotOnWhitelistFault,
|
11
|
-
)
|
12
|
-
from tesla_fleet_api.tesla.vehicle.proto.signatures_pb2 import (
|
13
|
-
Session_Info_Status,
|
14
|
-
SessionInfo,
|
15
|
-
)
|
16
8
|
from tesla_fleet_api.tesla.vehicle.proto.universal_message_pb2 import (
|
17
9
|
RoutableMessage,
|
18
10
|
)
|
@@ -41,9 +33,6 @@ class VehicleSigned(VehicleFleet, Commands):
|
|
41
33
|
json = await self.signed_command(
|
42
34
|
base64.b64encode(msg.SerializeToString()).decode()
|
43
35
|
)
|
44
|
-
|
45
36
|
resp = RoutableMessage.FromString(base64.b64decode(json["response"]))
|
46
|
-
|
47
37
|
self.validate_msg(resp)
|
48
|
-
|
49
38
|
return resp
|
@@ -1,10 +1,18 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from typing import TYPE_CHECKING
|
3
3
|
|
4
|
-
|
5
4
|
if TYPE_CHECKING:
|
6
5
|
from tesla_fleet_api.tesla.tesla import Tesla
|
7
6
|
|
7
|
+
MODELS = {
|
8
|
+
"S": "Model S",
|
9
|
+
"X": "Model X",
|
10
|
+
"3": "Model 3",
|
11
|
+
"Y": "Model Y",
|
12
|
+
"C": "Cybertruck",
|
13
|
+
"R": "Roadster",
|
14
|
+
"T": "Semi",
|
15
|
+
}
|
8
16
|
|
9
17
|
class Vehicle:
|
10
18
|
"""Base class describing a Tesla vehicle."""
|
@@ -14,6 +22,12 @@ class Vehicle:
|
|
14
22
|
def __init__(self, parent: Tesla, vin: str):
|
15
23
|
self.vin = vin
|
16
24
|
|
17
|
-
|
25
|
+
|
26
|
+
def pre2021(self) -> bool:
|
18
27
|
"""Checks if a vehicle is a pre-2021 model S or X."""
|
19
|
-
return vin[3] in ["S", "X"] and (vin[9] <= "L" or (vin[9] == "M" and vin[7] in ['1', '2', '3', '4']))
|
28
|
+
return self.vin[3] in ["S", "X"] and (self.vin[9] <= "L" or (self.vin[9] == "M" and self.vin[7] in ['1', '2', '3', '4']))
|
29
|
+
|
30
|
+
@property
|
31
|
+
def model(self) -> str:
|
32
|
+
"""Returns the model of the vehicle."""
|
33
|
+
return MODELS.get(self.vin[3], "Unknown")
|
@@ -15,25 +15,28 @@ class Vehicles(dict[str, Vehicle]):
|
|
15
15
|
"""Class containing and creating vehicles."""
|
16
16
|
|
17
17
|
_parent: TeslaFleetApi
|
18
|
+
Fleet = VehicleFleet
|
19
|
+
Signed = VehicleSigned
|
20
|
+
Bluetooth = VehicleBluetooth
|
18
21
|
|
19
22
|
def __init__(self, parent: TeslaFleetApi):
|
20
23
|
self._parent = parent
|
21
24
|
|
22
25
|
def createFleet(self, vin: str) -> VehicleFleet:
|
23
26
|
"""Creates a Fleet API vehicle."""
|
24
|
-
vehicle =
|
27
|
+
vehicle = self.Fleet(self._parent, vin)
|
25
28
|
self[vin] = vehicle
|
26
29
|
return vehicle
|
27
30
|
|
28
31
|
def createSigned(self, vin: str) -> VehicleSigned:
|
29
32
|
"""Creates a Fleet API vehicle that uses command protocol."""
|
30
|
-
vehicle =
|
33
|
+
vehicle = self.Signed(self._parent, vin)
|
31
34
|
self[vin] = vehicle
|
32
35
|
return vehicle
|
33
36
|
|
34
37
|
def createBluetooth(self, vin: str):
|
35
38
|
"""Creates a bluetooth vehicle that uses command protocol."""
|
36
|
-
vehicle =
|
39
|
+
vehicle = self.Bluetooth(self._parent, vin)
|
37
40
|
self[vin] = vehicle
|
38
41
|
return vehicle
|
39
42
|
|
@@ -5,7 +5,7 @@ import aiohttp
|
|
5
5
|
from tesla_fleet_api.tesla.charging import Charging
|
6
6
|
from tesla_fleet_api.tesla.energysite import EnergySites
|
7
7
|
from tesla_fleet_api.tesla.user import User
|
8
|
-
from tesla_fleet_api.teslemetry.
|
8
|
+
from tesla_fleet_api.teslemetry.vehicles import TeslemetryVehicles
|
9
9
|
from tesla_fleet_api.const import LOGGER, Method
|
10
10
|
from tesla_fleet_api.tesla import TeslaFleetApi
|
11
11
|
|
@@ -26,7 +26,7 @@ class Teslemetry(TeslaFleetApi):
|
|
26
26
|
self.charging = Charging(self)
|
27
27
|
self.energySites = EnergySites(self)
|
28
28
|
self.user = User(self)
|
29
|
-
self.
|
29
|
+
self.vehicles = TeslemetryVehicles(self)
|
30
30
|
|
31
31
|
async def ping(self) -> dict[str, bool]:
|
32
32
|
"""Send a ping."""
|
@@ -52,13 +52,15 @@ class TeslemetryVehicleFleet(VehicleFleet):
|
|
52
52
|
class TeslemetryVehicles(Vehicles):
|
53
53
|
"""Class containing and creating vehicles."""
|
54
54
|
|
55
|
+
Fleet = TeslemetryVehicleFleet
|
56
|
+
|
55
57
|
def create(self, vin: str) -> TeslemetryVehicleFleet:
|
56
58
|
"""Creates a specific vehicle."""
|
57
59
|
return self.createFleet(vin)
|
58
60
|
|
59
61
|
def createFleet(self, vin: str) -> TeslemetryVehicleFleet:
|
60
62
|
"""Creates a specific vehicle."""
|
61
|
-
vehicle =
|
63
|
+
vehicle = self.Fleet(self._parent, vin)
|
62
64
|
self[vin] = vehicle
|
63
65
|
return vehicle
|
64
66
|
|
tesla_fleet_api/tessie/tessie.py
CHANGED
@@ -6,7 +6,7 @@ from tesla_fleet_api.tesla.energysite import EnergySites
|
|
6
6
|
from tesla_fleet_api.tesla.user import User
|
7
7
|
from tesla_fleet_api.tesla import TeslaFleetApi
|
8
8
|
from tesla_fleet_api.const import Method
|
9
|
-
from tesla_fleet_api.tessie.
|
9
|
+
from tesla_fleet_api.tessie.vehicles import TessieVehicles
|
10
10
|
|
11
11
|
class Tessie(TeslaFleetApi):
|
12
12
|
|
@@ -25,7 +25,7 @@ class Tessie(TeslaFleetApi):
|
|
25
25
|
self.charging = Charging(self)
|
26
26
|
self.energySites = EnergySites(self)
|
27
27
|
self.user = User(self)
|
28
|
-
self.
|
28
|
+
self.vehicles = TessieVehicles(self)
|
29
29
|
|
30
30
|
async def scopes(self) -> list[str]:
|
31
31
|
"""Get user scopes."""
|
@@ -16,13 +16,15 @@ class TessieVehicleFleet(VehicleFleet):
|
|
16
16
|
class TessieVehicles(Vehicles):
|
17
17
|
"""Class containing and creating vehicles."""
|
18
18
|
|
19
|
+
Fleet = TessieVehicleFleet
|
20
|
+
|
19
21
|
def create(self, vin: str) -> TessieVehicleFleet:
|
20
22
|
"""Creates a specific vehicle."""
|
21
23
|
return self.createFleet(vin)
|
22
24
|
|
23
25
|
def createFleet(self, vin: str) -> TessieVehicleFleet:
|
24
26
|
"""Creates a specific vehicle."""
|
25
|
-
vehicle =
|
27
|
+
vehicle = self.Fleet(self._parent, vin)
|
26
28
|
self[vin] = vehicle
|
27
29
|
return vehicle
|
28
30
|
|
@@ -1,23 +1,23 @@
|
|
1
1
|
tesla_fleet_api/__init__.py,sha256=3DZMoZ-5srW-7SooAjqcRubQDuZPY8rMKH7eqIp4qtg,392
|
2
|
-
tesla_fleet_api/const.py,sha256=
|
3
|
-
tesla_fleet_api/exceptions.py,sha256=
|
2
|
+
tesla_fleet_api/const.py,sha256=XNOVuX2Vgu-qwbITC5ujSY8cohtFpC-M3pg39Auhv0Y,3748
|
3
|
+
tesla_fleet_api/exceptions.py,sha256=iZJv_6YJO6wK_lYvR18SugpNk-ZTzElmcsOqNqd05M0,35495
|
4
4
|
tesla_fleet_api/ratecalculator.py,sha256=4lz8yruUeouHXh_3ezsXX-CTpIegp1T1J4VuRV_qdHA,1791
|
5
5
|
tesla_fleet_api/tesla/__init__.py,sha256=Cvpqu8OaOFmbuwu9KjgYrje8eVluDp2IU_zwdtXbmO0,282
|
6
6
|
tesla_fleet_api/tesla/bluetooth.py,sha256=WhDo66OEwCGhvsGskvWcGUiNv6eyFsdEiQdIm571jQM,1835
|
7
7
|
tesla_fleet_api/tesla/charging.py,sha256=D7I7cAf-3-95sIjyP6wpVqCq9Cppj6U-VPFQGpQQ8bs,1704
|
8
|
-
tesla_fleet_api/tesla/energysite.py,sha256=
|
8
|
+
tesla_fleet_api/tesla/energysite.py,sha256=vStffklBQfQNAO_1wrHLFu7BlBCTVVbLh7_IrAUL3wg,6131
|
9
9
|
tesla_fleet_api/tesla/fleet.py,sha256=X74tzwGO9w65j9YUGuW04CwG7Bx6biEHwxIjWGCzB4c,5670
|
10
10
|
tesla_fleet_api/tesla/oauth.py,sha256=aWBsWmnM-QxzaU8W9TXVNxGsYn_LraXnpexwdE8wOqo,4104
|
11
11
|
tesla_fleet_api/tesla/partner.py,sha256=e-l6sEP6-IupjFEQieSUjhhvRXF3aL4ebPNahcGFRCE,1238
|
12
12
|
tesla_fleet_api/tesla/tesla.py,sha256=Jlz90-fM0nJbhnQN0k3ukNv59-9KqZZbyQ91IiLIbfo,2010
|
13
13
|
tesla_fleet_api/tesla/user.py,sha256=w8rwiAOIFjuDus8M0RpZ0wucJtw8kYFKtJfYVk7Ekr0,1194
|
14
14
|
tesla_fleet_api/tesla/vehicle/__init__.py,sha256=3A5_wTQHofRShof4pUNOtF78-7lUh62uz2jq2ecnmRY,381
|
15
|
-
tesla_fleet_api/tesla/vehicle/bluetooth.py,sha256=
|
15
|
+
tesla_fleet_api/tesla/vehicle/bluetooth.py,sha256=25UlaAatKxu_NzbG5te5sKHeM9jAufj42LjGJaIKNHg,16476
|
16
16
|
tesla_fleet_api/tesla/vehicle/commands.py,sha256=zgfc2yo1UxEh8ePqSb-4h0UTK0RmpCG_9LZX44CES2c,51268
|
17
17
|
tesla_fleet_api/tesla/vehicle/fleet.py,sha256=K9BVZj6CChJSDSMFroa7Cz0KrsYWj32ILtQumarkLaU,32080
|
18
|
-
tesla_fleet_api/tesla/vehicle/signed.py,sha256=
|
19
|
-
tesla_fleet_api/tesla/vehicle/vehicle.py,sha256=
|
20
|
-
tesla_fleet_api/tesla/vehicle/vehicles.py,sha256=
|
18
|
+
tesla_fleet_api/tesla/vehicle/signed.py,sha256=RUzVnZIfykz3YZW2gaxd1iaN1i8LkLaEoiXrbqZn9kg,1339
|
19
|
+
tesla_fleet_api/tesla/vehicle/vehicle.py,sha256=nIhfn2hGuHJoAj-LiipcZdS4abdrWI6yST2cuE-w23s,810
|
20
|
+
tesla_fleet_api/tesla/vehicle/vehicles.py,sha256=axiH33YRnkYcbQmolbL85PF69SRI_5FA5T10v-cMmBc,1644
|
21
21
|
tesla_fleet_api/tesla/vehicle/proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
tesla_fleet_api/tesla/vehicle/proto/__init__.pyi,sha256=qFXWNIgl71wB260u-XPzaAwWAHL6krw21q-aXnBtop0,252
|
23
23
|
tesla_fleet_api/tesla/vehicle/proto/car_server_pb2.py,sha256=v_eb4NDIkx_ZYPYW29_EFRky5vQ4b2q14gwuQSbouYw,29202
|
@@ -39,13 +39,13 @@ tesla_fleet_api/tesla/vehicle/proto/vcsec_pb2.pyi,sha256=cyK1uyRtDjRVqVlyl5uRQYY
|
|
39
39
|
tesla_fleet_api/tesla/vehicle/proto/vehicle_pb2.py,sha256=bqyFJM-1qZ7W9XKREINhYZx8yXAudmq6W8_Pdfkhbkk,44711
|
40
40
|
tesla_fleet_api/tesla/vehicle/proto/vehicle_pb2.pyi,sha256=sAUW_9aVB8NqJCnhZjXMLfqfePLVZv_7PfSKZKEBaQA,74251
|
41
41
|
tesla_fleet_api/teslemetry/__init__.py,sha256=CX7rMtlTuVvXoH9GkOAkQBTtM13ltuOO6EsGELuzQzY,94
|
42
|
-
tesla_fleet_api/teslemetry/teslemetry.py,sha256=
|
43
|
-
tesla_fleet_api/teslemetry/
|
42
|
+
tesla_fleet_api/teslemetry/teslemetry.py,sha256=wcZOD1GnZ4lwC9LoicuSNbZ3z-ka9I4m1AMZP4LDYCY,3088
|
43
|
+
tesla_fleet_api/teslemetry/vehicles.py,sha256=9nybVg7VHKLa2woMG6fzMmQP6xJIE_jdAdScXytxElI,2209
|
44
44
|
tesla_fleet_api/tessie/__init__.py,sha256=9lhQJaB6X4PObUL9QdaaZYqs2BxiTidu3zmHcBESLVw,78
|
45
|
-
tesla_fleet_api/tessie/tessie.py,sha256=
|
46
|
-
tesla_fleet_api/tessie/
|
47
|
-
tesla_fleet_api-1.0.
|
48
|
-
tesla_fleet_api-1.0.
|
49
|
-
tesla_fleet_api-1.0.
|
50
|
-
tesla_fleet_api-1.0.
|
51
|
-
tesla_fleet_api-1.0.
|
45
|
+
tesla_fleet_api/tessie/tessie.py,sha256=uhg0oOIxpwDvlvdBhKHeF3AGR2PzmdBgzh2-_EkmSq0,2617
|
46
|
+
tesla_fleet_api/tessie/vehicles.py,sha256=gfEatilI_ct-R4CM5xYhrlduqCR9IHlyc56WmJf7v7k,1149
|
47
|
+
tesla_fleet_api-1.0.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
48
|
+
tesla_fleet_api-1.0.6.dist-info/METADATA,sha256=oOKlAjIzVvxG2dAivlECWd6ia-t1EqsHjWrZC7Yu66k,4382
|
49
|
+
tesla_fleet_api-1.0.6.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
50
|
+
tesla_fleet_api-1.0.6.dist-info/top_level.txt,sha256=jeNbog_1saXBFrGpom9WyPWmilxsyP3szL_G7JLWQfM,16
|
51
|
+
tesla_fleet_api-1.0.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|