Modify advertising data at run time for nrf connect SDK 2.6.1

I want to update/modify advertising data at run time,
How can I do so?

Parents
  • Hello,

    Please see Lesson 2 from the Bluetooth Low Energy fundamentals course on DevAcademy for information on Bluetooth LE advertising and specifically Exercise 2 which demonstrates dynamically changing the advertising data.

    Best regards,

    Maria

  • #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/gap.h>
    #include <zephyr/bluetooth/gatt.h>
    
    LOG_MODULE_REGISTER(ilumi);
    
    #define NETWORK_KEY_UNCOMMISSIONED                  0xFFEEDDCC
    #define NETWORK_MATER_KEY                           0x4DBF315A
    #define BLE_MAX_BROADCAST_SIZE 31
    typedef struct {
        uint8_t option_length;
        uint8_t manu_type;        //0xff type
        union {
            uint8_t header[10];
            uint8_t bytes[29];
        } payload;
    } MANU_OPTION_t;
    
    typedef struct {
        uint16_t ilumi_id;
        uint8_t msg_type;
        uint8_t other_seq_num; // lower 4 bits are sequence number, rotate between 1 to 7
        uint8_t dsdv_seq_num;
        uint8_t model_num;
        uint16_t firmware_ver;
        uint16_t network_id;
        union {
            uint8_t status_bits;
            uint8_t status;
        };
        uint8_t mesh_depth;
        uint16_t bootload_ver;
        uint16_t ble_stack_ver;
        uint16_t gatt_handle;
        uint8_t current_status[6]; // 6 bytes for current status
    } iLumi_adv_heart_beat_t;
    
    typedef struct {
        uint8_t is_commissioned:1;
        uint8_t is_connected_as_slave:1;
        uint8_t is_can_connect_more:1;
        uint8_t is_neighbor_parentable:1;
        uint8_t expecting_parent_mesh_depth:4;
    } ilumi_scan_resp_status;
    
    typedef struct {
        uint16_t service_uuid;
        uint8_t routing_entry_amount;
        union {
            ilumi_scan_resp_status status_bits;
            uint8_t status;
        };
        uint8_t mac_address[6]; // Define the MAC_ADDRESS_t as an array of 6 bytes
        uint16_t firmware_ver;
        uint16_t network_id;
    } iLumi_scanResp_ServiceData_t;
    
    typedef struct __PACKED_STRUCT_BEGIN__ {
        uint8_t byte[6];
    } MAC_ADDRESS_t;
    
    void update_heart_beat_data(void);
    uint8_t get_dsdv_seq_no(void);
    void update_adv_data(void);
    void start_advertising(void);
    void set_device_name();
    void set_default_scan_resp_data(void);
    uint8_t create_adv_resp_data(uint8_t *Scan_Response_Data, uint8_t buffer_size, uint8_t *my_mac_address, uint8_t *Local_Device_Name);
    
    uint8_t Local_Device_Name[16];
    static iLumi_adv_heart_beat_t adv_heartbeat_pkt;
    static MANU_OPTION_t newpkt_data;
    static uint8_t new_adv_data[31];
    static uint8_t dsdv_seq_no = 0;
    MAC_ADDRESS_t ilumi_local_mac_address;
    struct k_timer update_dsdv_seq_timer;
    static uint8_t Scan_Response_Data[29];
    iLumi_scanResp_ServiceData_t scan_resp_option;
    static bool is_ble_adv_on = false;
    static uint8_t adv_data_count = 0;
    uint8_t uuid128[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x40, 0x51, 0x04, 0xC0, 0xF0, 0x00, 0xF0};
    struct bt_le_adv_param adv_param = {
        .options = BT_LE_ADV_OPT_CONNECTABLE,\
                        BT_LE_ADV_OPT_USE_NAME | \
                        BT_LE_ADV_OPT_FORCE_NAME_IN_AD,
        .id = BT_ID_DEFAULT,
        .interval_min = 0x0020,
        .interval_max = 0x4000
    };
    
    struct bt_data manu_spec_adv_data[2];
    
    struct bt_data scan_rsp_data[2];
    
    static void update_dsdsv_seq_no(struct k_timer *timer){
        dsdv_seq_no+=2;
        printk("dsdv_seq_no : %d\r\n",dsdv_seq_no);
        k_timer_start(&update_dsdv_seq_timer, K_SECONDS(1), K_NO_WAIT);
        update_adv_data();
    }
    
    static void on_connected(struct bt_conn *conn, uint8_t err)
    {
        if (err) {
            printk("Connection failed (err %d)\n", err);
        } else {
            printk("Connected\n");
        }
    }
    
    static void on_disconnected(struct bt_conn *conn, uint8_t reason)
    {
        printk("Disconnected (reason %d)\n", reason);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks)={
        .connected = on_connected,
        .disconnected = on_disconnected,
    };
    
    static ssize_t write_callback(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                                  const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
    {
        LOG_INF("Data received, length: %d", len);
        LOG_HEXDUMP_INF(buf, len, "Received data");
    
        return len;
    }
    
    BT_GATT_SERVICE_DEFINE(my_service,
        BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0xF000F0C0, 0x0451, 0x4000, 0xB000, 0x000000000000))),
        BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0xF000F0C0, 0x0451, 0x4000, 0xB000, 0x000000000000)),
                               BT_GATT_CHRC_WRITE,
                               BT_GATT_PERM_WRITE,
                               NULL, write_callback, NULL),
    );
    
    uint8_t get_dsdv_seq_no(void){
        return dsdv_seq_no;
    }
    
    void update_heart_beat_data(void)
    {
        memset(&adv_heartbeat_pkt, 0, sizeof(adv_heartbeat_pkt));
    
        adv_heartbeat_pkt.ilumi_id = 0xFACE; // Example company_id
        adv_heartbeat_pkt.firmware_ver = 0x01DD; // Example firmware version
        adv_heartbeat_pkt.msg_type = 6; // ILUMI_AD_MSG_ROUTE_HEART_BEAT
        adv_heartbeat_pkt.model_num = 0x51; // Example model number
        adv_heartbeat_pkt.dsdv_seq_num = get_dsdv_seq_no(); // Example DSDV sequence number
        adv_heartbeat_pkt.network_id = 0x00CC; // Example network ID
        adv_heartbeat_pkt.mesh_depth = 0;
        adv_heartbeat_pkt.bootload_ver = 0x106;
        adv_heartbeat_pkt.ble_stack_ver = 0x101;
    	//whenever change heart beat, send out A.S.A.P
        memcpy(newpkt_data.payload.bytes, &adv_heartbeat_pkt, sizeof(adv_heartbeat_pkt));
        newpkt_data.manu_type = 0xFF; // Example manufacturer specific type
        newpkt_data.option_length = sizeof(adv_heartbeat_pkt) + 1;
    
        memcpy(&new_adv_data, &newpkt_data.payload, sizeof(newpkt_data.payload));
    }
    
    uint8_t add_advertise_parameter(uint8_t *buffer, uint8_t *tail, uint8_t length, uint8_t type, uint8_t *data) {
        uint8_t total_len = 2 + length;
        if ((buffer + total_len) > (tail + 1)) { // not enough buffer to add new parameter
            return 0;
        } else {
            buffer[0] = total_len - 1; // not including type itself
            buffer[1] = type;
            memcpy(&buffer[2], data, length);
            return total_len;
        }
    }
    
    uint8_t create_adv_resp_data(uint8_t *Scan_Response_Data, uint8_t buffer_size, uint8_t *my_mac_address, uint8_t *Local_Device_Name) {
        uint8_t ad_offset = 0;
        // iLumi_scanResp_ServiceData_t scan_resp_option;
    
        memset(Scan_Response_Data, 0, buffer_size);
    
        /* <0> iLumi local device name */
        ad_offset += add_advertise_parameter(&Scan_Response_Data[ad_offset], &Scan_Response_Data[BLE_MAX_BROADCAST_SIZE - 1], 11, BT_DATA_NAME_COMPLETE, Local_Device_Name);
    
        /* <1> iLumi Service data with MAC address */
        scan_resp_option.service_uuid = 0xF0C0; // Example UUID
        scan_resp_option.status = 0;
        scan_resp_option.status_bits.is_commissioned = 0; // Example value
        scan_resp_option.status_bits.is_connected_as_slave = 0; // Example value
    
        scan_resp_option.routing_entry_amount = 5; // Example value
        scan_resp_option.network_id = 0xFFFF; // Example value
        scan_resp_option.firmware_ver = 0x0102; // Example value
    
        memcpy(scan_resp_option.mac_address, my_mac_address, sizeof(scan_resp_option.mac_address));
        ad_offset += add_advertise_parameter(&Scan_Response_Data[ad_offset], &Scan_Response_Data[BLE_MAX_BROADCAST_SIZE - 1], sizeof(scan_resp_option), BT_DATA_SVC_DATA16, (uint8_t*)&scan_resp_option);
    
        return ad_offset;
    }
    
    void update_scan_response_data(void){
        // memset(Scan_Response_Data, 0, buffer_size);
        memset(&scan_resp_option,0,sizeof(scan_resp_option));
        /* <1> iLumi Service data with MAC address */
        scan_resp_option.service_uuid = 0xF0C0; // Example UUID
        scan_resp_option.status = 0;
        scan_resp_option.status_bits.is_commissioned = 0; // Example value
        scan_resp_option.status_bits.is_connected_as_slave = 0; // Example value
    
        scan_resp_option.routing_entry_amount = 0; // Example value
        scan_resp_option.network_id = 0x00CC; // Example value
        scan_resp_option.firmware_ver = 0x01DD; // Example value
    
        memcpy(scan_resp_option.mac_address, &ilumi_local_mac_address, sizeof(scan_resp_option.mac_address));    
    }
    
    void set_default_scan_resp_data(void) {
        printk("MAC ADDRESS: %02X:%02X:%02X:%02X:%02X:%02X\r\n",ilumi_local_mac_address.byte[0],ilumi_local_mac_address.byte[1],ilumi_local_mac_address.byte[2],
                ilumi_local_mac_address.byte[3],ilumi_local_mac_address.byte[4],ilumi_local_mac_address.byte[5]);
        create_adv_resp_data(Scan_Response_Data, BLE_MAX_BROADCAST_SIZE,(uint8_t*)&ilumi_local_mac_address, Local_Device_Name);
    }
    
    void start_advertising(void)
    {
    	adv_param.interval_min = 160;
    	adv_param.interval_max = 800;
    
        manu_spec_adv_data[0].type = BT_DATA_FLAGS;
        manu_spec_adv_data[0].data_len = 1;
        manu_spec_adv_data[0].data = (uint8_t []) { 0x06 };
        manu_spec_adv_data[1].type = BT_DATA_MANUFACTURER_DATA;
        manu_spec_adv_data[1].data_len = sizeof(adv_heartbeat_pkt);
        memcpy(&new_adv_data, &newpkt_data.payload, sizeof(new_adv_data));
        manu_spec_adv_data[1].data = new_adv_data;
        adv_data_count = 1;
    
        scan_rsp_data[0].type = BT_DATA_NAME_COMPLETE;
        scan_rsp_data[0].data_len = 12;
        scan_rsp_data[0].data = Local_Device_Name;
        scan_rsp_data[1].type = BT_DATA_SVC_DATA16;
        scan_rsp_data[1].data_len = sizeof(scan_resp_option);
        scan_rsp_data[1].data = (uint8_t*)&scan_resp_option;
        for(uint8_t i = 0; i<sizeof(manu_spec_adv_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("ADV DATA-%d TYPE: %02x, DATA_LENGTH : %02X",i,manu_spec_adv_data[i].type,manu_spec_adv_data[i].data_len);
            LOG_HEXDUMP_INF(manu_spec_adv_data[i].data,manu_spec_adv_data[i].data_len,"ADV DATA");       
        }
        for(uint8_t i = 0; i<sizeof(scan_rsp_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("SCAN RESP-%d TYPE: %02x, DATA_LENGTH : %02X",i,scan_rsp_data[i].type,scan_rsp_data[i].data_len);
            LOG_HEXDUMP_INF(scan_rsp_data[i].data,scan_rsp_data[i].data_len,"SCAN RESP");       
        }
        
        error_t err = bt_le_adv_start(&adv_param, manu_spec_adv_data, ARRAY_SIZE(manu_spec_adv_data), scan_rsp_data, ARRAY_SIZE(scan_rsp_data));
        if (err) {
            printk("Advertising failed to start (err %d)\r\n", err);
            is_ble_adv_on = false;
            return;
        }else{
            is_ble_adv_on = true;
            printk("Advertising successfully started\r\n");
        }
    }
    
    void update_adv_data(void){
        if(is_ble_adv_on){
            error_t err = bt_le_adv_stop();
            if(err){
                printk("unable to stop adv err : %d\r\n",err);
                return;
            }else{
                printk("Adv stopped successfully\r\n");
            }
        }
          if(adv_data_count == 0){
            adv_data_count = 1;
            manu_spec_adv_data[0].type = BT_DATA_FLAGS;
            manu_spec_adv_data[0].data_len = 1;
            manu_spec_adv_data[0].data = (uint8_t []) { 0x06 };
            manu_spec_adv_data[1].type = BT_DATA_MANUFACTURER_DATA;
            manu_spec_adv_data[1].data_len = sizeof(adv_heartbeat_pkt);
            memcpy(&new_adv_data, &newpkt_data.payload, sizeof(new_adv_data));
            manu_spec_adv_data[1].data = new_adv_data;
        }else{
            adv_data_count = 0;
            adv_data_count = 1;
            manu_spec_adv_data[0].type = BT_DATA_UUID128_ALL;
            manu_spec_adv_data[0].data_len = sizeof(uuid128);
            manu_spec_adv_data[0].data = uuid128;
            manu_spec_adv_data[1].type = BT_DATA_TX_POWER;
            manu_spec_adv_data[1].data_len = 1;
            manu_spec_adv_data[1].data = (uint8_t[]){0x0C};
        }
            scan_rsp_data[0].type = BT_DATA_NAME_COMPLETE;
            scan_rsp_data[0].data_len = 12;
            scan_rsp_data[0].data = Local_Device_Name;
            scan_rsp_data[1].type = BT_DATA_SVC_DATA16;
            scan_rsp_data[1].data_len = sizeof(scan_resp_option);
            scan_rsp_data[1].data = (uint8_t*)&scan_resp_option;
        for(uint8_t i = 0; i<sizeof(manu_spec_adv_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("ADV DATA-%d TYPE: %02x, DATA_LENGTH : %02X",i,manu_spec_adv_data[i].type,manu_spec_adv_data[i].data_len);
            LOG_HEXDUMP_INF(manu_spec_adv_data[i].data,manu_spec_adv_data[i].data_len,"ADV DATA");       
        }
        for(uint8_t i = 0; i<sizeof(scan_rsp_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("SCAN RESP-%d TYPE: %02x, DATA_LENGTH : %02X",i,scan_rsp_data[i].type,scan_rsp_data[i].data_len);
            LOG_HEXDUMP_INF(scan_rsp_data[i].data,scan_rsp_data[i].data_len,"SCAN RESP");       
        }
        error_t err = bt_le_adv_update_data(manu_spec_adv_data, ARRAY_SIZE(manu_spec_adv_data), scan_rsp_data, ARRAY_SIZE(scan_rsp_data));
        if(err){
            printk("Unable to update adv data error: %d\r\n",err);
        }else{
            printk("Advertisment parameters updated successfuly\r\n");
        }
    
        bt_le_adv_resume();
    }
    
    void set_device_name(){
     	char addr_s[BT_ADDR_LE_STR_LEN];
    	bt_addr_le_t addr = {0};
    	size_t count = 1;
    	bt_id_get(&addr, &count);
    	bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s));
    
    	memcpy(&ilumi_local_mac_address, addr.a.val, sizeof(MAC_ADDRESS_t));
    	sprintf((char *)Local_Device_Name, "%s%02X%02X%02X", "Nrdic",
    			ilumi_local_mac_address.byte[2],
    			ilumi_local_mac_address.byte[1],
    			ilumi_local_mac_address.byte[0]);
    	printk("Device Name: %s\r\n", Local_Device_Name);
    
        error_t err = bt_set_name(Local_Device_Name);
        if(err){
            LOG_ERR("Unable sto set the device name : %d",err);
        }
    }
    
    void bt_ready(int err)
    {
        if (err) {
            LOG_ERR("Bluetooth init failed (err %d)\r\n", err);
            return;
        }
    
        printk("Bluetooth initialized\r\n");
    }
    
    void main(void)
    {
        int err;
        K_SECONDS(1);
        k_timer_init(&update_dsdv_seq_timer, update_dsdsv_seq_no, NULL);
        k_timer_start(&update_dsdv_seq_timer, K_SECONDS(1), K_NO_WAIT);
        err = bt_enable(bt_ready);
        if (err) {
            LOG_ERR("Bluetooth enable failed (err %d)", err);
        }
        set_device_name();
        update_scan_response_data();
        update_heart_beat_data();
        start_advertising();
    }
    

    Error I got after using the adv update function:

    *** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
    [00:00:00.000,488] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                36 f0 e5 0e 87 68 48 fb  02 fd 9f 82 cc 32 e5 7b |6....hH. .....2.{
                                                91 b1 5c ed                                      |..\.             
    [00:00:00.002,807] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.002,838] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.002,868] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 54.58864 Build 1214809870
    [00:00:00.003,723] <inf> bt_hci_core: Identity: DB:FD:39:59:2A:7F (random)
    [00:00:00.003,753] <inf> bt_hci_core: HCI: version 5.4 (0x0d) revision 0x118f, manufacturer 0x0059
    [00:00:00.003,784] <inf> bt_hci_core: LMP: version 5.4 (0x0d) subver 0x118f
    Bluetooth initialized
    Device Name: Nrdic592A7F
    [00:00:00.003,967] <inf> ilumi: ADV DATA-0 TYPE: 01, DATA_LENGTH : 01
    [00:00:00.003,997] <inf> ilumi: ADV DATA
                                    06                                               |.                
    [00:00:00.003,997] <inf> ilumi: ADV DATA-1 TYPE: ff, DATA_LENGTH : 18
    [00:00:00.004,028] <inf> ilumi: ADV DATA
                                    ce fa 06 00 00 51 dd 01  cc 00 00 00 06 01 01 01 |.....Q.. ........
                                    00 00 00 00 00 00 00 00                          |........         
    [00:00:00.004,058] <inf> ilumi: SCAN RESP-0 TYPE: 09, DATA_LENGTH : 0C
    [00:00:00.004,058] <inf> ilumi: SCAN RESP
                                    4e 72 64 69 63 35 39 32  41 37 46 00             |Nrdic592 A7F.    
    [00:00:00.004,089] <inf> ilumi: SCAN RESP-1 TYPE: 16, DATA_LENGTH : 0E
    [00:00:00.004,119] <inf> ilumi: SCAN RESP
                                    c0 f0 00 00 7f 2a 59 39  fd db dd 01 cc 00       |.....*Y9 ......  
    Advertising successfully started
    dsdv_seq_no : 2
    ASSERTION FAIL [err == 0] @ WEST_TOPDIR/zephyr/subsys/bluetooth/host/hci_core.c:331
            command opcode 0x2039 timeout with err -11
    [00:00:01.068,084] <err> fatal_error: k_sys_fatal_error_handler: Resetting system

Reply
  • #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/gap.h>
    #include <zephyr/bluetooth/gatt.h>
    
    LOG_MODULE_REGISTER(ilumi);
    
    #define NETWORK_KEY_UNCOMMISSIONED                  0xFFEEDDCC
    #define NETWORK_MATER_KEY                           0x4DBF315A
    #define BLE_MAX_BROADCAST_SIZE 31
    typedef struct {
        uint8_t option_length;
        uint8_t manu_type;        //0xff type
        union {
            uint8_t header[10];
            uint8_t bytes[29];
        } payload;
    } MANU_OPTION_t;
    
    typedef struct {
        uint16_t ilumi_id;
        uint8_t msg_type;
        uint8_t other_seq_num; // lower 4 bits are sequence number, rotate between 1 to 7
        uint8_t dsdv_seq_num;
        uint8_t model_num;
        uint16_t firmware_ver;
        uint16_t network_id;
        union {
            uint8_t status_bits;
            uint8_t status;
        };
        uint8_t mesh_depth;
        uint16_t bootload_ver;
        uint16_t ble_stack_ver;
        uint16_t gatt_handle;
        uint8_t current_status[6]; // 6 bytes for current status
    } iLumi_adv_heart_beat_t;
    
    typedef struct {
        uint8_t is_commissioned:1;
        uint8_t is_connected_as_slave:1;
        uint8_t is_can_connect_more:1;
        uint8_t is_neighbor_parentable:1;
        uint8_t expecting_parent_mesh_depth:4;
    } ilumi_scan_resp_status;
    
    typedef struct {
        uint16_t service_uuid;
        uint8_t routing_entry_amount;
        union {
            ilumi_scan_resp_status status_bits;
            uint8_t status;
        };
        uint8_t mac_address[6]; // Define the MAC_ADDRESS_t as an array of 6 bytes
        uint16_t firmware_ver;
        uint16_t network_id;
    } iLumi_scanResp_ServiceData_t;
    
    typedef struct __PACKED_STRUCT_BEGIN__ {
        uint8_t byte[6];
    } MAC_ADDRESS_t;
    
    void update_heart_beat_data(void);
    uint8_t get_dsdv_seq_no(void);
    void update_adv_data(void);
    void start_advertising(void);
    void set_device_name();
    void set_default_scan_resp_data(void);
    uint8_t create_adv_resp_data(uint8_t *Scan_Response_Data, uint8_t buffer_size, uint8_t *my_mac_address, uint8_t *Local_Device_Name);
    
    uint8_t Local_Device_Name[16];
    static iLumi_adv_heart_beat_t adv_heartbeat_pkt;
    static MANU_OPTION_t newpkt_data;
    static uint8_t new_adv_data[31];
    static uint8_t dsdv_seq_no = 0;
    MAC_ADDRESS_t ilumi_local_mac_address;
    struct k_timer update_dsdv_seq_timer;
    static uint8_t Scan_Response_Data[29];
    iLumi_scanResp_ServiceData_t scan_resp_option;
    static bool is_ble_adv_on = false;
    static uint8_t adv_data_count = 0;
    uint8_t uuid128[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x40, 0x51, 0x04, 0xC0, 0xF0, 0x00, 0xF0};
    struct bt_le_adv_param adv_param = {
        .options = BT_LE_ADV_OPT_CONNECTABLE,\
                        BT_LE_ADV_OPT_USE_NAME | \
                        BT_LE_ADV_OPT_FORCE_NAME_IN_AD,
        .id = BT_ID_DEFAULT,
        .interval_min = 0x0020,
        .interval_max = 0x4000
    };
    
    struct bt_data manu_spec_adv_data[2];
    
    struct bt_data scan_rsp_data[2];
    
    static void update_dsdsv_seq_no(struct k_timer *timer){
        dsdv_seq_no+=2;
        printk("dsdv_seq_no : %d\r\n",dsdv_seq_no);
        k_timer_start(&update_dsdv_seq_timer, K_SECONDS(1), K_NO_WAIT);
        update_adv_data();
    }
    
    static void on_connected(struct bt_conn *conn, uint8_t err)
    {
        if (err) {
            printk("Connection failed (err %d)\n", err);
        } else {
            printk("Connected\n");
        }
    }
    
    static void on_disconnected(struct bt_conn *conn, uint8_t reason)
    {
        printk("Disconnected (reason %d)\n", reason);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks)={
        .connected = on_connected,
        .disconnected = on_disconnected,
    };
    
    static ssize_t write_callback(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                                  const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
    {
        LOG_INF("Data received, length: %d", len);
        LOG_HEXDUMP_INF(buf, len, "Received data");
    
        return len;
    }
    
    BT_GATT_SERVICE_DEFINE(my_service,
        BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0xF000F0C0, 0x0451, 0x4000, 0xB000, 0x000000000000))),
        BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0xF000F0C0, 0x0451, 0x4000, 0xB000, 0x000000000000)),
                               BT_GATT_CHRC_WRITE,
                               BT_GATT_PERM_WRITE,
                               NULL, write_callback, NULL),
    );
    
    uint8_t get_dsdv_seq_no(void){
        return dsdv_seq_no;
    }
    
    void update_heart_beat_data(void)
    {
        memset(&adv_heartbeat_pkt, 0, sizeof(adv_heartbeat_pkt));
    
        adv_heartbeat_pkt.ilumi_id = 0xFACE; // Example company_id
        adv_heartbeat_pkt.firmware_ver = 0x01DD; // Example firmware version
        adv_heartbeat_pkt.msg_type = 6; // ILUMI_AD_MSG_ROUTE_HEART_BEAT
        adv_heartbeat_pkt.model_num = 0x51; // Example model number
        adv_heartbeat_pkt.dsdv_seq_num = get_dsdv_seq_no(); // Example DSDV sequence number
        adv_heartbeat_pkt.network_id = 0x00CC; // Example network ID
        adv_heartbeat_pkt.mesh_depth = 0;
        adv_heartbeat_pkt.bootload_ver = 0x106;
        adv_heartbeat_pkt.ble_stack_ver = 0x101;
    	//whenever change heart beat, send out A.S.A.P
        memcpy(newpkt_data.payload.bytes, &adv_heartbeat_pkt, sizeof(adv_heartbeat_pkt));
        newpkt_data.manu_type = 0xFF; // Example manufacturer specific type
        newpkt_data.option_length = sizeof(adv_heartbeat_pkt) + 1;
    
        memcpy(&new_adv_data, &newpkt_data.payload, sizeof(newpkt_data.payload));
    }
    
    uint8_t add_advertise_parameter(uint8_t *buffer, uint8_t *tail, uint8_t length, uint8_t type, uint8_t *data) {
        uint8_t total_len = 2 + length;
        if ((buffer + total_len) > (tail + 1)) { // not enough buffer to add new parameter
            return 0;
        } else {
            buffer[0] = total_len - 1; // not including type itself
            buffer[1] = type;
            memcpy(&buffer[2], data, length);
            return total_len;
        }
    }
    
    uint8_t create_adv_resp_data(uint8_t *Scan_Response_Data, uint8_t buffer_size, uint8_t *my_mac_address, uint8_t *Local_Device_Name) {
        uint8_t ad_offset = 0;
        // iLumi_scanResp_ServiceData_t scan_resp_option;
    
        memset(Scan_Response_Data, 0, buffer_size);
    
        /* <0> iLumi local device name */
        ad_offset += add_advertise_parameter(&Scan_Response_Data[ad_offset], &Scan_Response_Data[BLE_MAX_BROADCAST_SIZE - 1], 11, BT_DATA_NAME_COMPLETE, Local_Device_Name);
    
        /* <1> iLumi Service data with MAC address */
        scan_resp_option.service_uuid = 0xF0C0; // Example UUID
        scan_resp_option.status = 0;
        scan_resp_option.status_bits.is_commissioned = 0; // Example value
        scan_resp_option.status_bits.is_connected_as_slave = 0; // Example value
    
        scan_resp_option.routing_entry_amount = 5; // Example value
        scan_resp_option.network_id = 0xFFFF; // Example value
        scan_resp_option.firmware_ver = 0x0102; // Example value
    
        memcpy(scan_resp_option.mac_address, my_mac_address, sizeof(scan_resp_option.mac_address));
        ad_offset += add_advertise_parameter(&Scan_Response_Data[ad_offset], &Scan_Response_Data[BLE_MAX_BROADCAST_SIZE - 1], sizeof(scan_resp_option), BT_DATA_SVC_DATA16, (uint8_t*)&scan_resp_option);
    
        return ad_offset;
    }
    
    void update_scan_response_data(void){
        // memset(Scan_Response_Data, 0, buffer_size);
        memset(&scan_resp_option,0,sizeof(scan_resp_option));
        /* <1> iLumi Service data with MAC address */
        scan_resp_option.service_uuid = 0xF0C0; // Example UUID
        scan_resp_option.status = 0;
        scan_resp_option.status_bits.is_commissioned = 0; // Example value
        scan_resp_option.status_bits.is_connected_as_slave = 0; // Example value
    
        scan_resp_option.routing_entry_amount = 0; // Example value
        scan_resp_option.network_id = 0x00CC; // Example value
        scan_resp_option.firmware_ver = 0x01DD; // Example value
    
        memcpy(scan_resp_option.mac_address, &ilumi_local_mac_address, sizeof(scan_resp_option.mac_address));    
    }
    
    void set_default_scan_resp_data(void) {
        printk("MAC ADDRESS: %02X:%02X:%02X:%02X:%02X:%02X\r\n",ilumi_local_mac_address.byte[0],ilumi_local_mac_address.byte[1],ilumi_local_mac_address.byte[2],
                ilumi_local_mac_address.byte[3],ilumi_local_mac_address.byte[4],ilumi_local_mac_address.byte[5]);
        create_adv_resp_data(Scan_Response_Data, BLE_MAX_BROADCAST_SIZE,(uint8_t*)&ilumi_local_mac_address, Local_Device_Name);
    }
    
    void start_advertising(void)
    {
    	adv_param.interval_min = 160;
    	adv_param.interval_max = 800;
    
        manu_spec_adv_data[0].type = BT_DATA_FLAGS;
        manu_spec_adv_data[0].data_len = 1;
        manu_spec_adv_data[0].data = (uint8_t []) { 0x06 };
        manu_spec_adv_data[1].type = BT_DATA_MANUFACTURER_DATA;
        manu_spec_adv_data[1].data_len = sizeof(adv_heartbeat_pkt);
        memcpy(&new_adv_data, &newpkt_data.payload, sizeof(new_adv_data));
        manu_spec_adv_data[1].data = new_adv_data;
        adv_data_count = 1;
    
        scan_rsp_data[0].type = BT_DATA_NAME_COMPLETE;
        scan_rsp_data[0].data_len = 12;
        scan_rsp_data[0].data = Local_Device_Name;
        scan_rsp_data[1].type = BT_DATA_SVC_DATA16;
        scan_rsp_data[1].data_len = sizeof(scan_resp_option);
        scan_rsp_data[1].data = (uint8_t*)&scan_resp_option;
        for(uint8_t i = 0; i<sizeof(manu_spec_adv_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("ADV DATA-%d TYPE: %02x, DATA_LENGTH : %02X",i,manu_spec_adv_data[i].type,manu_spec_adv_data[i].data_len);
            LOG_HEXDUMP_INF(manu_spec_adv_data[i].data,manu_spec_adv_data[i].data_len,"ADV DATA");       
        }
        for(uint8_t i = 0; i<sizeof(scan_rsp_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("SCAN RESP-%d TYPE: %02x, DATA_LENGTH : %02X",i,scan_rsp_data[i].type,scan_rsp_data[i].data_len);
            LOG_HEXDUMP_INF(scan_rsp_data[i].data,scan_rsp_data[i].data_len,"SCAN RESP");       
        }
        
        error_t err = bt_le_adv_start(&adv_param, manu_spec_adv_data, ARRAY_SIZE(manu_spec_adv_data), scan_rsp_data, ARRAY_SIZE(scan_rsp_data));
        if (err) {
            printk("Advertising failed to start (err %d)\r\n", err);
            is_ble_adv_on = false;
            return;
        }else{
            is_ble_adv_on = true;
            printk("Advertising successfully started\r\n");
        }
    }
    
    void update_adv_data(void){
        if(is_ble_adv_on){
            error_t err = bt_le_adv_stop();
            if(err){
                printk("unable to stop adv err : %d\r\n",err);
                return;
            }else{
                printk("Adv stopped successfully\r\n");
            }
        }
          if(adv_data_count == 0){
            adv_data_count = 1;
            manu_spec_adv_data[0].type = BT_DATA_FLAGS;
            manu_spec_adv_data[0].data_len = 1;
            manu_spec_adv_data[0].data = (uint8_t []) { 0x06 };
            manu_spec_adv_data[1].type = BT_DATA_MANUFACTURER_DATA;
            manu_spec_adv_data[1].data_len = sizeof(adv_heartbeat_pkt);
            memcpy(&new_adv_data, &newpkt_data.payload, sizeof(new_adv_data));
            manu_spec_adv_data[1].data = new_adv_data;
        }else{
            adv_data_count = 0;
            adv_data_count = 1;
            manu_spec_adv_data[0].type = BT_DATA_UUID128_ALL;
            manu_spec_adv_data[0].data_len = sizeof(uuid128);
            manu_spec_adv_data[0].data = uuid128;
            manu_spec_adv_data[1].type = BT_DATA_TX_POWER;
            manu_spec_adv_data[1].data_len = 1;
            manu_spec_adv_data[1].data = (uint8_t[]){0x0C};
        }
            scan_rsp_data[0].type = BT_DATA_NAME_COMPLETE;
            scan_rsp_data[0].data_len = 12;
            scan_rsp_data[0].data = Local_Device_Name;
            scan_rsp_data[1].type = BT_DATA_SVC_DATA16;
            scan_rsp_data[1].data_len = sizeof(scan_resp_option);
            scan_rsp_data[1].data = (uint8_t*)&scan_resp_option;
        for(uint8_t i = 0; i<sizeof(manu_spec_adv_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("ADV DATA-%d TYPE: %02x, DATA_LENGTH : %02X",i,manu_spec_adv_data[i].type,manu_spec_adv_data[i].data_len);
            LOG_HEXDUMP_INF(manu_spec_adv_data[i].data,manu_spec_adv_data[i].data_len,"ADV DATA");       
        }
        for(uint8_t i = 0; i<sizeof(scan_rsp_data)/sizeof(struct bt_data) ; i++){
            LOG_INF("SCAN RESP-%d TYPE: %02x, DATA_LENGTH : %02X",i,scan_rsp_data[i].type,scan_rsp_data[i].data_len);
            LOG_HEXDUMP_INF(scan_rsp_data[i].data,scan_rsp_data[i].data_len,"SCAN RESP");       
        }
        error_t err = bt_le_adv_update_data(manu_spec_adv_data, ARRAY_SIZE(manu_spec_adv_data), scan_rsp_data, ARRAY_SIZE(scan_rsp_data));
        if(err){
            printk("Unable to update adv data error: %d\r\n",err);
        }else{
            printk("Advertisment parameters updated successfuly\r\n");
        }
    
        bt_le_adv_resume();
    }
    
    void set_device_name(){
     	char addr_s[BT_ADDR_LE_STR_LEN];
    	bt_addr_le_t addr = {0};
    	size_t count = 1;
    	bt_id_get(&addr, &count);
    	bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s));
    
    	memcpy(&ilumi_local_mac_address, addr.a.val, sizeof(MAC_ADDRESS_t));
    	sprintf((char *)Local_Device_Name, "%s%02X%02X%02X", "Nrdic",
    			ilumi_local_mac_address.byte[2],
    			ilumi_local_mac_address.byte[1],
    			ilumi_local_mac_address.byte[0]);
    	printk("Device Name: %s\r\n", Local_Device_Name);
    
        error_t err = bt_set_name(Local_Device_Name);
        if(err){
            LOG_ERR("Unable sto set the device name : %d",err);
        }
    }
    
    void bt_ready(int err)
    {
        if (err) {
            LOG_ERR("Bluetooth init failed (err %d)\r\n", err);
            return;
        }
    
        printk("Bluetooth initialized\r\n");
    }
    
    void main(void)
    {
        int err;
        K_SECONDS(1);
        k_timer_init(&update_dsdv_seq_timer, update_dsdsv_seq_no, NULL);
        k_timer_start(&update_dsdv_seq_timer, K_SECONDS(1), K_NO_WAIT);
        err = bt_enable(bt_ready);
        if (err) {
            LOG_ERR("Bluetooth enable failed (err %d)", err);
        }
        set_device_name();
        update_scan_response_data();
        update_heart_beat_data();
        start_advertising();
    }
    

    Error I got after using the adv update function:

    *** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
    [00:00:00.000,488] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                36 f0 e5 0e 87 68 48 fb  02 fd 9f 82 cc 32 e5 7b |6....hH. .....2.{
                                                91 b1 5c ed                                      |..\.             
    [00:00:00.002,807] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.002,838] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.002,868] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 54.58864 Build 1214809870
    [00:00:00.003,723] <inf> bt_hci_core: Identity: DB:FD:39:59:2A:7F (random)
    [00:00:00.003,753] <inf> bt_hci_core: HCI: version 5.4 (0x0d) revision 0x118f, manufacturer 0x0059
    [00:00:00.003,784] <inf> bt_hci_core: LMP: version 5.4 (0x0d) subver 0x118f
    Bluetooth initialized
    Device Name: Nrdic592A7F
    [00:00:00.003,967] <inf> ilumi: ADV DATA-0 TYPE: 01, DATA_LENGTH : 01
    [00:00:00.003,997] <inf> ilumi: ADV DATA
                                    06                                               |.                
    [00:00:00.003,997] <inf> ilumi: ADV DATA-1 TYPE: ff, DATA_LENGTH : 18
    [00:00:00.004,028] <inf> ilumi: ADV DATA
                                    ce fa 06 00 00 51 dd 01  cc 00 00 00 06 01 01 01 |.....Q.. ........
                                    00 00 00 00 00 00 00 00                          |........         
    [00:00:00.004,058] <inf> ilumi: SCAN RESP-0 TYPE: 09, DATA_LENGTH : 0C
    [00:00:00.004,058] <inf> ilumi: SCAN RESP
                                    4e 72 64 69 63 35 39 32  41 37 46 00             |Nrdic592 A7F.    
    [00:00:00.004,089] <inf> ilumi: SCAN RESP-1 TYPE: 16, DATA_LENGTH : 0E
    [00:00:00.004,119] <inf> ilumi: SCAN RESP
                                    c0 f0 00 00 7f 2a 59 39  fd db dd 01 cc 00       |.....*Y9 ......  
    Advertising successfully started
    dsdv_seq_no : 2
    ASSERTION FAIL [err == 0] @ WEST_TOPDIR/zephyr/subsys/bluetooth/host/hci_core.c:331
            command opcode 0x2039 timeout with err -11
    [00:00:01.068,084] <err> fatal_error: k_sys_fatal_error_handler: Resetting system

Children
  • Hi,

    It is somewhat difficult to make conclusions from your project when it is not a minimal example.

    Did you successfully run the (completed) code from the BLE exercise I linked?

    For further debugging, I recommend that you revert back to a version of your project which had no errors, and introduce new features gradually to find out which part of it is the cause of the error.

    I can see from the log that it is hci_core which throws the error, but I can't go much further because error -11 = -EAGAIN which means either that a semaphore was updated while waiting or that the wait timed out for k_sem_take.

    Best regards,

    Maria

Related