Skip to content

Commit 46748d2

Browse files
committed
aioble/server.py: Allow BufferedCharacteristic to support all ops.
Previously a BufferedCharacteristic could only be read by the client, where it should have been writeable. This makes it support all ops (read / write / write-with-response, etc). Adds a test to check the max_len and append functionality of BufferedCharacteristic. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent e5ba864 commit 46748d2

File tree

5 files changed

+164
-4
lines changed

5 files changed

+164
-4
lines changed

micropython/bluetooth/aioble-server/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(version="0.4.0")
1+
metadata(version="0.4.1")
22

33
require("aioble-core")
44

micropython/bluetooth/aioble/aioble/server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ def _indicate_done(conn_handle, value_handle, status):
290290

291291

292292
class BufferedCharacteristic(Characteristic):
293-
def __init__(self, service, uuid, max_len=20, append=False):
294-
super().__init__(service, uuid, read=True)
293+
def __init__(self, *args, max_len=20, append=False, **kwargs):
294+
super().__init__(*args, **kwargs)
295295
self._max_len = max_len
296296
self._append = append
297297

micropython/bluetooth/aioble/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# code. This allows (for development purposes) all the files to live in the
44
# one directory.
55

6-
metadata(version="0.4.0")
6+
metadata(version="0.4.1")
77

88
# Default installation gives you everything. Install the individual
99
# components (or a combination of them) if you want a more minimal install.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Test characteristic read/write/notify from both GATTS and GATTC.
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+
CHAR1_UUID = bluetooth.UUID("00000000-1111-2222-3333-444444444444")
18+
CHAR2_UUID = bluetooth.UUID("00000000-1111-2222-3333-555555555555")
19+
CHAR3_UUID = bluetooth.UUID("00000000-1111-2222-3333-666666666666")
20+
21+
22+
# Acting in peripheral role.
23+
async def instance0_task():
24+
service = aioble.Service(SERVICE_UUID)
25+
characteristic1 = aioble.BufferedCharacteristic(service, CHAR1_UUID, write=True)
26+
characteristic2 = aioble.BufferedCharacteristic(service, CHAR2_UUID, write=True, max_len=40)
27+
characteristic3 = aioble.BufferedCharacteristic(
28+
service, CHAR3_UUID, write=True, max_len=80, append=True
29+
)
30+
aioble.register_services(service)
31+
32+
multitest.globals(BDADDR=aioble.config("mac"))
33+
multitest.next()
34+
35+
# Wait for central to connect to us.
36+
print("advertise")
37+
connection = await aioble.advertise(
38+
20_000, adv_data=b"\x02\x01\x06\x04\xffMPY", timeout_ms=TIMEOUT_MS
39+
)
40+
print("connected")
41+
42+
# The first will just see the second write (truncated).
43+
await characteristic1.written(timeout_ms=TIMEOUT_MS)
44+
await characteristic1.written(timeout_ms=TIMEOUT_MS)
45+
print("written", characteristic1.read())
46+
47+
# The second will just see the second write (still truncated because MTU
48+
# exchange hasn't happened).
49+
await characteristic2.written(timeout_ms=TIMEOUT_MS)
50+
await characteristic2.written(timeout_ms=TIMEOUT_MS)
51+
print("written", characteristic2.read())
52+
53+
# MTU exchange should happen here.
54+
55+
# The second will now see the full second write.
56+
await characteristic2.written(timeout_ms=TIMEOUT_MS)
57+
await characteristic2.written(timeout_ms=TIMEOUT_MS)
58+
print("written", characteristic2.read())
59+
60+
# The third will see the two full writes concatenated.
61+
await characteristic3.written(timeout_ms=TIMEOUT_MS)
62+
await characteristic3.written(timeout_ms=TIMEOUT_MS)
63+
print("written", characteristic3.read())
64+
65+
# Wait for the central to disconnect.
66+
await connection.disconnected(timeout_ms=TIMEOUT_MS)
67+
print("disconnected")
68+
69+
70+
def instance0():
71+
try:
72+
asyncio.run(instance0_task())
73+
finally:
74+
aioble.stop()
75+
76+
77+
# Acting in central role.
78+
async def instance1_task():
79+
multitest.next()
80+
81+
# Connect to peripheral and then disconnect.
82+
print("connect")
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+
print("service", service.uuid)
89+
characteristic1 = await service.characteristic(CHAR1_UUID)
90+
print("characteristic1", characteristic1.uuid)
91+
characteristic2 = await service.characteristic(CHAR2_UUID)
92+
print("characteristic2", characteristic2.uuid)
93+
characteristic3 = await service.characteristic(CHAR3_UUID)
94+
print("characteristic3", characteristic3.uuid)
95+
96+
# Write to each characteristic twice, with a long enough value to trigger
97+
# truncation.
98+
print("write1")
99+
await characteristic1.write(
100+
"central1-aaaaaaaaaaaaaaaaaaaaaaaaaaaaa", response=True, timeout_ms=TIMEOUT_MS
101+
)
102+
await characteristic1.write(
103+
"central1-bbbbbbbbbbbbbbbbbbbbbbbbbbbbb", response=True, timeout_ms=TIMEOUT_MS
104+
)
105+
print("write2a")
106+
await characteristic2.write(
107+
"central2a-aaaaaaaaaaaaaaaaaaaaaaaaaaaa", response=True, timeout_ms=TIMEOUT_MS
108+
)
109+
await characteristic2.write(
110+
"central2a-bbbbbbbbbbbbbbbbbbbbbbbbbbbb", response=True, timeout_ms=TIMEOUT_MS
111+
)
112+
print("exchange mtu")
113+
await connection.exchange_mtu(100)
114+
print("write2b")
115+
await characteristic2.write(
116+
"central2b-aaaaaaaaaaaaaaaaaaaaaaaaaaaa", response=True, timeout_ms=TIMEOUT_MS
117+
)
118+
await characteristic2.write(
119+
"central2b-bbbbbbbbbbbbbbbbbbbbbbbbbbbb", response=True, timeout_ms=TIMEOUT_MS
120+
)
121+
print("write3")
122+
await characteristic3.write(
123+
"central3-aaaaaaaaaaaaaaaaaaaaaaaaaaaaa", response=True, timeout_ms=TIMEOUT_MS
124+
)
125+
await characteristic3.write(
126+
"central3-bbbbbbbbbbbbbbbbbbbbbbbbbbbbb", response=True, timeout_ms=TIMEOUT_MS
127+
)
128+
129+
# Disconnect from peripheral.
130+
print("disconnect")
131+
await connection.disconnect(timeout_ms=TIMEOUT_MS)
132+
print("disconnected")
133+
134+
135+
def instance1():
136+
try:
137+
asyncio.run(instance1_task())
138+
finally:
139+
aioble.stop()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--- instance0 ---
2+
advertise
3+
connected
4+
written b'central1-bbbbbbbbbbb'
5+
written b'central2a-bbbbbbbbbb'
6+
written b'central2b-bbbbbbbbbbbbbbbbbbbbbbbbbbbb'
7+
written b'central3-aaaaaaaaaaaaaaaaaaaaaaaaaaaaacentral3-bbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
8+
disconnected
9+
--- instance1 ---
10+
connect
11+
service UUID('a5a5a5a5-ffff-9999-1111-5a5a5a5a5a5a')
12+
characteristic1 UUID('00000000-1111-2222-3333-444444444444')
13+
characteristic2 UUID('00000000-1111-2222-3333-555555555555')
14+
characteristic3 UUID('00000000-1111-2222-3333-666666666666')
15+
write1
16+
write2a
17+
exchange mtu
18+
write2b
19+
write3
20+
disconnect
21+
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