Skip to content

fix(server): notify characteristics on client disconnect#1081

Open
m-mcgowan wants to merge 1 commit intoh2zero:masterfrom
m-mcgowan:fix/notify-characteristics-on-disconnect
Open

fix(server): notify characteristics on client disconnect#1081
m-mcgowan wants to merge 1 commit intoh2zero:masterfrom
m-mcgowan:fix/notify-characteristics-on-disconnect

Conversation

@m-mcgowan
Copy link

@m-mcgowan m-mcgowan commented Feb 1, 2026

Summary

When a BLE client disconnects, characteristics with active subscriptions are not notified. This leaves applications with stale subscription state, causing issues with reconnection.

This PR adds code to the BLE_GAP_EVENT_DISCONNECT handler to iterate through all characteristics and call processSubRequest(peerInfo, 0) for any that had active subscriptions from the disconnecting client.

Problem

Applications using wrappers like NuS-NimBLE-Serial track subscriber counts via the onSubscribe callback. Without this fix:

  1. Client connects and subscribes → onSubscribe(subValue=1) called → count = 1
  2. Client disconnects abruptly → no callback → count stays at 1
  3. Client reconnects → subscription state is stale → reconnection fails

Solution

In BLE_GAP_EVENT_DISCONNECT, before calling onDisconnect:

  • Iterate through all services and characteristics
  • For each characteristic with an active subscription from the disconnecting client
  • Call processSubRequest(peerInfo, 0) to trigger the onSubscribe callback with subValue=0

This ensures:

  1. The onSubscribe callback is called with subValue=0
  2. Applications tracking subscriber counts get properly notified
  3. Subscription state is cleaned up for reliable reconnection

Testing

Tested with ESP32-S3 using Arduino framework and NuS-NimBLE-Serial. Before the fix, reconnection after disconnect would fail. After the fix, reconnection works reliably.

Note

An equivalent fix has been submitted to esp-nimble-cpp (#393 in h2zero/esp-nimble-cpp) for ESP-IDF builds.

When a BLE client disconnects, iterate through all characteristics
and call processSubRequest(peerInfo, 0) for any that had active
subscriptions from the disconnecting client.

This ensures that:
1. The onSubscribe callback is called with subValue=0
2. Applications tracking subscriber counts get notified
3. Subscription state is properly cleaned up

Without this fix, applications using NuS-NimBLE-Serial or similar
wrappers that track subscriber counts would retain stale subscription
state after client disconnects, causing issues with reconnection.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@m-mcgowan m-mcgowan marked this pull request as ready for review February 1, 2026 00:52
@h2zero
Copy link
Owner

h2zero commented Feb 1, 2026

Thanks, this is good but the stack should be sending BLE_GAP_EVENT_SUBSCRIBE event which will call the onSubscribe callback, is this not the case for you? Can you share logs/code?

@m-mcgowan
Copy link
Author

BLE_GAP_EVENT_SUBSCRIBE is not sent on disconnect - only BLE_GAP_EVENT_DISCONNECT.

The CCCD write that triggers BLE_GAP_EVENT_SUBSCRIBE doesn't happen when a client disconnects abruptly. Should the stack be generating a synthetic unsubscribe event? If so, that might be a NimBLE core issue rather than NimBLE-arduino.

Happy to add logging to capture the exact GAP events if helpful. This seemed to be the simplest fix to handle the situation with the events that are currently sent.

@h2zero
Copy link
Owner

h2zero commented Feb 2, 2026

I'd like to see some logs for sure, in my experience the subscribe event is triggered with a 0 value every time a client disconnects if they were subscribed to a notification.

My log just now:

10:27:46.565 > I NimBLEServer: subscribe event; attr_handle=16, subscribed: false
10:27:46.570 > Disconnected, reason: 531

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.

2 participants