Skip to content

bluetooth: share workout HRM over BLE#1493

Open
lesserevil wants to merge 10 commits into
coredevices:mainfrom
lesserevil:ble-hrm-workout-sharing
Open

bluetooth: share workout HRM over BLE#1493
lesserevil wants to merge 10 commits into
coredevices:mainfrom
lesserevil:ble-hrm-workout-sharing

Conversation

@lesserevil

@lesserevil lesserevil commented Jun 11, 2026

Copy link
Copy Markdown

Summary

  • Advertise Pebble as a standard BLE Heart Rate Monitor while Run, Walk, or Workout sessions are active and Workout HR Sharing is enabled.
  • Add a Health setting, Workout HR Sharing, defaulting off, to control workout-mode BLE HRM sharing separately from the existing HR During Activity preference.
  • Keep ble_hrm_is_supported_and_enabled() tied to hardware support and the normal HRM sharing preference; workout-mode sharing is handled explicitly by ble_hrm_set_workout_mode().
  • Propagate HR During Activity preference changes to BLE HRM on hardware builds so the tested watch path updates correctly.

Split PRs

This branch is stacked on smaller prerequisite PRs so each piece can be reviewed and updated independently:

After those land, this PR can be rebased so the visible diff is only the workout-sharing feature commit. The QEMU NimBLE enablement work has been removed and can be handled separately if still useful.

Reviewers: the incremental change owned by this PR is the final commit f607deaa ("share workout hrm during workouts"). The prerequisite commits 1f8df9e8, 1dc70313, 172c3198, and 5a435886 appear here only because GitHub cannot base a cross-fork PR on a fork branch. They are genuine build/runtime dependencies for the workout-sharing behavior.

Supersedes

Related issue search

  • I did not find an exact existing issue or PR for BLE HRM workout sharing.
  • Related: Ant+ transmitter on pebble #660 asks for ANT+ transmitter support; one comment notes that BLE HR broadcasting may satisfy cycling GPS devices that can connect to BLE sensors. This PR does not implement ANT+.

Tested

  • git diff --check
  • gitlint --commits upstream/main..HEAD
  • ./pbl test -M 'test_workout_service|test_ble_hrm|test_gap_le_advert|test_gap_le_slave_reconnect|test_bluetooth_persistent_storage|test_nimble_hrm_service'
  • ./pbl build

Note: test_gap_le_connect remains in the repository BROKEN_TESTS list, so the new concurrent-slave-connection unit test in #1513 is not run by the default test target until that suite is re-enabled.

@lesserevil lesserevil marked this pull request as draft June 11, 2026 21:43
@lesserevil lesserevil force-pushed the ble-hrm-workout-sharing branch 2 times, most recently from df5eb06 to 9efe4d9 Compare June 12, 2026 03:14
@lesserevil lesserevil force-pushed the ble-hrm-workout-sharing branch 3 times, most recently from 023113d to 14d6f3f Compare June 14, 2026 21:47
lesserevil and others added 9 commits June 16, 2026 17:45
Allow the phone gateway connection and one external BLE client to coexist
by increasing the NimBLE connection limit and tracking multiple slave links
in the firmware BLE connection state.

Classify new NimBLE pairings as gateway only after the Pebble pairing
service is used. Prune stale BLE gateway bonds without deleting
non-gateway client bonds.

Co-authored-by: GPT-5 Codex <codex@openai.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
Implement the standard Heart Rate Service on the NimBLE backend and route
subscription updates back to the firmware HRM sharing service.

Co-authored-by: GPT-5 Codex <codex@openai.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
test_nimble_hrm_service never linked: the NimBLE transport include path was
missing, and including the host headers pulls in the NPL + transport layer.
Add the transport include, link the dummy NPL backend (no FreeRTOS needed for
a host-only service test), and stub the unused transport impls.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
Advertising the HRM service makes the watch discoverable as a standard BLE
heart-rate sensor, which (with the original consent-based sharing) prompts the
user to share heart rate on every reconnect. That model is being replaced by
workout-gated sharing, so retire it here, alongside the advertising that
exposes the service:

- Remove the per-device consent prompt, permission model, and reminder popup.
- Delete the ble_hrm sharing/reminder/stop-sharing popup windows and the
  settings + timeline stop-sharing controls (the serialized
  TimelineItemActionTypeBLEHRMStopSharing value is kept, handled as a no-op).
- ble_hrm.c now exposes the HRM GATT service but shares nothing; workout-gated
  sharing is added in a later change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
Add an explicit HRM reconnect advertising start path that keeps the
Heart Rate Service UUID in the advertising payload until stopped.

Co-authored-by: GPT-5 Codex <codex@openai.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
Allow HRM reconnect advertising to keep running while a slave
connection is active, so cycle computers can discover the HRM service
without disconnecting the phone link.

Normal discovery and reconnect advertisements remain paused until all slave
connections disconnect.

Co-authored-by: GPT-5 Codex <codex@openai.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
test_gap_le_slave_reconnect never linked (missing new_timer/ble-syscall/
serial/task/rand stubs). Once linked, it and test_gap_le_advert's
hrm_reconnection_continues_after_slave_connection both failed: they drove the
1-second advertising cycle timer with regular_timer_fire_seconds(N), which
fires once (N is a modulus), not N times, so the job never advanced to its
Long-interval term. Add the missing stubs and loop regular_timer_fire_seconds(1)
to advance the term.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
Add workout-gated BLE HRM sharing on top of the concurrent-client support,
NimBLE HRM service, and reconnect advertising from the earlier changes in this
series.

While a supported workout is active and the BLE HRM workout-sharing setting is
enabled, the watch enables the HRM service, advertises it, and automatically
shares heart rate with a subscribed consumer -- no per-device prompt. Once a
consumer subscribes the watch stops advertising (single consumer); it resumes
if that consumer disconnects. Sharing stops when the workout ends. Outside an
active workout the watch shares nothing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
- hrm_service.c: Use PBL_LOG_MODULE_DECLARE instead of LOG_DOMAIN_BT
- gap_le_slave_reconnect.c: Add PBL_LOG_MODULE_DECLARE
- ble_hrm.c: Fix HRM service enable logic - only enable during workout mode,
  not based on heart rate preference (which is for on-watch monitoring)

Co-Authored-By: Nemotron 3 Ultra <noreply@nvidia.com>
Signed-off-by: Shawn Edwards <lesser.evil@gmail.com>
@lesserevil lesserevil force-pushed the ble-hrm-workout-sharing branch from 14d6f3f to 27e866d Compare June 16, 2026 19:17
@lesserevil lesserevil marked this pull request as ready for review June 17, 2026 01:29
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.

1 participant