Skip to content

Commit 6e774a6

Browse files
committed
tutorials/wireless/hub-to-device/pc-communications: improve demo
- Remove extraneous Bleak code. - Add synchronization between hub program and pc program. - Handle case when device is not found. - Handle early hub disconnection.
1 parent 8f17408 commit 6e774a6

File tree

2 files changed

+47
-32
lines changed

2 files changed

+47
-32
lines changed
Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# SPDX-License-Identifier: MIT
22
# Copyright (c) 2020 Henrik Blidh
3-
# Copyright (c) 2022 The Pybricks Authors
3+
# Copyright (c) 2022-2023 The Pybricks Authors
44

55
import asyncio
6+
from contextlib import suppress
67
from bleak import BleakScanner, BleakClient
78

89
UART_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
@@ -14,54 +15,68 @@
1415
HUB_NAME = "Pybricks Hub"
1516

1617

17-
def hub_filter(device, ad):
18-
return device.name and device.name.lower() == HUB_NAME.lower()
18+
async def main():
19+
main_task = asyncio.current_task()
1920

21+
def handle_disconnect(_):
22+
print("Hub was disconnected.")
2023

21-
def handle_disconnect(_):
22-
print("Hub was disconnected.")
24+
# If the hub disconnects before this program is done,
25+
# cancel this program so it doesn't get stuck waiting
26+
# forever.
27+
if not main_task.done():
28+
main_task.cancel()
2329

30+
ready_event = asyncio.Event()
2431

25-
def handle_rx(_, data: bytearray):
26-
print("Received:", data)
32+
def handle_rx(_, data: bytearray):
33+
if data == b"rdy":
34+
ready_event.set()
35+
else:
36+
print("Received:", data)
2737

38+
# Do a Bluetooth scan to find the hub.
39+
device = await BleakScanner.find_device_by_name(HUB_NAME)
2840

29-
async def main():
30-
# Find the device and initialize client.
31-
device = await BleakScanner.find_device_by_filter(hub_filter)
32-
client = BleakClient(device, disconnected_callback=handle_disconnect)
41+
if device is None:
42+
print(f"could not find hub with name: {HUB_NAME}")
43+
return
3344

34-
# Shorthand for sending some data to the hub.
35-
async def send(client, data):
36-
await client.write_gatt_char(rx_char, data)
45+
# Connect to the hub.
46+
async with BleakClient(device, handle_disconnect) as client:
3747

38-
try:
39-
# Connect and get services.
40-
await client.connect()
48+
# Subscribe to notifications from the hub.
4149
await client.start_notify(UART_TX_CHAR_UUID, handle_rx)
42-
nus = client.services.get_service(UART_SERVICE_UUID)
43-
rx_char = nus.get_characteristic(UART_RX_CHAR_UUID)
50+
51+
# Shorthand for sending some data to the hub.
52+
async def send(data):
53+
# Wait for hub to say that it is ready to receive data.
54+
await ready_event.wait()
55+
# Prepare for the next ready event.
56+
ready_event.clear()
57+
# Send the data to the hub.
58+
await client.write_gatt_char(UART_RX_CHAR_UUID, data)
4459

4560
# Tell user to start program on the hub.
4661
print("Start the program on the hub now with the button.")
4762

4863
# Send a few messages to the hub.
4964
for i in range(5):
50-
await send(client, b"fwd")
65+
await send(b"fwd")
5166
await asyncio.sleep(1)
52-
await send(client, b"rev")
67+
await send(b"rev")
5368
await asyncio.sleep(1)
69+
print(".", end="", flush=True)
5470

5571
# Send a message to indicate stop.
56-
await send(client, b"bye")
72+
await send(b"bye")
73+
74+
print("done.")
5775

58-
except Exception as e:
59-
# Handle exceptions.
60-
print(e)
61-
finally:
62-
# Disconnect when we are done.
63-
await client.disconnect()
76+
# Hub disconnects here when async with block exits.
6477

6578

6679
# Run the main async program.
67-
asyncio.run(main())
80+
if __name__ == "__main__":
81+
with suppress(asyncio.CancelledError):
82+
asyncio.run(main())

tutorials/wireless/hub-to-device/pc-communication/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
while True:
2020

21+
# Let the remote program know we are ready for a command.
22+
stdout.buffer.write(b"rdy")
23+
2124
# Optional: Check available input.
2225
while not keyboard.poll(0):
2326
# Optional: Do something here.
@@ -35,6 +38,3 @@
3538
break
3639
else:
3740
motor.stop()
38-
39-
# Send a response.
40-
stdout.buffer.write(b"OK")

0 commit comments

Comments
 (0)