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

Updating advertising data (manuf. spec. data) in SDK15

Hello guys! And girls Slight smile

My project is working as expected in SDK14.2.
I'm updating adv data (manuf. spec. data) without any problem with this function

static void advertising_data_update(uint8_t adv_manuf_byte)
{
		ret_code_t err_code;

		ble_advertising_init_t 		init;
		ble_advdata_manuf_data_t 	adv_manuf_data;
		uint8_array_t            	adv_manuf_data_array;
		uint8_t                  	adv_manuf_data_data[1];
		adv_manuf_data_data[0] 		= adv_manuf_byte;

		memset(&init, 0, sizeof(init));

		init.advdata.name_type          		 = BLE_ADVDATA_FULL_NAME;
		init.advdata.include_appearance 		 = false;
		init.advdata.flags              		 = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
		init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
		init.advdata.uuids_complete.p_uuids  = m_adv_uuids;

		adv_manuf_data_array.p_data 							 = adv_manuf_data_data;
		adv_manuf_data_array.size 								 = sizeof(adv_manuf_data_data);
		adv_manuf_data.company_identifier 				 = APP_COMPANY_IDENTIFIER;
		adv_manuf_data.data 											 = adv_manuf_data_array;
		init.advdata.p_manuf_specific_data 				 = &adv_manuf_data;

		init.config.ble_adv_whitelist_enabled      = true;
		init.config.ble_adv_directed_enabled       = true;
		init.config.ble_adv_directed_slow_enabled  = false;
		init.config.ble_adv_directed_slow_interval = 0;
		init.config.ble_adv_directed_slow_timeout  = 0;
		init.config.ble_adv_fast_enabled  				 = true;
		init.config.ble_adv_fast_interval 				 = APP_ADV_INTERVAL;
		init.config.ble_adv_fast_timeout  				 = APP_ADV_TIMEOUT_IN_SECONDS;
							
		err_code = ble_advdata_set(&init.advdata, NULL);
		APP_ERROR_CHECK(err_code);	   
}


But in SDK15 the function ble_advdata_set() has been deprecated.
The migration guide is says to use ble_advdata_encode() and sd_ble_gap_adv_set_configure() instead.

So I changed it to something like this

static void advertising_data_update(uint8_t adv_manuf_byte)
{
		ret_code_t err_code;

		ble_advertising_init_t 		init;
		ble_advdata_manuf_data_t 	adv_manuf_data;
		uint8_array_t            	adv_manuf_data_array;
		adv_manuf_data_data[0] 		= adv_manuf_byte;

		memset(&init, 0, sizeof(init));

    init.advdata.name_type          		 = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance 		 = false;
    init.advdata.flags              		 = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
    init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
			
		adv_manuf_data_array.p_data 							 = adv_manuf_data_data;
		adv_manuf_data_array.size 								 = sizeof(adv_manuf_data_data);
		adv_manuf_data.company_identifier 				 = APP_COMPANY_IDENTIFIER;
		adv_manuf_data.data 											 = adv_manuf_data_array;
		init.advdata.p_manuf_specific_data 				 = &adv_manuf_data;

    init.config.ble_adv_whitelist_enabled      			= true;
		init.config.ble_adv_directed_high_duty_enabled 	= true;
    init.config.ble_adv_directed_enabled       			= false;
    init.config.ble_adv_fast_enabled  				 			= true;
    init.config.ble_adv_fast_interval 				 			= APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  				 			= APP_ADV_FAST_DURATION;

		//err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
		//APP_ERROR_CHECK(err_code);
			
		err_code = ble_advdata_encode(&init.advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);	
		APP_ERROR_CHECK(err_code);

		err_code = sd_ble_gap_adv_set_configure(&m_advertising.adv_handle, &m_adv_data, NULL);
		APP_ERROR_CHECK(err_code);
		
		//err_code = sd_ble_gap_adv_start(m_advertising.adv_handle, APP_BLE_CONN_CFG_TAG);
		//APP_ERROR_CHECK(err_code);
}


And of course... it's not working. :)
I'm getting a very strange error at sd_ble_gap_adv_set_configure() --> app: ERROR 12801 [Unknown error code]

Any idea why?
What I'm doing wrong?
What I have to change to get this working like in the SDK14.2?

Parents
  • Try this code:

    static void advertising_init(void)
    {
        ret_code_t 					err_code;
        ble_advertising_init_t 		init;
    
        ble_advdata_manuf_data_t 	adv_manuf_data;
        uint8_array_t            	adv_manuf_data_array;
    	
        adv_manuf_data_data[0] 		= 0x00;
    
    	
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type          		= BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance 		= false;
        init.advdata.flags              	    = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
        init.advdata.uuids_complete.uuid_cnt    = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_complete.p_uuids     = m_adv_uuids;
             
        adv_manuf_data_array.p_data 			= adv_manuf_data_data;
        adv_manuf_data_array.size 				= sizeof(adv_manuf_data_data);
        adv_manuf_data.company_identifier 		= APP_COMPANY_IDENTIFIER;
        adv_manuf_data.data 					= adv_manuf_data_array;
        init.advdata.p_manuf_specific_data 		= &adv_manuf_data;
    
        init.config.ble_adv_whitelist_enabled      		= true;
        init.config.ble_adv_directed_high_duty_enabled 	= false;
        init.config.ble_adv_directed_enabled       		= false;
        init.config.ble_adv_fast_enabled  				= true;
        init.config.ble_adv_fast_interval 				= APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  				= APP_ADV_FAST_DURATION;
    
        init.evt_handler 	= on_adv_evt;
        init.error_handler  = ble_advertising_error_handler; 
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    static void advertising_data_update(uint8_t adv_manuf_byte)
    {
        ret_code_t err_code;
        ble_advdata_t              advdata;       /**< Advertising data: name, appearance, discovery flags, and more. */
        //ble_advdata_t              srdata;        /**< Scan response data: Supplement to advertising data. */
    
    	ble_advdata_manuf_data_t 	adv_manuf_data;
    	
        uint8_array_t            	adv_manuf_data_array;
    	
    	adv_manuf_data_data[0]     = adv_manuf_byte;
    
        memset(&advdata, 0, sizeof(advdata));
        //memset(&srdata, 0, sizeof(srdata));
       
        advdata.name_type          	        = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance 	        = false;
        advdata.flags              	        = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
        advdata.uuids_complete.uuid_cnt     = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        advdata.uuids_complete.p_uuids      = m_adv_uuids;
    			
    	adv_manuf_data_array.p_data         = adv_manuf_data_data;
    	adv_manuf_data_array.size 			= sizeof(adv_manuf_data_data);
    	adv_manuf_data.company_identifier   = APP_COMPANY_IDENTIFIER;
    	adv_manuf_data.data 				= adv_manuf_data_array;
    	advdata.p_manuf_specific_data 		= &adv_manuf_data;
    
        update_advertising_data(&m_advertising, &advdata, m_advertising.adv_data.adv_data.len, NULL, 0);
    }
    
    /* PARAMS
    [IN] p_advertising: Pointer to an advertising instance, usually m_advertising in 'main' context.
    [IN] p_adv_data:    Pointer to an advertisment data instance.
    [IN] adv_data_len:  Length of advertisment data in bytes.
    [IN] p_sr_data:     Pointer to an scan respose data instance, set to NULL if no SR data.
    [IN] sr_data_len:   Length of scan response data in bytes.
    */
    void update_advertising_data(ble_advertising_t *p_advertising, ble_advdata_t *p_adv_data, uint16_t adv_data_len, ble_advdata_t *p_sr_data, uint16_t sr_data_len)
    {
        ASSERT(p_advertising->initialized);
    
        uint32_t ret = NRF_SUCCESS;
        ble_gap_adv_data_t *new_advdata;
    
        new_advdata->adv_data.len = adv_data_len;      
    
        ret = ble_advdata_encode(p_adv_data, new_advdata->adv_data.p_data, &new_advdata->adv_data.len);
        APP_ERROR_CHECK(ret);
    
        if (p_sr_data)
        {
            new_advdata->scan_rsp_data.len = sr_data_len;
    
            ret = ble_advdata_encode(p_sr_data,
                                   new_advdata->scan_rsp_data.p_data,
                                   &new_advdata->scan_rsp_data.len);
            APP_ERROR_CHECK(ret);
        }
        else
        {
            new_advdata->scan_rsp_data.p_data = NULL;
            new_advdata->scan_rsp_data.len    = 0;
        }
    
        ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, new_advdata, NULL);
        APP_ERROR_CHECK(ret);
    }
    

  • I also tried this, and recieve error 12, with a ble_advdata_encode(). May be we should encode data directly to m_advertising.enc_advdata? like when we initialize advertising?

  • Error goes from:

    err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size);

    advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;

    if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size)
    {
        return NRF_ERROR_DATA_SIZE;
    }

    This statment is false.

    Even if i call function like this:

    update_advertising_data(&m_advertising, &advdata, BLE_GAP_ADV_SET_DATA_SIZE_MAX, NULL, 0);

  • looks like my memory was littered. This code goes normaly:

    static void update_advertising_data(ble_advertising_t *p_advertising, ble_advdata_t *p_adv_data, uint16_t adv_data_len, ble_advdata_t *p_sr_data, uint16_t sr_data_len)
    {
        ASSERT(p_advertising->initialized);
        uint32_t ret = NRF_SUCCESS;
        ble_gap_adv_data_t new_advdata;
        memset(&new_advdata, 0, sizeof(new_advdata));
        new_advdata.adv_data.len = adv_data_len;      
        ret = ble_advdata_encode(p_adv_data, new_advdata.adv_data.p_data, &new_advdata.adv_data.len);
        APP_ERROR_CHECK(ret);
    
        if (p_sr_data)
        {
            new_advdata.scan_rsp_data.len = sr_data_len;
    
            ret = ble_advdata_encode(p_sr_data,
                                   new_advdata.scan_rsp_data.p_data,
                                   &new_advdata.scan_rsp_data.len);
            APP_ERROR_CHECK(ret);
        }
        else
        {
            new_advdata.scan_rsp_data.p_data = NULL;
            new_advdata.scan_rsp_data.len    = 0;
        }
    
        ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, &new_advdata, NULL);
        APP_ERROR_CHECK(ret);
    }
    But after that i recieve another error like as Spirit: NRF_ERROR_INVALID_ADDR but when on calling sd_ble_gap_device_name_get

  • Finaly get working code.

    Spirit try this:

    static void update_advertising_data(ble_advertising_t *p_advertising, ble_advdata_t *p_adv_data, uint16_t adv_data_len, ble_advdata_t *p_sr_data, uint16_t sr_data_len)
    {
        ASSERT(p_advertising->initialized);
        uint32_t ret = NRF_SUCCESS;
        uint8_t buffer[adv_data_len];
        memset(buffer, 0, adv_data_len);
        ble_gap_adv_data_t new_advdata;
        memset(&new_advdata, 0, sizeof(new_advdata));
        new_advdata.adv_data.p_data = buffer;
        new_advdata.adv_data.len = adv_data_len;      
        ret = ble_advdata_encode(p_adv_data, new_advdata.adv_data.p_data, &new_advdata.adv_data.len);
        APP_ERROR_CHECK(ret);
    
        if (p_sr_data)
        {
            new_advdata.scan_rsp_data.len = sr_data_len;
    
            ret = ble_advdata_encode(p_sr_data,
                                   new_advdata.scan_rsp_data.p_data,
                                   &new_advdata.scan_rsp_data.len);
            APP_ERROR_CHECK(ret);
        }
        else
        {
            new_advdata.scan_rsp_data.p_data = NULL;
            new_advdata.scan_rsp_data.len    = 0;
        }
    
        ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, &new_advdata, NULL);
        APP_ERROR_CHECK(ret);
    }
    I am just beginer codewriter, so i think this code can be more optimized and compact.

  • Not really Disappointed
    Just for the first data update.
    When I update the package for the second time, a get an "invalid state" error in sd_ble_gap_adv_set_configure() Disappointed

  • I setup update data every 5 sec, after first update data i recieve error 8 at: sd_ble_gap_adv_set_configure what it could be?

Reply Children
  • We have exactly the same problem.

    Nordic guys... this topic has more than 700 views.
    So this is really a problem that must me solved...
    I will give up very soon.

  • Dont give up solve is close, i found that we should change buffer for advdata:

    • NRF_ERROR_INVALID_STATE Invalid state to perform operation.
      • It is invalid to provide non-NULL advertising set parameters while advertising.
      • It is invalid to provide the same data buffers while advertising. To update advertising data, provide new advertising buffers.
  • Here is solution:

    //Adding new global variable that will be like pointer of ussed buffer
    uint8_t     P_buffer = 0;
    
    static void update_advertising_data(ble_advertising_t *p_advertising, ble_advdata_t *p_adv_data, uint16_t adv_data_len, ble_advdata_t *p_sr_data, uint16_t sr_data_len)
    {
        ASSERT(p_advertising->initialized);
        uint32_t ret = NRF_SUCCESS;
        uint8_t buffer[adv_data_len];
        uint8_t buffer2[adv_data_len];
        memset(buffer, 0, adv_data_len);
        memset(buffer2, 0, adv_data_len);
        ble_gap_adv_data_t new_advdata;
        memset(&new_advdata, 0, sizeof(new_advdata));
        if (P_buffer==0)
        {
        new_advdata.adv_data.p_data = buffer;
        P_buffer=1;
        }
        else 
        {
        new_advdata.adv_data.p_data = buffer2;
        P_buffer = 0;
        }
        new_advdata.adv_data.len = adv_data_len;      
        ret = ble_advdata_encode(p_adv_data, new_advdata.adv_data.p_data, &new_advdata.adv_data.len);
        APP_ERROR_CHECK(ret);
    
        if (p_sr_data)
        {
            new_advdata.scan_rsp_data.len = sr_data_len;
    
            ret = ble_advdata_encode(p_sr_data,
                                   new_advdata.scan_rsp_data.p_data,
                                   &new_advdata.scan_rsp_data.len);
            APP_ERROR_CHECK(ret);
        }
        else
        {
            new_advdata.scan_rsp_data.p_data = NULL;
            new_advdata.scan_rsp_data.len    = 0;
        }
    
        ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, &new_advdata, NULL);
        APP_ERROR_CHECK(ret);
    }
    It's allso not so optimized, but it's working :))

    add. or you can add variable like static inside of function

  • Yes! You need at least two buffers to switch between.

  • you can say what you want, but ble_advdata_set() what a much much better solution Slight smile
    I really don't know why the "SDK-makers" are making every single revision more difficult or complex for us Slight smile

    thank you! 
    I will try your solution a bit later.

Related