BLE How to set the device name dynamically

I have seen a few posts including:

but I still haven't been able to adapt one of the examples to show the name dynamically.

 

This is the code:

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/conn.h>
#include <dk_buttons_and_leds.h>

#include <stdio.h> // For snprintf
#include <stdlib.h>

#include "ble_manager.h"


LOG_MODULE_REGISTER(ble_manager, LOG_LEVEL_DBG);

#define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)


/* STEP 2.1 - Declare the Company identifier (Company ID) */
#define COMPANY_ID_CODE 0x0059

/* STEP 2.2 - Declare the structure for your custom data  */
typedef struct adv_mfg_data {
	uint16_t company_code; /* Company Identifier Code. */
} adv_mfg_data_type;


/* STEP 5.1 - Create the advertising parameter for connectable advertising */
static struct bt_le_adv_param *adv_param = BT_LE_ADV_PARAM(
	(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_IDENTITY), /* Connectable advertising and use identity address */
	800, /* Min Advertising Interval 500ms (800*0.625ms) */
	801, /* Max Advertising Interval 500.625ms (801*0.625ms) */
	NULL); /* Set to NULL for undirected advertising */

/* STEP 2.3 - Define and initialize a variable of type adv_mfg_data_type */
static adv_mfg_data_type adv_mfg_data = { COMPANY_ID_CODE, 0x00 };



static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
	//BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    /* STEP 3 - Include the Manufacturer Specific Data in the advertising packet. */
	BT_DATA(BT_DATA_MANUFACTURER_DATA, (unsigned char *)&adv_mfg_data, sizeof(adv_mfg_data)),
};

static unsigned char url_data[] ={0x17,'/','/','a','c','a','d','e','m','y','.',
                                 'n','o','r','d','i','c','s','e','m','i','.',
                                 'c','o','m'};

static const struct bt_data sd[] = {
        BT_DATA(BT_DATA_URI, url_data,sizeof(url_data)),
};

static void connected(struct bt_conn *conn, uint8_t err)
{
	if (err) {
		LOG_ERR("Connection failed (err %u)\n", err);
		return;
	}

	LOG_DBG("Connected\n");
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	LOG_DBG("Disconnected (reason %u)\n", reason);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected        = connected,
	.disconnected     = disconnected,
};


int ble_manager_init()
{
    LOG_DBG("Starting '%s'", DEVICE_NAME);

    int err;

    err = bt_enable(NULL);
    if (err) {
        LOG_ERR("Bluetooth init failed (err %d)", err);
        return -1;
    }
    LOG_DBG("Bluetooth initialized");

    // Generate a random 6-digit number
    unsigned int random_number = 100000 + rand() % 900000; // Ensures a range from 100000 to 999999
    LOG_DBG("Random number: %d", random_number);

    // Assuming random_number is already defined and holds a random 6-digit number
    char device_name[18]; // Ensure this is large enough to hold the resulting string
    
    // Create a formatted string with the random number
    snprintf(device_name, sizeof(device_name), "DeviceName %d", random_number);
    
    // Set the Bluetooth device name
    bt_set_name(device_name);
    LOG_DBG("Bluetooth device name: %s", device_name);

    err = bt_le_adv_start(adv_param, ad, ARRAY_SIZE(ad),sd, ARRAY_SIZE(sd));
    if (err) {
        LOG_ERR("Advertising failed to start (err %d)", err);	
        return -1;
    }

    LOG_DBG("Bluetooth advertising");

    return 0;
}

And this is the prj.conf:

# Logger module
CONFIG_LOG=y

# Button and LED library
CONFIG_DK_LIBRARY=y

# Bluetooth LE
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
#CONFIG_BT_DEVICE_NAME="TEST Peripheral"
CONFIG_BT_DEVICE_NAME_DYNAMIC=y
# Maximum chcaracter of the device name
# (Range: 2 to 248)
CONFIG_BT_DEVICE_NAME_MAX=17

# Increase stack size for the main thread and System Workqueue
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=2048

Is there something else I need to do either in the bt_data or in the bt_le_adv_start?

Parents
  • Hi Leo

    Error message -5 points to an input/output error reported when trying to start the advertisement. Can you share the full log and your main.c file so I can take a better look at what is going on here? I assume you're still trying to set a dynamic device name when advertising.

    Best regards,

    Simon

  • Ok. I resolved the -5 issue but still cannot change the name dynamically:

       LOG_DBG("Initializing BLE manager with name: %s", dynamic_name);
    
        int err;
    
    
        bt_addr_le_t addr;
    	err = bt_addr_le_from_str("FF:EE:DD:CC:BB:AA", "random", &addr);
    	if (err) {
    		LOG_ERR("Invalid BT address (err %d)", err);
            return err;
    	} else {
            LOG_DBG("BT address set");
        }
    
    
        err = bt_id_create(&addr, NULL);
    	if (err < 0) {
    		LOG_ERR("Creating new ID failed (err %d)", err);
            return err;
    	} else {
            LOG_DBG("New ID created with index %d", err);
        }
    
        err = bt_enable(NULL);
        if (err) {
            LOG_ERR("Bluetooth init failed (err %d)", err);
            return err;
        } else {
            LOG_DBG("Bluetooth enabled");
        }
    
        // set the device name
        err = bt_set_name(dynamic_name);
        if (err) {
            LOG_ERR("Setting device name failed (err %d)", err);
            return err;
        } else {
            LOG_DBG("Device name set to %s", dynamic_name);
        }
    
        // set the advertising data
        err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
        if (err) {
            LOG_ERR("Updating advertising data failed (err %d)", err);
            return err;
        } else {
            LOG_DBG("Advertising data updated");
        }
    
    
    	k_work_init(&adv_work, adv_work_handler);
    	advertising_start();
    
        return 0;

    but I get this error in the log:

    <dbg> ew_ble_manager: ew_ble_manager_init: Bluetooth enabled
    <dbg> ew_ble_manager: ew_ble_manager_init: Device name set to TEST001
    <err> ew_ble_manager: Updating advertising data failed (err -11)

    if I comment out the bt_le_adv_update_data there is no error but the name does not change.

    I have found this post as well [nRF Connect SDK] How to change BT name which seem to be recreating the sd rather than calling apis to change the name. But I can't do it exactly this way or the way I did it before because according to the latest DevAcademy lesson on Bluetooth LE Advertising (Lesson 2) for v3.1.1-v3.0.0 you need to do things a little differently because "Starting from version 3.0.0 of the nRF Connect SDK, advertising is automatically turned off when a peripheral connects to a central device, and it remains off after the disconnection."

    Ok. Took away static const on ad and did this on top of all that:

        ad[1].data = dynamic_name;
    	ad[1].data_len = strlen(dynamic_name);

    Which works, but I don't understand what bt_set_name(dynamic_name); actually does here if I'm udating the array directly.

Reply
  • Ok. I resolved the -5 issue but still cannot change the name dynamically:

       LOG_DBG("Initializing BLE manager with name: %s", dynamic_name);
    
        int err;
    
    
        bt_addr_le_t addr;
    	err = bt_addr_le_from_str("FF:EE:DD:CC:BB:AA", "random", &addr);
    	if (err) {
    		LOG_ERR("Invalid BT address (err %d)", err);
            return err;
    	} else {
            LOG_DBG("BT address set");
        }
    
    
        err = bt_id_create(&addr, NULL);
    	if (err < 0) {
    		LOG_ERR("Creating new ID failed (err %d)", err);
            return err;
    	} else {
            LOG_DBG("New ID created with index %d", err);
        }
    
        err = bt_enable(NULL);
        if (err) {
            LOG_ERR("Bluetooth init failed (err %d)", err);
            return err;
        } else {
            LOG_DBG("Bluetooth enabled");
        }
    
        // set the device name
        err = bt_set_name(dynamic_name);
        if (err) {
            LOG_ERR("Setting device name failed (err %d)", err);
            return err;
        } else {
            LOG_DBG("Device name set to %s", dynamic_name);
        }
    
        // set the advertising data
        err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
        if (err) {
            LOG_ERR("Updating advertising data failed (err %d)", err);
            return err;
        } else {
            LOG_DBG("Advertising data updated");
        }
    
    
    	k_work_init(&adv_work, adv_work_handler);
    	advertising_start();
    
        return 0;

    but I get this error in the log:

    <dbg> ew_ble_manager: ew_ble_manager_init: Bluetooth enabled
    <dbg> ew_ble_manager: ew_ble_manager_init: Device name set to TEST001
    <err> ew_ble_manager: Updating advertising data failed (err -11)

    if I comment out the bt_le_adv_update_data there is no error but the name does not change.

    I have found this post as well [nRF Connect SDK] How to change BT name which seem to be recreating the sd rather than calling apis to change the name. But I can't do it exactly this way or the way I did it before because according to the latest DevAcademy lesson on Bluetooth LE Advertising (Lesson 2) for v3.1.1-v3.0.0 you need to do things a little differently because "Starting from version 3.0.0 of the nRF Connect SDK, advertising is automatically turned off when a peripheral connects to a central device, and it remains off after the disconnection."

    Ok. Took away static const on ad and did this on top of all that:

        ad[1].data = dynamic_name;
    	ad[1].data_len = strlen(dynamic_name);

    Which works, but I don't understand what bt_set_name(dynamic_name); actually does here if I'm udating the array directly.

Children
No Data
Related