I am working on an Android application that reads data from a BLE device. Here I found a lot of solutions on how to read a few characteristics, and most of them suggested Queues.
I implemented the Queue method and everything works fine in my code, as expected. The reason I started this topic is to find the best and most effective solution, as well as eliminate some of my doubts about how some of the features of the BLE service work.
I used two links as a link that helped me in creating my code.
Source 1:
Android: BLE, how to read several characteristics?
Source 2:
Android BLE API: GATT Notification Received
My requirement was to read a heart rate measurement and battery level . First I tried to add the heart rate and battery characteristics to the queue, and then call the read / set methods for each of the added items.
MainActivity:
private void displayGattServices(List<BluetoothGattService> gattServices) {
bluetoothHDPService:
public void read(BluetoothGattCharacteristic characteristic) { if (bluetoothAdapter == null || bluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; }; bluetoothGatt.readCharacteristic(characteristic); }; public void set(BluetoothGattCharacteristic characteristic, boolean enabled) { if(bluetoothAdapter == null || bluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; }; bluetoothGatt.setCharacteristicNotification(characteristic, enabled); BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_UUID); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); bluetoothGatt.writeDescriptor(descriptor); };
Back to MainActivity: (after the read BLE callback function has been triggered)
I used the broadcast receiver to read / set the next Queue element.
private final BroadcastReceiver gattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub final String action = intent.getAction(); if (Service_HeartRateX_HDP.ACTION_GATT_CONNECTED.equals(action)) { // Connection with the BLE device successful ................ ................ } else if (Service_HeartRateX_HDP.ACTION_GATT_DISCONNECTED.equals(action)) { // BLE device is disconnected ................ ................ } else if (Service_HeartRateX_HDP.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { displayGattServices(bluetoothHDPService.getSupportedGattServices()); } else if (Service_HeartRateX_HDP.ACTION_DATA_AVAILABLE.equals(action)) { Log.i(TAG, "Collecting data"); // Collecting the incoming data displayData(intent.getStringExtra(Service_HeartRateX_HDP.HEART_DATA), intent.getStringExtra(Service_HeartRateX_HDP.BATTERY_DATA)); if(hRM_characteristicReadQueue.size() > 0) { read_Characteristic(); }; }; }; };
The above code fragment worked correctly for only one sign ( heart rate ) The BLE device continued to send heart rate measurement data, and for another characteristic ( percentage of battery ), the BLE device sent data about the battery only once . Please note that the order of the Queue element is such that the heart rate characteristic is read / installed and removed from the queue with the subsequent battery characteristic.
Initially, I thought that the queue was not working properly and tried to rearrange the order of the characteristics in the queue with the percentage of battery being the first item to read / install and remove, followed by the heart rate characteristic to see if the problem is really due to incorrect programming .
But this did not work, since the BLE device did the same as before (continuing to send heart rate measurement data, and the percentage of the battery was sent only once).
Thus, given the above scenarios, I came to the conclusion that the percentage characteristic of the battery level should be periodically read / set to make the BLE device send its data. This was also helped by the following publication, in which one developer had to use a timer thread to regularly update battery interest rates from a BLE device.
how to update the battery level every 5 seconds in android
I did not want to use the timer thread in my code, as this made my already complex code complex endless. Then I added the condition below to read_Characteristic () to solve this problem.
@ MainActivity
// where hrmBattery_Characteristics is a temporary variable which holds the // battery characteristics if(hRM_characteristicReadQueue.element() != hrmBattery_Characteristics) { hRM_characteristicReadQueue.remove(); };
Thus, the battery characteristics are never removed from the queue, and the read_Characteristic () method will be called every time through the broadcast receiver (a synchronous template is supported). This currently works fine in my code, but I need expert advice on whether this is correct.
This problem is only related to the battery or other specifications. Fortunately, at the moment I need data only for these two characteristics (heart rate measurement data and battery percentage).
I have not tried more than two characteristics, since my BLE device has only a limited set of functions, and these are the only two that are currently present in it.
Is it due to the inability of the BLE device to send large data packets to the Android device in this section? The reason is that, despite the fact that the above code works fine, there has never been a single case where data (heart rate and percentage of battery) were sent on the same site.
If anyone can shed light on this, I will be very grateful.
Thanks in advance!