tesla-fleet-api 1.0.4__py3-none-any.whl → 1.0.5__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 CHANGED
@@ -3,7 +3,7 @@
3
3
  from enum import Enum
4
4
  import logging
5
5
 
6
- VERSION = "1.0.4"
6
+ VERSION = "1.0.5"
7
7
  LOGGER = logging.getLogger(__package__)
8
8
  SERVERS = {
9
9
  "na": "https://fleet-api.prd.na.vn.cloud.tesla.com",
@@ -21,7 +21,6 @@ class ResponseError(TeslaFleetError):
21
21
  """The response from the server was not JSON."""
22
22
 
23
23
  message = "The response from the server was not JSON."
24
- data: str | None = None
25
24
 
26
25
 
27
26
  class InvalidCommand(TeslaFleetError):
@@ -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] = EnergySite(self._parent, 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
- self.client = await establish_connection(BleakClient, self.device, self.vin, max_attempts=max_attempts, ble_device_callback=self.get_device)
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
- LOGGER.debug(f"Received {len(self._recv)} of {self._recv_len} bytes")
145
- while len(self._recv) > self._recv_len:
146
- LOGGER.warn(f"Received more data than expected: {len(self._recv)} > {self._recv_len}")
147
- await self._on_message(bytes(self._recv[:self._recv_len]))
148
- self._recv_len = int.from_bytes(self._recv[self._recv_len:self._recv_len+2], 'big')
149
- self._recv = self._recv[self._recv_len+2:]
150
- continue
151
- if len(self._recv) == self._recv_len:
152
- await self._on_message(bytes(self._recv))
153
- self._recv = bytearray()
154
- self._recv_len = 0
155
-
156
- async def _on_message(self, data:bytes) -> None:
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.info(f"Received response: {msg}")
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(10):
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
- def pre2021(self, vin: str) -> bool:
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 = VehicleFleet(self._parent, vin)
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 = VehicleSigned(self._parent, vin)
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 = VehicleBluetooth(self._parent, vin)
39
+ vehicle = self.Bluetooth(self._parent, vin)
37
40
  self[vin] = vehicle
38
41
  return vehicle
39
42
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tesla_fleet_api
3
- Version: 1.0.4
3
+ Version: 1.0.5
4
4
  Summary: Tesla Fleet API library for Python
5
5
  Home-page: https://github.com/Teslemetry/python-tesla-fleet-api
6
6
  Author: Brett Adams
@@ -1,23 +1,23 @@
1
1
  tesla_fleet_api/__init__.py,sha256=3DZMoZ-5srW-7SooAjqcRubQDuZPY8rMKH7eqIp4qtg,392
2
- tesla_fleet_api/const.py,sha256=HK5PibaarH3CjrtN2Ma-xytZyhkpTdlbQ8rpVbL9DDo,3748
3
- tesla_fleet_api/exceptions.py,sha256=1EkMnDxQYxZBn4ApjGodIBZyNPu9oa_Pgpdl6lQQ5gk,35523
2
+ tesla_fleet_api/const.py,sha256=1GEFPEYxka-ADBs_MWNaxdr2FPH7ObxaKRX2NvFrGaY,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=96Q5npsJ2YIa257o_NL5_3gJNUS-ioAL7sTeQeGPgAM,6110
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=tEbuUMjG3PfDLc1s1ACg-3zdnF-lSwDsH1U5tg5qbRI,15746
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=ggdtq8PydKoCk044L5b2262nfNzZqPBnsJ4SonTFbb4,1539
19
- tesla_fleet_api/tesla/vehicle/vehicle.py,sha256=TyW5-LRlgRulWsm2indE3utSTdrJJRfG7H45Cc-ZASk,505
20
- tesla_fleet_api/tesla/vehicle/vehicles.py,sha256=wyMLfHNK_QaNTDtU9mkGRl2fB3Gb6lvmSfcgXzKu7WY,1565
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
@@ -44,8 +44,8 @@ tesla_fleet_api/teslemetry/vehicle.py,sha256=9_2N1iNNDouqfb6YBBWAFjnlzVRTf5frhXi
44
44
  tesla_fleet_api/tessie/__init__.py,sha256=9lhQJaB6X4PObUL9QdaaZYqs2BxiTidu3zmHcBESLVw,78
45
45
  tesla_fleet_api/tessie/tessie.py,sha256=qdMZ61TcQi5JRuv2qaxuLHtOuy8WZJ1WNqWg5WDAwwU,2615
46
46
  tesla_fleet_api/tessie/vehicle.py,sha256=9khv4oCkGGLxHzQ2FYhDPH7wczxEDiUppsDXalawarE,1125
47
- tesla_fleet_api-1.0.4.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
48
- tesla_fleet_api-1.0.4.dist-info/METADATA,sha256=KxQg4FAxCoWBheKhRSo104TIDTtcswTz-LhgFN7UAUo,4382
49
- tesla_fleet_api-1.0.4.dist-info/WHEEL,sha256=nn6H5-ilmfVryoAQl3ZQ2l8SH5imPWFpm1A5FgEuFV4,91
50
- tesla_fleet_api-1.0.4.dist-info/top_level.txt,sha256=jeNbog_1saXBFrGpom9WyPWmilxsyP3szL_G7JLWQfM,16
51
- tesla_fleet_api-1.0.4.dist-info/RECORD,,
47
+ tesla_fleet_api-1.0.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
48
+ tesla_fleet_api-1.0.5.dist-info/METADATA,sha256=nL7RUQYO8-i8R0-zkSQBNvJD7BtruTEkNxywMB5lsT4,4382
49
+ tesla_fleet_api-1.0.5.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
50
+ tesla_fleet_api-1.0.5.dist-info/top_level.txt,sha256=jeNbog_1saXBFrGpom9WyPWmilxsyP3szL_G7JLWQfM,16
51
+ tesla_fleet_api-1.0.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.1)
2
+ Generator: setuptools (75.8.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5