Skip to content

Commit 0e20265

Browse files
committed
ble.lwp3.bootloader: add new module
This adds a new ble.lwp3.bootloader module and moves the Bootloader* types there.
1 parent 0e0bf0b commit 0e20265

File tree

8 files changed

+133
-112
lines changed

8 files changed

+133
-112
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
- Added ``ble.lpw3.AdvertisementData`` class.
1111
- Added ``ble.lpw3.BootloaderAdvertisementData`` class.
1212

13+
### Changed
14+
- Moved ``Bootloader*`` to new ``ble.lwp3.bootloader`` module.
15+
1316
## [1.0.0-alpha.21] - 2022-01-12
1417

1518
### Changed

docs/api/ble/lwp3/bootloader.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
Bootloader
3+
==========
4+
5+
.. automodule:: pybricksdev.ble.lwp3.bootloader
6+
:members:
7+
:undoc-members:

docs/api/ble/lwp3/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LEGO Wireless Protocol v3
55
:maxdepth: 1
66
:caption: Additional modules:
77

8+
bootloader
89
bytecodes
910
messages
1011

pybricksdev/ble/lwp3/__init__.py

Lines changed: 3 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# SPDX-License-Identifier: MIT
22
# Copyright (c) 2021-2022 The Pybricks Authors
33

4-
"""This module and its submodules are used for Bluetooth Low Energy
4+
"""
5+
This module and its submodules are used for Bluetooth Low Energy
56
communications with devices that provide the LEGO Wireless Protocol v3.
67
"""
78

8-
from enum import IntEnum
9-
10-
from .bytecodes import Capabilities, HubKind, LastNetwork, Status, Version
9+
from .bytecodes import Capabilities, HubKind, LastNetwork, Status
1110

1211
# LEGO Wireless Protocol v3 is defined at:
1312
# https://lego.github.io/lego-ble-wireless-protocol-docs/
@@ -47,105 +46,6 @@ def _lwp3_uuid(short: int) -> str:
4746
"""LEGO wireless protocol v3 bootloader characteristic UUID."""
4847

4948

50-
# Bootloader characteristic bytecodes
51-
52-
53-
class BootloaderCommand(IntEnum):
54-
"""Commands that are sent to the bootloader GATT characteristic."""
55-
56-
ERASE_FLASH = 0x11
57-
"""Erases the flash memory."""
58-
59-
PROGRAM_FLASH = 0x22
60-
"""Writes to a segment of the flash memory."""
61-
62-
START_APP = 0x33
63-
"""Starts running the firmware (causes Bluetooth to disconnect)."""
64-
65-
INIT_LOADER = 0x44
66-
"""Initializes the firmware flasher."""
67-
68-
GET_INFO = 0x55
69-
"""Gets info about the hub and flash memory layout."""
70-
71-
GET_CHECKSUM = 0x66
72-
"""Gets the current checksum for the data that has been written so far."""
73-
74-
GET_FLASH_STATE = 0x77
75-
"""Gets the STM32 flash memory debug protection state.
76-
77-
Not all bootloaders support this command.
78-
"""
79-
80-
DISCONNECT = 0x88
81-
"""Causes the remote device to disconnect from Bluetooth."""
82-
83-
84-
class BootloaderMessageKind(IntEnum):
85-
"""Type for messages received from bootlaoder GATT characteristic notifications.
86-
87-
Messages that are a response to a command will have the same value as
88-
:class:`BootloaderCommand` instead of a value from this enum.
89-
"""
90-
91-
ERROR = 0x05
92-
"""Indicates that an error occurred."""
93-
94-
95-
class BootloaderResult(IntEnum):
96-
"""Status returned by certain bootloader commands."""
97-
98-
OK = 0x00
99-
"""The command was successful."""
100-
101-
ERROR = 0xFF
102-
"""The command failed."""
103-
104-
105-
class BootloaderError(IntEnum):
106-
"""Error type returned by bootloader error messages."""
107-
108-
UNKNOWN_COMMAND = 0x05
109-
"""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-
14949
class AdvertisementData:
15050
"""
15151
The 6-byte manufacturer-specific advertisement data sent when a hub running

pybricksdev/ble/lwp3/bootloader.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# SPDX-License-Identifier: MIT
2+
# Copyright (c) 2021-2022 The Pybricks Authors
3+
4+
"""
5+
The bootloader module contains the bytecodes and messages for using the separate
6+
LWP3 bootloader service and characteristic for flashing firmware on the hub.
7+
"""
8+
9+
from enum import IntEnum
10+
11+
from .bytecodes import Capabilities, HubKind, Version
12+
13+
# Bootloader characteristic bytecodes
14+
15+
16+
class BootloaderCommand(IntEnum):
17+
"""Commands that are sent to the bootloader GATT characteristic."""
18+
19+
ERASE_FLASH = 0x11
20+
"""Erases the flash memory."""
21+
22+
PROGRAM_FLASH = 0x22
23+
"""Writes to a segment of the flash memory."""
24+
25+
START_APP = 0x33
26+
"""Starts running the firmware (causes Bluetooth to disconnect)."""
27+
28+
INIT_LOADER = 0x44
29+
"""Initializes the firmware flasher."""
30+
31+
GET_INFO = 0x55
32+
"""Gets info about the hub and flash memory layout."""
33+
34+
GET_CHECKSUM = 0x66
35+
"""Gets the current checksum for the data that has been written so far."""
36+
37+
GET_FLASH_STATE = 0x77
38+
"""Gets the STM32 flash memory debug protection state.
39+
40+
Not all bootloaders support this command.
41+
"""
42+
43+
DISCONNECT = 0x88
44+
"""Causes the remote device to disconnect from Bluetooth."""
45+
46+
47+
class BootloaderMessageKind(IntEnum):
48+
"""Type for messages received from bootlaoder GATT characteristic notifications.
49+
50+
Messages that are a response to a command will have the same value as
51+
:class:`BootloaderCommand` instead of a value from this enum.
52+
"""
53+
54+
ERROR = 0x05
55+
"""Indicates that an error occurred."""
56+
57+
58+
class BootloaderResult(IntEnum):
59+
"""Status returned by certain bootloader commands."""
60+
61+
OK = 0x00
62+
"""The command was successful."""
63+
64+
ERROR = 0xFF
65+
"""The command failed."""
66+
67+
68+
class BootloaderError(IntEnum):
69+
"""Error type returned by bootloader error messages."""
70+
71+
UNKNOWN_COMMAND = 0x05
72+
"""The command was not recognized."""
73+
74+
75+
class BootloaderAdvertisementData:
76+
"""
77+
The 6-byte manufacturer-specific advertisement data sent when a hub in
78+
bootloader mode is advertising.
79+
"""
80+
81+
def __init__(self, data: bytes) -> None:
82+
if len(data) != 6:
83+
raise ValueError("expecting 6 bytes of data")
84+
85+
self._data = data
86+
87+
def __bytes__(self) -> bytes:
88+
return self._data
89+
90+
@property
91+
def version(self) -> Version:
92+
"""
93+
Gets the bootloader software version.
94+
"""
95+
return Version(int.from_bytes(self._data[:4], "little"))
96+
97+
@property
98+
def hub_kind(self) -> HubKind:
99+
"""
100+
Gets the hub type identifier.
101+
"""
102+
return HubKind(self._data[4])
103+
104+
@property
105+
def hub_capabilities(self) -> Capabilities:
106+
"""
107+
Gets the hub capability flags.
108+
"""
109+
return Capabilities(self._data[5])

pybricksdev/flash.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from tqdm.contrib.logging import logging_redirect_tqdm
2020

2121
from .ble import BLERequestsConnection
22-
from .ble.lwp3 import BootloaderCommand
22+
from .ble.lwp3.bootloader import BootloaderCommand
2323
from .ble.lwp3.bytecodes import HubKind
2424
from .compile import compile_file, save_script
2525
from .tools.checksum import crc32_checksum, sum_complement

tests/ble/test_lwp3.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
LWP3_HUB_CHARACTERISTIC_UUID,
55
LWP3_HUB_SERVICE_UUID,
66
AdvertisementData,
7-
BootloaderAdvertisementData,
87
)
98
from pybricksdev.ble.lwp3.bytecodes import Capabilities, HubKind, LastNetwork, Status
109

@@ -25,13 +24,6 @@ def test_lwp3_bootloader_characteristic_uuid():
2524
assert LWP3_BOOTLOADER_CHARACTERISTIC_UUID == "00001626-1212-efde-1623-785feabcd123"
2625

2726

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-
3527
def test_advertisement_data():
3628
adv = AdvertisementData(b"\x01\x40\x02\x05\x03\x00")
3729
assert adv.is_button_pressed

tests/ble/test_lwp3_bootloader.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from pybricksdev.ble.lwp3.bootloader import BootloaderAdvertisementData
2+
from pybricksdev.ble.lwp3.bytecodes import Capabilities, HubKind
3+
4+
5+
def test_bootloader_advertisement_data():
6+
adv = BootloaderAdvertisementData(b"\x78\x56\x34\x12\x40\x02")
7+
assert adv.version == 0x12345678
8+
assert adv.hub_kind == HubKind.BOOST
9+
assert adv.hub_capabilities == Capabilities.PERIPHERAL

0 commit comments

Comments
 (0)