How to force to discover service and characteristic from device, not from local database?

Hi all,


We found iOS may return services and characteristics from cache if our application invoke CBPeripheral::discoverServices().

14:59:18.824260 +0800bluetoothdAttempting to find all services on device "<private>"
14:59:18.824785 +0800bluetoothdReturning primary services from cache


But our product may change the chracteristics attribute handle number after product firmware updated.



For example, FW Ver1: discovered serivce like below,


14:59:18.826036 +0800 bluetoothd Using local database for discover services by UUID.

14:59:18.826926 +0800 bluetoothd statedump: 0x0001 Primary Service [ serviceUUID: -, endHandle: 0x0006, discoveredCharacteristics: all ]

14:59:18.827124 +0800 bluetoothd statedump: 0x0002 Characteristic [ valueUUID: -, valueHandle: 0x0003, properties: notify, discoveredDescriptors: all ]

14:59:18.827412 +0800 bluetoothd statedump: 0x0003 Characteristic Value [ - ]

14:59:18.827549 +0800 bluetoothd statedump: 0x0004 Client Configuration [ none ]

14:59:18.827713 +0800 bluetoothd statedump: 0x0005 Characteristic [ valueUUID: -, valueHandle: 0x0006, properties: responseless-writes write, discoveredDescriptors: none ]



But after FW updated, FW Ver2: discovered service should like below,



15:00:09.204374 +0800 bluetoothd statedump: 0x0001 Primary Service [ serviceUUID: -, endHandle: 0x0006, discoveredCharacteristics: none ]

15:00:09.204613 +0800 bluetoothd statedump: 0x0007 Primary Service [ serviceUUID: -, endHandle: 0x000C, discoveredCharacteristics: none ]

15:00:09.205718 +0800 bluetoothd Finding all characteristics in range [0x0007, 0x000c] on device "<private>"

15:00:09.265822 +0800 bluetoothd statedump: 0x0001 Primary Service [ serviceUUID: -, endHandle: 0x0006, discoveredCharacteristics: none ]

15:00:09.266798 +0800 bluetoothd statedump: 0x0007 Primary Service [ serviceUUID: -, endHandle: 0x000C, discoveredCharacteristics: all ]

15:00:09.267084 +0800 bluetoothd statedump: 0x0008 Characteristic [ valueUUID: -, valueHandle: 0x0009, properties: notify, discoveredDescriptors: none ]

15:00:09.267562 +0800 bluetoothd statedump: 0x000B Characteristic [ valueUUID: -, valueHandle: 0x000C, properties: responseless-writes write, discoveredDescriptors: none ]



But if we didnot power off/on iPhone's Setting >> Bluetooth switch (reset bluetooth), we cannot setNotifyValue() successfuly.


14:59:18.883104 +0800 bluetoothd Received error response for write value 3 (status=65535)

14:59:18.883522 +0800 bluetoothd Failed to write descriptor at handle 0x0004 on device "<private>" - result was 3



How can app force to discover service and characteristic from BLE device but not just from iOS local cache database?

Thank you

Answered by Engineer in 378281022

To indicate to an Apple device that it should read the services/characteristics directly from the device instead of using the cached values, your peripheral must implement the Device Changed characteristic. This is also mentioned in the Accessory Design Guidelines document.



23.12.2 Generic Attribute Profile Service

The accessory must implement the Service Changed characteristic only if the accessory has the ability to change its services during its lifetime.


The device may use the Service Changed characteristic to determine if it can rely on previously read (cached) information from the device. See the Bluetooth 4.0 specification, Volume 3, Part G, Section 7.1.


May have a look here to see how to flush the cache:

https://forums.developer.apple.com/thread/19381


And this other discussion:

https://stackoverflow.com/questions/29203983/clearing-ios-ble-cache

Thank you for your information.


It seems only way to flush the cache (I mean service & characteristic ) is manual reset BT power.


But I found there is a discussion about didModifyService callback function, althought I sill not be able to get the callback in our case.


https://forums.developer.apple.com/message/353277#353277

Accepted Answer

To indicate to an Apple device that it should read the services/characteristics directly from the device instead of using the cached values, your peripheral must implement the Device Changed characteristic. This is also mentioned in the Accessory Design Guidelines document.



23.12.2 Generic Attribute Profile Service

The accessory must implement the Service Changed characteristic only if the accessory has the ability to change its services during its lifetime.


The device may use the Service Changed characteristic to determine if it can rely on previously read (cached) information from the device. See the Bluetooth 4.0 specification, Volume 3, Part G, Section 7.1.


Thank you so much!!!


We will try this.

Hello @airohatool, have u try this solution, can you confirm that indicate 0x2A05 is working correctly. I'm facing the same issue and i try to indicate 0x2A05 character when device servives changed but still can not get new services in my app Thanks

@Engineer Can we get access/entitlements for a private API that allows us to delete the BLE cache? Or is there any other way to delete the BLE cache from an app?

Our embedded team creates firmware based on Espressif, so they can't add the Service Changed characteristic. Espressif added a new characteristic in ESP-IDF v5.2; if you upgrade from ESP-IDF v4.4 to v5.2, that characteristic is not discovered. The characteristic is discovered after turning Bluetooth to OFF and ON in Settings.

How to force to discover service and characteristic from device, not from local database?
 
 
Q