Conditions for GATT caching

I have an app that is using BLE to connect and exchage a small amount of data from a mobile device to a Linux application. The Linux system is Ubuntu with BlueZ and a simple BLE peripheral app that we wrote. The mobile side has both an Android and iOS app in central mode that does a simple scan/connect/write/disconnect. There is a single service and characteristic on the peripheral for receiving the data.


The issue is that we need this cycle to happen very quickly - ideally in 500ms or less. We've actually implemented a version of the peripheral in iOS, and with two iOS devices talking to each other the cycle time is actually around 300ms. Talking to the Linux peripheral the time is 1.5s minimum, and often longer. The Android app talking to the Linux peripheral has a cycle time around 700ms.


After some investigation we realized that the Android app is caching the GATT database and is only doing service/characteristic discovery the first time. The iOS application is apparently not caching, and we're seeing the service/characteristic discovery exchange on every connection (which is taking close to a second). The iOS app is running on 9.3.1 on an iPhone 6. From what I've read (although I can't find anything in the Core Bluetooth documentation) the GATT caching should just be happening automatically. Am I missing something?

What's different about the iOS peripheral implementation than the linux peripheral implementation?

iOS will cache things if you do a ble pairing. If you make your peripheral require encryption this will force a pairing. It is in one of the CoreBluetooth WWDC videos but I forget which.


Hope this helps.

P.S. Because Android caches stuff without your desire, if your services were say, to change, what do you do then? Since Android cached your service and characteristic handles, you would never know about these new services. There are no public methods to 'refresh' the gatt table to be re-discovered in Android Bluetooth API.

Conditions for GATT caching
 
 
Q