This document is a guide for creating Java* IoT applications that can access remote Bluetooth® low energy devices on IoT platforms, such as the Intel® Edison development board. Support for developing these applications is provided as part of the Intel® IoT Developer Kit, using the open source TinyB project. TinyB exposes simple C++ and Java APIs for using Bluetooth low energy devices. This guide will only cover developing applications using the Java API in TinyB on the Intel® Edison development board.

Compatibility and requirements

The current Bluetooth® API in TinyB has been tested with the Java 8 runtime environment (OpenJDK 8). This environment as well as TinyB are provided as part of the official Intel® IoT Developer Kit image builds for Intel® Edison boards.

On other Linux-based systems, TinyB can be used as long as BlueZ* version 5.37 or newer is installed and the bluetoothd daemon has been started with experimental features enabled (-E flag). More details can be found in the online README file.

In this guide, the TinyB application uses a Texas Instruments* Sensor Tag as a Bluetooth low energy device.

Documentation and application examples

The documentation for the Bluetooth low energy API exposed by TinyB can be found online at the following locations:

The HelloTinyB (or hellotinyb for C++) example uses a Texas Instruments Sensor Tag, from which it reads the ambient and object temperature. The application requires the MAC address of the Sensor Tag as a first parameter to the program (XX:XX:XX:XX:XX:XX in the following example).

./examples/hellotinyb XX:XX:XX:XX:XX:XX

java -cp examples/java/HelloTinyB.jar:/usr/lib/java/tinyb.jar HelloTinyB XX:XX:XX:XX:XX:XX

Writing a Bluetooth low energy Java* IoT application

We will use the HelloTinyB Java sample found in the TinyB repository as an example showing how to write a program that reads data from a GATT Service over Bluetooth low energy. A wiki entry describing the Texas Instruments Sensor Tag device can be found here: http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User's_Guide.

To start looking at the device, we first must initialize the TinyB library. A BluetoothManager object provides an entry point for using Bluetooth devices. There can be only one BluetoothManager at one time, and the reference to it is obtained through the getBluetoothManager() method.

BluetoothManager manager = BluetoothManager.getBluetoothManager();

The manager will try to initialize a BluetoothAdapter if any Bluetooth adapter is present in the system. To initialize discovery we can call startDiscovery(), which will put the default adapter in discovery mode.

boolean discoveryStarted = manager.startDiscovery();

We should expect to see the following output:

The discovery started: true
Address = C4:BE:84:72:2B:09 Name = CC2650 SensorTag Connected = false 

After discovery is started, new devices will be detected. We can get a list of all devices through the manager's getDevices() method. We can look through the list of devices to find the device with the MAC address that we provided as a parameter. We continue looking until we find it, or until we have tried 15 times without success (about 1 minute).

static BluetoothDevice getDevice(String address) throws InterruptedException  {
    BluetoothManager manager = BluetoothManager.getBluetoothManager();
    BluetoothDevice sensor = null;
    for (int i = 0; (i < 15) && running; ++i) {
        List<BluetoothDevice> list = manager.getDevices();
         for (BluetoothDevice device : list) {
             * Here we check if the address matches.
            if (device.getAddress().equals(address))
                sensor = device;
        if (sensor != null) {
            return sensor;
    return null;
Afterwards, we can run the connect method on the returned device. The output should be as follows:
Found device: Address = C4:BE:84:72:2B:09 Name = CC2650 SensorTag Connected = false 
Sensor with the provided address connected

Our device should expose a temperature service, which has a UUID we can find out from the data sheet. The service description of the SensorTag can be found here: http://processors.wiki.ti.com/images/a/a8/BLE_SensorTag_GATT_Server.pdf. The service we are looking for has the short UUID AA00, which we insert into the TI Base UUID instead of the XXXX: f000XXXX-0451-4000-b000-000000000000.

static BluetoothGattService getService(BluetoothDevice device, String 
 UUID) throws InterruptedException {
    System.out.println("Services exposed by device:");
    BluetoothGattService tempService = null;
    List<BluetoothGattService> bluetoothServices = null;
    do {
        bluetoothServices = device.getServices();
for (BluetoothGattService service : bluetoothServices) { System.out.println("UUID: " + service.getUuid()); if (service.getUuid().equals(UUID)) tempService = service; } Thread.sleep(4000); } while (bluetoothServices != null && bluetoothServices.isEmpty() && running); return tempService; }

The code above should produce the following output:

Services exposed by device:
UUID: f000aa64-0451-4000-b000-000000000000
UUID: 0000180a-0000-1000-8000-00805f9b34fb
UUID: f000ccc0-0451-4000-b000-000000000000
UUID: f000ac00-0451-4000-b000-000000000000
Found service f000aa00-0451-4000-b000-000000000000

First of all, we should obtain the characteristics of this service. There are three of them: the value (UUID AA01), configuration (AA02), and period (AA03). We can obtain them using the following code:

static BluetoothGattCharacteristic getCharacteristic(BluetoothGattService service, String UUID) {
    List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
    for (BluetoothGattCharacteristic characteristic : characteristics) {
        if (characteristic.getUuid().equals(UUID))
            return characteristic;
    return null;
BluetoothGattCharacteristic tempValue = getCharacteristic(tempService, "f000aa01-0451-4000-b000-000000000000"); BluetoothGattCharacteristic tempConfig = getCharacteristic(tempService, "f000aa02-0451-4000-b000-000000000000"); BluetoothGattCharacteristic tempPeriod = getCharacteristic(tempService, "f000aa03-0451-4000-b000-000000000000");

We need to turn on the Temperature Service by writing 1 in the configuration characteristic, as mentioned in the PDF above. We could also modify the update interval by writing in the period characteristic, but the default value of 1s is good enough for our purposes.

byte[] config = { 0x01  };

After this configuratio,n we should be able to read the temperature from the device. The temperature service returns the data in an encoded format, which can be found in the wiki entry for the Sensor Tag device. Convert the raw temperature format to Celsius and print it. Conversion for object temperature depends on ambient temperature according to the wiki, but we will assume the result without conversion is good enough for our purposes.

while (running) {
    byte[] tempRaw = tempValue.readValue();
    System.out.print("Temp raw = {");
    for (byte b : tempRaw) {
        System.out.print(String.format("%02x,", b));
int objectTempRaw = tempRaw[0] + (tempRaw[1] << 8); int ambientTempRaw = tempRaw[2] + (tempRaw[3] << 8);
float objectTempCelsius = convertCelsius(objectTempRaw); float ambientTempCelsius = convertCelsius(ambientTempRaw);
System.out.println(String.format(" Temp: Object = %fC, Ambient = %fC", objectTempCelsius, ambientTempCelsius));
Thread.sleep(1000); }

Running this loop will print the temperature values collected from the Bluetooth low energy sensor:

Temp raw = {10,0b,c8,0d,} Temp: Object = 22.125000C, Ambient = 25.562500C
Temp raw = {10,0b,c8,0d,} Temp: Object = 22.125000C, Ambient = 25.562500C
Temp raw = {04,0b,cc,0d,} Temp: Object = 22.031250C, Ambient = 25.593750C
Temp raw = {34,0b,cc,0d,} Temp: Object = 22.406250C, Ambient = 25.593750C

Known limitations

The API used in this example is based on TinyB v0.3, which only supports polling, but v0.4 will introduce a simplified API for discovering devices and services.

Legal Information

Intel, the Intel logo, Intel Atom, Intel Core, Intel Xeon Phi, VTune and Xeon are trademarks of Intel Corporation in the U.S. and/or other countries.

*Other names and brands may be claimed as the property of others.

Java is a registered trademark of Oracle and/or its affiliates.

Copyright 2016-2018 Intel Corporation.

This software and the related documents are Intel copyrighted materials, and your use of them is governed by the express license under which they were provided to you (License). Unless the License provides otherwise, you may not use, modify, copy, publish, distribute, disclose or transmit this software or the related documents without Intel's prior written permission.

This software and the related documents are provided as is, with no express or implied warranties, other than those that are expressly stated in the License.

For more complete information about compiler optimizations, see our Optimization Notice.