Starting with Bluetooth LE on the Raspberry Pi

Raspberry Pi 2B

Hinweis: Diesen Blog schreibe ich ausnahmsweise auf Englisch, weil das Thema für viele Rasperry-Pi-Bastler interessant sein könnte.

Some days ago I started a project where I assembled a Bluetooth low energy (BLE) device that sends out some sensor data. In addition to reading these data with a smartphone I also want to receive and process them with a Raspberry Pi. However, it turned out that working with BLE on the Raspberry Pi is not as easy as I thought, especially if you want to write applications in Java or C/C++.

Finally I found a way to do it, and I would like to share it here for people who are looking for an easy entry into the world of BLE on the Raspberry Pi.

As prerequisites you need nothing more than a current Raspbian Jessie installation and a Bluetooth LE capable USB stick. The latter might not be necessary for a Raspberry Pi 3 since it should have Bluetooth already on board. And of course, a BLE device to test your setup is also quite helpful.

The setup procedure for the stuff you need to develop BLE applications consists of three steps:

  1. Install and test the bluez software stack
  2. Install cmake
  3. Install and test the tinyb library from the Intel® IoT Developer Kit.

If you want to work with Python you can stop already after the first step and try for instance the library from Adafruit (https://github.com/adafruit/Adafruit_Python_BluefruitLE) or the one from Ian Harvey (https://github.com/IanHarvey/bluepy).

1. Install and test bluez

If you look at the bluez web page (www.bluez.org) you will find that it is the “official Linux Bluetooth stack”. But what does that mean?

After installing bluez you can communicate with Bluetooth devices by using the D-Bus message bus system. A good introduction to that topic can be found in the paper “Playing BlueZ on the D-Bus”.

You might notice that the Raspbian Jessie installation already comes with bluez installed. However, it is an old version and BLE support is still patchy. So it’s best to remove it and install the latest version, which was 5.43 at the time of writing. The following command does the job:

> sudo apt-get --purge remove bluez

After you removed the old bluez installation you can do the following:

> sudo apt-get update
> sudo apt-get install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
> cd ~
> wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.43.tar.gz
> tar xvf bluez-5.43.tar.gz
> cd bluez-5.43
> export LDFLAGS=-lrt
> ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-library -disable-systemd
> make
> sudo make install
> sudo cp attrib/gatttool /usr/bin/
> sudo cp ./src/bluetoothd /usr/local/bin/
> hash -r
> sudo nano /etc/rc.local

Scroll to the end of file and just before the ‚exit 0‘ line add the following line

/usr/local/bin/bluetoothd --experimental &

Press Ctrl-O and enter to save the file, then Ctrl-X to exit the editor. The experimental parameter is important since without it some needed plugins will not be loaded.

After you have done all that you should be able to communicate with your BLE device. But first you might have to switch on the BLE stick on the Raspberry.

Check if the Bluetooth hardware is switched on by entering

> hciconfig

If it is down just enter

> sudo hciconfig hci0 up

After that try the following

> sudo hcitool lescan

If you see your BLE devices listed you are nearly done. You should now test if you can connect to a device in the list. But take care: It is important to choose the correct address type (random or public). My device had “random” device address which means that the module uses a 48-bit address that was randomly generated during the manufacturing process.

To test the connection to a BLE device that was discovered by the scan you can enter:

> sudo hcitool lecc --random <address>

where you replace <address> with the BLE device address (MAC address format XX:XX:XX:XX:XX:XX). Alternatively, for an interactive session you can use:

> sudo gatttool -t random -b <address> -I

In both commands you should omit the “random” parameters if your device has a public address.

2. Install cmake

Although cmake can be installed by using the package manager (apt-get) you will only get an old version. To install the tinyb library later we need a newer version that can be installed by the following commands.

If you already installed the version from the repository remove it with

> sudo apt-get --purge autoremove cmake

Afterwards just execute the following lines (assuming 3.6.2 is the current stable release):

> sudo apt-get install build-essential
> cd ~
> wget http://www.cmake.org/files/v3.6/cmake-3.6.2.tar.gz
> tar xvf cmake-3.6.2.tar.gz
> cd cmake-3.6.2
> ./configure
> make
> sudo make install
> hash -r

Consider having some coffee during installation since it really takes time to configure the Makefile and build cmake.

Since cmake does not configure the currently installed JDK you can either manually correct the following file

/usr/local/share/cmake-3.6/Modules/FindJNI.cmake

or (as I did) just export the following variables (replace the path with your JDK installation directory; I used Java 8 JDK from Oracle):

export JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt
export JAVA_AWT_LIBRARY=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/libawt.so
export JAVA_JVM_LIBRARY=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/server/libjvm.so
export JAVA_INCLUDE_PATH=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include
export JAVA_INCLUDE_PATH2=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include/linux
export JAVA_AWT_INCLUDE_PATH=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include

These export statements are important to correctly build the tinyb library for Java.

3. Install tinyb

tinyb (https://github.com/intel-iot-devkit/tinyb/) is a BLE library from the Intel® IoT Developer Kit. If you want to develop applications in Java or C/C++ and do not want play with D-Bus yourself it is extremely helpful. With bluez and cmake set up as described before it should be a piece of cake.

Just do the following:

> cd ~
> git clone https://github.com/intel-iot-devkit/tinyb
> cd tinyb
> mkdir build
> cd build
> cmake -DBUILDJAVA=ON ..
> make
> sudo make install

That should have been everything. To test if tinyb is working you can execute the following commands:

> cd ~/tinyb/build
> sudo ./examples/hellotinyb <address>

Or for Java:

> cd ~/tinyb/build
> sudo su
> export LD_LIBRARY_PATH=/usr/local/lib
> java -cp examples/java/HelloTinyB.jar:/usr/local/lib/java/tinyb.jar HelloTinyB <address>
> exit

Although the HelloTinyB programs were designed to work with the TI sensor tag they should be able to discover the BLE device and list its services.

The Java and C++ examples coming with the tinyb library should be sufficient to start building your own applications. In addition the Intel web page https://software.intel.com/en-us/java-for-bluetooth-le-apps contains an introduction for how to write a BLE Java application.

Final Remarks

I hope this little blog can help you to start writing BLE applications quickly without spending too much time to setup the BLE basic stack on the Raspberry Pi. If you find it helpful please leave me a comment.

And finally, for a general introduction to BLE I can highly recommend this guide from Adafruit: https://learn.adafruit.com/introduction-to-bluetooth-low-energy/introduction.

PS: Stay tuned for the blog about setting up my BLE sensor project.

28 Gedanken zu „Starting with Bluetooth LE on the Raspberry Pi“

  1. Hi MichaelHaugk,

    I follow your guide for my raspberry pi 3, but after install bluez 5.43, I had checked by cmd: systemctl status bletooth
    ● bletooth.service
    Loaded: not-found (Reason: No such file or directory)
    Active: inactive (dead)

    So, could you help active bluetooth device on Raspberry pi 3?

    1. Hi thanhlu,

      It’s perfectly fine that you don’t see bluetooth running as a service since the „disable-systemd“ switch was used in the configure-command for bluez. If you followed my instructions above you should see the bluetooth daemon running if you enter (it was started using „rc.local“): ps -eF | grep bluetoothd

      All the other commands should work as well (e.g. sudo hcitool lescan). This means bluetooth le is working well.

      If you would like to install the daemon as a service, I can recommend this page from Adafruit since some more steps are involved: https://learn.adafruit.com/install-bluez-on-the-raspberry-pi/installation

      Please let me know, if you still experience problems with bluetooth.

      Best regards,
      Michael

  2. Thanks for the helpful blog. I have a problem setting parameter JDK Oracle:

    export JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt
    export JAVA_AWT_LIBRARY=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/libawt.so
    export JAVA_JVM_LIBRARY=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/server/libjvm.so
    export JAVA_INCLUDE_PATH=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include
    export JAVA_INCLUDE_PATH2=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include/linux
    export JAVA_AWT_INCLUDE_PATH=/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include

    In my case JDK is located in /usr/local/java/jdk1.7.0_79….but i cannot find inside jre/lib any arm folder….infact when i launch cmake i got errors.
    Can you help me please?

    1. Hi Alex,

      As long as the libraries are present in your jdk installation there shouldn’t be any general problem. Just try to find the path where the libraries are located in your local java installation, e.g. by
      cd /usr/local/java/
      find . -name "libawt.so" -print
      .
      Then you just can set the paths correctly (see e.g. https://cmake.org/cmake/help/v3.0/module/FindJNI.html ).

      Once you know where the libraries are you can alternatively modify FindJNI.cmake, see for example: http://stackoverflow.com/questions/17636166/cmake-find-packagejni-not-work-in-ubuntu-12-04-amd64 ).

      Hope that this helps. Please let me know.

      Best regards,
      Michael

      1. Hi Micheal, thanks for your help. Really appreciate. I removed the build folder inside tinyb with older JVM include and now I can create the tinyb.jar needed for my BLE project.
        Now I have to communicate from my desktop PC to a Bluetooth LE 4.0., I included tinyb.jar in classpath and try the Intel example „HelloTinyb.class“. When I try to launch it, i have this exception:

        Native code library failed to load.
        java.lang.UnsatisfiedLinkError: no javatinyb in java.library.path

        Can you please help me? Thanks in advance

  3. Hi Alex,

    you need to tell Java where the native library „libjavatinyb.so“ is located. In my case it is installed in „/usr/local/lib“.
    Therefore, I used „export LD_LIBRARY_PATH=/usr/local/lib“ before executing Java. If you followed my instructions above, the library is probably installed in the same directory and the command to set the environment variable should work for you as well.

    Best regards,
    Michael

  4. Hi again Micheal, resolved starting Eclipse in a bash with: export LD_LIBRARY_PATH=/usr/local/lib
    Not working using Run Configurations VM arguments.
    Resolved one problem, here now with a new one:
    When i try to connect (in my case):

    BluetoothDevice sensor = getDevice(„D0:4E:4A:11:CB:C7“);
    boolean connect = sensor.connect();

    I got an exception:
    Exception in thread „main“ tinyb.BluetoothException: GDBus.Error:org.bluez.Error.Failed: Software caused connection abort

    Thanks in advance for any reply.
    Bye

    1. Hi Alex,

      I’m afraid that I cannot help you here without further analysis or debugging. And the GDBus interface has some flaws you might need to work around.

      My best advice would be: Before you start to work with tinyb make sure everything else (i.e. your bluetooth setup) works correctly. Use the gatttool in interactive mode (see above) and if the session is started enter „connect“. If this works and you can read and/or write to the services of your device using the gatttool it should work with tinyb as well. With that you also make sure that your devices advertises everything correctly and the services are working as expected (if you built and programmed your own BLE device).

      In a second step you need to make sure that you really get a valid device back from your method call above.

      Once that also works your program will probably run without exceptions.

      Best regards,
      Michael

  5. Is it possible to use these steps to build Bluez 5.44 without –enable-deprecated? The steps aren’t working for me for this latest Bluez version.

    1. I still didn’t find the time to update this guide to reflect the changes in 5.44. I guess as long as you rely on the D-Bus interface it should work fine. However, I need to check.

  6. Hi Michael. Thanks so much for writing this up. My problem is that after following step 1 my raspberry pi 3 bluetooth adapter stops working. It says no adapter found. I tried with external dongle as well but can’t seem to find any adapter. Basically after executing „sudo apt-get –purge remove bluez“ it removes not only bluez but also firmware for bluetooth and even after installing bluez-5.43 it never comes up.
    >bluetoothd -v
    5.43
    >sudo systemctl status bluetooth● bluetooth.service
    Loaded: not-found (Reason: No such file or directory)
    Active: inactive (dead)

    >sudo hciconfig hci0 up
    Can’t get device info: No such device
    >sudo bluetoothctl
    [bluetooth]# show
    No default controller available
    >sudo hcitool lescan
    Could not open device: No such device

    1. Hi Amit,

      Thank you very much for your feedback.

      Removing bluez should usually not remove any drivers. However, since I didn’t check the latest Debian/Raspbian versions I don’t know if it is still necessary to remove bluez or if a version is included that is supported by tinyb.

      But just to check: You see the bluetooth devices on a freshly installed OS?

      Best regards,
      Michael

  7. What can I say ? THANK YOU

    I’ve been struggling with BLE for 5 days now, and I finally made it, thanks to you !

    I just had to install cmake with apt-get install, cause when I was doing it manually, ‚./configure‘ was making an error (file not found)

    But I finally suceeded, connected my BLE Arduino Feather 32u4 with ‚bluetoothctl‘ (and not hcitool !) and then I ran the example, and IT WORKED !

    Thanks a lot, you just saved my school project !

    1. Hello. I’m trying to setup a connection between Adafruit Feather 32u4 and my laptop. Can you please let me know how did you do it using „bluetoothctl“ and were you running an example script on the feather board?

  8. Hi Michael,

    congratulations — this is a very good article, and at last I’ve managed to get a working Bluetooth system on my Pi. At least as far as the examples go. But I need a bit of help: I’m a bit new to Linux and raw GCC (G++), having done all my previous development on IDE’s which offer a front end (eg Xcode on Mac OS).

    As in your tutorial, everything worked great, including using the built version of hellotinyb

    As a first step to writing my own software, I’ve simply tried compiling the vanilla hellotinyb.cpp example, having first copied it to a new directory (as my own code will be in such a new directory).
    If I try a simple g++ hellotinyb.cpp -o hello, I get an error becasue tinyb.hpp isn’t found. If I add -I ~/tinyb/api (which is where it is), G++ generates pages of errors, including from the standard libraries. Something is wrong.

    Can you offer any suggestions?

    thanks,
    Richard

    1. Solved, after a night’s sleep!

      We had many power cuts on the day I was building the package and eventually I didn’t run the make install command!

      Then after extending the scrollback (a lot!) I could find the initial errors saying that I need to include the option -std+gnu++11.

      After specifically including the library (-ltinyb) everything seems good.

      cheers,
      Richard

  9. Thx very much for this guide, it helped me get my first BLE project running on the RPI. Very much appreciated!

    Furtunately: in the September release of Raspbian, the versions of bluez and cmake are now up to date, and can be apt-getted, so steps 1 and 2 are now out-of-date.

    Inspired by your guide, I wrote a small post on the new situation: https://nisone.wordpress.com/2017/09/30/java-bluetooth-low-energy-on-the-raspberry-pi-3-september-2017-update/

  10. I faced below DBUS related issue. Installed on my Ubuntu PC.

    Issue logs:

    Exception in thread „main“ java.lang.RuntimeException: Error getting object manager client: Error calling StartServiceByName for org.bluez: GDBus.Error:org.freedesktop.DBus.Error.Spawn.ChildExited: Launch helper exited with unknown return code 1
    at tinyb.BluetoothManager.getNativeAPIVersion(Native Method)
    at tinyb.BluetoothManager.getBluetoothManager(BluetoothManager.java:304)
    at HelloTinyB.main(HelloTinyB.java:109)

    Please help

  11. Hallo,
    danke für dein Tutorial, das hat mir schon sehr viel geholfen.
    Ich würde gerne das Java example abändern auf meine Bedürfnisse und würde gerne wissen wie ich denn dann daraus die .jar File compelieren kann?

    Ich sehe den Wald vor lauter Bäume nicht mehr 🙂

    Danke schon mal

    Gruß Pano

    1. Hallo Pano,

      Vielen Dank für die positive Rückmeldung!

      Zum Java-Paket erstellen:
      Nach dem Compilieren kann man das JAR-File manuell erstellen, wenn man möchte: https://docs.oracle.com/javase/tutorial/deployment/jar/build.html

      Auf der anderen Seite verwende ich selbst eine IDE (Eclipse), bei der man fertige (compilierte) Java-Projekte einfach per Maus-Click als JAR-File exportieren kann. Ich denke, das ist die einfachste Möglichkeit.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.