Skip to content

micropython/aioble: Place multiple UUIDs in single advertisement LTV. - #787

Merged
dpgeorge merged 1 commit into
micropython:masterfrom
xyzzy42:trent/adv-combine-uuids
May 24, 2024
Merged

dpgeorge merged 1 commit into
micropython:masterfrom
xyzzy42:trent/adv-combine-uuids

Conversation

@xyzzy42

@xyzzy42 xyzzy42 commented Jan 10, 2024

Copy link
Copy Markdown
Contributor

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.

@xyzzy42
xyzzy42 force-pushed the trent/adv-combine-uuids branch 2 times, most recently from 419c6ff to 1a6902b Compare January 10, 2024 23:04
@dpgeorge

Copy link
Copy Markdown
Member

Thanks for the contribution. What you've done here looks correct, according to the BT Core Supplement.

A few points:

  • Prior to this change, if the user specifies a list of services then the order in which they specify them is the order they appear in the advertising data. With this change, 16-bit services appear first, then 32-bit, then 128-bit. That probably doesn't matter but worth discussing.
  • The aioble central logic will need to change to be compatible with the fix in this PR. The central code currently assumes that a service field contains exactly one service, and that will have to be extended to support 0 or more services per field (the spec apparently allows a zero length payload in the service field, to indicate no services of this size are available on this peripheral).

@xyzzy42

xyzzy42 commented May 24, 2024

Copy link
Copy Markdown
Contributor Author

I chose the order of increasing size so as to pack the most services possible into the available space. I thought that would be the best result, if there are more services advertised than fit in the available space. If someone is concerned about exactly what services are advertised, then they should probably not try to advertise more than can fit in the packet, in which case the order should not matter.

As I understand it, the aioble central logic is decoding the advertisement data from any other BLE device. The fact that it can't decode BT spec compliant data is a bug that should be triggered already by existing devices, regardless of whether aioble peripherals generate spec compliant advertising data or not.

@dpgeorge

Copy link
Copy Markdown
Member

I chose the order of increasing size so as to pack the most services possible into the available space. I thought that would be the best result, if there are more services advertised than fit in the available space.

Yes, that makes sense.

If someone is concerned about exactly what services are advertised, then they should probably not try to advertise more than can fit in the packet, in which case the order should not matter.

If needed the user can specify the exact byte format of the advertising/response data, so they do have full control over it if needed.

As I understand it, the aioble central logic is decoding the advertisement data from any other BLE device. The fact that it can't decode BT spec compliant data is a bug that should be triggered already by existing devices,

Yes you are correct, fixing the central can be done separately.

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 <tpiepho@gmail.com>
@dpgeorge

Copy link
Copy Markdown
Member

See #863 for the corresponding fix on the central side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants