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?

  • Line 681 of ble_advertising.c: // Upon disconnection, whitelist will be activated and direct advertising is started.


    ble_advertising_on_ble_evt is the event handler registered with the macro  BLE_ADVERTISING_DEF(m_advertising); on line 104 of main.c.


    This event handler will call on_disconnected() given the event is BLE_GAP_EVT_DISCONNECTED. You need to update the advertising data of m_advertising in main before you can restart the advertisements if you want the updated advertisement data. You should be able to to this by setting m_advertising.adv_data.adv_data.p_data and .len to the address and length of your previously used buffer, 
    new_advdata.adv_data.p_data and new_advdata.adv_data.len.



  •  I really do not understand what do you mean by that and what I have to change :)
    I had a perfecty working solution in SDK14 and now, in SDK15, I'm completely lost Slight smile

    After all you wrote in this debate it seems that the easiest solution is to uninit the module and restart it again with a new adv vaules and without all the mess with above in this conversation (various double buffers etc). Which in my opinion is absolutely unnecessary.

    I still do not understand why after every disconnect, the module starts to advertise with 

    init.advdata.p_manuf_specific_data = &adv_manuf_data;

    and not with a xy times updated adv data in 
    advdata.p_manuf_specific_data = &adv_manuf_data;


    Can you please resend to me (by PM) my code and show me what I have to change to get this work?

  • "I still do not understand why after the disconnect, the module starts to advertise with "

    Because ble_advertising_start() takes m_advertising as input and it's advertising data has not changed since it was initialized in advertising_init. 

  • What did you mean by "it's advertising data has not changed"?
    So we are not changing m_advertising with your update_advertising_data() function?

    From the other side...
    Can we update this (init) adv data directly without use of adv data (without init)? 

  • "So we are not changing m_advertising with your update_advertising_data() function?"

    Yes, you're correct. We're updating the SoftDevice's advertising buffer directly.

    "Can we update this (init) adv data directly without use of adv data (without init)?" 
    I'm sorry I do not understand, can you please explain in a bit more concrete manner?

Reply Children
  • "Yes, you're correct. We're updating the SoftDevice's advertising buffer directly."
    This is the main problem... we are constantly updating the SD buffer directly, but after a disconnect we get an adv packed with a value used in the adv module initializiation. I still do not understand why...

    "I'm sorry I do not understand, can you please explain in a bit more concrete manner?"
    I'm only asking how to update this additional manuf adv byte (init or not init) values that won't be changed to the init values after every single disconnect... Is that so really damn hard to achieve in SDK15?

  • , I will give you an example:
    If I initialize the adv module with an adv packet that consists of an additional manuf. adv byte with value 0xFF... and then if during the application I change/update this value to 0x00, 0x24, etc... I do not want that that byte on every single disconnect becomes again 0xFF.

    That's all. Is that understandable?

  • Then you've got to change the advertisement data in m_advertising in main.c because this is the fallback advertising data for the advertising module, who restarts advertisements on a BLE_GAP_EVT_DISCONNECT. 

  • Can you please tell me or better, show me in my code, how to do it?

  • Hi,

    I will try to clear up any misunderstandings here.

    There are mainly two ways to control the advertising data. The first one is to go directly, using the SoftDevice call sd_ble_gap_adv_set_configure(). This is what you do to change advertising data on the fly, as you have already successfully implemented.

    The second way to control advertising data is through the advertising module. The way that it works, is that you provide advertising data when initializing the advertising module with ble_advertising_init(). That piece of advertising data is stored by the advertising module, and it will automatically use that same data whenever it starts advertising. In other words: The advertising module calls sd_ble_gap_adv_set_configure() on its own, with the data that it was given during initialization. (To find all the places it does that you can search for ble_advertising_start in your project. It is multiple places, three of them is in event handling inside the advertising module itself.)

    The easy way to not getting erroneous data is to initialize the advertising module to not send manufacturer specific data at all. That way all the manufacturer specific data (if present in the advertising packet) is controlled in the first way described above. This is safe as long as the device receiving the packets can handle advertising packets without manufacturer specific data. (If you use other advertising types for the changing data then you do the same for them instead, i.e. do not include it for the advertising initialization.)

    The hard way is to change the advertising data stored by the advertising module, whenever that is needed. For that you can have a look at advertising_init() and the call to ble_advertising_init(). In example code, the first argument to ble_advertising_init() is usually &m_advertising. This is where the advertising module will save state information such as the advertising data. More precisely, m_advertising.adv_data.adv_data.p_data is a pointer to the buffer containing advertising data, and m_advertising.adv_data_adv_data.len is the size of that buffer. Similar to how you manage advertising data for sending directly through sd_ble_gap_adv_set_configure(), you should be able to update the p_data and len fields correspondingly, so that the advertising module will use those values instead. You may be able to do that in ble_evt_handler() in main if you change the priorities for that event handler (APP_BLE_OBSERVER_PRIO) and that of the adveritising module (BLE_ADV_BLE_OBSERVER_PRIO) so that your event handler is run before that of the advertising module. I am not quite sure if something else will blow up if you change those priorities around, though. You may have other parts of code that relies on a certain order of execution for the ble event handlers.

    Regards,
    Terje

Related