Force GATT client to sync database with Zephyr

I have a device that added a characteristic in a software update. After doing a DFU, some clients (specifically older Android phones and Linux devices) don't perform discovery and update their cached GATT databases. Is there a way to force the GATT client to perform discovery of all services? My first thought was to send a "Service Changed" indication for all attributes, but that interface doesn't seem to be exposed by Zephyr's GATT API.

Device: nRF5340

NCS version: 2.0.2

  • Hello,

    Please ensure that CONFIG_BT_GATT_SERVICE_CHANGED is enabled in your application. 

    Are your devices bonded? If not, I am not sure how the service changed indication will work in this case. Usually disconnecting, turning bluetooth completely off and back on will cause at least android devices to forget unbonded devices, and they will perform a service discovery on the next connection. If they are bonded, and they were initially bonded when the CONFIG_BT_GATT_SERVICE_CHANGED was disabled, there is no way for the device to send a service changed indication, because it is located in a characteristic that was not originally present, and not subscribed to. In this case, deleting the bonding information from the android/linux device (and the nRF) is the only way to force a new service discovery. 

    Lastly, in case you don't have any more options, you can forcibly change the BLE address of the device, which will make it appear as a new device. You can use bt_id_create() to set a new address. 

    Best regards,

    Edvin

  • Hi Edvin, my devices are bonded and CONFIG_BT_GATT_SERVICE_CHANGED is enabled on both software versions.

    If I modify the SDK to expose the "sc_indicate()" function and call that after a connection in cases where I want to make sure the database re-synchronizes, I see the database update on the Linux device, which is the more critical device for my application.

    I also have the databash hash enabled and in the SDK gatt.c, I see this comment in "db_hash_process()":

    /* GATT database has been modified since last boot, likely due
    * to a firmware update or a dynamic service that was not
    * re-registered on boot.
    * Indicate Service Changed to all bonded devices for the full
    * database range to invalidate client-side cache and force
    * discovery on reconnect.
    */
    sc_indicate(0x0001, 0xffff);
    This doesn't appear to be working as intended since the next reconnect doesn't refresh the database, but calling sc_indicate(0x0001, 0xffff) after connecting to the device works.
Related