0

I am currently working to Android application which communicates with a CC2650 Bluetooth Low Energy (BLE) device.

I have to need to make a writeCharacteristic call followed by multiple readCharacteristic calls with a function. This order can be reversed without affecting functionality.


Question 1: When only a writeCharacteristic or readCharacteristic are called individually the software works as expected. But software doesn't seem to work when the calls are made in sequence.

Below is the code.


Code section referencing writeCharacteristic code (UI Thread)

final BluetoothGattCharacteristic characteristic_select = mGattCharacteristicMap.get("hotstate");
    if (characteristic_select != null) {
        final int charaProp = characteristic_select.getProperties();
        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
            String strData = "00";
            int len = strData.length();
            byte[] data = new byte[len / 2];
            for (int i = 0; i < len; i += 2) {
                data[i / 2] = (byte) ((Character.digit(strData.charAt(i), 16) << 4)
                        + Character.digit(strData.charAt(i + 1), 16));
            }
            characteristic_select.setValue(data);
            mBLE_Service.writeCharacteristic(characteristic_select);
        }
    }

Code section with readCharacteristic (UI Thread). Note Multiple read call, which are queued

final BluetoothGattCharacteristic characteristic_time = mGattCharacteristicMap.get("timestate");
if (characteristic_time != null) {
        final int charaProp = characteristic_time.getProperties();
        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
            for (int i = 0; i < 10; i++) {
                mBLE_Service.readCharacteristic(characteristic_time);
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                    }
                }, 5000);
            }
        }
    }

Code for readCharacteristic

 public void readCharacteristic(BluetoothGattCharacteristic characteristic) {

        // Queue the characteristic to read, since several reads are done on startup
        characteristicQueue.add(characteristic);

        // If there is only 1 item in the queue, then read it. If more than 1, it is handled
        // asynchronously in the callback
        if((characteristicQueue.size() <= 1)) {

            mBluetoothGatt.readCharacteristic(characteristic);
        }

    }

Code for writeCharacteristic

  public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    mBluetoothGatt.writeCharacteristic(characteristic);

}

Code for onCharacteristicRead

       @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic,
                                     int status) {
        // Read action has finished, remove from queue
        characteristicQueue.remove();

        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

        // Handle the next element from the queues
        if(characteristicQueue.size() > 0)
            mBluetoothGatt.readCharacteristic(characteristicQueue.element());
        else if(descriptorWriteQueue.size() > 0)
            mBluetoothGatt.writeDescriptor(descriptorWriteQueue.element());
    }

Code for onCharacteristicWrite

       @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
        if (status==BluetoothGatt.GATT_SUCCESS){
            broadcastUpdate(ACTION_WRITE_SUCCESS, characteristic);
            } 
    }

Question 2: Since I have multiple reads I created a queue to handle. Do you think read and write are causing the issue? If so any suggestion on how to manage and block reads and writes?

Note: Code is for Android API 21 and higher

References:

Mahendra Gunawardena
  • 1,956
  • 5
  • 26
  • 45
  • What error are you seeing? – Submersed Oct 02 '18 at 15:20
  • @Submersed So if I do `writeCharacteristic` followed by `readCharacteristic` (multiple read calls) the `readCharacteristic` calls are not serviced. If reverse the then the `writeCharacteristic` are serviced. if necessary I can post the logcat. To keep the post manageable I have left out some details. BTW thank you for trying to help. – Mahendra Gunawardena Oct 02 '18 at 15:37

2 Answers2

1

This is because you need to wait for the callback to return before writing/reading again. Similar problem for the answer here.

Android BLE BluetoothGattDescriptor writeDescriptor issue

Except instead you may need to wait for the readDescriptor/Characteristic in addition to the write.

zafrani
  • 4,030
  • 5
  • 31
  • 39
1

You are half-way there by understanding you need a queue. But you must make sure you use it for ALL GATT operations. See my full answer: Android BLE BluetoothGatt.writeDescriptor() return sometimes false.

Emil
  • 16,784
  • 2
  • 41
  • 52
  • Your suggestion queue worked. Thank you for the response.Also read some of your other post. Also I wonder why the -1 vote. Anyhow I accepted your answer. – Mahendra Gunawardena Oct 02 '18 at 18:49