Skip to content

Commit ef6e8bb

Browse files
committed
aioble/multitests: Add re-registration multitest.
Test that singleton service/characteristic instances can be re-registered across multiple stop/start cycles without data loss. Verifies initial= values persist and writable characteristics accept cycle-specific values after each re-registration. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent e9b5a79 commit ef6e8bb

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Test that singleton service/characteristic instances can be re-registered
2+
# across multiple stop/start cycles without data loss.
3+
4+
import sys
5+
6+
# ruff: noqa: E402
7+
sys.path.append("")
8+
9+
from micropython import const
10+
import machine
11+
import time
12+
13+
import asyncio
14+
import aioble
15+
import bluetooth
16+
17+
TIMEOUT_MS = 5000
18+
19+
SERVICE_UUID = bluetooth.UUID("A5A5A5A5-FFFF-9999-1111-5A5A5A5A5A5A")
20+
CHAR_INITIAL_UUID = bluetooth.UUID("00000000-1111-2222-3333-444444444444")
21+
CHAR_WRITE_UUID = bluetooth.UUID("00000000-1111-2222-3333-555555555555")
22+
23+
24+
# Acting in peripheral role.
25+
async def instance0_task():
26+
# Create service and characteristics ONCE (singleton pattern).
27+
service = aioble.Service(SERVICE_UUID)
28+
aioble.Characteristic(service, CHAR_INITIAL_UUID, read=True, initial=b"hello")
29+
char_write = aioble.Characteristic(
30+
service, CHAR_WRITE_UUID, read=True, write=True
31+
)
32+
33+
multitest.globals(BDADDR=aioble.config("mac"))
34+
multitest.next()
35+
36+
for i in range(3):
37+
# Re-register the same service instances.
38+
aioble.register_services(service)
39+
40+
# Write a cycle-specific value to the writable characteristic.
41+
char_write.write("periph{}".format(i))
42+
43+
multitest.broadcast("connect-{}".format(i))
44+
45+
# Wait for central to connect.
46+
print("advertise", i)
47+
connection = await aioble.advertise(
48+
20_000, adv_data=b"\x02\x01\x06\x04\xffMPY", timeout_ms=TIMEOUT_MS
49+
)
50+
print("connected", i)
51+
52+
# Wait for the central to write.
53+
await char_write.written(timeout_ms=TIMEOUT_MS)
54+
print("written", i)
55+
56+
# Wait for the central to disconnect.
57+
await connection.disconnected(timeout_ms=TIMEOUT_MS)
58+
print("disconnected", i)
59+
60+
# Shutdown aioble.
61+
print("shutdown", i)
62+
aioble.stop()
63+
64+
await asyncio.sleep_ms(100)
65+
66+
67+
def instance0():
68+
try:
69+
asyncio.run(instance0_task())
70+
finally:
71+
aioble.stop()
72+
73+
74+
# Acting in central role.
75+
async def instance1_task():
76+
multitest.next()
77+
78+
for i in range(3):
79+
multitest.wait("connect-{}".format(i))
80+
81+
# Connect to peripheral.
82+
print("connect", i)
83+
device = aioble.Device(*BDADDR)
84+
connection = await device.connect(timeout_ms=TIMEOUT_MS)
85+
86+
# Discover characteristics.
87+
service = await connection.service(SERVICE_UUID)
88+
char_initial = await service.characteristic(CHAR_INITIAL_UUID)
89+
char_write = await service.characteristic(CHAR_WRITE_UUID)
90+
91+
# Read the initial= characteristic — must be the same every cycle.
92+
print("read initial", await char_initial.read(timeout_ms=TIMEOUT_MS))
93+
94+
# Read the writable characteristic — should have cycle-specific value.
95+
print("read written", await char_write.read(timeout_ms=TIMEOUT_MS))
96+
97+
# Write to the writable characteristic.
98+
print("write", i)
99+
await char_write.write("central{}".format(i), response=True, timeout_ms=TIMEOUT_MS)
100+
101+
# Disconnect from peripheral.
102+
print("disconnect", i)
103+
await connection.disconnect(timeout_ms=TIMEOUT_MS)
104+
print("disconnected", i)
105+
106+
# Shutdown aioble.
107+
aioble.stop()
108+
109+
await asyncio.sleep_ms(100)
110+
111+
112+
def instance1():
113+
try:
114+
asyncio.run(instance1_task())
115+
finally:
116+
aioble.stop()

0 commit comments

Comments
 (0)