Small Single Board Computers (SBC) such as Raspberry Pi 3 (RPi3) with their built in BLE 4.0 controllers are enough to scan for Bluetooth Low Energy beacons such as those that use the Eddystone format beacons.
>The BlueZ maintainers however are not so keen on supporting scanning for beacons with their command=line tools as there is a concern that such activity is quite resource intensive.
Many tutorials on the internet are done with command-line tools with the now deprecated tools of hcitool and hcidump. This 'HowTo' looks at how to scan for beacons without using those tools.
The go-to tool when using Bluetooth from the Linux command-line is bluetoothctl
.
In a terminal use the BlueZ command-line tool to put the RPi3 into scanning mode by issuing the `scan on` command. It is also a good idea to clear all filtering options. My session looked like this:
pi@RPi3:~ $ bluetoothctl [bluetooth]# set-scan-filter-clear SetDiscoveryFilter success [bluetooth]# scan on Discovery started [CHG] Controller B8:27:EB:22:57:E0 Discovering: yes [CHG] Device F1:55:90:65:29:DC RSSI: -55 [CHG] Device F1:55:90:65:29:DC ServiceData Key: 0000feaa-0000-1000-8000-00805f9b34fb [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0xf6 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x21 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x09 [bluetooth]# scan off
The 16-bit UUID for the Eddystone Service is 0xfeaa.
Once we know the Service UUID we can filter to see just Eddystone beacons in bluetoothctl. For example:
[bluetooth]# set-scan-filter-uuids 0xfeaa SetDiscoveryFilter success [bluetooth]# scan on Discovery started [CHG] Controller B8:27:EB:22:57:E0 Discovering: yes [CHG] Device F1:55:90:65:29:DC RSSI: -76 [CHG] Device F1:55:90:65:29:DC RSSI: -78 [CHG] Device F1:55:90:65:29:DC ServiceData Key: 0000feaa-0000-1000-8000-00805f9b34fb [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0xf6 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x21 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x0a
In this example it has not made any difference. However, if you have other Bluetooth devices advertising nearby it will be very helpful to reduce how much is reported.
To view all the activity on the RPi's Bluetooth controller there is a Bluetooth monitoring tool from BlueZ called "btmon". This has a very verbose output as it does tell us everything that is happening with the Bluetooth controller and is typically used for debugging low-level issues.
To run btmon in a terminal use the following command:
sudo btmon
With bluetoothctl scanning in the first terminal, btmon will report such things as an "LE Advertising Report" which will contain information about nearby devices that are advertising. Our beacon should be in amongst all the output in btmon. For example:
> HCI Event: LE Meta Event (0x3e) plen 41 [hci0] 1316.838336 LE Advertising Report (0x02) Num reports: 1 Event type: Non connectable undirected - ADV_NONCONN_IND (0x03) Address type: Random (0x01) Address: F1:55:90:65:29:DC (Static) Data length: 29 Flags: 0x06 LE General Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Google (0xfeaa) Service Data (UUID 0xfeaa): 00f600000000000000000021000000000009 RSSI: -55 dBm (0xc9)
Beacons are broadcasting/advertising very frequently (every second or so) and you will notice that the BlueZ tools are not reporting all occurrences of those adverts. This is because the BlueZ tools are filtering duplicate adverts. This is done because of concerns about the machine resources being consumed in doing such activity.
The BlueZ project has deprecated the command-line tool hcitool
that did allow this. This is because
the tool used the Host Controller Interface
(HCI) which is a very low-level interface and did not protect
the user from being able to do very bad things to their system. The new BlueZ tools give the user more protection
however it does mean the tools do not report duplicates.
btmon
using the following command:
sudo hcitool lescan --duplicates
Some of the Bluetooth libraries that act as scanners can read all beacon broadcasts.
One of the best Python libraries I've found for scanning for beacons is aioblescan.
Much of what is described above should work for any BLE beacons. I've focused on Eddystone as it is an open specification and most widely supported. One interesting place that has Eddystone support is the MakeCode editor for micro:bit which supports very easy access to programming Eddystone beacons.
Jos Ryke (@josryke) has posted on Twitter a great summary on how the packets vary between the different beacon types.
With the aid of Jos's diagram and the
Generic Access Profile specification we can see that Eddystone adverts have a type of 03
(Complete List of 16-bit Service Class UUIDs) where as ibeacon has a type of FF
(Manufacturer Specific Data).
This means data being broadcast is reported slightly differently. For example, for ibeacon the Major and Minor values are Manufacturer Data while for Eddystone UID Namespace and Instance values are Service Data.
In bluetoothctl this presents itself as the following:
For ibeacon:
[CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Key: 0x004c [CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Value: 0x10 [CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Value: 0x05 [CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Value: 0x0b [CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Value: 0x10 [CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Value: 0x88 [CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Value: 0xed [CHG] Device 56:9E:9F:3D:3A:EB ManufacturerData Value: 0x6e [CHG] Device 56:9E:9F:3D:3A:EB RSSI: -80And for Eddystone UID:
[CHG] Device F1:55:90:65:29:DC ServiceData Key: 0000feaa-0000-1000-8000-00805f9b34fb [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0xf6 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x21 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x00 [CHG] Device F1:55:90:65:29:DC ServiceData Value: 0x09
By looking at the list Company Identifiers we can learn that the ManufacturerData Key of 0x004c is for Apple.