BLE subscriptions for bonded devices

I have a problem understanding notifications/subscriptions in the BLE context.

I have two devices, Central (nRF5340) and Peripheral (nRF52832). My peripheral provides a GATT profile. The Central establishes a connection to the Peripheral.

I have implemented the following sequence:
- Central establishes connection to Peripheral
- Central changes security level to L4 (cause I know that the characteristics of my peripheral expect this security level)
- If successful, Central performs GATT discovery
- If successful, the Central subscribes to a specific characteristic
- The Peripheral sends a one-time notification update as soon as the subscription is received (value 1 written to CCC --> received in BT_GATT_CCC cfg_changed callback)

Problem:
- If both devices are already bonded and the security level is changed to L4, in the Peripheral, the value of CCC is automatically retrieved from the bonding information and applied (even before the Central executes a bt_gatt_subscribe). This happens in the 'bt_gatt_encrypt_change' function.
- This will call the BT_GATT_CCC cfg_changed callback directly.
- This means that the notification sent once during the first subscribe cannot be interpreted by the Central, as on Central side the callback has not yet been registered (which happens during bt_gatt_subscribe).

It appears to me that this behavior, whereby the CCC value is loaded from the bonding information, is not configurable. However, it is unclear to me how the central should perform the subscription without a GATT discovery and a corresponding security level in time, since the handle (characteristic) is required for this.

Can anyone assist me with this?

Parents
  • The Bluetooth spec requires that subscriptions persist at the GATT server across connections for bonded devices.

    For the GATT client to be able to handle receiving a notification prior to GATT service discovery, you could implement Attribute Caching to bypass the discovery. You can see a discussion on that at 2.5.2. Attribute caching.  However, that would require some work on the client side and may not be easy since you would probably want to support the Service Changed characteristic, along with storing the handles at the client for each bonded peer.

    Alternatively, since your notification is a one-time update, you could use a GATT Read operation instead of a GATT notification: After the GATT client completes service discovery, the client can send a GATT Read to the server. The server would then reply to the Read with the value that you are currently sending with a notification. See 4.8.1. Read Characteristic Value.

  • Thank you for this good answer  . From our side, I think that to properly support receiving notifications immediately upon connection, we would need to add support for attribute caching as well so that attribute handle assignments can be restored together with the CCCs on connection. Since this is currently not supported, I also think it would be better to look at alternatives like doing a GATT read as suggested above.

    Edit: It looks like bt_gatt_resubscribe() can be used, but it still requires you to cache the attribute handle.

Reply
  • Thank you for this good answer  . From our side, I think that to properly support receiving notifications immediately upon connection, we would need to add support for attribute caching as well so that attribute handle assignments can be restored together with the CCCs on connection. Since this is currently not supported, I also think it would be better to look at alternatives like doing a GATT read as suggested above.

    Edit: It looks like bt_gatt_resubscribe() can be used, but it still requires you to cache the attribute handle.

Children
No Data
Related