Skip to content

Peripheral discovery API comparison

Andrew Walbran edited this page Mar 14, 2021 · 6 revisions

This page compares the APIs for discovering BLE peripherals on different platforms. This includes starting and stopping a scan, getting events for advertisements, and getting information about peripherals the system knows about in some way.

BlueZ (Linux)

Start a scan

Calling StartDiscovery() on an org.bluez.Adapter1 starts discovery. This appears to be an active scan; there is no way to explicitly request a passive scan.

Various options may be set with SetDiscoveryFilter(dict filter), e.g. to filter by service UUID, MAC address or name, or to choose whether duplicate service data and manufacturer-specific data are included. This is set per application but applied system-wide, so if two different applications set different discovery filters then BlueZ will discover peripherals which match either filter and return them to both applications. Thus an application must be prepared to see peripherals it didn't ask for.

Get peripherals

BlueZ maintains a set of peripherals which it knows about as D-Bus objects implementing org.bluez.Device1. These may be queried cheaply at any time (without talking to hardware) to get the latest information that BlueZ knows about them. The set of peripherals is system-wide and persistent, so will change in response to other applications using Bluetooth (e.g. starting scans, connecting to devices). It includes not just peripherals which are currently in range, but also those that were discovered at some point in the past, or that have been paired.

There are no events directly corresponding to advertisements, but it is possible to use standard D-Bus interfaces to subscribe to signals for new objects being added (via org.freedesktop.DBus.ObjectManager.InterfacesAdded) or some properties being updated (via org.freedesktop.DBus.Properties.PropertiesChanged).

CoreBluetooth (MacOS and iOS)

Start a scan

CBCentralManager -scanForPeripheralsWithServices:options: will start a scan. If serviceUUIDs is nil then it will scan for all peripherals, otherwise it will filter to ones with the given service UUIDs advertised. The options control duplicate filtering. There is no way to explicitly choose between active or passive scanning.

Get peripherals

A CBCentralManagerDelegate may be registered with the CBCentralManager. This has several different methods for various events, but in particular centralManager:didDiscoverPeripheral:advertisementData:RSSI: is called in response to advertisements. This includes the advertisement data (e.g. name, manufacturer data, service data), the current RSSI, and the CBPeripheral object used to connect to the peripheral and perform other operations on it.

CBCentralManager also has two methods to retrieve peripherals directly: retrieveConnectedPeripheralsWithServices: to get all connected peripherals with a particular set of service UUIDs, and retrievePeripheralsWithIdentifiers: to look them up by ID. The latter could be used by an application to connect to a peripheral it has previously connected to without having to scan again.

Note that CoreBluetooth doesn't expose the MAC addresses of peripherals to applications, only the unique IDs which it assigns internally.

Clone this wiki locally