I’m trying to send “continuous” notifications from a Nordic nRF52840 (peripheral) to a Samsung S8 (central) running Android 9. The phone reports that the Kernel version is: 4.4.111-17263988. I request an MTU of 247 and a Phy of 2MBPS. The characteristics being sent are 244 bytes in size and include a sequence number. Right now, I have a test loop in the peripheral that sends 1 notification every 15ms (I’d like to get it to one every 7.5ms eventually). But first, I’d like to get the notifications transmitted/received correctly! (By the way, things work well if I only send notifications every 30 ms, so this appears to be notification transmission rate dependent.)
I set up a BLEManager as a service in the Android app, and the connection from the peripheral to the central is made, the notification is subscribed, and a command is sent from the central to the peripheral to start sending sensor data. I’m using the “stock” Android BLE library in the central (running on the S8).
The stream of characteristics starts, with sequence numbers 0, 1, 2, and 3, but then it appears that packet 6 arrives 3 times. (in place of 4, 5, and 6). The next characteristic reported is 0x000a, so sequence numbers 7, 8, and 9 appear to have been lost.
Originally, when a characteristic was received, I passed it to the MainActivity via “broadcastUpdate”, but I thought perhaps there was too much overhead doing this, so I moved the test code that reports the notifications directly into the “OnCharacteristicChanged” callback:
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
Timber.d("onCharacteristicChanged: ");
Timber.d(" characteristic UUID: %s", characteristic.getUuid().toString());
//broadcastUpdate(ACTION_GATT_DATA_READY, characteristic);
final byte[] data = characteristic.getValue();
ByteBuffer buf = ByteBuffer.wrap(data);
buf.order(ByteOrder.LITTLE_ENDIAN);
if (characteristic.getUuid().toString().equals(MIC_DATA_UUID)) {
Timber.d("Data received from Microphone: %d", data.length);
buf.asShortBuffer().get(micData, micWriteIndex, MIC_SAMPLES_PER_PACKET);
// Service the rotating buffer write pointer
micWriteIndex = micWriteIndex + MIC_SAMPLES_PER_PACKET;
if (micWriteIndex >= MIC_BUFFER_SIZE) micWriteIndex = 0;
// Read the sequence number...
// buf pointer is still at the beginning, so
// index of NNN skips over data we just read.
micSeqNum = buf.getShort(MIC_SAMPLES_PER_PACKET * MIC_SAMPLE_SIZE_IN_BYTES);
micChkSum = buf.getShort();
Timber.d(" Mic seq: %04x Mic chk: %04x", micSeqNum, micChkSum);
}
}
Here is a portion of the log that is produced:
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0000 Mic chk: 0000
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0001 Mic chk: 0078
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0002 Mic chk: 00f0
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0003 Mic chk: 0168
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0006 Mic chk: 02d0
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0006 Mic chk: 02d0
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0006 Mic chk: 02d0
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000a Mic chk: 04b0
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000b Mic chk: 0528
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000b Mic chk: 0528
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000b Mic chk: 0528
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000e Mic chk: 0690
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000e Mic chk: 0690
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000e Mic chk: 0690
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 000e Mic chk: 0690
> D/BLEManager: onCharacteristicChanged: D/BLEManager: characteristic
> UUID: f000af03-0807-0605-0403-020100000000 D/BLEManager: Data received
> from Microphone: 244 D/BLEManager: Mic seq: 0012 Mic chk: 0870
I believe the code to receive the notifications is correct.
I captured the btsnoop_hci log and viewed it in WireShark. It shows the same info as represented in the log above. The log of notifications being sent from the peripheral, shows all of the characteristics being sent in the correct order.
Is there an issue with the Samsung BLE implementation that Android BLE uses when notifications arrive quickly?
Thanks!