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
  • 71 replies, none of them is the solution. Why Nordic changes the original simple API "ble_advdata_set", the new API really sucks !!!

  • I found a solution that seems to work fine. Once you have started the advertising, just use ble_advdata_encode to encode your data and write it to the buffer used when you first called sd_ble_gap_adv_set_configure . Do not call the sd_ble_gap_adv_set_configure function again, only encode the data. Your advertising data will be updated every time you do this. This might not be the recommend way for doing this, but I did not encounter any errors yet.

  • static void advertising_data_update()
    {
        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_t adv_manuf_data_elements[] = {mydata};
        uint8_array_t                       adv_manuf_data_array;
    	
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type          	 = BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance 	 = false; //https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml&u=org.bluetooth.characteristic.gap.appearance.xml
        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_elements;
        adv_manuf_data_array.size            = sizeof(adv_manuf_data_elements);
        adv_manuf_data.company_identifier    = 0x0059;
        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_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);*/
    
        err_code = ble_advertising_update(&m_advertising, &init);
        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)
        {
            bool erase_bonds;
            advertising_start(erase_bonds);
        }
    }

    uint32_t ble_advertising_update(ble_advertising_t            * const p_advertising,
                                  ble_advertising_init_t const * const p_init)
    {
        uint32_t ret;
        if ((p_init == NULL) || (p_advertising == NULL))
        {
            return NRF_ERROR_NULL;
        }
        if (!config_is_valid(&p_init->config))
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        p_advertising->adv_mode_current               = BLE_ADV_MODE_IDLE;
        p_advertising->adv_modes_config               = p_init->config;
        p_advertising->conn_cfg_tag                   = BLE_CONN_CFG_TAG_DEFAULT;
        p_advertising->evt_handler                    = p_init->evt_handler;
        p_advertising->error_handler                  = p_init->error_handler;
        p_advertising->current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID;
        p_advertising->p_adv_data                     = &p_advertising->adv_data;
    
        memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address));
    
        // Copy advertising data.
        if (!p_advertising->initialized)
        {
            p_advertising->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
        }
        p_advertising->adv_data.adv_data.p_data = p_advertising->enc_advdata;
        p_advertising->adv_data.adv_data.len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX;
    
        ret = ble_advdata_encode(&p_init->advdata, p_advertising->enc_advdata, &p_advertising->adv_data.adv_data.len);
        VERIFY_SUCCESS(ret);
    
        if (&p_init->srdata != NULL)
        {
            p_advertising->adv_data.scan_rsp_data.p_data = p_advertising->enc_scan_rsp_data;
            p_advertising->adv_data.scan_rsp_data.len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX;
    
            ret = ble_advdata_encode(&p_init->srdata,
                                      p_advertising->adv_data.scan_rsp_data.p_data,
                                     &p_advertising->adv_data.scan_rsp_data.len);
            VERIFY_SUCCESS(ret);
        }
        else
        {
            p_advertising->adv_data.scan_rsp_data.p_data = NULL;
            p_advertising->adv_data.scan_rsp_data.len    = 0;
        }
        
        /*
        // Configure a initial advertising configuration. The advertising data and and advertising
        // parameters will be changed later when we call @ref ble_advertising_start, but must be set
        // to legal values here to define an advertising handle.
        p_advertising->adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
        p_advertising->adv_params.duration        = p_advertising->adv_modes_config.ble_adv_fast_timeout;
        p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        p_advertising->adv_params.p_peer_addr     = NULL;
        p_advertising->adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        p_advertising->adv_params.interval        = p_advertising->adv_modes_config.ble_adv_fast_interval;
    
        ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, NULL, &p_advertising->adv_params);
        VERIFY_SUCCESS(ret);
    
        p_advertising->initialized = true;
        return ret;
        */
    }

    Something like this, have not really changed anything substantial. This works only when not connecting to the device. I have encountered some new problems which I have written in my previous post, under EDIT.

  • What you got there works for SDK14 but is only half of the solution for SDK15.  it doesn't update when you are already advertising.  I already showed you full solution month ago.  All you needed to do was to lookup the code, copy paste a couple of line and replace the buffer pointer from your own code but some said "it's only a good workaround" other said "I don't want to use a third party library".  

  • Ok, I thought the solution would not involve stopping and restarting advertising. Anyway, I will try your solution in my application and see if i run into the same problems.

  • Please let us know in here, still looking for a solution.

  • I am using this solution with SDK15 and while the advertising is already started, works just fine.

Reply Children
  • Can you post your solution code? Is it much different from what I posted?

  • My Update Function is only performing an update on the manufacturer specific data section of the advertising data (basicly I am copying new data to the array), then I am calling ble_advdata_encode to reencode the data.


    static void advertising_init(void)
    {
        ret_code_t    err_code;
        //ble_advdata_t advdata;
        ble_advdata_t srdata;
    
        ble_uuid_t adv_uuids[] = {{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE}};
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = false;
        advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        adv_manuf_data.data.p_data        = adv_manuf_data_data;
        adv_manuf_data.data.size          = 9;
        adv_manuf_data.company_identifier = 0x0054; 
        advdata.p_manuf_specific_data     = &adv_manuf_data;
    
        memset(&srdata, 0, sizeof(srdata));
        srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        srdata.uuids_complete.p_uuids  = adv_uuids;
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
        APP_ERROR_CHECK(err_code);
    
        // Set advertising parameters.
        memset(&adv_params, 0, sizeof(adv_params));
    
        adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
        adv_params.duration        = APP_ADV_DURATION;
        adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        adv_params.p_peer_addr     = NULL;
        adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        adv_params.interval        = default_advertising_interval;
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
        APP_ERROR_CHECK(err_code);
    }

    void update_advertising_data(void)
    {
    
        ret_code_t    err_code;
    
        memcpy(&adv_manuf_data_data[0], (uint8_t*) &data, sizeof(data));
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len); 
    
        APP_ERROR_CHECK(err_code);
    
    }

    I am calling the init function once at the beginning of the program, then I am only calling the update function while the program is running. If a connection is closed, I am just restarting the advertising, without changing the configuration.

  • Do you use the following sequence : Broadcast, Connection , End Connection , Broadcast with new data ?

    If you do that, that's mean that the data can't be updated dynamically. Just for a simple Broadcaster without any connection.

    In fact, I've tried your following way but it doesn't work without stop the advertiser and restart it again ... So it's the same problem as initially.

  • Can you please tell me...What is  "data" parameter  in  memcpy(&adv_manuf_data_data[0], (uint8_t*) &data, sizeof(data))  function???

Related