How to Get Started with Bluetooth Low Energy on Linux

Jared Wolff · 2014.4.14· 6 Minute Read · engineering · bluetooth low energy · best

Main image

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 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. If you need a helping hand installing Debian may I suggest this step-by-step guide?

  1. 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
  2. Extract the source

    tar xvf bluez-5.18.tar.xz
  3. Install dependencies

    sudo apt-get install libglib2.0-dev libdbus-1-dev libusb-dev libudev-dev libical-dev systemd libreadline-dev
  4. 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

  5. Compile and install the source

    make -j8 && sudo make install
  6. 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.

  1. Attach your Bluetooth device to your VM.

    Virtualbox Add BLTE Device

    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.

  2. Check if hcitool can see your device:

    hcitool dev

    My output looked like this:

            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)

  3. 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.

  1. 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

  2. Once open, type connect to connect.

    Gatttool 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 run sudo hcitool lescan before opening gatttool.

  3. 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
  4. 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

    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.

  5. 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.

  6. 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:

  1. How to use Particle’s New Bluetooth Low Energy Api to make connected hardware easy
  2. How to use Protobuf to Enhance Your Bluetooth Enabled Device (A 3 part series)
  3. 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!


The Ultimate Guide to Particle Mesh Cover

Get Ready for the Ultimate Guide

Signup to get updates on The Ultimate Guide to Particle Mesh. Early subscribers get a discount when it becomes available!

Sign me up!

You may also like

5 Reasons Your Company Needs an Item Master

Business success in a hardware world is centered around the concept of a part. You track inventory by part. You organize your bill of materials (BOM) by part. You track assembly…

Dimming AC Lights With a Micro Controller Part 2

No matter how much you research and design a circuit board, sometimes things still go wrong. And nine times out of ten, it’s due to human error. In part two of Dimming AC lights…

The Steps to a Successful Product

I was stressed out. The startup I was working for just closed its doors. Having a family to take care of, I was on edge. I had a tightness in my chest that didn’t quite go away.…