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

Testing for notification enabled s110 v. 8.0.0

In a project I worked on using softdevice s110 v. 7.1.0, if the receiver hadn't enabled notifications, sd_ble_gatts_hvx would return an error, so I used the following construct to check whether notifications had been enabled before attempting to send a notification:

uint32_t ble_mysvc_notify_button(ble_mysvc_t *p_mysvc)
{
	uint32_t err_code = NRF_SUCCESS;
    ble_gatts_hvx_params_t params;
    uint16_t cccdv;
	ble_gatts_value_t gatts_value;
	ble_gatts_value_t cccd_value;

	cccd_value.len = sizeof(ble_gatts_value_t);
	cccd_value.offset = 0;
    sd_ble_gatts_value_get(p_mysvc->conn_handle, p_mysvc->button_char_handles.cccd_handle, &cccd_value);
    cccdv = (uint16_t)*(cccd_value.p_value);

    if ((cccdv & BLE_GATT_HVX_NOTIFICATION) != 0)
    {
        uint16_t len = 1;

	    memset(&params, 0, sizeof(params));
	    params.type = BLE_GATT_HVX_NOTIFICATION;
	    params.handle = p_mysvc->button_char_handles.value_handle;
	    params.p_data = &(p_mysvc->button_state);
	    params.p_len = &len;

	    return sd_ble_gatts_hvx(p_mysvc->conn_handle, &params);
	}

    return NRF_SUCCESS;
}

However, this doesn't seem to be working in s110 v. 8.0.0; (cccdv & BLE_GATT_HVX_NOTIFICATION) intermittently returns true or false, regardless of whether notifications are enabled. Moreover, it seems that sd_ble_gatts_hvx no longer actually returns an error if the receiver hasn't enabled notifications.

My questions are:

  1. should this, in fact, work to detect whether notifications have been enabled?
  2. has v. 8.0.0 changed such that it is no longer necessary to perform this test?

Thanks in advance for any advice.

Parents
  • Sorry for the late reply. Not sure if this will help but just some observation.

    ble_gatts_value_t define is as below in s1108.0 headers.

    /**@brief GATT Attribute Value. */
    typedef struct
    {
      uint16_t  len;        /**< Length in bytes to be written or read. Length in bytes written or read after successful return.*/
      uint16_t  offset;     /**< Attribute value offset. */
      uint8_t   *p_value;   /**< Pointer to where value is stored or will be stored. 
                                 If value is stored in user memory, only the attribute length is updated when p_value == NULL.
                                 Set to NULL when reading to obtain the complete length of the attribute value */
    } ble_gatts_value_t;
    
    
    sd_ble_gatts_value_get(p_mysvc->conn_handle, p_mysvc->button_char_handles.cccd_handle, &cccd_value);
    cccdv = (uint16_t)*(cccd_value.p_value);
    

    Even though you are not fetching full CCCD value it should have worked as the notification bit is the lowest bit. you are first derefering uint8_t p_value pointer and then casting the uint8_t value to uint16_t. So in real you are only fetching

    instead safest way to do this is

    sd_ble_gatts_value_get(p_mysvc->conn_handle, p_mysvc->button_char_handles.cccd_handle, &cccd_value);
    cccdv = (uint16_t)(( cccd_value.p_value[1] << 8) | (cccd_value.p_value[0]));
    
Reply
  • Sorry for the late reply. Not sure if this will help but just some observation.

    ble_gatts_value_t define is as below in s1108.0 headers.

    /**@brief GATT Attribute Value. */
    typedef struct
    {
      uint16_t  len;        /**< Length in bytes to be written or read. Length in bytes written or read after successful return.*/
      uint16_t  offset;     /**< Attribute value offset. */
      uint8_t   *p_value;   /**< Pointer to where value is stored or will be stored. 
                                 If value is stored in user memory, only the attribute length is updated when p_value == NULL.
                                 Set to NULL when reading to obtain the complete length of the attribute value */
    } ble_gatts_value_t;
    
    
    sd_ble_gatts_value_get(p_mysvc->conn_handle, p_mysvc->button_char_handles.cccd_handle, &cccd_value);
    cccdv = (uint16_t)*(cccd_value.p_value);
    

    Even though you are not fetching full CCCD value it should have worked as the notification bit is the lowest bit. you are first derefering uint8_t p_value pointer and then casting the uint8_t value to uint16_t. So in real you are only fetching

    instead safest way to do this is

    sd_ble_gatts_value_get(p_mysvc->conn_handle, p_mysvc->button_char_handles.cccd_handle, &cccd_value);
    cccdv = (uint16_t)(( cccd_value.p_value[1] << 8) | (cccd_value.p_value[0]));
    
Children
No Data
Related