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
  • I understand your confusion, the new APIs can be confusing at first. A colleague has made a function to demonstrate how it should be done:

    /* 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've not been able to test it, but I believe this function will operate as intended. 

Reply
  • I understand your confusion, the new APIs can be confusing at first. A colleague has made a function to demonstrate how it should be done:

    /* 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've not been able to test it, but I believe this function will operate as intended. 

Children
  • Thank you for that,  

    It would be possible to get in contact with this your colleague?
    I have some more questions for him.

  • Ok Slight smile


    My initialization function

    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);
    }

    and a updating function

    static void advertising_data_update(uint8_t adv_manuf_byte)
    {
    	ret_code_t err_code;
    
    	// Stop advertising
    	if(m_conn_handle == BLE_CONN_HANDLE_INVALID)
    	{
    		err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
    		NRF_LOG_INFO("sd_ble_gap_adv_stop: %d", err_code);
    		APP_ERROR_CHECK(err_code);
    	}
    		
    	// New initialization
        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 	= 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);
    	NRF_LOG_INFO("ble_advertising_init: %d", err_code);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    		
    	// Restart advertising
    	if(m_conn_handle == BLE_CONN_HANDLE_INVALID)
    	{
    		//err_code = sd_ble_gap_adv_start(m_advertising.adv_handle, APP_BLE_CONN_CFG_TAG);
    		//NRF_LOG_INFO("sd_ble_gap_adv_start: %d", err_code);
    		//APP_ERROR_CHECK(err_code);
    		
    		advertising_start();
    	}
    }



    Until now this was an only (working) solution for me.
    So... every single time I stop the advertising module, I reconfigure it and start it again.

    Compared to the solution I don't use ble_gap_adv_data_t

    My main question is... if a initialize the module with ble_advertising_init_t, how can I switch and update only the ble_advdata_manuf_data_t without stop and completly reconfigure the module?

    p.s.
    I'm using a whitelist.

  • Function doesn't work.

    First the typedef "ble_advertising_t" doesn't exist ... Even if I bypass it I got a error 12 [NRF_ERROR_DATA_SIZE]. I don't understand because the size of my datas is exactly the same as in the first init.

  • Hi Martin

    I have problems too with porting code from an earlier SDK version which was using ble_advdata_set() for updating the advertiser data while adertising.

    I tried out your function: update_advertising() but there is a compiler error: variable "new_advdata" is used before its value is set.

Related