iosbluetooth-lowenergycore-bluetoothcbperipheralcbcentralmanager

CoreBluetooth peripheral service becomes empty while reconnecting/restoring


In my iOS app I am able to successfully connect to BLE peripherals, discover service and subscribe to characteristics so that app gets notified whenever there is a change in characteristic value. All these happens with no issues as long as app runs in background.

But issue occurs when state restoration happens. In centralManager:willRestoreState: method, I am able to retrieve previously connected peripherals using the method retrieveConnectedPeripheralsWithServices:. But nothing happens when I call discoverServices: method on the retrieved peripheral. peripheral:didDiscoverServices: method never gets called. The value of retrieved peripheral's services property is also null. Does iOS not cache the services and characteristics ?

Note: Our BLE peripheral advertises service initially. When the app launches for first time, it reads value from peripheral and writes user specific data to a characteristic. Post writing, peripheral stops advertising services. But firmware engineer claims that even though service is stopped by peripheral, peripheral retrieved from state restoration should have the cached service. Is it true ?


Solution

  • Have you checked the connection state of the peripherals that you have retrieved via retrieveConnectedPeripheralsWithServices:? The CoreBluetooth framework has some quirks that you need to be aware of, one being the behaviour of the retrieveConnectedPeripheralsWithServices: method:

    When you obtain the peripherals via the aforementioned method they might only be connected on the system level (iOS) but not within your app (see the Discussion section in the API documentation). Therefore, you still have to call connect on the peripherals before you can use them properly. Here is the corresponding part from the API documentation:

    The list of connected peripherals can include those that are connected by other apps and that will need to be connected locally using the connectPeripheral:options: method before they can be used.

    Regarding the caching of services: iOS caches any discovered service and corresponding characteristic. There are only to ways to force iOS to update the cache:

    Note: You can also activate log messages from the Bluetooth Stack via the Bluetooth Configuration Profile. They can be quite helpful when debugging BLE related issues especially with custom hardware involved (even though the logs are a bit cumbersome to use).