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

    In the second link you provided, Einar explains that most scanners/phones will cache the device name, so in most cases you need to toggle Bluetooth on/off on the scanner side to update a name on the scanner. If you've already done that, you should make sure that the name is updated in the advertising packet with bt_le_adv_update_data() which I don't see you're using.

    Best regards,

    Simon

  • I did turn Bluetooth on and off.

    I tried adding:

    // Set the Bluetooth device name
    bt_set_name(device_name);
    LOG_DBG("Bluetooth device name: %s", device_name);
    
    err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    if (err) {
        LOG_ERR("Failed to update (err %d)", err);
        return -1;
    }

    and got:

    [00:00:00.470,611] <err> ble_manager: Failed to update (err -11)

    but I don't know why I would need to update the data if I'm setting the name before I start advertising. I guess that's my question. What is the right order of methods to call in order to set the name dynamically.

Reply
  • I did turn Bluetooth on and off.

    I tried adding:

    // Set the Bluetooth device name
    bt_set_name(device_name);
    LOG_DBG("Bluetooth device name: %s", device_name);
    
    err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    if (err) {
        LOG_ERR("Failed to update (err %d)", err);
        return -1;
    }

    and got:

    [00:00:00.470,611] <err> ble_manager: Failed to update (err -11)

    but I don't know why I would need to update the data if I'm setting the name before I start advertising. I guess that's my question. What is the right order of methods to call in order to set the name dynamically.

Children
No Data
Related