|
9 | 9 | from bleak import BleakClient, BleakScanner |
10 | 10 | from bleak.backends.characteristic import BleakGATTCharacteristic |
11 | 11 | from bleak.backends.device import BLEDevice |
| 12 | +from bleak.exc import BleakError |
12 | 13 | from bleak_retry_connector import MAX_CONNECT_ATTEMPTS, establish_connection |
13 | 14 | from cryptography.hazmat.primitives.asymmetric import ec |
14 | 15 | from google.protobuf.message import DecodeError |
|
17 | 18 | from tesla_fleet_api.exceptions import ( |
18 | 19 | WHITELIST_OPERATION_STATUS, |
19 | 20 | BluetoothTimeout, |
| 21 | + BluetoothTransportError, |
20 | 22 | WhitelistOperationStatus, |
21 | 23 | ) |
22 | 24 | from tesla_fleet_api.tesla.vehicle.commands import Commands |
@@ -174,7 +176,13 @@ def discard_packet(self): |
174 | 176 |
|
175 | 177 |
|
176 | 178 | class VehicleBluetooth(Commands[BluetoothParentT], Generic[BluetoothParentT]): |
177 | | - """Class describing the Tesla Fleet API vehicle endpoints and commands for a specific vehicle with command signing.""" |
| 179 | + """Class describing the Tesla Fleet API vehicle endpoints and commands for a specific vehicle with command signing. |
| 180 | +
|
| 181 | + Callers can catch failures from this class with a single ``TeslaFleetError``: |
| 182 | + connect/write transport failures surface as ``BluetoothTransportError`` and |
| 183 | + a response-wait timeout as ``BluetoothTimeout``, both ``TeslaFleetError`` |
| 184 | + subclasses with the original transport exception chained as their cause. |
| 185 | + """ |
178 | 186 |
|
179 | 187 | ble_name: str |
180 | 188 | device: BLEDevice | None = None |
@@ -239,15 +247,18 @@ async def connect(self, max_attempts: int = MAX_CONNECT_ATTEMPTS) -> None: |
239 | 247 | """Connect to the Tesla BLE device.""" |
240 | 248 | if not self.device: |
241 | 249 | raise ValueError(f"BLEDevice {self.ble_name} has not been found or set") |
242 | | - self.client = await establish_connection( |
243 | | - BleakClient, |
244 | | - self.device, |
245 | | - self.vin, |
246 | | - max_attempts=max_attempts, |
247 | | - # ble_device_callback=self.get_device, |
248 | | - services=[SERVICE_UUID], |
249 | | - ) |
250 | | - await self.client.start_notify(READ_UUID, self._on_notify) |
| 250 | + try: |
| 251 | + self.client = await establish_connection( |
| 252 | + BleakClient, |
| 253 | + self.device, |
| 254 | + self.vin, |
| 255 | + max_attempts=max_attempts, |
| 256 | + # ble_device_callback=self.get_device, |
| 257 | + services=[SERVICE_UUID], |
| 258 | + ) |
| 259 | + await self.client.start_notify(READ_UUID, self._on_notify) |
| 260 | + except BleakError as e: |
| 261 | + raise BluetoothTransportError from e |
251 | 262 |
|
252 | 263 | async def disconnect(self) -> bool: |
253 | 264 | """Disconnect from the Tesla BLE device.""" |
@@ -322,7 +333,10 @@ async def _send( |
322 | 333 |
|
323 | 334 | await self.connect_if_needed() |
324 | 335 | assert self.client is not None |
325 | | - await self.client.write_gatt_char(WRITE_UUID, payload, True) |
| 336 | + try: |
| 337 | + await self.client.write_gatt_char(WRITE_UUID, payload, True) |
| 338 | + except BleakError as e: |
| 339 | + raise BluetoothTransportError from e |
326 | 340 |
|
327 | 341 | # Process the response |
328 | 342 | try: |
|
0 commit comments