From 1a6902b2f2c804d2efe1903dea04e5f8347601be Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 10 Jan 2024 13:40:24 -0800 Subject: [PATCH] aioble/peripheral.py: Place multiple UUIDs in single advertisement LTV. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When multiple UUIDs of the same size are advertised, they should all be listed in a single LTV. Supplement to the Bluetooth Core Specification, Part A, ยง1.1.1: "A packet or data block shall not contain more than one instance for each Service UUID data size." When aioble construct the advertisement data, it is creating a new data block for each UUID that contains only that single UUID. Rather than, e.g., a single 16-bit UUID block with a list of multiple UUIDs. Not only is this against the specification, it wastes two bytes of limited advertisement space per UUID beyond the first for the repeated data block length and type fields. Fix this by grouping each UUID size together. Signed-off-by: Trent Piepho --- micropython/bluetooth/aioble/aioble/peripheral.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/micropython/bluetooth/aioble/aioble/peripheral.py b/micropython/bluetooth/aioble/aioble/peripheral.py index 099f2c55..a156ccd2 100644 --- a/micropython/bluetooth/aioble/aioble/peripheral.py +++ b/micropython/bluetooth/aioble/aioble/peripheral.py @@ -129,14 +129,13 @@ async def advertise( # Services are prioritised to go in the advertising data because iOS supports # filtering scan results by service only, so services must come first. if services: - for uuid in services: - b = bytes(uuid) - if len(b) == 2: - resp_data = _append(adv_data, resp_data, _ADV_TYPE_UUID16_COMPLETE, b) - elif len(b) == 4: - resp_data = _append(adv_data, resp_data, _ADV_TYPE_UUID32_COMPLETE, b) - elif len(b) == 16: - resp_data = _append(adv_data, resp_data, _ADV_TYPE_UUID128_COMPLETE, b) + for uuid_len, code in ( + (2, _ADV_TYPE_UUID16_COMPLETE), + (4, _ADV_TYPE_UUID32_COMPLETE), + (16, _ADV_TYPE_UUID128_COMPLETE), + ): + if uuids := [bytes(uuid) for uuid in services if len(bytes(uuid)) == uuid_len]: + resp_data = _append(adv_data, resp_data, code, b"".join(uuids)) if name: resp_data = _append(adv_data, resp_data, _ADV_TYPE_NAME, name)