BlueBright
BlueBright

Reputation: 803

Receiving multiple BLE Packets per one connection interval in Android

My device information

  1. Nordic board :

    • MTU size : 247.
    • This board send notification multiple packets in one connection interval (Just counter value like 1,2,3,4...) at "Heart Rate Measurement".
  2. Android device :

    • Version 5.0 and 6.0. (Using two device).
    • communicate Bluetooth Low Energy(BLE) with board.
    • board connect with my Android app MTU is setting 244.
    • Application source is google sample project BluetoothLeGatt
    • App send notification value at "Heart Rate Service" characteristic.
    • Receive notification value at Gattcallback "onCharacteristicChanged()"
  3. Problem

    • My Android app lost some packet.

I read this post. Maximizing BLE Throughput on iOS and Android. So I send E-mail this post author and I search another information for Android.

I found some similarly question. but that question answer was not work. Then I found one question what I want exactly. but this question have no answers. Android receiving multiple BLE packets per connection interval. Unfortunately I don't have any reply E-mail answer.

My question is how do I set Android BLE notification. (Not Nordic board setting) (My question is same Android receiving multiple BLE packets per connection interval)

Under line is my sample code. at notification.

@Connect

public boolean connect(final String address) {
    if (mBluetoothAdapter == null || address == null) {
        Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
        return false;
    }

    // Previously connected device.  Try to reconnect.
    if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
        Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
        if (mBluetoothGatt.connect()) {
            mConnectionState = STATE_CONNECTING;
            return true;
        } else {
            return false;
        }
    }

    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
    if (device == null) {
        Log.w(TAG, "Device not found.  Unable to connect.");
        return false;
    }

    // We want to directly connect to the device, so we are setting the autoConnect
    // parameter to false.
    mBluetoothGatt = device.connectGatt(this, false, mGattCallback);

    Log.d(TAG, "Trying to create a new connection.");
    mBluetoothDeviceAddress = address;
    mConnectionState = STATE_CONNECTING;
    return true;
}

@GattCallback

  /*broadcastUpdate method is display value*/
 @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

        if (newState == BluetoothProfile.STATE_CONNECTED) {
            mConnectionState = STATE_CONNECTED;
            // Attempts to discover services after successful connection.
            Log.i(TAG, "Attempting to start service discovery:");
            mBluetoothGatt.discoverServices();

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            Log.i(TAG, "Disconnected from GATT server.");
            mConnectionState = STATE_DISCONNECTED;
            broadcastUpdate(ACTION_GATT_DISCONNECTED);
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "onServicesDiscovered success: (status)" + status);
            //findServiceOther(gatt);
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            Log.d(TAG, "Request MTU");
            gatt.requestMtu(SET_MTU);
        } else {
            Log.w(TAG, "onServicesDiscovered failed: (status)" + status);
        }
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "onCharRead Success");
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        } else {
            Log.d(TAG, "OnCharRead Error: " + status);
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        if (characteristic.getUuid().equals(SampleGattAttributes.UUID_HEART_RATE_MEASUREMENT))
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic, FLAG_HEART_RATE);
        else
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
    }

    @Override
    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
        super.onMtuChanged(gatt, mtu, status);
        boolean priority = gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
        Log.d(TAG, "MTU changed (mtu/status) / Priority : (" + mtu + "/" + status + ") / " + priority);
        changed_MTU_Size = mtu;
        broadcastUpdate(ACTION_DATA_AVAILABLE, changed_MTU_Size, FLAG_MTU);
        broadcastUpdate(ACTION_GATT_CONNECTED);
    }

@set notification

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

    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

    if (SampleGattAttributes.UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
        // This is specific to Heart Rate Measurement.
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(SampleGattAttributes.UUID_CLIENT_CHARACTERISTIC_CONFIG);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        mBluetoothGatt.writeDescriptor(descriptor);
    }
}

Edit_1

I test Nordic offical app in Google play store. nRF Connect for Mobile but this app miss packet too.

Edit_2

I found some problem too.

< Nordic board constant setting>

< Run in my Android app >

I wonder requestMTU and notification receive interrelation.

Upvotes: 0

Views: 5143

Answers (1)

AD1170
AD1170

Reputation: 418

i have implemented a file transfer over LE on a nrf51422 and SD310 by using the Nordic UART Service. The android App is written in CPP by using Qt and the QtBluetooth library. Therefore, this answer my not really help you. But, i have taken some afford to achive a usable data rate. 1st, set the connection parameters to 7.5ms (min) and 15ms (max). 2nd, on the peripheral side, i send up to 7 packets (til the buffer is full). So the peripheral send up to 7 packets per connection event. On the Android side, the charachteritic changed event arrive me frequently with a data size of 20 bytes (due to the maximum MTU size of 23, 3 bytes used by nordic uart service) and i read the data instantly. Perhaps your mistake is the MTU size of 244. The default BLE MTU size is 23 (Core spec 4.1).

Regards

Upvotes: 1

Related Questions