In this post I'll show you how to turn the Arduino YUN into an iBeacon transmitter.
For those who didn't hear about iBeacon yet, I can say it's a new technology built into the latest version of iOS, which allows proximity tracking using Bluetooth Low Energy.
iBeacon-enabled apps can provide the user for example location-related content in indoor settings. It is also possible to establish an approximation of distance to the iBeacon thus allowing to build precise context aware apps.
Using Arduino YUN also as an iBeacon allows to pack into the same low-device both a transmitter, a webserver and a smart device. Cool uh?
What you need to get started
Aside from a working latest version of the Arduino IDE, you will also need a suitable USB Bluetooth Low Energy dongle.
When I started playing with iBeacons I got a dongle marked C.S.R. and ordered from Amazon for around 11 Euros., I didn't manage to have it working. I don't know if this was due to the fact I was using an older version of the bluez stack. In the meanwhile I lost it: I cannot recommend it, but maybe it works with the instructions provided here.
Next one i tried is the IOGEAR Bluetooth 4.0 USB Micro Adapter (mod. GBU521) got from Ebay for 20 Euro which I can recommend as working.
Configuring iBeacon from the command line
In this section I will explain the single steps that you can execute using the ssh connection of the YUN. First we check if the device is recognized at the USB port:
The device shows up as:
Bus 001 Device 003: ID 0a5c:21e8 Broadcom Corp.
Now we need to setup the Bluetooth modules
root@Arduino:~# opkg update root@Arduino:~# opkg install kmod-bluetooth
The standard Linino distribution for bluez is outdated, you should get this package built for the new Bluez 5.13 version which supports ble, copy it over the Yun and run
root@Arduino:~# opkg install bluez_5.13-1_ar71xx.ipk
Once you installed these you can query if the bluetooth stack found your device using the hciconfig program:
root@Arduino:~# hciconfig hci0: Type: USB BD Address: 00:15:83:64:CB:C4 ACL MTU: 310:10 SCO MTU: 64:8 DOWN RX bytes:501 acl:0 sco:0 events:23 errors:0 TX bytes:369 acl:0 sco:0 commands:22 errors:0
If you get similar output we are on the right way. Let's turn on the hci0 interface:
root@Arduino:~# hciconfig hci0 up root@Arduino:~# hciconfig hci0: Type: USB BD Address: 00:15:83:64:CB:C4 ACL MTU: 310:10 SCO MTU: 64:8 UP RUNNING RX bytes:996 acl:0 sco:0 events:45 errors:0 TX bytes:738 acl:0 sco:0 commands:44 errors:0
With the interface up and running we can setup the iBeacon params.
iBeacons transmit three main parameters, which allow a single iBeacon to be identified by the iOS devices looking for them. These parameters are:
- UUID: a unique identifier shared by all iBeacons handled by a given iOS application. For example this would be the same for all stores of a given company, or all museums in a region.
- major: this single integer number, is meant to identify iBeacons for a given general location, i.e. a specific museum or shop
- minor: another single integer number, which can be used to define the identity of a specific place within a location. i.e. an iBeacon for a specific piece of art within a museum, or a specific stand within a supermarket.
In order to setup our dongle to advertise using Bluetooth LE we must dig a bit into the Bluetooth specification. What we basically do is to send an Host-Controller-Interface command to the dongle telling to start advertising with sending out a specific data block.
It turns out that the magic command to do this is:
root@Arduino:~# hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 <UUID> <MAJOR> <MINOR> <POWER> 00
This tutorial from Adafruit takes at least part of the magic out of this synthax. What we are doing is setting up a
Manufacturer Specific data field on the Bluetooth advertising data:
- 0xFF marks the beginning of the manufacturing specific data bloc
- 0x4C 0x00 is Apple manufacturer code
- 0x02 is the data type
- 0x15 is the length of the remaining data
So we just need to generate a uuid and we are set, for this we can install the uuidgen package:
root@Arduino:~# opkg install uuidgen root@Arduino:~# uuidgen d28c3c18-945a-49b5-809f-d5c09ba095e6
We can now take this UUID and start advertising with the generated UUID, major 0 and minor 0, please not you need to rewrite the UUID in pairs of 2 bytes:
root@Arduino:~# hciconfig hci0 noleadv root@Arduino:~# hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 D2 8C 3C 18 94 5A 49 B5 80 9F D5 C0 9B A0 95 E6 00 00 00 00 C9 00 < HCI Command: ogf 0x08, ocf 0x0008, plen 32 1E 02 01 1A 1A FF 4C 00 02 15 D2 8C 3C 18 94 5A 49 B5 80 9F D5 C0 9B A0 95 E6 00 00 00 00 C9 00 > HCI Event: 0x0e plen 4 01 08 20 00
Turn on advertising
root@Arduino:~# hciconfig hci0 leadv
The board is still scanning for other peripherals, so in order to avoid conflicts it's also necessary to turn it off.
root@Arduino:~# hciconfig hci0 noscan
Testing on iOS
If you have an iOS device (> iphone 4s, >iPad retina and mini), and a developer account, you can test iBeacon discovery with the following Receiver project you can find at:
Please make sure you change the UUID to the one used in the example, in our case
Testing on Android
Not many know that even if iBeacon is an Apple technology, it's fully compatible with the BLE spec. So many of the Android phones and tables supporting BLE can locate and range iBeacons too. There are several iBeacon apps for supported Android devices, like AirLocate.
Please let me know if all works, especially with other dongle models.