Adding counter or timestamp to extended periodic advertisements

Hello!

I am trying to distinguish between each individual periodic advertisement by adding either a counter (1 byte is enough) or a timestamp. I want to be able to read that counter when scanning the periodic advertisement. I tried using bt_le_adv_update_data, but I seem to be getting nowhere. I am using the direction finding connectionless tx example from the latest stable release of nRF Connect SDK for reference (working with nrf5340dk).

I imagined I would need to change a counter in the advertising data with a callback that triggers when an advertisement is sent, but I'm not sure if that would be the right approach. Including a timestamp in each advertisement would also suffice.

I tried looking for examples that do something similar, but I couldn't find anything.

Any pointers or suggestions would be incredibly helpful.

Parents
  • Hello

    I tried using bt_le_adv_update_data

    I believe this should work fine

    I seem to be getting nowhere.

    Could you be more specific about this? What isn't working, what have you tried to do?

    Best regards,

    Einar

  • Here is my code:

    static uint8_t counter = 0;  
    
    static const struct bt_data ad[] = {                                             
        BT_DATA(BT_DATA_URI, &counter, 1),                                           
    };                       
    
    void main(void)                                                                  
    {                                                                                
        char addr_s[BT_ADDR_LE_STR_LEN];                                             
        struct bt_le_oob oob_local;                                                  
        int err;                                                                                                        
                                                                                     
        printk("Starting Connectionless Beacon Demo\n");                             
                                                                                     
        /* Initialize the Bluetooth Subsystem */                                     
        printk("Bluetooth initialization...");                                       
        err = bt_enable(NULL);                                                       
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Advertising set create...");                                         
        err = bt_le_ext_adv_create(&param, &adv_callbacks, &adv_set);                
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Update CTE params...");                                              
        err = bt_df_set_adv_cte_tx_param(adv_set, &cte_params);                      
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Periodic advertising params set...");                                
        err = bt_le_per_adv_set_param(adv_set, &per_adv_param);                      
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");           
        
        printk("Enable CTE...");                                                     
        err = bt_df_adv_cte_tx_enable(adv_set);                                      
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Periodic advertising enable...");                                    
        err = bt_le_per_adv_start(adv_set);                                          
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Extended advertising enable...");                                    
        err = bt_le_ext_adv_start(adv_set, &ext_adv_start_param);                    
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Updating advertising data...");                                      
        err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), NULL, 0);                    
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        bt_le_ext_adv_oob_get_local(adv_set, &oob_local);                            
        bt_addr_le_to_str(&oob_local.addr, addr_s, sizeof(addr_s));                  
                                                                                     
        printk("Started extended advertising as %s\n", addr_s);                      
    }   

    This is code is mostly from the direction finding connectionless tx sample (I left out part of the code, let me know if showing everything would be helpful). the only lines I wrote are from 76 to 82, and the first 5 lines where i am declaring the advertising data.
    I am trying to use bt_le_adv_update_data to broadcast a 1 byte counter, but the function fails with error code -22. 
    Besides the fact that this does not work, I don't know how to set a callback such that the counter and advertising data would get updated after every periodic advertisement.

  • Hi

    Looks like your -22 error comes from here in bt_le_adv_update_data:

    struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy();

    if (!adv) {
    return -EINVAL;
    }

    Where bt_le_adv_lookup_legacy expands to

    struct bt_le_ext_adv *bt_le_adv_lookup_legacy(void)
    {
    #if defined(CONFIG_BT_EXT_ADV)
    return bt_dev.adv;
    #else
    return &bt_dev.adv;
    #endif
    }

    So I suspect that you should double check whether bt_le_ext_adv_create actually sets things up properly.

    I believe this function should also set up the advertising callbacks you are interested in.

    -Einar

  • Hello! I made some slight progress with the information from your response, so thank you for that!

    I am still struggling though, I now think that I need to use the function bt_le_ext_adv_set_data in order to update the advertising data, because I can pass the adv_set to the function, so bt_le_adv_lookup_legacy won't be called at all. 

    But when calling that I am now getting a -5 (which I believe is an IO error) when calling bt_le_ext_adv_set_data.

    Here is the entirety of the code:

    /*                                                                               
     * Copyright (c) 2021 Nordic Semiconductor ASA                                   
     *                                                                               
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause                           
     */                                                                              
                                                                                     
    #include <zephyr/types.h>                                                        
    #include <stddef.h>                                                              
    #include <errno.h>                                                               
    #include <zephyr/kernel.h>                                                       
    #include <zephyr/sys/printk.h>                                                                                
                                                                                     
    #include <zephyr/bluetooth/bluetooth.h>                                          
    #include <zephyr/bluetooth/direction.h>                                          
    #include <zephyr/sys/byteorder.h>                                                
    #include <zephyr/sys/util.h>                                                     
                                                                                     
    #define DEVICE_NAME CONFIG_BT_DEVICE_NAME                                        
    #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)                                
                                                                                     
    /* Length of CTE in unit of 8[us] */                                             
    #define CTE_LEN (0x14U)                                                          
    /* Number of CTE send in single periodic advertising train */                    
    #define PER_ADV_EVENT_CTE_COUNT 5                                                
                                                                                     
    static void adv_sent_cb(struct bt_le_ext_adv *adv,                               
                struct bt_le_ext_adv_sent_info *info);                               
                                                                                     
    const static struct bt_le_ext_adv_cb adv_callbacks = {                           
        .sent = adv_sent_cb,                                                         
    };                                                                               
                                                                                     
    static struct bt_le_ext_adv *adv_set;                                            
                                                                                     
    static uint8_t counter = 0;                                                      
                                                                                     
    static const struct bt_data ad[] = {                                             
        BT_DATA(BT_DATA_URI, &counter, 1)                                            
    };                                                                               
                                                                                     
    const static struct bt_le_adv_param param =                                      
            BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_EXT_ADV |                             
                         BT_LE_ADV_OPT_USE_NAME,                                     
                         BT_GAP_ADV_FAST_INT_MIN_2,                                  
                         BT_GAP_ADV_FAST_INT_MAX_2,                                  
                         NULL);   
    
    static struct bt_le_ext_adv_start_param ext_adv_start_param = {                  
        .timeout = 0,                                                                
        .num_events = 0,                                                             
    };                                                                               
                                                                                     
    const static struct bt_le_per_adv_param per_adv_param = {                        
        .interval_min = 400, // 500 ms                                               
        .interval_max = 500, // 625 ms                                               
        .options = BT_LE_ADV_OPT_USE_TX_POWER,                                       
    };                                                                               
                                                                                     
    struct bt_df_adv_cte_tx_param cte_params = { .cte_len = CTE_LEN,                 
                             .cte_count = PER_ADV_EVENT_CTE_COUNT,                   
                             .cte_type = BT_DF_CTE_TYPE_AOA,                                                      
                             .num_ant_ids = 0,                                       
                             .ant_ids = NULL                                         
    };                                                                               
                                                                                     
    static void adv_sent_cb(struct bt_le_ext_adv *adv,                               
                struct bt_le_ext_adv_sent_info *info)                                
    {                                                                                
        printk("Advertiser[%d] %p sent %d\n", bt_le_ext_adv_get_index(adv),          
               adv, info->num_sent);                                                 
    }                                                                                
                                                                                     
    void main(void)                                                                  
    {                                                                                
        char addr_s[BT_ADDR_LE_STR_LEN];                                             
        struct bt_le_oob oob_local;                                                  
        int err;                                                                     
                                                                                     
        printk("Starting Connectionless Beacon Demo\n");                             
                                                                                     
        /* Initialize the Bluetooth Subsystem */                                     
        printk("Bluetooth initialization...");                                       
        err = bt_enable(NULL);                                                       
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Advertising set create...");                                         
        err = bt_le_ext_adv_create(&param, &adv_callbacks, &adv_set);                
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n"); 
        
        printk("Update CTE params...");                                              
        err = bt_df_set_adv_cte_tx_param(adv_set, &cte_params);                      
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Periodic advertising params set...");                                
        err = bt_le_per_adv_set_param(adv_set, &per_adv_param);                      
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Enable CTE...");                                                     
        err = bt_df_adv_cte_tx_enable(adv_set);                                      
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Periodic advertising enable...");                                    
        err = bt_le_per_adv_start(adv_set);                                          
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        printk("Extended advertising enable...");                                    
        err = bt_le_ext_adv_start(adv_set, &ext_adv_start_param);                    
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
                                                                                     
        bt_le_ext_adv_oob_get_local(adv_set, &oob_local);                            
        bt_addr_le_to_str(&oob_local.addr, addr_s, sizeof(addr_s));                  
        
        printk("Started extended advertising as %s\n", addr_s);                      
                                                                                     
        printk("Updating advertising data...");                                      
        err = bt_le_ext_adv_set_data(adv_set, ad, ARRAY_SIZE(ad), NULL, 0);          
        if (err) {                                                                   
            printk("failed (err %d)\n", err);                                        
            return;                                                                  
        }                                                                            
        printk("success\n");                                                         
    }          

    I tried looking for code samples that use bt_le_ext_adv_set_data, but I couldn't find any. I am not sure what could be causing this error even though I read through the Bluetooth code, and I am not sure I am even on the right track. Perhaps there are sample applications that I can read over in order to figure out what I am missing here?

  • I think you're on the right track, but you might have to run bt_le_ext_adv_set_data before you start advertising.

    Then afterwards you might be able to run update data while advertising.

    -Einar

  • I managed to set the advertising data using bt_le_ext_adv_set_data, but I would need to update the counter every time an advertisement is sent. But the adv_sent_cb does't seem to work. You can see how it's set up in the latest code I pasted. 

    As I understand it from the documentation for bt_le_ext_adv_create, passing a bt_le_ext_adv_cb object as I did above should get me a callback for every sent extended advertisement. This function is never called when testing the code. 

    Is there even a way to set up a callback for each periodic advertisement?

    EDIT: It seems the callback I have been trying to use gets called when the advertisement is finished rather than after every individual advertisement, and I can't find any other relevant callback. So is there a way to call bt_le_ext_adv_set_data in order to update the counter value in the advertisement data after every individual periodic advertisement?

  • Ok, so bt_le_ext_adv_start takes bt_le_ext_adv_start_param as input, in which you can set the desired number of advertising events.

    If you set num_events to 1, you should get the bt_le_ext_adv_cb triggered after a single advertisement, so you can set your data and call bt_le_ext_adv_start again.

    I wish there was a more "sleek" way to do this, but I'm not aware of any, and this should at least get the behavior you want.

    https://github.com/nrfconnect/sdk-nrf/blob/45a51fc620ef52421106c7cf4c8eb0f80b2fddcf/samples/bluetooth/peripheral_power_profiling/src/main.c#L350

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/connectivity/bluetooth/api/gap.html#c.bt_le_ext_adv_start

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/connectivity/bluetooth/api/gap.html#c.bt_le_ext_adv_start_param

    -Einar

Reply Children
No Data
Related