Losing/Duplicating BLE Notifications to Samsung S8

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!

Hi, I am facing similar issue. Did you get your answer?

M A Saiyed
Twin infosys

No… Please let me know if you find an answer! Thanks!