Skip to content

Commit 0e0bf0b

Browse files
committed
ble/lwp3: add AdvertisementData
This adds data structures for parsing manufacturer-specific advertising data according the the LWP3 protocol.
1 parent 0dd7836 commit 0e0bf0b

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
- Added ``ble.lpw3.AdvertisementData`` class.
11+
- Added ``ble.lpw3.BootloaderAdvertisementData`` class.
12+
913
## [1.0.0-alpha.21] - 2022-01-12
1014

1115
### Changed

pybricksdev/ble/lwp3/__init__.py

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# SPDX-License-Identifier: MIT
2-
# Copyright (c) 2021 The Pybricks Authors
2+
# Copyright (c) 2021-2022 The Pybricks Authors
33

44
"""This module and its submodules are used for Bluetooth Low Energy
55
communications with devices that provide the LEGO Wireless Protocol v3.
66
"""
77

88
from enum import IntEnum
99

10+
from .bytecodes import Capabilities, HubKind, LastNetwork, Status, Version
11+
1012
# LEGO Wireless Protocol v3 is defined at:
1113
# https://lego.github.io/lego-ble-wireless-protocol-docs/
1214

@@ -105,3 +107,91 @@ class BootloaderError(IntEnum):
105107

106108
UNKNOWN_COMMAND = 0x05
107109
"""The command was not recognized."""
110+
111+
112+
class BootloaderAdvertisementData:
113+
"""
114+
The 6-byte manufacturer-specific advertisement data sent when a hub in
115+
bootloader mode is advertising.
116+
"""
117+
118+
def __init__(self, data: bytes) -> None:
119+
if len(data) != 6:
120+
raise ValueError("expecting 6 bytes of data")
121+
122+
self._data = data
123+
124+
def __bytes__(self) -> bytes:
125+
return self._data
126+
127+
@property
128+
def version(self) -> Version:
129+
"""
130+
Gets the bootloader software version.
131+
"""
132+
return Version(int.from_bytes(self._data[:4], "little"))
133+
134+
@property
135+
def hub_kind(self) -> HubKind:
136+
"""
137+
Gets the hub type identifier.
138+
"""
139+
return HubKind(self._data[4])
140+
141+
@property
142+
def hub_capabilities(self) -> Capabilities:
143+
"""
144+
Gets the hub capability flags.
145+
"""
146+
return Capabilities(self._data[5])
147+
148+
149+
class AdvertisementData:
150+
"""
151+
The 6-byte manufacturer-specific advertisement data sent when a hub running
152+
official LEGO firmware is advertising.
153+
"""
154+
155+
def __init__(self, data: bytes) -> None:
156+
if len(data) != 6:
157+
raise ValueError("expecting 6 bytes of data")
158+
159+
self._data = data
160+
161+
def __bytes__(self) -> bytes:
162+
return self._data
163+
164+
@property
165+
def is_button_pressed(self) -> bool:
166+
"""
167+
Gets the state of the button on the hub.
168+
"""
169+
return bool(self._data[0])
170+
171+
@property
172+
def hub_kind(self) -> HubKind:
173+
"""
174+
Gets the hub type identifier.
175+
"""
176+
return HubKind(self._data[1])
177+
178+
@property
179+
def hub_capabilities(self) -> Capabilities:
180+
"""
181+
Gets the hub capability flags.
182+
"""
183+
return Capabilities(self._data[2])
184+
185+
@property
186+
def last_network(self) -> LastNetwork:
187+
"""
188+
Gets the ID of the last network the hub was connected to.
189+
"""
190+
return LastNetwork(self._data[3])
191+
192+
@property
193+
def status(self) -> Status:
194+
"""
195+
Gets the status of the advertising hub.
196+
"""
197+
return Status(self._data[4])

tests/ble/test_lwp3.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
LWP3_BOOTLOADER_SERVICE_UUID,
44
LWP3_HUB_CHARACTERISTIC_UUID,
55
LWP3_HUB_SERVICE_UUID,
6+
AdvertisementData,
7+
BootloaderAdvertisementData,
68
)
9+
from pybricksdev.ble.lwp3.bytecodes import Capabilities, HubKind, LastNetwork, Status
710

811

912
def test_lwp3_hub_service_uuid():
@@ -20,3 +23,19 @@ def test_lwp3_bootloader_service_uuid():
2023

2124
def test_lwp3_bootloader_characteristic_uuid():
2225
assert LWP3_BOOTLOADER_CHARACTERISTIC_UUID == "00001626-1212-efde-1623-785feabcd123"
26+
27+
28+
def test_bootloader_advertisement_data():
29+
adv = BootloaderAdvertisementData(b"\x78\x56\x34\x12\x40\x02")
30+
assert adv.version == 0x12345678
31+
assert adv.hub_kind == HubKind.BOOST
32+
assert adv.hub_capabilities == Capabilities.PERIPHERAL
33+
34+
35+
def test_advertisement_data():
36+
adv = AdvertisementData(b"\x01\x40\x02\x05\x03\x00")
37+
assert adv.is_button_pressed
38+
assert adv.hub_kind == HubKind.BOOST
39+
assert adv.hub_capabilities == Capabilities.PERIPHERAL
40+
assert adv.last_network == LastNetwork(5)
41+
assert adv.status == Status.PERIPHERAL | Status.CENTRAL

0 commit comments

Comments
 (0)