Timing of BLE Advertising Packets Delivered via didDiscoverPeripheral

When a CBManager is initalized with a background queue the delegate method didDiscoverPeripheral is called multiple times for multiple advertising packets. However, my testing is showing that the method is not called for every advertising packet sent by the peripheral. It is understandable that due to the nature of the BLE protocol, radio timing, etc. that some packets may go missing. However, I'm using a development peripheral that can be customized to deliver advertising packets at different intervals. At 100ms the delegate method is called once every 2-4 seconds. At 1000ms the delegate method is called more sproadically. Our application relies on broadcasted data encoded in the kCBAdvDataManufacturerData. Is there any way to achieve deterministic delegate calls for this purpose?

Answered by Engineer in 26198022

As both the scanning and advertising in BLE are discrete events (that is an iOS device does not scan continuously, but periodically), the probability of discovery for each advertising packet cannot be 1 (100%). Indeed, the probability curve of the chance of detection for a single packet is asymptotic, and every single packet cannot be guaranteed to be detected.

That said, Apple recommends certain advertising intervals to increase the probability of discovery.

To have a high probability of being discovered by an iOS device you should first use the recommended advertising interval of 20 ms for at least 30 seconds.

If it is not discovered within the initial 30 seconds, you can switch to using one of the following longer intervals to increase chances of discovery:

152.5 ms, 211.25 ms, 318.75 ms, 417.5 ms, 546.25 ms, 760 ms, 852.5 ms, 1022.5 ms, 1285 ms.


Any advertising interval outside these values will significantly reduce the chances of discovery of a peripheral. Detection of single packets still cannot be guaranteed.


In the field, there is no way of knowing what the scanning interval of an iOS device will be in order to even think of deterministic delegate callbacks. That will depend on the state of your app, the states of other apps using BLE, system processes, whether the device is actively being used or sitting idle, etc.

Additionally, when your app is in the background, the

CBCentralManagerScanOptionAllowDuplicatesKey
scan option key is ignored, and multiple discoveries of an advertising peripheral are coalesced into a single discovery event.

Unfortunately, you cannot rely on the detection of every single advertising packet all the time.

CBCentralManagerScanOptionAllowDuplicatesKey is being used as an option for scanForPeripheralsWithServices.

Accepted Answer

As both the scanning and advertising in BLE are discrete events (that is an iOS device does not scan continuously, but periodically), the probability of discovery for each advertising packet cannot be 1 (100%). Indeed, the probability curve of the chance of detection for a single packet is asymptotic, and every single packet cannot be guaranteed to be detected.

That said, Apple recommends certain advertising intervals to increase the probability of discovery.

To have a high probability of being discovered by an iOS device you should first use the recommended advertising interval of 20 ms for at least 30 seconds.

If it is not discovered within the initial 30 seconds, you can switch to using one of the following longer intervals to increase chances of discovery:

152.5 ms, 211.25 ms, 318.75 ms, 417.5 ms, 546.25 ms, 760 ms, 852.5 ms, 1022.5 ms, 1285 ms.


Any advertising interval outside these values will significantly reduce the chances of discovery of a peripheral. Detection of single packets still cannot be guaranteed.


In the field, there is no way of knowing what the scanning interval of an iOS device will be in order to even think of deterministic delegate callbacks. That will depend on the state of your app, the states of other apps using BLE, system processes, whether the device is actively being used or sitting idle, etc.

Additionally, when your app is in the background, the

CBCentralManagerScanOptionAllowDuplicatesKey
scan option key is ignored, and multiple discoveries of an advertising peripheral are coalesced into a single discovery event.

Unfortunately, you cannot rely on the detection of every single advertising packet all the time.

Thanks Gualtier. Is this the latest revision of this document? https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf This R7 version is dated 9/18/2013. BLE has evolved quite a bit since the document was released, especially concerning "broadcast" modes where data is transmitted without a full connection.

Yes, that is still the latest revision.

Well, count me as a +1 for needing a CBManager option where advertisement packets are more speedily delivered, perhaps on a per UUID basis. For what it's worth, we simulaneously develop on Android and 99% of advertising packets make it to the BLE API.


Additionally, I've found that calling -stopScan and then -scanForPeripheralsWithServices every 2 seconds yields very good results (not 1 second, not 3 seconds). However, I wager that this is not a recommended use of the CB API.

What android devices are you testing with? I have observed with API 21 that even though the API says all callbacks will be delivered if match filter criteria, there are still some devices that only ever raise a single discovery event.


I have observed in iOS 8.x that after a few minutes of scanning, with several beacons and apple tv's around my apartment, that the percentage of advertisements that hit the app level are reduced. I know these devices are advertising and my little usb sniffer can see them. Stopping and starting the scan again seemes to reset any discovery algorithm that could possibly be going on under the hood.


Have you tried just calling scanForPeripherals: again? Somewhere in the doc says any subsuquent call replaces the scanning parameters. Wondering if a stop scan is really needed or not.

Timing of BLE Advertising Packets Delivered via didDiscoverPeripheral
 
 
Q