I have implemented duplex BLE communication (essentially, something like serial TX/RX cable) using two ATT characteristics on the peripheral - one is writable, the other is readable with notifications. Everything works as expected, except reported write speed.
When I call the following code:
txCharacteristic.setValue(data);
boolean queuedOk =
connectedPeripheralGatt.writeCharacteristic(txCharacteristic);
the onCharacteristicWrite
callback is being triggered almost immediately, and then I repeat the code fragment above to apply next data fragment on the characteristic. While the receiving side is reporting correct speed (about 10 KB/s), as measured from timestamps collected in onCharacteristicWriteRequest
, the sending side reports unbelievable speeds (like 50 - 300 KB/s) and it reports that it has finished pushing all the data to writeCharacteristic
, although the receiving side still is receiving the incoming data.
So, clearly onCharacteristicWriteRequest
is being called while most of the data is still on its way to the target device.
The same thing happens when I send the data from the peripheral to the central device, only this time onNotificationSent
on the peripheral is lying about its speed and onCharacteristicChanged
on the central is reporting correct speed.
Is there any more or less reliable way to approximately measure outgoing data rate from the sender's side without turning ACKs on (which I don't want to do for performance reasons)?
The data itself arrives intact, I'm testing it with image files of 0.5 - 5 megabytes of size and the images are always decoded correctly on the receiving side.
To maximize the throughput, the writable characteristic was set up to be non-reliable as follows:
BluetoothGattCharacteristic rxCharacteristic = new BluetoothGattCharacteristic(UUID.fromString(RX_CHARACTERISTIC_UUID),
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
BluetoothGattCharacteristic.PERMISSION_WRITE);
rxCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
I'm not sure of my use of PROPERTY_WRITE_NO_RESPONSE
and WRITE_TYPE_NO_RESPONSE
but from some articles on some websites it vaguely seemed that it's a good practice to specify both; correct me if I'm wrong.
I understand that with such setup I cannot expect real acknowledgements of the data on the receiving side, but still I expected that onCharacteristicWrite
and onNotificationSent
themselves would provide at least realistic timing to detect when the data was actually sent out of the source device. Instead, it seems, there is a pretty large cache which consumes my data and reports it being sent almost immediately.