Skip to content

Commit d63d821

Browse files
committed
aioble/multitests: Add test for subscription and notification.
This replicates the failure described in #453 (which is fixed by #459. Also adds a test for subscription. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 9169ca6 commit d63d821

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Test notification-specific behavior.
2+
3+
import sys
4+
5+
sys.path.append("")
6+
7+
from micropython import const
8+
import time, machine
9+
10+
import uasyncio as asyncio
11+
import aioble
12+
import bluetooth
13+
14+
TIMEOUT_MS = 5000
15+
16+
SERVICE_UUID = bluetooth.UUID("A5A5A5A5-FFFF-9999-1111-5A5A5A5A5A5A")
17+
CHAR_UUID = bluetooth.UUID("00000000-1111-2222-3333-444444444444")
18+
19+
20+
# Acting in peripheral role.
21+
async def instance0_task():
22+
service = aioble.Service(SERVICE_UUID)
23+
characteristic = aioble.Characteristic(
24+
service, CHAR_UUID, read=True, notify=True
25+
)
26+
aioble.register_services(service)
27+
28+
multitest.globals(BDADDR=aioble.config("mac"))
29+
multitest.next()
30+
31+
# Wait for central to connect to us.
32+
print("advertise")
33+
connection = await aioble.advertise(
34+
20_000, adv_data=b"\x02\x01\x06\x04\xffMPY", timeout_ms=TIMEOUT_MS
35+
)
36+
print("connected")
37+
38+
# Send a subscribed-write (but client isn't subscribed, won't send anything).
39+
multitest.wait("discovery")
40+
await asyncio.sleep_ms(100)
41+
characteristic.write("before-subscribe", send_update=True)
42+
43+
# Send a subscribed-write (now client is subscribed, client should get notified).
44+
multitest.wait("subscribed")
45+
await asyncio.sleep_ms(100)
46+
characteristic.write("after-subscribe", send_update=True)
47+
48+
# Send a subscribed-write (now client is unsubscribed, won't send anything).
49+
multitest.wait("unsubscribed")
50+
await asyncio.sleep_ms(100)
51+
characteristic.write("after-unsubscribe", send_update=True)
52+
53+
# Send 5 direct notifications.
54+
multitest.wait("start-direct")
55+
for i in range(5):
56+
# Send 1 notification each time, except for 3 quick notifications the third time.
57+
# The client should only see the last one.
58+
for j in range(3 if i == 2 else 1):
59+
if j > 0:
60+
await asyncio.sleep_ms(100)
61+
msg = "direct-{}-{}".format(i, j)
62+
print("notify", msg)
63+
characteristic.notify(connection, msg)
64+
65+
# Tell client to wait for notification.
66+
multitest.broadcast("notified")
67+
# Wait until client is ready for next notification.
68+
multitest.wait("next")
69+
70+
# Wait for the central to disconnect.
71+
await connection.disconnected(timeout_ms=TIMEOUT_MS)
72+
print("disconnected")
73+
74+
75+
def instance0():
76+
try:
77+
asyncio.run(instance0_task())
78+
finally:
79+
aioble.stop()
80+
81+
82+
# Acting in central role.
83+
async def instance1_task():
84+
multitest.next()
85+
86+
# Connect to peripheral and then disconnect.
87+
print("connect")
88+
device = aioble.Device(*BDADDR)
89+
connection = await device.connect(timeout_ms=TIMEOUT_MS)
90+
91+
# Discover characteristics.
92+
service = await connection.service(SERVICE_UUID)
93+
print("service", service.uuid)
94+
characteristic = await service.characteristic(CHAR_UUID)
95+
print("characteristic", characteristic.uuid)
96+
97+
98+
# Expect to not receive a notification (not subscribed).
99+
multitest.broadcast("discovery")
100+
try:
101+
await characteristic.notified(timeout_ms=500)
102+
print("fail")
103+
return
104+
except asyncio.TimeoutError:
105+
print("no notification")
106+
107+
# Subscribe and expect a notification.
108+
await characteristic.subscribe(notify=True)
109+
multitest.broadcast("subscribed")
110+
value = await characteristic.notified()
111+
print("notified", value)
112+
113+
# Unsubscribe, and expect not to receive a notification.
114+
await characteristic.subscribe(notify=False)
115+
multitest.broadcast("unsubscribed")
116+
try:
117+
await characteristic.notified(timeout_ms=500)
118+
print("fail")
119+
return
120+
except asyncio.TimeoutError:
121+
print("no notification")
122+
123+
# Receive 5 notifications.
124+
multitest.broadcast("start-direct")
125+
for i in range(5):
126+
multitest.wait("notified")
127+
await asyncio.sleep_ms(200)
128+
value = await characteristic.notified()
129+
print("notified", value)
130+
131+
# Expect that after receiving a notification we don't get another one
132+
# until we broadcast to the server.
133+
try:
134+
value = await characteristic.notified(timeout_ms=100)
135+
print("unexpected notify", value)
136+
except asyncio.TimeoutError:
137+
pass
138+
139+
multitest.broadcast("next")
140+
141+
# Disconnect from peripheral.
142+
print("disconnect")
143+
await connection.disconnect(timeout_ms=TIMEOUT_MS)
144+
print("disconnected")
145+
146+
147+
def instance1():
148+
try:
149+
asyncio.run(instance1_task())
150+
finally:
151+
aioble.stop()
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--- instance0 ---
2+
advertise
3+
connected
4+
notify direct-0-0
5+
notify direct-1-0
6+
notify direct-2-0
7+
notify direct-2-1
8+
notify direct-2-2
9+
notify direct-3-0
10+
notify direct-4-0
11+
disconnected
12+
--- instance1 ---
13+
connect
14+
service UUID('a5a5a5a5-ffff-9999-1111-5a5a5a5a5a5a')
15+
characteristic UUID('00000000-1111-2222-3333-444444444444')
16+
no notification
17+
notified b'after-subscribe'
18+
no notification
19+
notified b'direct-0-0'
20+
notified b'direct-1-0'
21+
notified b'direct-2-2'
22+
notified b'direct-3-0'
23+
notified b'direct-4-0'
24+
disconnect
25+
disconnected

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy