Especially when working with Bluetooth Beacons like iBeacon or Eddystone, you will often want to use embedded hardware to create a low-cost, always running system. This short guide explains how to read Bluetooth Beacon messages using the Arduino 101 / Genuino 101 board.
The Arduino / Genuino 101 already includes a Bluetooth chipset and is based on the Intel Curie platform. You can use the same Arduino IDE as for all the other variants of the Arduino Board.
Intel Curie Board and CurieBLE Library
Make sure that you have the board support installed in your Arduino IDE through: Tools > Board > Boards Manager > Intel Curie Boards by Intel.
Next, select the board as the active board through: Tools > Board -> Arduino / Genuino 101 (Note: do not select the Genuino UNO, that’s different – the 101 variant is at the bottom of the list).
Also make sure that you have the CurieBLE library installed and up-to-date (Sketch > Include Library > Library Manager…). This provides the necessary functionality to interact with the Bluetooth LE functionality of the Arduino 101.
Bluetooth LE Scan Example
Make sure your board is connected and recognized (test with Tools > Port, and with Tools > Get Board Info). Next, open the “Scan” example from File > Examples > CurieBLE > Central > Scan.
This should now already run fine through the Upload button in the toolbar.
Note: to see the output, of the example, you need to open Tools > Serial Monitor. On my PC, sometimes opening the Serial Monitor fails with the message that the port is already in use. Best is to open it only after the app is already running on the board.
Analyzing Eddystone Bluetooth Beacons
With the out-of-the-box Scan example, you can already recognize Eddystone Bluetooth beacons. They have the Service UUID “FEAA”, which is shown by the example.
The next step would be to read the actual service data from the Eddystone advertisment. This is not part of the CurieBLE examples, so I searched for other implementations by the Arduino community.
Note that the Bluetooth LE library by Sandeep Mistry is not compatible to the Arduino / Genuino 101 and as such can not be used directly. It would have been nice, as it contains ready-made iBeacon and Eddystone implementations. However, the CurieBLE library is promised to be 99% compatible to the implementation by Sandeep, so his examples can be used as reference when working with the CurieBLE lib.
The example by Bradford Needham is based on a modified version of the CurieBLE lib, which adds a method to read the service data. The CurieBLE library has since then been changed also based on his Pull Request, but not in a way that remains compatible to the example sketch by Bradford.
Instead, the CurieBLE library was extended in a way more compatible to the library by Sandeep. As such, it should be possible to read the Eddystone service data through the BLECharacteristic
. See the EddystoneBeacon implementation by Sandeep for reference.
Analyzing iBeacon
Apple iBeacons have the Apple Manufacturer ID set to 4C. The example does not read and show the value.
However, if you take a look at the source code of the CurieBLE library, you will see that the CurieBLE library has support for getting the manufacturer data. By default, the library is installed in your user directory, e.g.:
C:\Users\[Username]\AppData\Local\Arduino15\packages\Intel\hardware\arc32\2.0.2\libraries\CurieBLE\src
In BLEDevice.h
, you will find the method getManufacturerData()
, which is just what we need. Add the following code in the example to read and print the manufacturer data. This code also converts the byte array to a human-readable hex string, so that you can easily recognize the contents:
// print the manufacturer data if (peripheral.hasManufacturerData()) { Serial.print("Manufacturer Data: "); unsigned char manu_data[255]; unsigned char manu_data_length; bool success = peripheral.getManufacturerData (manu_data, manu_data_length); if (success) { int i; char* buf_str = (char*) malloc (2*manu_data_length + 1); char* buf_ptr = buf_str; for (i = 0; i < manu_data_length; i++) { buf_ptr += sprintf(buf_ptr, "%02X", (unsigned char)manu_data[i]); } *(buf_ptr + 1) = '\0'; Serial.println(buf_str); free(buf_str); } }
If you run the extended code, you will see the Manufacturer Data printed as well:
The second peripheral is the iBeacon. You can recognize the Apple ID 4C at the beginning of the data. The rest of the data also contains the advertised iBeacon UUID “1EFC34D3…” – see the simulator screenshot. Now, you just need to parse the bytes out of the data array, according to the iBeacon specification and developer agreement.
For simulating the beacons, I used the free Beacon Simulator app for Android.
Conclusion
With the Beacon Simulator and an Android phone, it’s easy to play around with various beacons. To work with embedded hardware and beacons, you can use the Arduino / Genuino 101 board, which has Bluetooth LE on board.
This guide shows how to work with the board to read Bluetooth Beacon data. For working with iBeacons, I’ve written a short code snippet to read the Manufacturer Data from the beacon advertisement for the Intel CurieBLE library.
Recognizing Eddystone beacons works with the off-the-shelf example included in the official library. Parsing their data would require a bit more research, though – but it should be possible and easy to do thanks to the Arduino community!