Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
May 24, 2024

Conversation

xyzzy42
Copy link
Contributor

@xyzzy42 xyzzy42 commented Jan 10, 2024

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
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
Copy link
Contributor Author

xyzzy42 commented May 24, 2024

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
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 dpgeorge merged commit e5389eb into micropython:master May 24, 2024
3 checks passed
@dpgeorge
Copy link
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.

None yet

2 participants