Bluetooth Low Energy is an awesome technology. It enables us to connect to every day things that, say 10 years ago, think it would be crazy to do. (Thinking about connecting your phone to your shoes in the early 2000’s. Isn’t it weird?) I have no doubts that connected items will be ubiquitous with every day life. So, why not join the party?
During my initial foray into developing for Bluetooth Low Energy, I took some notes that I feel would benefit everyone. I use a Mac as my primary development platform but unfortunately the SDK is not as easy and open (and you need to rely on mostly closed source tools). Luckily Bluez, the Bluetooth stack for Linux is open source at easy to work with.
First, lets discuss the most important tools that are included with the Bluez stack.
Get Acquainted With The Tools
hcitool is the swiss army knife for Bluetooth in Linux. It is aptly named hcitool as it communicates via a common HCI (Host Controller Interface) port to your bluetooth devices. You can utilize the utility to scan for devices and send commands/data for standard Bluetooth and Bluetooth Low Energy.
gatttool is used to access the “services” running on your bluetooth device. In my case, it was instrumental in accessing the Bluetooth Low Energy services running on my nrf51822. The Bluetooth SIG has already spec’d out several services for general use. More information on these services can be found here.
Install The Tools
In order to use Bluez, I needed to install Linux on a virtual machine. I chose Debian as i’m very used to it since working on Full-Stack. If you need a helping hand installing Debian may I suggest this step-by-step guide?
Get the latest Bluez source:
Note: make sure you uninstall Bluez if it is already installed. (apt-get doesn’t have a very recent version) To check if it’s installed run this command:
dpkg --get-selections | grep -v deinstall | grep bluez
Extract the source
tar xvf bluez-5.18.tar.xz
sudo apt-get install libglib2.0-dev libdbus-1-dev libusb-dev libudev-dev libical-dev systemd libreadline-dev
Note: –enable-library will enable use of the library so you can create your own applications utilizing the Bluez stack
Compile and install the source
make -j8 && sudo make install
The install script does not copy
/usr/local/bin/directory. You must do it manually:
sudo cp attrib/gatttool /usr/local/bin/
Scan For Bluetooth Low Energy Devices
After installing Bluez (and tools) lets see if we can find a Bluetooth Low Energy device.
Note: because my Mac does not have built in Bluetooth Low Energy I am using a cheap Bluetooth Low Energy dongle. These dongles can usually be picked up for around $8.
Attach your Bluetooth device to your VM.
Note: if you get a Failed to attach USB device error, you may need to create a device filter that will autoconnect. More information on creating a device filter here.
hcitoolcan see your device:
My output looked like this:
Devices: hci0 00:15:83:6B:CC:EB
Note: if nothing shows up you may have to reinsert your Bluetooth dongle. (if you’re using one)
Now, run a low energy scan
sudo hcitool lescan
If you device is advertising it should show up.
In my case, the device I’m using is call ‘TWI’ and its address is ‘F4:C7:F8:0A:BF:C9’
Note: you need to make sure your BTLE device is advertising for it to show up.
Connect To Your Bluetooth Low Energy Device
Now that we can see the intended Bluetooth device let’s connect to it.
sudo gatttool -b <BLE ADDRESS> -I
<BLE ADDRESS>is the address you obtained in the earlier steps.
-I indicates you want to open up an interactive session
Once open, type
Note: As long as your BTLE device is still advertising you should the address change to a purple color in the command prompt.
If you get a
connect: No route to host (113), that means the device is not advertising, you’ve used the wrong address or you haven’t run
sudo hcitool lescanbefore opening
Get the primary UUIDs
The command above will generate a list of all the available “services” running on the low energy device. This could give you an idea of what type of functionality the device has (if you have no idea how it works).
An example output is:
attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x0008, end grp handle: 0x000b uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x000c, end grp handle: 0xffff uuid: 0000180f-0000-1000-8000-00805f9b34fb
Get all the available handles
This command generates a list of all the available handles. Handles are the “connection points” where you can read and write access data. For instance, my device has a handle to access battery level data and another to enable automatic reporting of the battery level data.
An example output is:
handle: 0x0001, uuid: 2800 handle: 0x0002, uuid: 2803 handle: 0x0003, uuid: 2a00 handle: 0x0004, uuid: 2803 handle: 0x0005, uuid: 2a01 handle: 0x0006, uuid: 2803 handle: 0x0007, uuid: 2a04 handle: 0x0008, uuid: 2800 handle: 0x0009, uuid: 2803 handle: 0x000a, uuid: 2a05 handle: 0x000b, uuid: 2902 handle: 0x000c, uuid: 2800 handle: 0x000d, uuid: 2803 handle: 0x000e, uuid: 2a19 handle: 0x000f, uuid: 2902 Discover descriptors finished: No attribute found within the given range
Read from a handle
In my case, I know that the handle for reading the battery level is
0x000e. The command to read a handle is as follows:
So, when I run
char-read-hnd 0x000I get a response of:
Characteristic value/descriptor: 64
The result returned is a hexadecimal number which, when converted to decimal, is equal to 100. In this case, this number is the percent battery power left on the device according to the Battery Service definition.
Write to a handle
Now, for giggles, I want to enable notifications for my battery level. I know that, in my case, the handle to enable notifications is
0x000f. The command to write to a handle is as follows:
char-write-req <handle> <data>
So, when I run
char-write-req 0x000f 0100I start receiving battery level messages (if the level has changed) like the following:
Characteristic value was written successfully Notification handle = 0x000e value: 64 Notification handle = 0x000e value: 64 Notification handle = 0x000e value: 64
To disable, I simply run the following:
char-write-req 0x000f 0000
We have only reached the tip of the iceberg in terms of information regarding Bluetooth (and Bluetooth Low Energy). Stay tuned for more Bluetooth Low Energy related posts in the future!