Summary
On iOS 18+, OpenStrap pairs exclusively through the AccessorySetupKit (ASK) system sheet. The ASK discovery descriptor matches only the WHOOP 4.0 "Harvard" service UUID 61080001-8D6D-82B8-614A-1C8CB0F8DCC6, and that is the only UUID declared in Info.plist under NSAccessorySetupBluetoothServices.
A WHOOP MG / 5.0 does not advertise that service, so the ASK sheet has nothing to match and shows "No Accessory Found" — regardless of the band being in pairing mode, flashing blue, and plainly visible to the rest of the system.
There is also no fallback: on iOS 18+ the pairing screen short-circuits to the ASK path before the service-filtered scan is ever reached, so a gen5 owner has no route to pairing at all.
Environment
|
|
| Band |
WHOOP MG, serial redacted (advertises as WHOOP MGB…) |
| Phone / OS |
iOS 18+ (AccessorySetupKit path) |
| Edge version |
v0.9.25-whoop5-experimental and earlier whoop5 tags |
| Official WHOOP app |
Force-quit for the whole test |
| Band state |
Pairing mode, LED flashing blue |
Steps to reproduce
- Force-quit the official WHOOP app.
- Put the WHOOP MG on its charger and enter pairing mode (LED flashes solid blue).
- Open OpenStrap → pairing screen → tap "My strap is in pairing mode" → tap Pair.
- The system AccessorySetupKit sheet appears.
Expected
The ASK sheet lists WHOOP MGB… (or a generic "WHOOP band" row) and lets me select it, after which OpenStrap provisions it and connects.
Actual
The ASK sheet stays empty and shows:
No Accessory Found.
Make sure the accessory is nearby and ready to connect.
The band never appears in the sheet, even while flashing blue and even though it is simultaneously listed in Settings → Bluetooth → My Devices as WHOOP MGB… — Connected.
Additional observations
- In iOS Bluetooth Settings the entry frequently has no (i) button, so it cannot be forgotten normally — only a full Reset Network Settings clears it. Worth establishing whether that stale/foreign bond has any effect on ASK discovery, or whether it is a red herring next to the descriptor mismatch below.
- The 4.0 flow on the same phone/build is unaffected.
Where this appears to come from
Reading main at 6bddec4 (pubspec.yaml version 0.9.26+57):
| Location |
What it does |
ios/Runner/AccessorySetup.swift:31 |
whoopServiceUUID hardcoded to the gen4 service only |
ios/Runner/AccessorySetup.swift:148 |
The single ASDiscoveryDescriptor matches only that UUID |
ios/Runner/Info.plist:54-57 |
NSAccessorySetupBluetoothServices declares only that UUID; no NSAccessorySetupBluetoothNames |
lib/ui/pairing_screen.dart:217-222 |
On iOS 18+ the screen returns at askReady — the scan fallback is unreachable |
lib/ble/ble_engine.dart:1081,1091,1098 |
The non-ASK scan also filters on the gen4 service only |
lib/ble/ble_engine.dart:1275 |
Post-connect service discovery requires a 61080001… service or aborts |
ASK will only surface an accessory that matches a descriptor whose every criterion is also declared in Info.plist. With only the gen4 UUID declared and matched, a gen5 / MG band can never appear in the sheet. This is sufficient on its own to produce the reported symptom — no bond weirdness required.
Note on the current gen5 claims
README.md:146-147 states that "WHOOP 5.0 / MG support is in progress and experimental — the band is detected and spoken to". On main today there is no gen5 code at all: fd4b appears nowhere in the repository, and lib/sync/sync_policy.dart:7-11 records that the one speculative WHOOP5 helper was removed as unwired dead code ("WHOOP 4.0 only (the only family OpenStrap supports)").
If the whoop5-experimental tags carry gen5 work on a branch, that's fine — but the README on main currently overstates the state of support, which is how a gen5 owner ends up here expecting discovery to work.
Why community captures matter here
The maintainer does not own a 5.0 or MG strap, so every gen5 path is written from captures and community reports.
I have an MG and can capture whatever is useful. Tell me what you want and I'll produce it. The most valuable single artifact is a raw BLE advertisement dump of the band in pairing mode:
- nRF Connect (iOS or Android) → scan → find
WHOOP MGB… → export the full RAW advertisement, including:
- Complete/shortened local name
- Service UUIDs in both the advertisement and the scan response
- Manufacturer-specific data (company ID + payload)
- Service data, TX power, flags
- The same capture again after connecting, showing the full GATT service and characteristic tree.
If a 16-bit 0xFD4B service is what the band advertises, it should be visible in an ordinary unfiltered iOS scan — iOS only hides 128-bit UUIDs that land in the scan response's hashed overflow area. That makes the capture cheap and decisive.
Suggested direction
- Declare and match the gen5 service UUID(s) in both
Info.plist and the ASK descriptor, as an additional ASPickerDisplayItem so the 4.0 path is untouched (a single descriptor AND-combines its criteria — gen4 and gen5 must be separate items).
- Add a name-substring descriptor (
WHOOP, with a matching NSAccessorySetupBluetoothNames entry) as a safety net while the gen5 UUID is unconfirmed.
- Extend the Dart scan filter and post-connect service discovery to accept the gen5 UUID family alongside gen4.
- Add an opt-in discovery-probe / diagnostics dump to the pairing screen so gen5 owners can report a real capture from inside the app.
- Keep every gen5 path explicitly marked experimental in comments and release notes.
I've taken a run at all five — draft PR incoming, linked below. It is unbuilt (authored on Windows, no Xcode) and the gen5 UUID in it is a guess, so please treat it as a starting point rather than a finished change.
Suggested labels: bug, iOS, and a gen5 / whoop5 label if you want one — neither of the latter two exist on the repo yet.
Summary
On iOS 18+, OpenStrap pairs exclusively through the AccessorySetupKit (ASK) system sheet. The ASK discovery descriptor matches only the WHOOP 4.0 "Harvard" service UUID
61080001-8D6D-82B8-614A-1C8CB0F8DCC6, and that is the only UUID declared inInfo.plistunderNSAccessorySetupBluetoothServices.A WHOOP MG / 5.0 does not advertise that service, so the ASK sheet has nothing to match and shows "No Accessory Found" — regardless of the band being in pairing mode, flashing blue, and plainly visible to the rest of the system.
There is also no fallback: on iOS 18+ the pairing screen short-circuits to the ASK path before the service-filtered scan is ever reached, so a gen5 owner has no route to pairing at all.
Environment
WHOOP MGB…)v0.9.25-whoop5-experimentaland earlierwhoop5tagsSteps to reproduce
Expected
The ASK sheet lists
WHOOP MGB…(or a generic "WHOOP band" row) and lets me select it, after which OpenStrap provisions it and connects.Actual
The ASK sheet stays empty and shows:
The band never appears in the sheet, even while flashing blue and even though it is simultaneously listed in Settings → Bluetooth → My Devices as
WHOOP MGB… — Connected.Additional observations
Where this appears to come from
Reading
mainat6bddec4(pubspec.yamlversion0.9.26+57):ios/Runner/AccessorySetup.swift:31whoopServiceUUIDhardcoded to the gen4 service onlyios/Runner/AccessorySetup.swift:148ASDiscoveryDescriptormatches only that UUIDios/Runner/Info.plist:54-57NSAccessorySetupBluetoothServicesdeclares only that UUID; noNSAccessorySetupBluetoothNameslib/ui/pairing_screen.dart:217-222askReady— the scan fallback is unreachablelib/ble/ble_engine.dart:1081,1091,1098lib/ble/ble_engine.dart:127561080001…service or abortsASK will only surface an accessory that matches a descriptor whose every criterion is also declared in
Info.plist. With only the gen4 UUID declared and matched, a gen5 / MG band can never appear in the sheet. This is sufficient on its own to produce the reported symptom — no bond weirdness required.Note on the current gen5 claims
README.md:146-147states that "WHOOP 5.0 / MG support is in progress and experimental — the band is detected and spoken to". Onmaintoday there is no gen5 code at all:fd4bappears nowhere in the repository, andlib/sync/sync_policy.dart:7-11records that the one speculative WHOOP5 helper was removed as unwired dead code ("WHOOP 4.0 only (the only family OpenStrap supports)").If the
whoop5-experimentaltags carry gen5 work on a branch, that's fine — but the README onmaincurrently overstates the state of support, which is how a gen5 owner ends up here expecting discovery to work.Why community captures matter here
The maintainer does not own a 5.0 or MG strap, so every gen5 path is written from captures and community reports.
I have an MG and can capture whatever is useful. Tell me what you want and I'll produce it. The most valuable single artifact is a raw BLE advertisement dump of the band in pairing mode:
WHOOP MGB…→ export the full RAW advertisement, including:If a 16-bit
0xFD4Bservice is what the band advertises, it should be visible in an ordinary unfiltered iOS scan — iOS only hides 128-bit UUIDs that land in the scan response's hashed overflow area. That makes the capture cheap and decisive.Suggested direction
Info.plistand the ASK descriptor, as an additionalASPickerDisplayItemso the 4.0 path is untouched (a single descriptor AND-combines its criteria — gen4 and gen5 must be separate items).WHOOP, with a matchingNSAccessorySetupBluetoothNamesentry) as a safety net while the gen5 UUID is unconfirmed.I've taken a run at all five — draft PR incoming, linked below. It is unbuilt (authored on Windows, no Xcode) and the gen5 UUID in it is a guess, so please treat it as a starting point rather than a finished change.
Suggested labels:
bug,iOS, and agen5 / whoop5label if you want one — neither of the latter two exist on the repo yet.