
Working with Bluetooth LE from Java Applications
- Transfer
Today we’ll talk about how to use Java to create applications for IoT that can work with remote Bluetooth Low Energy devices. Thanks to the open source project TinyB , the development of such applications is supported by the Intel IoT Development Kit. TinyB provides the developer with simple APIs for C ++ and Java that allow you to work with BLE devices. Here we look at the TinyB API for Java, and we will conduct experiments on Intel Edison.

The current version of the Bluetooth API in TinyB is tested in the Java 8 runtime (OpenJDK 8). This environment, like TinyB, comes as part of the official build of the Intel IoT Development Kit image for Intel Edison boards.
On Linux systems, TinyB can be used with BlueZ installed (version 5.37. Or higher). In this case, the bluetoothd daemon is launched with the experimental functions enabled (flag
Here are two documentation options for the Bluetooth API that TinyB provides. Here are materials for those using C ++, and here are for Java developers.
The HelloTinyB example , which is written in Java (or in hellotinyb for C ++) uses the aforementioned SensorTag. It reads indicators about the ambient temperature and the temperature of the object. For the application to work properly, the SensorTag MAC address is required. It must be passed as the first parameter when the program starts:
Here we will use the HelloTinyB example, which is written in Java. It can be found in the TinyB repository . We will show how to write an application that reads data from the GATT service via Bluetooth LE.
In order to start working with SensorTag, you need to initialize the TinyB library. The BluetoothManager object provides an entry point for using Bluetooth devices. A program can have only one instance of this manager object. You can get a link to it using the getBluetoothManager () method :
The manager will try to initialize the BluetoothAdapter object if a Bluetooth adapter is present in the system. In order to start the search for other devices, you need to call the startDiscovery () method , which puts the adapter used by default in search mode:
After executing this command, you can wait for the following debug output:
After starting the search, a new device was found. A list of all found devices can be obtained using the manager method getDevices () . You need to look through this list in order to find the device with the MAC address specified as a parameter when the program starts. The search continues either until the desired device is found, or until 15 attempts are made to detect it (it takes about a minute).
After the desired Bluetooth device is found, you can start the process of connecting to it using the connect method of the object that corresponds to it. Here is what the test output should look like at this stage of work:
The device we are connecting to should give access to the temperature sensing service, whose UUID can be found in the documentation . The service we need has a short UUID AA00 . It must be inserted into the main UUID TI instead of XXXX: f000XXXX-0451-4000-b000-000000000000.
As a result of the above code, the following should be output:
First of all, we need to get the characteristics of the service. There are three such characteristics: value (UUID AA01 ), configuration ( AA02 ) and period: ( AA03 ). We recognize them using the following code:
Now you need to enable the temperature detection service, writing “1” in the configuration characteristic. Details on this are in the above documentation. You can change the interval for updating indicators by writing the desired value to the characteristic of the period, but the default value, “1”, is suitable for us.
After setting, you can start reading temperature information from the device. The temperature service returns data in encoded format. Features of working with this data format can be found in the documentation for SensorTag. We are going to convert the data to degrees Celsius and display them in the console. The temperature of the object, in accordance with the documentation, depends on the ambient temperature. Here we will assume that the results without additional transformations suit us.
During this cycle, temperature information received from the Bluetooth LE sensor will be displayed:
We talked about how to write Java applications that can work with Bluetooth LE devices. It should be noted that the API used in this example is based on TinyB v0.3. This version of the library supports only operation in the device polling mode, but in version 0.4. introduced a simplified API for discovering devices and services.
We hope that what you learned today will help you in developing your own IoT projects.

About compatibility and prerequisites
The current version of the Bluetooth API in TinyB is tested in the Java 8 runtime (OpenJDK 8). This environment, like TinyB, comes as part of the official build of the Intel IoT Development Kit image for Intel Edison boards.
On Linux systems, TinyB can be used with BlueZ installed (version 5.37. Or higher). In this case, the bluetoothd daemon is launched with the experimental functions enabled (flag
–E
). You can read more about this in the README file . In our example, the SensorTag from Texas Instruments acts as a Bluetooth LE device . Details about the device can be found here .Documentation and sample applications
Here are two documentation options for the Bluetooth API that TinyB provides. Here are materials for those using C ++, and here are for Java developers.
The HelloTinyB example , which is written in Java (or in hellotinyb for C ++) uses the aforementioned SensorTag. It reads indicators about the ambient temperature and the temperature of the object. For the application to work properly, the SensorTag MAC address is required. It must be passed as the first parameter when the program starts:
./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
Bluetooth IoT application for working with Bluetooth LE
Here we will use the HelloTinyB example, which is written in Java. It can be found in the TinyB repository . We will show how to write an application that reads data from the GATT service via Bluetooth LE.
In order to start working with SensorTag, you need to initialize the TinyB library. The BluetoothManager object provides an entry point for using Bluetooth devices. A program can have only one instance of this manager object. You can get a link to it using the getBluetoothManager () method :
BluetoothManager manager = BluetoothManager.getBluetoothManager();
The manager will try to initialize the BluetoothAdapter object if a Bluetooth adapter is present in the system. In order to start the search for other devices, you need to call the startDiscovery () method , which puts the adapter used by default in search mode:
boolean discoveryStarted = manager.startDiscovery();
After executing this command, you can wait for the following debug output:
The discovery started: true
Address = C4:BE:84:72:2B:09 Name = CC2650 SensorTag Connected = false
After starting the search, a new device was found. A list of all found devices can be obtained using the manager method getDevices () . You need to look through this list in order to find the device with the MAC address specified as a parameter when the program starts. The search continues either until the desired device is found, or until 15 attempts are made to detect it (it takes about a minute).
static BluetoothDevice getDevice(String address) throws InterruptedException {
BluetoothManager manager = BluetoothManager.getBluetoothManager();
BluetoothDevice sensor = null;
for (int i = 0; (i < 15) && running; ++i) {
List list = manager.getDevices();
for (BluetoothDevice device : list) {
printDevice(device);
/*
* Здесь проверяем, совпадает ли адрес с заданным.
*/
if (device.getAddress().equals(address))
sensor = device;
}
if (sensor != null) {
return sensor;
}
Thread.sleep(4000);
}
return null;
}
After the desired Bluetooth device is found, you can start the process of connecting to it using the connect method of the object that corresponds to it. Here is what the test output should look like at this stage of work:
Found device: Address = C4:BE:84:72:2B:09 Name = CC2650 SensorTag Connected = false
Sensor with the provided address connected
The device we are connecting to should give access to the temperature sensing service, whose UUID can be found in the documentation . The service we need has a short UUID AA00 . It must be inserted into the main UUID TI instead of 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 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;
}
As a result of the above code, the following should be 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 need to get the characteristics of the service. There are three such characteristics: value (UUID AA01 ), configuration ( AA02 ) and period: ( AA03 ). We recognize them using the following code:
static BluetoothGattCharacteristic getCharacteristic(BluetoothGattService service, String UUID) {
List 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");
Now you need to enable the temperature detection service, writing “1” in the configuration characteristic. Details on this are in the above documentation. You can change the interval for updating indicators by writing the desired value to the characteristic of the period, but the default value, “1”, is suitable for us.
byte[] config = { 0x01 };
tempConfig.writeValue(config);
After setting, you can start reading temperature information from the device. The temperature service returns data in encoded format. Features of working with this data format can be found in the documentation for SensorTag. We are going to convert the data to degrees Celsius and display them in the console. The temperature of the object, in accordance with the documentation, depends on the ambient temperature. Here we will assume that the results without additional transformations suit us.
while (running) {
byte[] tempRaw = tempValue.readValue();
System.out.print("Temp raw = {");
for (byte b : tempRaw) {
System.out.print(String.format("%02x,", b));
}
System.out.print("}");
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);
}
During this cycle, temperature information received from the Bluetooth LE sensor will be displayed:
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
Summary
We talked about how to write Java applications that can work with Bluetooth LE devices. It should be noted that the API used in this example is based on TinyB v0.3. This version of the library supports only operation in the device polling mode, but in version 0.4. introduced a simplified API for discovering devices and services.
We hope that what you learned today will help you in developing your own IoT projects.