📜 ⬆️ ⬇️

Work with Bluetooth LE from Java applications

Today we will talk about how, using Java, create applications for IoT that can work with remote Bluetooth Low Energy-based devices. The development of such applications, thanks to the open source project TinyB , supports 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.



About compatibility and prerequisites


The current version of the Bluetooth API in TinyB has been tested in Java 8 Runtime (OpenJDK 8). This environment, like TinyB, is supplied as part of the official Intel IoT Development Kit image for Intel Edison boards.

On Linux-based systems, TinyB can be used with BlueZ installed (version 5.37. Or higher). At the same time, the bluetoothd daemon starts up with the experimental functions enabled (the –E flag). You can read more about this in the README file . In our example, the SensorTag from Texas Instruments acts as the Bluetooth LE device. Details about the device can be found here .
')

Documentation and sample applications


Here are two options for the Bluetooth API documentation that TinyB provides. Here are the materials for those who use C ++, and here for Java developers.

The HelloTinyB example, which is written in Java (or hellotinyb for C ++), uses the above-mentioned SensorTag. From it is read indicators about the ambient temperature and the temperature of the object. For proper operation, the application requires the SensorTag MAC address. It must be passed as the first parameter when starting the program:

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

Java IoT application for working with Bluetooth LE


Here we will use an example of HelloTinyB, 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. A link to it can be obtained using the getBluetoothManager () method:

 BluetoothManager manager = BluetoothManager.getBluetoothManager(); 

The manager will attempt to initialize the BluetoothAdapter object if there is a Bluetooth adapter on the system. In order to start the search for other devices, you need to call the startDiscovery () method, which will put the default adapter into 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 getDevices () manager method. This list must be viewed in order to find a device with a MAC address specified as a parameter when starting the program. 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<BluetoothDevice> 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 detected, 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 the work:

 Found device: Address = C4:BE:84:72:2B:09 Name = CC2650 SensorTag Connected = false Sensor with the provided address connected 

The device to which we are connected must give access to the temperature determination service, the UUID of which can be found in the documentation . The service we need has a short UUID AA00 . It should 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<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; } 

As a result of the above code, the following should be displayed:

 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 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 by 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"); 

Now you need to include the service to determine the temperature, writing "1" in the configuration characteristic. Details on this are in the above documentation. You can change the update interval of the indicators by writing the desired value in the characteristic of the period, but the default value, "1", suits us.

 byte[] config = { 0x01 }; tempConfig.writeValue(config); 

After setting, you can start reading temperature information from the device. The temperature service returns data in a coded format. Features of working with this data format can be found in the documentation for the SensorTag. We are going to convert the data to degrees Celsius and output it to the console. The temperature of the object, in accordance with the documentation, depends on the ambient temperature. Here we will consider 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, the 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 

Results


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 only supports operation in the device polling mode, but in version 0.4. Presents a simplified API for discovering devices and services.

We hope that what you learned today will help you in developing your own IoT projects.

Source: https://habr.com/ru/post/304782/


All Articles