Friday 9 December 2016

Advertising using a BLE beacon in Linux

Beacons are a great way to send brief but important data to nearby scanning objects. They will be a force to be reckoned with in the future i.e. a world full of Internet of Things. In this post I will present a way in which you can advertise like a beacon from a Linux machine with attached or inbuilt Bluetooth low energy hardware. 
Since one expects beacons to advertise constantly, it is more likely that you'll be applying this concept to less consuming computers like your Raspberry Pi's or BeagleBone Black's. 
Let us get on with some primary installation stuff. Most of these things should already be installed on most systems but run these commands just for the sake of it:

sudo apt-get install libusb-dev 
sudo apt-get install libdbus-1-dev 
sudo apt-get install libglib2.0-dev --fix-missing
sudo apt-get install libudev-dev 
sudo apt-get install libical-dev
sudo apt-get install libreadline-dev
sudo apt-get install xclip

After this, you need to start your Bluetooth adaptor (assuming it is BLE supportive, find all about this here). Now lets get to business.
A beacons advertises. You know that. But the next defining thing about beacons is their inability to connect to any scanning device. A beacon just transmits data, it does not engage in a connection with any other BLE device. So the first thing we need to do is get your adaptor advertising in non-connectable mode:

sudo hciconfig hci0 leadv 3
sudo hciconfig hci0 noscan

The number 3 in the above command represents the non-connectable state. To advertise in connectable state use 0 instead and loose the successive "noscan" command.
Your adaptor should be advertising now. Now it is time to put some data in the advertisement. The data to be advertised has to be classified into a type. The beacon must also tell what type of data it is advertising. After all the thing to be advertised will be binary digits only but the way these bits are to be interpreted by the scanner depends on the type of data the bits represent.
The type of data in BLE specs is governed by the UUID which stands for Universally Unique ID. UUIDs are of different types (learn more about them here). The type of UUID we are going to use is a 16 byte UUID.
Since the UUID is 16 bytes long, it can practically be any random number. So go ahead make up any 16 bytes of imaginary data, write them up in hex like so:

63 6F 3F 8F 64 91 4B EE 95 F7 D8 CC 64 A8 63 B5

The command used for sending out data is

sudo hcitool -i hci0 cmd 0x08 0x0008

But it takes a few arguments, one of which is the UUID that we have just covered, now lets look at the rest of the arguments.
The first byte in the argument list is the length of the entire packet to be sent. Lets just assume it to be XX for now, once we have figured out the entire packet then we can come back and fill in the length accordingly.
The rest of the packet is made of structures called AD structures. An advertising packet basically contains, the length field (XX for now) followed by any arbitrary number of AD structures each having a special purpose. An AD structure has the following format:

1 byte for the length of the structure following the length byte (assume this to be n)
1 byte for the type of the AD structure. There are certain types of these structures, each type representing a purpose.
n -1 bytes of data.

Our packet is going to have 2 AD structures.
The first AD structure is to set certain flags. Such AD structures that are used configure flags have the type 01. The value of the structure is the flag mask to be used to configure the flags. The flag mask is only 1 byte long and I am not even going to pretend that I know anything about what these flags mean. You're just going to have to trust me with the value and the value is 1A. So in total the length should be 02 as that is the number of bytes in this AD structure after the first length byte.
The next and last AD structure will eventually contain the payload of this packet which constitutes the value and UUID. We will calculate the length after all the other bytes have been accounted for in this structure. The type of this AD structure is FF. It represents Manufacturer information. The value of this AD structure contains the company ID followed by the payload. The company ID is a two byte code assigned by Bluetooth SIG to top semiconductor industries in the world. The code for STMicroelectronics for example is 00 30 (to be written in the reverse order in the packet). After the company code, there is a byte that represents the number of bytes remaining from here in out in this AD structure. The value for this is 15 in hex which equals to 21 more bytes. 16 of these 21 bytes are the UUID. Following the UUID is your 4 byte data which can be anything of your choice (I am going to use 00 00 00 00). The last byte in the structure is the Tx power with which this signal is to be transmitted.
Let me put this in order and then we can count the number of bytes and substitute that for XX.

XX 02 01 1A 1A FF 30 00 02 15 63 6F 3F 8F 64 91 4B EE 95 F7 D8 CC 64 A8 63 B5 00 00 00 00 C8

So these are 30 bytes following one byte for length. Hence the first byte should be the hex representation for 30 i.e. 1E. Now, finally our command looks like this:

sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 30 00 02 15 63 6F 3F 8F 64 91 4B EE 95 F7 D8 CC 64 A8 63 B5 00 00 00 00 C8

You can now scan the beacon from other BLE devices. I would recommend using the beacon scanner app for Android.

To stop advertising use the following command:

sudo hciconfig hci0 noleadv

1 comment:

  1. Great post, Very informative and well thought out.

    ReplyDelete