Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android BLE: knowing MTU on the GattServer side

I have implemented BLE communications on Android. I'm negotiating the MTU on the client side using requestMtu. This works well, as the client gets the MTU change on onMtuChanged. However, I still don't have the means to know the MTU on the server side, only the client. I implement my own mechanism for fragmentation/segmentation as sometimes I'm sending reasonable amounts of data. I'd like to segment the data according to MTU size for faster communications. I'm currently sending 20 bytes at a time on the server side, which works but is slower. Is there a way to get the MTU on the server?

like image 691
André Fratelli Avatar asked Aug 10 '16 18:08

André Fratelli


4 Answers

The way I made this work was to wait for a connection, then create a connection with the device that connected via the onConnectionStateChange(...) function.

private final BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
  @Override
  public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
      if (newState == Bluetooth.STATE_CONNECTED)
        device.connectGatt(MainActivity.this, false, mGattCallback);
      super.onConnectionStateChange(device, status, newState);
}

This allowed me to requestMtu() on the resulting successful connection.

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
      if (newState == Bluetooth.STATE_CONNECTED) {
        gatt.requestMtu(512);
      }
      super.onConnectionStateChange(gatt, status, newState);

    }
  };
like image 178
clinky Avatar answered Sep 27 '22 16:09

clinky


The requestMtu call will lead to a Gatt MTU exchange between the client & server。The smaller mtu will be the final one in use。 If you want to know the mtu size on the server side, just give a parameter big enough to the “requestMtu” call, and get the result in “onMtuChanged”。 Alternatively,see your btsnoop file on the platform & you will get exactly what the mtu size on the server is.

like image 30
utada Avatar answered Sep 27 '22 17:09

utada


BluetoothGattServerCallback has the method onMtuChanged that you can override and directly obtain the MTU once negotiated (after request from central side):

@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
   super.onMtuChanged(gatt, mtu, status);
   this.mtu = mtu;
   Log.i(TAG, "New MTU: " + mtu + " , Status: " + status + " , Succeed: " + (status == BluetoothGatt.GATT_SUCCESS));
}
like image 42
FireZenk Avatar answered Sep 27 '22 16:09

FireZenk


Per the Bluetooth Core specification document, in 3.F 3.2.8:

A device that is acting as a server and client at the same time shall use the same value for Client Rx MTU and Server Rx MTU.

Therefore, use MTU you get through GATT client API, it has to be the same.

like image 21
Nipo Avatar answered Sep 27 '22 16:09

Nipo