diff --git a/transports/__init__.py b/transports/__init__.py new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/transports/__init__.py differ diff --git a/transports/ble.py b/transports/ble.py new file mode 100644 index 0000000..fe089bf --- /dev/null +++ b/transports/ble.py @@ -0,0 +1,52 @@ +import asyncio +from bleak import BleakClient + +RACE_SERVICE_UUID = "00001200-0000-1000-8000-00805f9b34fb" +RACE_TX_UUID = "00001201-0000-1000-8000-00805f9b34fb" +RACE_RX_UUID = "00001202-0000-1000-8000-00805f9b34fb" + +class BLETransport: + def __init__(self, address: str): + self.address = address + self.client = None + self.tx_char = None + self.rx_char = None + self.response_queue = asyncio.Queue() + + async def connect(self): + self.client = BleakClient(self.address) + await self.client.connect() + + for service in self.client.services: + if service.uuid.lower() == RACE_SERVICE_UUID.lower(): + for char in service.characteristics: + if char.uuid.lower() == RACE_TX_UUID.lower(): + self.tx_char = char + if char.uuid.lower() == RACE_RX_UUID.lower(): + self.rx_char = char + + if not self.tx_char: + raise Exception("RACE TX characteristic not found") + + if self.rx_char: + await self.client.start_notify(self.rx_char, self._notification_handler) + + return True + + def _notification_handler(self, sender, data): + self.response_queue.put_nowait(data) + + async def send_command(self, cmd: int, payload: bytes = b'') -> bytes: + from utils.packet import build_race_packet + packet = build_race_packet(cmd, payload) + await self.client.write_gatt_char(self.tx_char, packet, response=True) + + try: + response = await asyncio.wait_for(self.response_queue.get(), timeout=5.0) + return response + except asyncio.TimeoutError: + raise TimeoutError("No RACE response") + + async def disconnect(self): + if self.client: + await self.client.disconnect()