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

  • thank you for that!

    But still does not work Slight smile
    I get a NRF_ERROR_INVALID_ADDR with a ble_advdata_encode()

    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)
    {
        ...
    
        ret = ble_advdata_encode(p_adv_data, new_advdata->adv_data.p_data, &new_advdata->adv_data.len);
        APP_ERROR_CHECK(ret);
        
        ...
        
    }

  • I'm struggling with the same problem and i'm pretty sure it is the pointer to the encoded data (p_encoded_data) since the error is thrown in the next encode function (name_encode in my case) if no UUID's are provided. 

    So my question is if anybody has found the answer yet

    EDIT:

    Found out that the  new_advdata.adv_data.p_data pointer is NULL which is why the NRF_ERROR_INVALID_ADDR is returned. In ble_advertising_init this pointer is set to  m_advertising.enc_advdata which cannot be done in the update function since then a NRF_ERROR_INVALID_STATE error is returned. 

  • In the new sdk15.2, you need to stop the adv before updating, otherwise you get that error.

  • I'd like to see Nordic weigh in on this.  I had nothing but trouble in trying to stop and restart advertising when changing advertising data in SDK 15.2.  I implemented a function to update manufacturer's advertising data using the 2-buffer approach and pass it to ble_advertising_advdata_update() in ble_advertising.c from SDK 15.2.  The advertisements update reliably without stopping/re-starting advertising.

  • Yes, effectively there are 2 ways to do it.  Either stop/start or pass another different pointer.  SD reject it if same pointer while still advertising.  I never have any issue with stop/start and my adv data length varies from one time to the next.  The best approche for most of my application is to sync data change with adv timeout.  At adv timeout event, the adv is already stopped.  All you need to do then is to update the data and advertise again.

  • Hi,

    Rob C said:
    I'd like to see Nordic weigh in on this.

    Unfortunately there are issues with ble_advertising_advdata_update(), for SDK v15.x and SoftDevice v6.

    If you set the "permanent" parameter to true it will try to reuse the original buffer, but that is not allowed when advertising is ongoing. This is a known issue. The workaround is to stop advertising, then update the data, then start advertising again.

    You can use it with "permanent" of false at any time if you manage double buffering yourself. If you use a single buffer then you will still have to do the drill of stop advertising, update data, start advertising.

    If you use sd_ble_gap_adv_set_configure() directly for updating the advertising data you also need to use double buffering or stop advertising, update data, start advertising.

    So yes, essentially you have two options:

    1. Stop advertising, then change data, then start advertising again.
    2. Use double buffers, which you handle yourself.

    Regards,
    Terje

Reply
  • Hi,

    Rob C said:
    I'd like to see Nordic weigh in on this.

    Unfortunately there are issues with ble_advertising_advdata_update(), for SDK v15.x and SoftDevice v6.

    If you set the "permanent" parameter to true it will try to reuse the original buffer, but that is not allowed when advertising is ongoing. This is a known issue. The workaround is to stop advertising, then update the data, then start advertising again.

    You can use it with "permanent" of false at any time if you manage double buffering yourself. If you use a single buffer then you will still have to do the drill of stop advertising, update data, start advertising.

    If you use sd_ble_gap_adv_set_configure() directly for updating the advertising data you also need to use double buffering or stop advertising, update data, start advertising.

    So yes, essentially you have two options:

    1. Stop advertising, then change data, then start advertising again.
    2. Use double buffers, which you handle yourself.

    Regards,
    Terje

Children
No Data
Related