Skip to content

Commit 0a108d4

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 0a108d4

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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(service, CHAR_WRITE_UUID, read=True, write=True)
30+
31+
multitest.globals(BDADDR=aioble.config("mac"))
32+
multitest.next()
33+
34+
for i in range(3):
35+
# Re-register the same service instances.
36+
aioble.register_services(service)
37+
38+
# Write a cycle-specific value to the writable characteristic.
39+
char_write.write("periph{}".format(i))
40+
41+
multitest.broadcast("connect-{}".format(i))
42+
43+
# Wait for central to connect.
44+
print("advertise", i)
45+
connection = await aioble.advertise(
46+
20_000, adv_data=b"\x02\x01\x06\x04\xffMPY", timeout_ms=TIMEOUT_MS
47+
)
48+
print("connected", i)
49+
50+
# Wait for the central to write.
51+
await char_write.written(timeout_ms=TIMEOUT_MS)
52+
print("written", i)
53+
54+
# Wait for the central to disconnect.
55+
await connection.disconnected(timeout_ms=TIMEOUT_MS)
56+
print("disconnected", i)
57+
58+
# Shutdown aioble.
59+
print("shutdown", i)
60+
aioble.stop()
61+
62+
await asyncio.sleep_ms(100)
63+
64+
65+
def instance0():
66+
try:
67+
asyncio.run(instance0_task())
68+
finally:
69+
aioble.stop()
70+
71+
72+
# Acting in central role.
73+
async def instance1_task():
74+
multitest.next()
75+
76+
for i in range(3):
77+
multitest.wait("connect-{}".format(i))
78+
79+
# Connect to peripheral.
80+
print("connect", i)
81+
device = aioble.Device(*BDADDR)
82+
connection = await device.connect(timeout_ms=TIMEOUT_MS)
83+
84+
# Discover characteristics.
85+
service = await connection.service(SERVICE_UUID)
86+
char_initial = await service.characteristic(CHAR_INITIAL_UUID)
87+
char_write = await service.characteristic(CHAR_WRITE_UUID)
88+
89+
# Read the initial= characteristic — must be the same every cycle.
90+
print("read initial", await char_initial.read(timeout_ms=TIMEOUT_MS))
91+
92+
# Read the writable characteristic — should have cycle-specific value.
93+
print("read written", await char_write.read(timeout_ms=TIMEOUT_MS))
94+
95+
# Write to the writable characteristic.
96+
print("write", i)
97+
await char_write.write("central{}".format(i), response=True, timeout_ms=TIMEOUT_MS)
98+
99+
# Disconnect from peripheral.
100+
print("disconnect", i)
101+
await connection.disconnect(timeout_ms=TIMEOUT_MS)
102+
print("disconnected", i)
103+
104+
# Shutdown aioble.
105+
aioble.stop()
106+
107+
await asyncio.sleep_ms(100)
108+
109+
110+
def instance1():
111+
try:
112+
asyncio.run(instance1_task())
113+
finally:
114+
aioble.stop()

0 commit comments

Comments
 (0)