Skip to content

Commit

Permalink
aioble/server.py: Add data arg for indicate.
Browse files Browse the repository at this point in the history
In micropython/micropython#11239 we added support for passing data to
gatts_indicate (to make it match gatts_notify).

This adds the same to aioble.

Also update the documentation to mention this (and fix some mistakes and
add a few more examples).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <[email protected]>
  • Loading branch information
jimmo committed Oct 4, 2023
1 parent 55d1d23 commit e5ba864
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 13 deletions.
2 changes: 1 addition & 1 deletion micropython/bluetooth/aioble-server/manifest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
metadata(version="0.3.0")
metadata(version="0.4.0")

require("aioble-core")

Expand Down
83 changes: 74 additions & 9 deletions micropython/bluetooth/aioble/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Alternatively, install the `aioble` package, which will install everything.
Usage
-----

Passive scan for nearby devices for 5 seconds: (Observer)
#### Passive scan for nearby devices for 5 seconds: (Observer)

```py
async with aioble.scan(duration_ms=5000) as scanner:
Expand All @@ -87,7 +87,7 @@ async with aioble.scan(duration_ms=5000, interval_us=30000, window_us=30000, act
print(result, result.name(), result.rssi, result.services())
```

Connect to a peripheral device: (Central)
#### Connect to a peripheral device: (Central)

```py
# Either from scan result
Expand All @@ -101,7 +101,7 @@ except asyncio.TimeoutError:
print('Timeout')
```

Register services and wait for connection: (Peripheral, Server)
#### Register services and wait for connection: (Peripheral, Server)

```py
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
Expand All @@ -126,30 +126,95 @@ while True:
print("Connection from", device)
```

Update characteristic value: (Server)
#### Update characteristic value: (Server)

```py
# Write the local value.
temp_char.write(b'data')
```

```py
# Write the local value and notify/indicate subscribers.
temp_char.write(b'data', send_update=True)
```

#### Send notifications: (Server)

temp_char.notify(b'optional data')
```py
# Notify with the current value.
temp_char.notify(connection)
```

await temp_char.indicate(timeout_ms=2000)
```py
# Notify with a custom value.
temp_char.notify(connection, b'optional data')
```

Query the value of a characteristic: (Client)
#### Send indications: (Server)

```py
# Indicate with current value.
await temp_char.indicate(connection, timeout_ms=2000)
```

```py
# Indicate with custom value.
await temp_char.indicate(connection, b'optional data', timeout_ms=2000)
```

This will raise `GattError` if the indication is not acknowledged.

#### Wait for a write from the client: (Server)

```py
# Normal characteristic, returns the connection that did the write.
connection = await char.written(timeout_ms=2000)
```

```py
# Characteristic with capture enabled, also returns the value.
char = Characteristic(..., capture=True)
connection, data = await char.written(timeout_ms=2000)
```

#### Query the value of a characteristic: (Client)

```py
temp_service = await connection.service(_ENV_SENSE_UUID)
temp_char = await temp_service.characteristic(_ENV_SENSE_TEMP_UUID)

data = await temp_char.read(timeout_ms=1000)
```

#### Wait for a notification/indication: (Client)

```py
# Notification
data = await temp_char.notified(timeout_ms=1000)
```

```py
# Indication
data = await temp_char.indicated(timeout_ms=1000)
```

#### Subscribe to a characteristic: (Client)

```py
# Subscribe for notification.
await temp_char.subscribe(notify=True)
while True:
data = await temp_char.notified()
```

Open L2CAP channels: (Listener)
```py
# Subscribe for indication.
await temp_char.subscribe(indicate=True)
while True:
data = await temp_char.indicated()
```

#### Open L2CAP channels: (Listener)

```py
channel = await connection.l2cap_accept(_L2CAP_PSN, _L2CAP_MTU)
Expand All @@ -158,7 +223,7 @@ n = channel.recvinto(buf)
channel.send(b'response')
```

Open L2CAP channels: (Initiator)
#### Open L2CAP channels: (Initiator)

```py
channel = await connection.l2cap_connect(_L2CAP_PSN, _L2CAP_MTU)
Expand Down
4 changes: 2 additions & 2 deletions micropython/bluetooth/aioble/aioble/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def notify(self, connection, data=None):
raise ValueError("Not supported")
ble.gatts_notify(connection._conn_handle, self._value_handle, data)

async def indicate(self, connection, timeout_ms=1000):
async def indicate(self, connection, data=None, timeout_ms=1000):
if not (self.flags & _FLAG_INDICATE):
raise ValueError("Not supported")
if self._indicate_connection is not None:
Expand All @@ -270,7 +270,7 @@ async def indicate(self, connection, timeout_ms=1000):

try:
with connection.timeout(timeout_ms):
ble.gatts_indicate(connection._conn_handle, self._value_handle)
ble.gatts_indicate(connection._conn_handle, self._value_handle, data)
await self._indicate_event.wait()
if self._indicate_status != 0:
raise GattError(self._indicate_status)
Expand Down
2 changes: 1 addition & 1 deletion micropython/bluetooth/aioble/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# code. This allows (for development purposes) all the files to live in the
# one directory.

metadata(version="0.3.1")
metadata(version="0.4.0")

# Default installation gives you everything. Install the individual
# components (or a combination of them) if you want a more minimal install.
Expand Down

0 comments on commit e5ba864

Please sign in to comment.