Closed dononcharles closed 1 year ago
Try connecting to the device using nRF Connect and select Refresh services from the top-menu. Perhaps your phone has cached previous services of the peripheral. Then try again.
@philips77 thanks for your tips, but does not help me. If i remove the device from the phone bonding table, i start the connection with pairing. After the pairing, i can connect to the BT module, 2nd times too, but from the 3rd times, i could not and the error above is shown. I would like to understand what can block the Gatt like this.
Are you nullifying references to your characteristics and descriptors in onServicesInvalidated()
and seeing them again in isRequiredServiceFound(...)
?
Could you paste here relevant part of your BLE manager?
Hi @philips77 please have a look below:
override fun onServicesInvalidated() {
rxCharacteristic = null
txCharacteristic = null
modemInCharacteristic = null
modemOutCharacteristic = null
}
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
var writeRequest = false
gatt.getService(LAIRD_VPS_SERVICE_UUID)?.run {
rxCharacteristic = getCharacteristic(rxUUID)
txCharacteristic = getCharacteristic(txUUID)
modemInCharacteristic = getCharacteristic(modemInUUID)
modemOutCharacteristic = getCharacteristic(modemOutUUID)
writeRequest = (txCharacteristic?.properties ?: 0) > 0 && (modemInCharacteristic?.properties ?: 0) > 0 && (modemOutCharacteristic?.properties ?: 0) > 0
}
return rxCharacteristic != null && txCharacteristic != null && writeRequest
}
override fun initialize() {
setNotificationCallback(txCharacteristic).with(txCallback)
beginAtomicRequestQueue()
.add(
enableNotifications(txCharacteristic).fail { device, status: Int ->
Logger.error("Could not subscribe to $device, status: $status")
disconnect().enqueue()
})
.done { device: BluetoothDevice? ->
Logger.info("Target: $device is initialized")
}.enqueue()
}
Hi @philips77 i found that clearing the cache after every gatt.close() solve the problem. But it's a solution i do not really like.
override fun shouldClearCacheWhenDisconnected(): Boolean {
Log.i(TAG, "fooo:shouldClearCacheWhenDisconnected")
return true
}
Does your device change services at some point? If so, is it sending Service Changed indication either after the change or after next reconnection?
You may also use refreshServices().enqueued()
, but don't think that will work on the initialize(..)
as it would run in an endless loop.
Does your device change services at some point? If so, is it sending Service Changed indication either after the change or after next reconnection?
how can my device change services? i do not think about something like this. How can i know that?
I've also seen that with nRF Connect App, i can not even enable or disable the notification state on the characteristics. I need to 'click on refresh services' as you said in your first comment, before it works.
Before i used the clear cache function, if i disconnect from the server gatt and i restart the BT module on my "controller" than the connection work as intended.
Then it looks like the device changes services, or at least handle numbers. Are you the author of the firmware?
A Bluetooth LE device as an Attribute Table with Services, Characteristics and Descriptors. Each attribute and value has a Handle number associated (UInt16). When you write/read an attribute/value, you send the handle number, not the full UUID (although there are options to read/write by UUID, but they are not supported on mobiles). A device may change its table at any time. For example, in Nordic nRF5 SDK when a device enters DFU mode it changes services to expose the DFU service, do the update and then runs again in the app mode with old (or new) services. Sometimes for the DFU mode the device increments its MAC address, so from the phone point of view it's a new device, not the old with changed table. Anyway, if it changes services it should indicate the change to the client. It the device is bonded it shall use Service Changed characteristic by sending an indication. The client should invalidate its cache and do service discovery again. On Android's native API you should get onServiceChanged callback (API 31+). Very often the change happens when the device restarts, so the indication is sent immediately after enabling encryption after connection. That's why in the BLE library it is possible to delay service discovery to make sure the indication is handled (otherwise Android would return cached services):
https://github.com/NordicSemiconductor/Android-BLE-Library/blob/107435fcfcbe48ed26f4e550c033842cff6e5d3a/ble/src/main/java/no/nordicsemi/android/ble/BleManager.java#L617-L648
For non-bonded devices it's a bit easier. If the Service Change characteristic is present in the Attribute Table of a device it means the the client shall not cache services at all and shall do service discovery after each connection. If the Generic Attribute service does not have this characteristic a client is free to cache services and never clear them as this indicates that the device will never ever change services, e.g. does not support update, etc. And iOS respects that. Android, on the other hand, always caches on some versions, never caches on some other versions, etc. Hard to say. But there's a hidden API to clear the cache, which the BLE library allows by either returning true from shouldClearCacheWhenDisconnected()
, or executing refreshDeviceCache
request.
If the service change you're describing is not intended, try a different phone (perhaps there's some issue with your phone?) and check your firmware.
@philips77 , thanks for this detailed explanations. Am not the author of the fw. It bt (Lyra P) module bought from LAIRD company. I've tried Android 11, 12, 13 same issus, but with Huawey Android 10, i've not seen this issue. Also as info: if we do not enable the bonding config on the Bt module, everything works as well. The problem happens only when we've activated the bonding configuration
Anyway, if the device does change service you may need to use you solution from here: https://github.com/NordicSemiconductor/Android-BLE-Library/issues/481#issuecomment-1479812561
@philips77, please i need your help for one more thing: my team is asking me to report this behavior to the owner of the BT module. What kind of question can i ask them? Do you think the can help us on this issue? or i need to figure out myself solution? Thanks
What module or chip is used it doesn't matter. It depends on the firmware programmed on it. And this behavior may be intended. I have no idea what fw is that.
Thanks so much for yr time. You can close this issue.
Hi, Please can you help me understand this error when i'm trying to enable notification on TX characteristic?