Skip to content

Fix BLE notification and heartbeat state races - #112

Open
ODevStudio wants to merge 9 commits into
mainfrom
odev/ble-weight-live-connection
Open

Fix BLE notification and heartbeat state races#112
ODevStudio wants to merge 9 commits into
mainfrom
odev/ble-weight-live-connection

Conversation

@ODevStudio

@ODevStudio ODevStudio commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • derive physical BLE connection state from NimBLE's live server connection count
  • track current FFF4 subscription readiness separately from physical connection state
  • gate every outbound FFF4 notification through bleCanNotifyCurrent()
  • defer status replies requested before CCCD registration and send them from loop()
  • disconnect the current client after a status reply remains blocked for two seconds so advertising and subscription state can recover
  • preserve stale-disconnect protection, keep-awake behavior, and early heartbeat-policy loading

Root causes

After rapid reconnects, the callback-maintained deviceConnected flag can disagree with NimBLE's connection table. Incoming writes may still work while outbound notifications are suppressed.

A physical connection can also remain live while FFF4 is not ready to notify. Physical connection state and current FFF4 subscription readiness therefore need separate gates.

During cold boot, BLE advertising previously started before b_requireHeartBeat was restored from NVS. A client could change heartbeat enforcement and then have that command overwritten by the continuing setup path.

Recovery behavior

A small critical-section-protected mailbox serializes the current connection, FFF4 subscription, pending status reply, request timestamp, connection generation, and one-shot notification-failure state. No lock is held across notify() or disconnect().

If a status command arrives before FFF4 subscription, the reply remains pending. Subscription delivers it; a two-second timeout retires it and disconnects only if the same connection generation is still current. Revalidation prevents a late subscription, newer request, reused connection handle, or stale disconnect callback from affecting the current client.

Scope

No BLE UUID, packet, command, NVS, client API, or Arduino-ESP32 framework changes. PR #113 remains independent.

Validation

  • python tools/test_ble_subscription_contract.py
  • python tools/test_ai_docs_contract.py
  • git diff --check
  • project-local ignored .pio-core: pio run -e esp32s3 (RAM 18.4%, flash 49.7%)
  • both contract checks and the ESP32-S3 build are wired into pull-request CI

Only the existing wifi_setup.cpp volatile-increment warnings remain. Hardware checks for normal subscription, deferred status delivery, timeout reconnect, rapid reconnects, 10 Hz weight traffic, and one-shot notification-failure logging remain required.

@ODevStudio ODevStudio changed the title Fix BLE weight delivery after reconnect Use live BLE connection state for notifications after reconnect Jul 27, 2026
@ODevStudio
ODevStudio marked this pull request as ready for review July 27, 2026 15:11
@ODevStudio ODevStudio changed the title Use live BLE connection state for notifications after reconnect Fix BLE notification and heartbeat state races Jul 28, 2026
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