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

Error 0x00003002 while sending a notification

Hi, 

Using nRF52840 with SDK15.0.0.

I started my projetc based on BLE tutorial characteristics.

I created my service and add 2 characteristics successfully.

My module is advertising and i can see its characteristics correctly.

One charac is CHARACTERISTIC_READER_RESULT, i can see its value correctly with nRF application but i try to change its value with a notification and it doesn't work.

I got err 0x00003002 err_code return from function sd_ble_gatts_hvx. it's stand for BLE_ERROR_INVALID_CONN_HANDLE but i don't know where is the problem ...

here is my code : 

static uint32_t our_char_add(ble_os_t * p_our_service)
{
    
	uint32_t            err_code;
	ble_uuid128_t       base_uuid = BLE_UUID_OUR_BASE_UUID;
		


//----------------------------------------------------------------------
	//FIRST CHARAC
	//CHARACTERISTIC_READER_RESULT : BLE module send a message utf8 to mobile application by notification

// OUR_JOB: Step 2.A, Add a custom characteristic UUID
	ble_uuid_t          char_uuid_2;
	char_uuid_2.uuid      = BLE_UUID_CHARACTERISTIC_READER_RESULT;
	err_code = sd_ble_uuid_vs_add(&base_uuid, &char_uuid_2.type);
	APP_ERROR_CHECK(err_code);
    
    // OUR_JOB: Step 2.F Add read/write properties to our characteristic
    ble_gatts_char_md_t char_md_2;
    memset(&char_md_2, 0, sizeof(char_md_2));
    char_md_2.char_props.read = 1;
    //char_md_2.char_props.write = 1;
    char_md_2.char_props.write = 0;

    
    // OUR_JOB: Step 3.A, Configuring Client Characteristic Configuration Descriptor metadata and add to char_md structure
    ble_gatts_attr_md_t cccd_md_2;
    memset(&cccd_md_2, 0, sizeof(cccd_md_2));
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md_2.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md_2.write_perm);
	cccd_md_2.vloc                = BLE_GATTS_VLOC_STACK;
	char_md_2.p_cccd_md           = &cccd_md_2;
	char_md_2.char_props.notify   = 1;
   
    
    // OUR_JOB: Step 2.B, Configure the attribute metadata
    ble_gatts_attr_md_t attr_md_2;
    memset(&attr_md_2, 0, sizeof(attr_md_2));  
	attr_md_2.vloc        = BLE_GATTS_VLOC_STACK;
    
    
    // OUR_JOB: Step 2.G, Set read/write security levels to our characteristic
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_2.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_2.write_perm);

    // OUR_JOB: Step 2.C, Configure the characteristic value attribute
    ble_gatts_attr_t    attr_char_value_2;
    memset(&attr_char_value_2, 0, sizeof(attr_char_value_2));
	attr_char_value_2.p_uuid      = &char_uuid_2;
	attr_char_value_2.p_attr_md   = &attr_md_2;


    // OUR_JOB: Step 2.H, Set characteristic length in number of bytes
	attr_char_value_2.max_len     = 10;
	attr_char_value_2.init_len    = 10;
	uint8_t value_2[10]            = {0x44,0x6f,0x6e,0x65,0x44,0x6f,0x6e,0x65,0x44,0x6f};
	attr_char_value_2.p_value     = value_2;
    // OUR_JOB: Step 2.E, Add our new characteristic to the service
	err_code = sd_ble_gatts_characteristic_add(p_our_service->service_handle,
                               &char_md_2,
                               &attr_char_value_2,
                               &p_our_service->char_handles);
	APP_ERROR_CHECK(err_code);


	//----------------------------------------------------------------------
	//SECOND CHARAC
	//CHARASTERISTIC_IDENTIFIER : mobile phone will write Badge ID on it
	// OUR_JOB: Step 2.A, Add a custom characteristic UUID

	ble_uuid_t          char_uuid;
	char_uuid.uuid      = BLE_UUID_CHARACTERISTIC_IDENTIFIER;
	err_code = sd_ble_uuid_vs_add(&base_uuid, &char_uuid.type);
	APP_ERROR_CHECK(err_code);
    
    // OUR_JOB: Step 2.F Add read/write properties to our characteristic
    ble_gatts_char_md_t char_md;
    memset(&char_md, 0, sizeof(char_md));
    //char_md.char_props.read = 1;
    char_md.char_props.read = 0;
    char_md.char_props.write = 1;

    
    // OUR_JOB: Step 3.A, Configuring Client Characteristic Configuration Descriptor metadata and add to char_md structure
    ble_gatts_attr_md_t cccd_md;
    memset(&cccd_md, 0, sizeof(cccd_md));
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
	cccd_md.vloc                = BLE_GATTS_VLOC_STACK;
	char_md.p_cccd_md           = &cccd_md;
	char_md.char_props.notify   = 0;
   
    
    // OUR_JOB: Step 2.B, Configure the attribute metadata
    ble_gatts_attr_md_t attr_md;
    memset(&attr_md, 0, sizeof(attr_md));  
	attr_md.vloc        = BLE_GATTS_VLOC_STACK;
    
    
    // OUR_JOB: Step 2.G, Set read/write security levels to our characteristic
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);

    // OUR_JOB: Step 2.C, Configure the characteristic value attribute
    ble_gatts_attr_t    attr_char_value;
    memset(&attr_char_value, 0, sizeof(attr_char_value));
	attr_char_value.p_uuid      = &char_uuid;
	attr_char_value.p_attr_md   = &attr_md;


    // OUR_JOB: Step 2.H, Set characteristic length in number of bytes
	attr_char_value.max_len     = 10;
	attr_char_value.init_len    = 10;
	uint8_t value[4]            = {0x44,0x6f,0x6e,0x65};
	attr_char_value.p_value     = value;
    // OUR_JOB: Step 2.E, Add our new characteristic to the service
	err_code = sd_ble_gatts_characteristic_add(p_our_service->service_handle,
                               &char_md,
                               &attr_char_value,
                               &p_our_service->char_handles);
	APP_ERROR_CHECK(err_code);
	//--------------------------------------------------------------------------------------------


//SEGGER_RTT_WriteString(0, "APPEL UPDATE POUR NOTIF\n");
//int32_t temperature = 0;
//our_temperature_characteristic_update(&p_our_service, &temperature);

    return NRF_SUCCESS;
}


/**@brief Function for initiating our new service.
 *
 * @param[in]   p_our_service        Our Service structure.
 *
 */
void our_service_init(ble_os_t * p_our_service)
{
    uint32_t   err_code; // Variable to hold return codes from library and softdevice functions
    SEGGER_RTT_WriteString(0, "debut our_service_init().\n");
    // FROM_SERVICE_TUTORIAL: Declare 16-bit service and 128-bit base UUIDs and add them to the BLE stack
    ble_uuid_t        service_uuid;
    ble_uuid128_t     base_uuid = BLE_UUID_OUR_BASE_UUID;
    service_uuid.uuid = BLE_UUID_OUR_SERVICE_UUID;
    err_code = sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type);
    APP_ERROR_CHECK(err_code);
    
    // OUR_JOB: Step 3.B, Set our service connection handle to default value. I.e. an invalid handle since we are not yet in a connection.
	p_our_service->conn_handle = BLE_CONN_HANDLE_INVALID;
	

    // FROM_SERVICE_TUTORIAL: Add our service
	err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                        &service_uuid,
                                        &p_our_service->service_handle);
    
    APP_ERROR_CHECK(err_code);
    SEGGER_RTT_WriteString(0, "our_service_init() après service_add.\n");
    
    // OUR_JOB: Call the function our_char_add() to add our new characteristic to the service. 
    our_char_add(p_our_service);
}

// ALREADY_DONE_FOR_YOU: Function to be called when updating characteristic value
void our_temperature_characteristic_update(ble_os_t *p_our_service, int32_t *temperature_value)
{
    SEGGER_RTT_WriteString(0, "DEBUT FONCTION NOTIFICATION\n");
	// OUR_JOB: Step 3.E, Update characteristic value
	if (p_our_service->conn_handle != BLE_CONN_HANDLE_INVALID)
	{
			SEGGER_RTT_WriteString(0, "DEBUT NOTIFICATION\n");
			uint16_t               len = 10;
			ble_gatts_hvx_params_t hvx_params;
			memset(&hvx_params, 0, sizeof(hvx_params));

			hvx_params.handle = p_our_service->char_handles.value_handle;
			hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
			hvx_params.offset = 0;
			hvx_params.p_len  = &len;
			//hvx_params.p_data = (uint8_t*)temperature_value;
			uint8_t gdedata[10] = {0x47,0x6f,0x6f,0x64,0x44,0x6f,0x6e,0x65,0x44,0x6f};
			hvx_params.p_data = gdedata;

			uint32_t err_code;
			err_code = sd_ble_gatts_hvx(p_our_service->conn_handle, &hvx_params);
			SEGGER_RTT_printf(0, "err_code f° notification : 0x%#08x\n", err_code);
	}


}

  • I assume you have updated the connection handle, e.g. somewhere along the lines of:

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                p_our_service->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

    Typically the value is 0 on first connection.

    You may also find \examples\ble_peripheral\ble_app_blinky useful as reference.

  • Thank you Kenneth,

    I tryed to notify before my gatt is connected.

    so right now i call this notification function after connection.

    now i get err_code 0x00003400 which stand for  BLE_ERROR_GATTS_INVALID_ATTR_TYPE (with NRF_GATTS_ERR_BASE).

    i don't know where is the problem, here i have : 

    // Use UUIDs for service(s) used in your application.
    static ble_uuid_t m_adv_uuids[] =                                               /**< Universally unique service identifiers. */
    {
    	{BLE_UUID_OUR_SERVICE_UUID, BLE_UUID_TYPE_BLE}
    	{BLE_UUID_OUR_SERVICE_UUID, BLE_UUID_TYPE_VENDOR_BEGIN}//originaly but don't advertise
    };

    here if i declare BLE_UUID_TYPE_VENDOR_BEGIN for ble_uuid_t type, my module doesn't advertise

  • You may also find \examples\ble_peripheral\ble_app_blinky useful as reference.

    If you call sd_ble_gatts_hvx() and the return error code is:

    * @retval ::BLE_ERROR_GATTS_INVALID_ATTR_TYPE Invalid attribute type(s) supplied, only characteristic values may be notified and indicated.

    Then I think either hvx_params.handle is wrong (maybe it's not the correct handle to the characteristic that can notify values), or the handle you are using is pointing to a characteristic that don't support notifications (char_props.notify).

  • Hum ble_app_blinky seems to don't use notifications...

    I started from tuto_charac.

    Because i have 2 characteristics, i changed the way i handle char_handles : 

    typedef struct
    {
        uint16_t                    conn_handle;    /**< Handle of the current connection (as provided by the BLE stack, is BLE_CONN_HANDLE_INVALID if not in a connection).*/
        uint16_t                    service_handle; /**< Handle of Our Service (as provided by the BLE stack). */
        // OUR_JOB: Step 2.D, Add handles for the characteristic attributes to our struct
        //ble_gatts_char_handles_t char_handles;
        ble_gatts_char_handles_t first_char_handles;
        ble_gatts_char_handles_t second_char_handles;
    }ble_os_t;

    Then i checked, right now hvx_params.handle that value_handle after sd_ble_gatts_characteristic_add.

    now err_code is 0x00003401.

    here is how i create my charac : 

    ble_uuid_t          char_uuid_2;
    	char_uuid_2.uuid      = BLE_UUID_CHARACTERISTIC_READER_RESULT;
    	err_code = sd_ble_uuid_vs_add(&base_uuid, &char_uuid_2.type);
    	APP_ERROR_CHECK(err_code);
        
        // OUR_JOB: Step 2.F Add read/write properties to our characteristic
        ble_gatts_char_md_t char_md_2;
        memset(&char_md_2, 0, sizeof(char_md_2));
        char_md_2.char_props.read = 1;
        char_md_2.char_props.write = 1;
    
        
        // OUR_JOB: Step 3.A, Configuring Client Characteristic Configuration Descriptor metadata and add to char_md structure
        ble_gatts_attr_md_t cccd_md_2;
        memset(&cccd_md_2, 0, sizeof(cccd_md_2));
    	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md_2.read_perm);
    	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md_2.write_perm);
    	cccd_md_2.vloc                = BLE_GATTS_VLOC_STACK;
    	char_md_2.p_cccd_md           = &cccd_md_2;
    	char_md_2.char_props.notify   = 1;
    
    
        
        // OUR_JOB: Step 2.B, Configure the attribute metadata
        ble_gatts_attr_md_t attr_md_2;
        memset(&attr_md_2, 0, sizeof(attr_md_2));  
    	attr_md_2.vloc        = BLE_GATTS_VLOC_STACK;
        
        
        // OUR_JOB: Step 2.G, Set read/write security levels to our characteristic
    	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_2.read_perm);
    	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_2.write_perm);
    
        // OUR_JOB: Step 2.C, Configure the characteristic value attribute
        ble_gatts_attr_t    attr_char_value_2;
        memset(&attr_char_value_2, 0, sizeof(attr_char_value_2));
    	attr_char_value_2.p_uuid      = &char_uuid_2;
    	attr_char_value_2.p_attr_md   = &attr_md_2;
    
    
    	SEGGER_RTT_printf(0, "value handle dans char_add 1A : 0x%#08x\n", p_our_service->second_char_handles.value_handle);
        // OUR_JOB: Step 2.H, Set characteristic length in number of bytes
    	attr_char_value_2.max_len     = 10;
    	attr_char_value_2.init_len    = 10;
    	uint8_t value_2[10]            = {0x44,0x6f,0x6e,0x65,0x44,0x6f,0x6e,0x65,0x44,0x6f};
    	//uint8_t value_2[10];
    	attr_char_value_2.p_value     = value_2;
        // OUR_JOB: Step 2.E, Add our new characteristic to the service
    	err_code = sd_ble_gatts_characteristic_add(p_our_service->service_handle,
                                   &char_md_2,
                                   &attr_char_value_2,
                                   &p_our_service->second_char_handles);
    	APP_ERROR_CHECK(err_code);

    so it looks like hvx_params.handle is right and i support notification ...

  • i increased len : len = 15; (instead of len = 10).

    right now err_code (from sd_ble_gatts_hvx) is 0x0000000C do you know what does it stand for ?

Related