feat(ble): also scan for the 16-bit FD4B advertisement on 5.0/MG - #1457
feat(ble): also scan for the 16-bit FD4B advertisement on 5.0/MG#1457ryanbr wants to merge 1 commit into
Conversation
A 128-bit UUID often does not fit the 31-byte advertising payload, so a peripheral may advertise the 16-bit SIG member form instead. CoreBluetooth and Android both surface that as its Bluetooth-base expansion 0000FD4B-0000-1000-8000-00805F9B34FB, which does NOT equal the vendor UUID fd4b0001-... So a scan filtered only on the vendor UUID would never see such a strap, and the owner would read it as "NOOP cannot find my 5.0" rather than as a discovery bug. Advertisement-only, deliberately. After connecting, the strap exposes the real 128-bit service in GATT, so retrieveConnectedPeripherals and service discovery keep using the vendor UUID alone - widening those would be wrong, not merely redundant. The new accessor is named for that distinction and the tests pin it, because the natural mistake when reading this change later is to "finish the job" by widening GATT too. UNCONFIRMED against hardware, and worth saying plainly. The 16-bit possibility is a fact re-derived from OpenStrap/edge#255 (Dart; no code taken), which ships the same widening while its own test plan still asks for the nRF Connect capture of primary AD versus scan response that would settle it. Straps do pair with NOOP today, so the vendor UUID demonstrably works at least often; this only removes a way for discovery to fail silently. The change is strictly additive - the vendor UUID stays first in the filter and the 4.0 set is untouched - so the downside is bounded to slightly more scan traffic on the 5/MG path, and there is no case where a strap that pairs today stops pairing. Mirrored tests on both platforms cover the 4.0 set being unchanged, the 5/MG set gaining exactly the base-expanded form, that expansion differing from the vendor UUID, and GATT staying single. Android 4,089 tests / 0 failures; Kotlin compile and doc-comment gates clean.
|
Closing — this cannot work as written, and I should have checked the acceptance path before opening it. Widening the scan filter only changes which peripherals reach if advertised.isEmpty || advertised.contains(selectedServiceUUIDString.lowercased())with Net effect: more scan callbacks, zero additional straps found. Pure cost on a path #477 documents as Making it real would require widening acceptance as well, and that is where it stops being The useful part is the finding, which moves to #1451: NOOP rejects a 16-bit-advertising band at TWO Revisit only if a capture shows the vendor UUID is absent from the primary AD. |

Removes a way for 5.0/MG discovery to fail silently. Unconfirmed against hardware — see the honesty
section, which is the part worth reviewing.
The gap
A 128-bit UUID often does not fit the 31-byte advertising payload, so a peripheral may advertise the
16-bit SIG member form instead. Both CoreBluetooth and Android surface that as its Bluetooth-base
expansion
0000FD4B-0000-1000-8000-00805F9B34FB, which does not equal our vendor UUIDfd4b0001-cce1-4033-93ce-002d5875f58a.Our scans filter on the vendor UUID alone, on both platforms. A strap advertising the 16-bit form would
therefore never appear — and to its owner that reads as "NOOP cannot find my 5.0", not as a discovery
bug worth reporting.
Advertisement-only, deliberately
After connecting, the strap exposes the real 128-bit service in GATT. So
retrieveConnectedPeripheralsand
discoverServiceskeep using the vendor UUID alone — widening those would be wrong, not merelyredundant. The new accessor is named for that distinction (
advertisedScanServices/advertisedScanUuids)and a test pins GATT staying single, because the natural mistake when reading this later is to "finish the
job" by widening service discovery too.
Honesty about the evidence
The 16-bit possibility is a fact re-derived from OpenStrap/edge#255 (Dart; no code taken), which ships
the same widening while its own test plan still asks for the nRF Connect capture of primary AD versus
scan response that would settle it. So neither project has confirmed what a real MG advertises.
Straps do pair with NOOP today, so the vendor UUID demonstrably works at least often. What is unknown is
whether it fails for MG specifically, or on particular firmware.
I would normally want the capture first. What makes this shippable without it is that the change is
strictly additive: the vendor UUID stays first in the filter, the 4.0 set is untouched, and there is
no case where a strap that pairs today stops pairing. The bounded downside is slightly more scan traffic
on the 5/MG path.
Verification
expansion differs from the vendor UUID, GATT stays single
Still worth asking for
An nRF Connect dump of a real MG (primary AD vs scan response) alongside the
rr emitcapture #1451 wants— one volunteer session would close this question for both projects. If it shows the vendor UUID is always
in the primary AD, this can be reverted as unnecessary rather than left as folklore.