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

NRF_ERROR_NOT_FOUND on sd_ble_gatts_value_get

Hi,

After implementing my own services, I run into a problem when trying to read the value.of a characteristic. I basically have four services, of which one only holds one read/write characteristic. Now my next step was to try to read and write this characteristic. 

But the function sd_ble_gatts_value_get returns the error NRF_ERROR_NOT_FOUND. Since my service implementation is based on the Nordic UART service, my services now all have - among others - the two functions on_connect and on_write. Since I want to read the characteristic value when the data is written, I added the function sd_ble_gatts_value_get to the on_write function. Please correct me if I got something wrong in this concept.

So my fault curiously only happens when using sd_ble_gatts_value_get in the function on_write, not in on_connect (where it was in the example originally).

This is the code from on_write:

ret_code_t                    err_code;
ble_dcs_evt_t                 evt;
ble_dcs_client_context_t    * p_client;
ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
ble_gatts_value_t             gatts_val;
uint8_t                       cccd_value[2];

memset(&gatts_val, 0, sizeof(ble_gatts_value_t));
gatts_val.p_value = cccd_value;
gatts_val.len     = sizeof(cccd_value);
gatts_val.offset  = 0;

err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle,
                                  p_dcs->cmd.cccd_handle,
                                  &gatts_val);
if (err_code != NRF_SUCCESS)
{
    NRF_LOG_ERROR("Attribute could not be read. Error code: 0x%08X", err_code);
}
APP_ERROR_CHECK(err_code);


if (*(gatts_val.p_value) == 0x06)
{
    err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                         BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    APP_ERROR_CHECK(err_code);
}

And this is how I added the characteristic I am attempting to read (the initialization of the service is always successfull)

memset(&add_char_params, 0, sizeof(add_char_params));
add_char_params.uuid                     = BLE_UUID_DCS_CMD_CHAR;
add_char_params.uuid_type                = p_dcs->uuid_type;
add_char_params.max_len                  = BLE_DCS_MAX_CMD_CHAR_LEN;
add_char_params.init_len                 = sizeof(uint8_t);
add_char_params.is_var_len               = false;
add_char_params.char_props.write         = 1;
add_char_params.char_props.write_wo_resp = 1;
add_char_params.char_props.read          = 1;

add_char_params.read_access  = SEC_OPEN;
add_char_params.write_access = SEC_OPEN;

err_code = characteristic_add(p_dcs->service_handle, &add_char_params, &p_dcs->cmd);
if (err_code != NRF_SUCCESS)
{
    return err_code;
}    

Used SW and HW:

  • SDK17.0.2
  • S140
  • PCA10056

Thank you for any hints.

  • Hi

    It doesn't really make sense to read the CCCD status in the on_write event. 

    If the CCCD is changed by the client the on_write event will be called automatically, and you can update the is_notification_enabled field accordingly:

    if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) &&
        (p_evt_write->len == 2))
    {
        if (p_client != NULL)
        {
            if (ble_srv_is_notification_enabled(p_evt_write->data))
            {
                p_client->is_notification_enabled = true;
                evt.type                          = BLE_NUS_EVT_COMM_STARTED;
            }
            else
            {
                p_client->is_notification_enabled = false;
                evt.type                          = BLE_NUS_EVT_COMM_STOPPED;
            }
    
            if (p_nus->data_handler != NULL)
            {
                p_nus->data_handler(&evt);
            }
    
        }
    }

    The CCCD is read in the on_connect handler to make sure you know the status of the CCCD at the start of the connection. 

    When the on_write event is called the data written can be found in the p_evt_write->data array, so there is no need to read it out explicitly. 

    Best regards
    Torbjørn

Related