I want to update/modify advertising data at run time,
How can I do so?
I want to update/modify advertising data at run time,
How can I do so?
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#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 systemHi,
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