LongVo
LongVo

Reputation: 41

Android bluetooth low energy (ble) writeCharacteristic delay callback

I am implementing a application on Android using BLE Api (SDK 18), and I have a issue that the transfer data process is delay very slow. This is my log.

03-12 16:20:05.121: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:06.272: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

03-12 16:20:06.972: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:08.254: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

03-12 16:20:10.055: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:11.257: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

03-12 16:20:12.478: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:14.250: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

03-12 16:20:14.960: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:16.242: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

03-12 16:20:16.402: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:20.225: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

03-12 16:20:20.526: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:24.219: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

03-12 16:20:25.360: D/BluetoothGatt(13578): writeCharacteristic() - uuid: ...

03-12 16:20:27.222: D/BluetoothGatt(13578): onCharacteristicWrite() - Device=... UUID=... Status=0

For more information, I found that every Transfer Progress only completes when it has the onCharacteristicWrite callback, this means that all sending command before receive onCharacteristicWrite callback will be ignored.

Is this the flow of Android we have to following or there is any way to setup it skip the callback step to speed up the progress.

My code is:

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
......
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    mSending = false;
}
};

private void writeCharacteristic() {
    .....

    mGattCharacSetIntensity.setValue(data);
    mGattCharacSetIntensity.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
    mBluetoothGatt.writeCharacteristic(mGattCharacSetIntensity);
    return;
}

EDIT: I have a comparison with iPhone (a BLE transfer data app from AppStore), the BLE transfer data is very quick (less than 0.5 sec), so impressive. How can we work around to SPEED UP the Android BLE Transfer progress?.

EDIT: If I set WriteType of BluetoothGattCharacteristic to WRITE_TYPE_NO_RESPONSE, and when I send many command sequentially, the Android stores them on a queue and send to remote device one by one after receive writeCharacteristic CallBack, this leads to a issue, when you stop your sending lood, the Android Sending Progress still continue with the delay (Sometime more than 3 sec).

Upvotes: 4

Views: 12184

Answers (4)

Droid Chris
Droid Chris

Reputation: 3783

This seems to be a problem for me as well. If you delay the calls in the debugger you can confirm that there is a delay when writing to BLE radios. I will be implementing a queue in my application to handle the latency.

Here is what I do for queueing up commands:

public void sendWriteCommandToConnectedMachine(byte[] commandByte) {
    if(commandByte.length > 20)
        dissectAndSendCommandBytes(commandByte);
    else
        queueCommand(commandByte); //TODO - need to figure out if service is valid or not
}

private void queueCommand(byte[] command) {
    mCommandQueue.add(command);

    if(!mWaitingCommandResponse)
        dequeCommand();
}

Hereis what I do for dequeuing BLE commands

private void dequeCommand() {
    if(mCommandQueue.size() > 0) {
        byte[] command = mCommandQueue.get(0);
        mCommandQueue.remove(0);
        sendWriteCommand(command);
    }
}

here is my characteristic write method

@Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        if(status != BluetoothGatt.GATT_SUCCESS)
            logMachineResponse(characteristic, status);     

        mWaitingCommandResponse = false;
        dequeCommand();
    }

Upvotes: 1

pogorman
pogorman

Reputation: 1711

You'll have to implement you're own flow control, don't start a write until the OnCharacteristicWrite is sent for the previous write

Upvotes: 1

Dirk Jäckel
Dirk Jäckel

Reputation: 3025

We had the same problem. It occurs after several writes and goes away when you reconnect the Gatt. What we do is measure the delay between writeCharacteristic() and onCharacteristicWrite(). If it is above a certain threshold (1500ms), we disconnect() and close() the gatt server and reconnect. After that it is usually fine for a while.

When doing this it might become necessary to disable the whole bluetooth adapter and reenable it. Otherwise the first reconnect to the gatt server fails and it takes about 15 seconds until it is reconnected. Sometimes it never reconnects.

When disabling the adapter you might run into the problem that service discovery does not return in onServicesDiscovered(). We have currently no solution for that.

Upvotes: 4

hlnd
hlnd

Reputation: 286

Performance of a BLE link is highly dependent on the connection interval used, and if your connection interval is high, the performance you see may not be that unreasonable. By the Core Specification, the connection interval can be between 7.5 ms and 4 s, so there's quite some flexibility.

If it's possible for you, I'd recommend you to try changing the Peripheral you're talking to to use a shorter connection interval, which should improve performance. You may have use in taking a look at this page, explaining BLE throughput, and this page, explaining connection parameters.

Upvotes: 5

Related Questions