This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Enabling Notification on a Characteristic

Hi, I was trying to send notification from nRF51822 to an android central when notification is enabled on the nordic uart rx characteristic and I discovered that if I enable notification on the characteristic once it has been discovered by the android app, nothing is received by the app but when I enable notification more than once, for example each time, the battery level characteristic is read, then I would start receiving data. I found out that in the source code of nrftoolbox, precisely in the hrs code, notification is enabled on the hrm characteristic each time the battery level characteristic is read:

	public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
		if (status == BluetoothGatt.GATT_SUCCESS) {
			if (characteristic.getUuid().equals(HR_SENSOR_LOCATION_CHARACTERISTIC_UUID)) {
				final String sensorPosition = getBodySensorPosition(characteristic.getValue()[0]);
				//This will send callback to HRSActicity when HR sensor position on body is found in HR device
				mCallbacks.onHRSensorPositionFound(sensorPosition);

				if (mBatteryCharacteritsic != null) {
					readBatteryLevel();
				} else {
					enableHRNotification();
				}
			}
			if (characteristic.getUuid().equals(BATTERY_LEVEL_CHARACTERISTIC)) {
				int batteryValue = characteristic.getValue()[0];
				//This will send callback to HRSActicity when Battery value is received from HR device
				mCallbacks.onBatteryValueReceived(batteryValue);

				enableHRNotification();
			}
		} else {
			mCallbacks.onError(ERROR_READ_CHARACTERISTIC, status);
		}
	}

So why wont notification be sent when it is enable just once?

  • Hi augustio,

    As per BT SIG specification 4.0+: GATT CCCD (Client Characteristic Configuration Descriptor) values should be persistent across connections for bonded devices. If you are not using bonding you need to enable Handle Value Notifications each time you connect (from Central side).

    Cheers Jan


    Edit #1 (2015/05/22):

    Hi augustio,

    I cannot help you with Android or another API reflection of core BLE events so I'll stick to what is only real (on RF interface): CCCD state for not bonded nRF51 device with Nordic stacks (at least according to my experience and Nordic documentation) is kept between CONNECT_REQ and termination of BLE connection on LL layer (either by some time out or explicitly by particular TERMINATE command). I'd suggest to go down to the BLE principles and carefully map your solution to it in detailed flow charts. Then you also must include limitations coming from stack implementation on both sides (mainly what connection and advertising intervals are allowed, what is MTU size, how many events per connection interval it can handle, known bugs from release notest etc.) If you are then tight to some 3rd party HW and SW such as particular Android phone you must add significant cost/time into your project planning for debugging and testing (e.g. you might need more expensive BLE sniffer then Nordic's nRF51 DK/Dongle). Plus overall risk that if you push BLE to its "limits" (in this case it's anything else than vague bi-directional data transfer in range of several hundreds of bytes within couple of seconds) you might fail completely with your HW+SW set-up...

    Cheers Jan

  • Thanks again, but by connection are you referring to the period between the beginning of a connection interval and the end or between the time for eg, in android BluethootGatt.connect() is called and BluetoothGatt.disconnect() is called. I really get confused with these two scenarios.

  • My post seems to be too long for comment so see amended question above;)

  • @Augustio: CCCD should be set just once on every connection if it's not bonded. If the connection is bonded previously, the CCCD value will automatically be restored on both side. No write command needed.

    What you were seeing in the source code came from the way we implemented service discovery and CCCD setting in nRFToolbox. First, we do service discovery, after we done with service discovery, we read the HR sensor location characteristic. When we have the call back "onCharacteristicRead()", if it's the HR_SENSOR_LOCATION_CHARACTERISTIC_UUID returned, we read the battery level characteristic. And only after either we receive battery level (or if battery level is not exist) we will enable CCCD on HR value.

    We don't do further characteristic read in this app. So the CCCD set is only perform once.

    You can also take a look at the nRFUART, where we also only enable CCCD once.

    I would suggest you to capture a sniffer trace, and can find what happened over the air.

Related