1 Android phone (N5X 6.0.1) is running a BLE server, another one (N5X O) is subscribing. Notification for a characteristic can be enabled however, on the write descriptor part, I'm consistently getting a 133.
Server.java
private void createServer() {
bluetoothGattServer = bluetoothManager.openGattServer(this, serverCallback);
BluetoothGattService service = new BluetoothGattService(Constants.SERVICE,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
characteristic =
new BluetoothGattCharacteristic(Constants.CHARACTERISTIC,
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
// public static UUID DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
characteristic.addDescriptor(new BluetoothGattDescriptor(Constants.DESCRIPTOR,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE));
characteristic.setWriteType(
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
service.addCharacteristic(characteristic);
bluetoothGattServer.addService(service);
}
private BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
Log.d(TAG, "onConnectionStateChange " + device.getName() + " " + status + " " + newState);
if (newState == BluetoothGatt.STATE_CONNECTED) {
bluetoothDevice = device;
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
bluetoothGattServer.cancelConnection(bluetoothDevice);
bluetoothGattServer.close();
}
}
};
private void sendData(String message) {
characteristic.setValue(message);
bluetoothGattServer.notifyCharacteristicChanged(bluetoothDevice, characteristic, true);
}
All the other UUIDs have been created from here.
Client.java
device.establishConnection(false)
.flatMap(bleConnection -> bleConnection.setupNotification(Constants.CHARACTERISTIC))
.flatMap(onNotificationReceived -> onNotificationReceived)
.subscribe(data -> {
Log.d(TAG, "data: " + data);
}, throwable -> {
Log.d(TAG, "data error " + throwable);
});
logcat
05-15 15:26:50.097 D/BluetoothGatt: setCharacteristicNotification() - uuid: 8d7dda32-3759-11e7-a919-92ebcb67fe33 enable: true
05-15 15:26:50.105 D/RxBle#Radio: QUEUED RxBleRadioOperationDescriptorWrite(60042487)
05-15 15:26:50.110 D/RxBle#Radio: FINISHED RxBleRadioOperationServicesDiscover(231218312)
05-15 15:26:50.112 D/RxBle#Radio: STARTED RxBleRadioOperationDescriptorWrite(60042487)
05-15 15:27:20.119 D/RxBle#Radio: FINISHED RxBleRadioOperationDescriptorWrite(60042487)
05-15 15:27:20.121 D/BluetoothGatt: setCharacteristicNotification() - uuid: 8d7dda32-3759-11e7-a919-92ebcb67fe33 enable: false
05-15 15:27:20.126 D/RxBle#BluetoothGatt: onDescriptorWrite descriptor=00002902-0000-1000-8000-00805f9b34fb status=133
05-15 15:27:20.129 D/BLE: data error BleGattDescriptorException{macAddress=42:EE:5A:C6:C1:F0, status=133 (0x85 -> https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.0_r1/stack/include/gatt_api.h), bleGattOperationType=BleGattOperation{description='DESCRIPTOR_WRITE'}}
Note: if I'm using the native Android API, I'm able to subscribe and receive notifications without having to write into the descriptor.
update: interesting thing though, while the write descriptor process is happening (it takes about 30s until it gets back with the error), I'm able to receive onCharacteristicChanged
.
update2: added callback and write to characteristic code
Bluetooth Core Specification says that if a characteristic supports notifications it should contain a Client Characteristic Config descriptor and start notifying only when CCC descriptor will be written with a proper value.
It seems that in your configuration there is a problem which manifests as status = 133
. It seems that you may have made a mistake when setting properties on the characteristic
. I assume that you want to have a characteristic that you can read, write and set notifications - in this situation it would look like:
characteristic =
new BluetoothGattCharacteristic(Constants.CHARACTERISTIC,
BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
Edit - Remember that if the central is requesting to turn on notifications it is trying to write Client Characteristic Config descriptor. Unless it is a request with NO_RESPONSE
setting then the central is expecting a response.
The proper solution is to add a callback to onDescriptorWriteRequest
and send a response to the central:
BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {
// (...)
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor,
boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
// validate if the request is exactly what you expect if needed
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
}
// (...)
};
Potential workaround
Some chinese manufacturers are not conforming to the Bluetooth Core Specification and they do not have CCC descriptor under characteristics that are sending notifications. If you are able to get the notifications without setting CCC then you could use a compatibility mode RxBleConnection.setupNotifications(characteristic, NotificationSetupMode.COMPAT)
although it is discouraged and a proper fix to the configuration should be aplied.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With