Bluetooth: SetDiscoveryFilter for filtered scanning

In continuation to our previous blog on bluetooth scanning and remove device after scanning, we will explore on discovery filters. Filters are typically used to narrow down our search. By default “StartDiscovery” will scan for all the nearby bluetooth devices. But in many situations user/developer already knows the desired category of devices.

Few examples are,

  • Developer wants to search only for Apple devices
  • User only wants to search for Bluetooth low energy devices
  • Search only for the devices which are very closely located

To control or narrow down our search for devices during “StartDiscovery”, bluetoothd provides “SetDiscoveryFilter” D-Bus API. We will explore in details about the “filter” options which can be used.

Code:

Here we are extending our previous start discovery example by adding new functions for handling discovery filters. More specifically the function “bluez_set_discovery_filter” is introduced to handle the discovery filter.

Extracted from,

dbus-send –system –print-reply –type=method_call –dest=’org.bluez’ ‘/org/bluez/hci0’ org.freedesktop.DBus.Introspectable.Introspect

<methodname="SetDiscoveryFilter">
<argname="properties" type="a{sv}" direction="in"/>
</method>

<methodname="GetDiscoveryFilters">
<argname="filters" type="as" direction="out"/>
</method>

Before using the “SetDiscoveryFilter” method, we will first examine the method parameters in details. As we can see above it takes the signature type “a{sv}” as input argument and there is no output response. The counter part API GetDiscoveryFilters can be used to get the currently active filters.

There are 5 filters which we can use.

  • UUIDs:
    • as: we can specify the array of UUID stings to filter the supported services. In bluetoothd, all the functionalities are exported or referenced by unique UUID. Services can either be built in to bluetoothd as profiles or implemented as external profiles.
    • array of UUIDs filter can be used to find devices which supports the specified list of UUIDs. All the other devices will not be listed and will not be populated in /org/bluez/hciX/dev_ path.
  • RSSI:
    • Received Signal Strength Indication refers to the signal strength of the device, which is signed integer i.e. 0 to -100. Where 0 indicates the device is very close and -100 shows the devices is far away from the controller
    • We can specify this value to filter the devices with only in defined range. For example, value “-50” means, the scanning will pop all the devices between 0 to -50 in signal strength
  • Pathloss: Attenuation of the Bluetooth signal in the space
  • Transport: Possible values are “auto, bredr, le
    • bredr: Scan only Bluetooth classic devices
    • le: Scan only for bluetooth low energy devices
    • auto: Both le and bredr if the controller supports. This is the default value when no explicit filter is set for transport.
  • DuplicateData: Specific to low every Bluetooth devices advertisement values. When enabled, signal will be emitted everytime when the device is discovered.

In our example, we are using only “Transport, RSSI and UUID” to filter the discovery. All three values _must_ be specified in the same order as argument.

So far in our previous examples of GetManagedObjects, InterfacesAdded, InterfacesRemoved and PropertiesChanged we have handled various DBUS signatures and decoded the values using GDBUS and GVariant API’s. But in this example we need to formulate/create “a{sv}” to send as argument to SetDiscoveryFilter.

In this example we are using GVariant builder API’s to build the GVariant of our interest. You can refer GVariant manual for more details on how to build your variants. We will explore more in details about GVariants building and parsing in our future blog on DBUS specification and it’s type system. The device with specified filter will be populated under /org/bluez/hciX/dev_ and this program will exit after removal of any device (either automatically after 180 seconds of device idleness or explicit removal using “RemoveDevice” or bluetoothcrl remove).