Bluetooth Low Energy is awesome. The problem, even in 2019, it’s still can be tough to work with.
In this article, you’ll learn the in’s and outs of Bluez. It’s Linux’s answer to connecting and using Bluetooth devices from the command line. It’s open source and it’s easy to use.
First, lets discuss the most important tools that are included with the Bluez stack.
Sidenote: things have changed a bunch since I first wrote this. It’s becoming much easier to create Bluetooth based hardware. I’ll show you how much in this handy how-to.
Get Acquainted With The Tools
hcitool
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
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. If you need a helping hand installing Debian may I suggest this step-by-step guide?
-
Get the latest Bluez source:
wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.18.tar.xz
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
-
Install dependencies
sudo apt-get install libglib2.0-dev libdbus-1-dev libusb-dev libudev-dev libical-dev systemd libreadline-dev
-
Run configure
.configure --enable-library
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
gatttool
to your/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.
-
Check if
hcitool
can see your device:hcitool dev
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.
F4:C7:F8:0A:BF:C9 TWI
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.
-
Open
gatttool
sudo gatttool -b <BLE ADDRESS> -I
Where
<BLE ADDRESS>
is the address you obtained in the earlier steps.-I indicates you want to open up an interactive session
-
Once open, type
connect
to connect.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 runsudo hcitool lescan
before openinggatttool
. -
Get the primary UUIDs
primary
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
char-desc
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
Remember, a handle is a sequential number generated by Bluez which is tied to a specific characteristic. You can use the output of
char-desc
to relate the characteristic UUID to each open handle. -
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:char-read-hnd <handle>
So, when I run
char-read-hnd 0x0001
I 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 0100
I 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
More resources
As you can imagine, there’s more to learn when it comes to BLE. Here are some links:
- How to use Particle’s New Bluetooth Low Energy Api to make connected hardware easy
- How to use Protobuf to Enhance Your Bluetooth Enabled Device (A 3 part series)
- How to Optimize Bluetooth Device battery life using a few simple tools.
Moving forward
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!
In the meantime subscribe below to my list if you haven’t already and i’ll see you on the next one!
👇👇👇👇
Last Modified: 2021.5.18