Autoprovisioning and autoconfiguring of nRF52840

Hello,

After a lot of efforts I managed to autoprovision and autoconfigure my nrf52840 board (provisioning and configuring inside the software and not through external app).

In particular, I have configured a switch and a led like a client and his server in an element of my node.

All is OK: when I toggle the switch the led goes on/off

But when I try to configure another couple of led/switch I fail.

The file that I use for provisioning is this:

#include "provision.h"
#include <zephyr/logging/log.h>

LOG_MODULE_DECLARE(main);

static const uint8_t net_key[16] = {
	0x6f, 0xea, 0x5b, 0x86, 0x38, 0x45, 0x26, 0xb9,
	0x0e, 0x7b, 0x73, 0x0c, 0x69, 0x94, 0x75, 0x0a,
};

static const uint8_t dev_key[16] = {
	0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
	0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
};

static const uint8_t first_app_key[16] = {
    // First AppKey
	0x8c, 0x32, 0x9f, 0x41, 0xd1, 0xd2, 0xc2, 0x9f,
	0x5a, 0xb7, 0x09, 0x0c, 0x0b, 0x31, 0x4d, 0x1d,
};

static const uint8_t second_app_key[16] = {
    0x88, 0xed, 0x35, 0xc4, 0x95, 0x01, 0xaf, 0x8a,
	0xce, 0x47, 0xd3, 0x11, 0xbf, 0x77, 0xb4, 0xc1,
};

static const uint8_t third_app_key[16] = {
	0x6a, 0x1a, 0xf1, 0xdb, 0xe8, 0x38, 0xdc, 0xf5,
	0x5c, 0x83, 0xa5, 0x33, 0x35, 0xd2, 0xe9, 0xde,
};

static uint16_t net_idx = 0;
static uint32_t iv_index = 0;
static uint8_t flags;
static bool needs_configuration = false;

uint16_t addr = 0x8000;

void configure()
{
	int res;
	uint8_t status = 0;

	if (needs_configuration)
	{
		if (addr == 0x8000)
		{
			LOG_ERR("Device hasn't been provisioned yet.");
			return;
		}

		LOG_INF("Configuring addr %d...", addr);

		res = bt_mesh_cfg_cli_net_key_add(net_idx, addr, net_idx, net_key, NULL);
		LOG_INF("NetKey %d: res %d, status = %d", net_idx, res, status);

		res = bt_mesh_cfg_cli_app_key_add(net_idx, addr, net_idx, 0, first_app_key, NULL);
		LOG_INF("AppKey 0: res %d, status = %d", res, status);

		res = bt_mesh_cfg_cli_app_key_add(net_idx, addr, net_idx, 1, second_app_key, NULL);
		LOG_INF("AppKey 1: res %d, status = %d", res, status);

		res = bt_mesh_cfg_cli_app_key_add(net_idx, addr, net_idx, 2, third_app_key, NULL);
		LOG_INF("AppKey 2: res %d, status = %d", res, status);

		LOG_INF("Configuration completed");
	}
}

void provision()
{

	int err;
	volatile uint32_t *node_addr  = (volatile uint32_t *) 0x10001080; // address node in UICR
	addr = *node_addr;
	/*err = sys_csrand_get(&addr, 2);
	if (err != 0)
	{
		LOG_ERR("Could not get a random address");
		return;
	}
	else
	{
		addr %= 0x7fff;
	}*/
	
	err = bt_mesh_provision(net_key, net_idx, flags, iv_index, addr, dev_key);
	if (err == -EALREADY)
	{
		LOG_INF("Using stored settings");
	}
	else if (err)
	{
		LOG_ERR("Provisioning failed (err %d)", err);
		return;
	}
	else
	{
		LOG_INF("Provisioning completed");
		// configure(addr);
	}
	needs_configuration = true;
}

Instead the file for configuring switch/led (and also chat in my example) is this:

#include "model_handler.h"
#include <zephyr/logging/log.h>
#include "reset_node.h"

#define BUTTON_IDX 0
#define LED_IDX 0
LOG_MODULE_REGISTER(model_handler, CONFIG_BT_MESH_MODEL_HANDLER_LOG_LEVEL);

/* HEALTH SERVER INIT */
/* Model Pub must be initialized here because the macro is defined as static, therefore it can't be externally defined and included here. */
BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
/* Model Health srv and srv callbacks must be initialized in the caller file due to a conflict with health_srv.c */
static const struct bt_mesh_health_srv_cb health_srv_cb = {
	.attn_on = attention_on,
	.attn_off = attention_off,
};
static struct bt_mesh_health_srv health_srv = {
	.cb = &health_srv_cb,
};

/* CONFIGURATION CLIENT INIT */
const struct bt_mesh_cfg_cli_cb cfg_cli_cb = {};
struct bt_mesh_cfg_cli cli_data = {
	.cb = &cfg_cli_cb};

/* ELEMENTS */
static struct bt_mesh_elem elements[] = {
	BT_MESH_ELEM(1,
				 BT_MESH_MODEL_LIST(
					 BT_MESH_MODEL_CFG_SRV,
					 BT_MESH_MODEL_CFG_CLI(&cli_data),
					 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
					 BT_MESH_MODEL_DFD_SRV(&dfd_srv),
					 BT_MESH_MODEL_ONOFF_CLI(&buttons[BUTTON_IDX].client),
					 BT_MESH_MODEL_ONOFF_SRV(&led_ctx[LED_IDX].srv)),
				 BT_MESH_MODEL_LIST(
					 BT_MESH_MODEL_CHAT_CLI(&chat))),
	BT_MESH_ELEM(2,
				 BT_MESH_MODEL_LIST(
					 BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
				 BT_MESH_MODEL_NONE),
};

/* COMPOSITION */
static const struct bt_mesh_comp comp = {
	.cid = CONFIG_BT_COMPANY_ID,
	.elem = elements,
	.elem_count = ARRAY_SIZE(elements),
};

const struct bt_mesh_comp *model_handler_init(void)
{
	dk_button_handler_add(&button_handler);
	dk_button_handler_add(&reset_handler);

	// health_k_work_init_delayable();
#ifdef CONFIG_MODEL_CHAT_SHELL
	chat_k_work_init_delayable();
#endif
	return &comp;
}

/**********************************************************************************/
/****************************** App Key Callbacks *********************************/
/**********************************************************************************/
#include <../subsys/bluetooth/mesh/mesh.h>

void on_app_key_added(uint16_t app_idx, uint16_t net_idx)
{
	int res;
	uint8_t status = 0;
	const struct bt_mesh_elem *elem;
	uint16_t addr;
	uint16_t elem_addr;

	switch (app_idx)
	{
	// Chat Vendor Model
	case (0):
	{
		elem = bt_mesh_model_elem(chat.model);
		addr = elem->rt->addr - elem->loc + 1;
		elem_addr = addr + elem->loc - 1;

		uint16_t sub_addr = 0xc000;
		struct bt_mesh_cfg_cli_mod_pub pub = {
			.addr = sub_addr,
			.app_idx = app_idx,
			.ttl = CONFIG_BT_MESH_DEFAULT_TTL,
			.transmit = BT_MESH_TRANSMIT(0, 10),
		};

		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind_vnd(net_idx, addr, elem_addr, app_idx, BT_MESH_CHAT_CLI_VENDOR_MODEL_ID, BT_MESH_CHAT_CLI_VENDOR_COMPANY_ID, NULL);
		LOG_INF("bind res = %d, status = %d", res, status);
		status = 0;
		res = bt_mesh_cfg_cli_mod_pub_set_vnd(net_idx, addr, elem_addr, BT_MESH_CHAT_CLI_VENDOR_MODEL_ID, BT_MESH_CHAT_CLI_VENDOR_COMPANY_ID, &pub, NULL);
		LOG_INF("pub res = %d, status = %d", res, status);
		status = 0;
		res = bt_mesh_cfg_cli_mod_sub_add_vnd(net_idx, addr, elem_addr, sub_addr, BT_MESH_CHAT_CLI_VENDOR_MODEL_ID, BT_MESH_CHAT_CLI_VENDOR_COMPANY_ID, NULL);
		LOG_INF("sub res = %d, status = %d", res, status);

		break;
	}
	// Light switch and Light server models
	case (1):
	{
		elem = bt_mesh_model_elem(led_ctx[LED_IDX].srv.model);
		addr = elem->rt->addr - elem->loc + 1;
		elem_addr = addr + elem->loc - 1;
		uint16_t sub_addr = 0xc001;

		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
		LOG_INF("bind res = %d.", res);
		res = bt_mesh_cfg_cli_mod_sub_add(net_idx, addr, elem_addr, sub_addr, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
		LOG_INF("sub res = %d.", res);

		elem = bt_mesh_model_elem(buttons[BUTTON_IDX].client.model);
		addr = elem->rt->addr - elem->loc + 1;
		elem_addr = addr + elem->loc - 1;
		struct bt_mesh_cfg_cli_mod_pub pub = {
			.addr = sub_addr,
			.app_idx = app_idx,
			.ttl = CONFIG_BT_MESH_DEFAULT_TTL,
			.transmit = BT_MESH_TRANSMIT(1, 10),
		};

		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, NULL);
		LOG_INF("bind res = %d.", res);
		res = bt_mesh_cfg_cli_mod_pub_set(net_idx, addr, elem_addr, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, &pub, NULL);
		LOG_INF("pub res = %d.", res);
		break;
	}
	// DFU and DFD
	case (2):
	{

		elem = bt_mesh_model_elem(dfd_srv.mod);
		addr = elem->rt->addr - elem->loc + 1;
		elem_addr = addr + elem->loc - 1;
		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_BLOB_CLI, NULL);
		LOG_INF("bind res = %d, status = %d", res, status);
		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_DFU_CLI, NULL);
		LOG_INF("bind res = %d, status = %d", res, status);
		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_BLOB_SRV, NULL);
		LOG_INF("bind res = %d, status = %d", res, status);
		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_DFD_SRV, NULL);
		LOG_INF("bind res = %d, status = %d", res, status);

		elem = bt_mesh_model_elem(dfu_srv.mod);
		addr = elem->rt->addr - elem->loc + 1;
		elem_addr = addr + elem->loc - 1;
		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_BLOB_SRV, NULL);
		LOG_INF("bind res = %d, status = %d", res, status);
		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_DFU_SRV, NULL);
		LOG_INF("bind res = %d, status = %d", res, status);

		break;
	}

	default:
	{
		LOG_ERR("Unforseen AppKey idx %d", app_idx);
	}
	}
}

void on_app_key_event(uint16_t app_idx, uint16_t net_idx, enum bt_mesh_key_evt evt)
{
	switch (evt)
	{
	case BT_MESH_KEY_ADDED:
	{

		on_app_key_added(app_idx, net_idx);

		break;
	}
	case BT_MESH_KEY_DELETED:
	{

		break;
	}
	case BT_MESH_KEY_UPDATED:
	{

		break;
	}
	case BT_MESH_KEY_SWAPPED:
	{

		break;
	}
	case BT_MESH_KEY_REVOKED:
	{

		break;
	}
	}

	// LOG_INF("AppKey event: AppIDX=%d - NetIDX=%d - evt=%d", app_idx, net_idx, evt);
}

BT_MESH_APP_KEY_CB_DEFINE(on_app_key_event);

What have I to do for adding another couple of switch/led (client/server), so that when I toggle the second switch the second led goes on/off?

I'm ready to add other information if these can permit you to resolve.

Thank you in advance for your replay

Parents
  • Hello,

    Sorry for the late reply! We have had a period with a few public holidays, so the backlog has built up. I am sorry for the inconvenience.

    The file that I use for provisioning is this:

    Is this running on the provisioner or the node that is being provisioned? Do you have a provisioner at all?

    What happens when you add the second pair? Do you see any errors in the log? 

    It is not that easy to read out of the code, but when you bind the models and set up the subscribe and publish addresses. Do you use the Unicast addresses, or group addresses? And do you use the same address when you add the second pair? Or do you use different unicast/group addresses for the two pairs?

    Best regards,

    Edvin

  • Hi,

    Is this running on the provisioner or the node that is being provisioned? Do you have a provisioner at all?

    The file belongs to FW that is running in every node of the net. I have not provisioner, because I "autoiprovision" every node

    What happens when you add the second pair? Do you see any errors in the log? 

    Nothing happens, all is blocked and I don't manage to read any log

    Do you use the Unicast addresses, or group addresses? And do you use the same address when you add the second pair? Or do you use different unicast/group addresses for the two pairs?

    I use Unicast address and group address, as you can see:

    elem = bt_mesh_model_elem(led_ctx[LED_IDX].srv.model);
    addr = elem->rt->addr - elem->loc + 1;

    elem_addr = addr + elem->loc - 1;

    uint16_t sub_addr = 0xc001;

    My intention is to use different unicast address and group address for second pair, replying more or less the same code used for the first pair. I also added another app_key for the second pair. But something goes wrong, and this is the reason for which I need your help.

Reply
  • Hi,

    Is this running on the provisioner or the node that is being provisioned? Do you have a provisioner at all?

    The file belongs to FW that is running in every node of the net. I have not provisioner, because I "autoiprovision" every node

    What happens when you add the second pair? Do you see any errors in the log? 

    Nothing happens, all is blocked and I don't manage to read any log

    Do you use the Unicast addresses, or group addresses? And do you use the same address when you add the second pair? Or do you use different unicast/group addresses for the two pairs?

    I use Unicast address and group address, as you can see:

    elem = bt_mesh_model_elem(led_ctx[LED_IDX].srv.model);
    addr = elem->rt->addr - elem->loc + 1;

    elem_addr = addr + elem->loc - 1;

    uint16_t sub_addr = 0xc001;

    My intention is to use different unicast address and group address for second pair, replying more or less the same code used for the first pair. I also added another app_key for the second pair. But something goes wrong, and this is the reason for which I need your help.

Children
  • stefanogradozzi said:
    Nothing happens, all is blocked and I don't manage to read any log

    How about the different "LOG_INF("sub res = %d, status = %d", res, status);"? Do they all return 0?

    BR,
    Edvin

  • Hi,

    as I said, I don't manage to read any log.

    Surely I'm making something wrong when I try to add a second pair of light/switch (server/client).

    So, starting from the snippets that I sent you, which work properly for a single pair of light/switch, could you please suggest me which instructions I have to add and where in the code I have to add them for a correct firmware with two pairs of client/server?

    For example: is it correct to add a specific app_key for the new pair?

    Here is the modified files that I tried to use.

    Provisioning:

    #include "provision.h"
    #include <zephyr/logging/log.h>
    
    LOG_MODULE_DECLARE(main);
    
    static const uint8_t net_key[16] = {
    	0x6f, 0xea, 0x5b, 0x86, 0x38, 0x45, 0x26, 0xb9,
    	0x0e, 0x7b, 0x73, 0x0c, 0x69, 0x94, 0x75, 0x0a,
    };
    
    static const uint8_t dev_key[16] = {
    	0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
    	0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
    };
    
    static const uint8_t first_app_key[16] = {
        // First AppKey
    	0x8c, 0x32, 0x9f, 0x41, 0xd1, 0xd2, 0xc2, 0x9f,
    	0x5a, 0xb7, 0x09, 0x0c, 0x0b, 0x31, 0x4d, 0x1d,
    };
    
    static const uint8_t second_app_key[16] = {
        0x88, 0xed, 0x35, 0xc4, 0x95, 0x01, 0xaf, 0x8a,
    	0xce, 0x47, 0xd3, 0x11, 0xbf, 0x77, 0xb4, 0xc1,
    };
    
    static const uint8_t third_app_key[16] = {
    	0x6a, 0x1a, 0xf1, 0xdb, 0xe8, 0x38, 0xdc, 0xf5,
    	0x5c, 0x83, 0xa5, 0x33, 0x35, 0xd2, 0xe9, 0xde,
    };
    
    static const uint8_t fourth_app_key[16] = {
    	0x7a, 0x2a, 0xfa, 0xdb, 0xe8, 0x38, 0xdc, 0xf5,
    	0x7a, 0x2a, 0xfa, 0x33, 0x35, 0xd2, 0xe9, 0xde,
    };
    
    static uint16_t net_idx = 0;
    static uint32_t iv_index = 0;
    static uint8_t flags;
    static bool needs_configuration = false;
    
    uint16_t addr = 0x8000;
    
    void configure()
    {
    	int res;
    	uint8_t status = 0;
    
    	if (needs_configuration)
    	{
    		if (addr == 0x8000)
    		{
    			LOG_ERR("Device hasn't been provisioned yet.");
    			return;
    		}
    
    		LOG_INF("Configuring addr %d...", addr);
    
    		res = bt_mesh_cfg_cli_net_key_add(net_idx, addr, net_idx, net_key, NULL);
    		LOG_INF("NetKey %d: res %d, status = %d", net_idx, res, status);
    
    		res = bt_mesh_cfg_cli_app_key_add(net_idx, addr, net_idx, 0, first_app_key, NULL);
    		LOG_INF("AppKey 0: res %d, status = %d", res, status);
    
    		res = bt_mesh_cfg_cli_app_key_add(net_idx, addr, net_idx, 1, second_app_key, NULL);
    		LOG_INF("AppKey 1: res %d, status = %d", res, status);
    
    		res = bt_mesh_cfg_cli_app_key_add(net_idx, addr, net_idx, 2, third_app_key, NULL);
    		LOG_INF("AppKey 2: res %d, status = %d", res, status);
    		
    		res = bt_mesh_cfg_cli_app_key_add(net_idx, addr, net_idx, 3, fourth_app_key, NULL);
    		LOG_INF("AppKey 3: res %d, status = %d", res, status);
    
    		LOG_INF("Configuration completed");
    	}
    }
    
    void provision()
    {
    
    	int err;
    	volatile uint32_t *node_addr  = (volatile uint32_t *) 0x10001080; // address node in UICR
    	addr = *node_addr;
    	/*err = sys_csrand_get(&addr, 2);
    	if (err != 0)
    	{
    		LOG_ERR("Could not get a random address");
    		return;
    	}
    	else
    	{
    		addr %= 0x7fff;
    	}*/
    	
    	err = bt_mesh_provision(net_key, net_idx, flags, iv_index, addr, dev_key);
    	if (err == -EALREADY)
    	{
    		LOG_INF("Using stored settings");
    	}
    	else if (err)
    	{
    		LOG_ERR("Provisioning failed (err %d)", err);
    		return;
    	}
    	else
    	{
    		LOG_INF("Provisioning completed");
    		// configure(addr);
    	}
    	needs_configuration = true;
    }
    

    Configuring:

    #include "model_handler.h"
    #include <zephyr/logging/log.h>
    #include "reset_node.h"
    
    #define BUTTON_IDX 0
    #define LED_IDX 0
    #define BUTTON_IDX2 1
    #define LED_IDX2 1
    LOG_MODULE_REGISTER(model_handler, CONFIG_BT_MESH_MODEL_HANDLER_LOG_LEVEL);
    
    /* HEALTH SERVER INIT */
    /* Model Pub must be initialized here because the macro is defined as static, therefore it can't be externally defined and included here. */
    BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
    /* Model Health srv and srv callbacks must be initialized in the caller file due to a conflict with health_srv.c */
    static const struct bt_mesh_health_srv_cb health_srv_cb = {
    	.attn_on = attention_on,
    	.attn_off = attention_off,
    };
    static struct bt_mesh_health_srv health_srv = {
    	.cb = &health_srv_cb,
    };
    
    /* CONFIGURATION CLIENT INIT */
    const struct bt_mesh_cfg_cli_cb cfg_cli_cb = {};
    struct bt_mesh_cfg_cli cli_data = {
    	.cb = &cfg_cli_cb};
    
    /* ELEMENTS */
    static struct bt_mesh_elem elements[] = {
    	BT_MESH_ELEM(1,
    				 BT_MESH_MODEL_LIST(
    					 BT_MESH_MODEL_CFG_SRV,
    					 BT_MESH_MODEL_CFG_CLI(&cli_data),
    					 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
    					 BT_MESH_MODEL_DFD_SRV(&dfd_srv),
    					 BT_MESH_MODEL_ONOFF_CLI(&buttons[BUTTON_IDX].client),
    					 BT_MESH_MODEL_ONOFF_SRV(&led_ctx[LED_IDX].srv)),
    				 BT_MESH_MODEL_LIST(
    					 BT_MESH_MODEL_CHAT_CLI(&chat))),
    	BT_MESH_ELEM(2,
    				 BT_MESH_MODEL_LIST(
    					 BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
    				 BT_MESH_MODEL_NONE),
    	BT_MESH_ELEM(3,
    				 BT_MESH_MODEL_LIST(
    					 BT_MESH_MODEL_ONOFF_CLI(&buttons[BUTTON_IDX2].client),
    					 BT_MESH_MODEL_ONOFF_SRV(&led_ctx[LED_IDX2].srv)),
    				 BT_MESH_MODEL_NONE),
    };
    
    /* COMPOSITION */
    static const struct bt_mesh_comp comp = {
    	.cid = CONFIG_BT_COMPANY_ID,
    	.elem = elements,
    	.elem_count = ARRAY_SIZE(elements),
    };
    
    const struct bt_mesh_comp *model_handler_init(void)
    {
    	dk_button_handler_add(&button_handler);
    	dk_button_handler_add(&reset_handler);
    
    	// health_k_work_init_delayable();
    #ifdef CONFIG_MODEL_CHAT_SHELL
    	chat_k_work_init_delayable();
    #endif
    	return &comp;
    }
    
    /**********************************************************************************/
    /****************************** App Key Callbacks *********************************/
    /**********************************************************************************/
    #include <../subsys/bluetooth/mesh/mesh.h>
    
    void on_app_key_added(uint16_t app_idx, uint16_t net_idx)
    {
    	int res;
    	uint8_t status = 0;
    	struct bt_mesh_elem *elem;
    	uint16_t addr;
    	uint16_t elem_addr;
    
    	switch (app_idx)
    	{
    	// Chat Vendor Model
    	case (0):
    	{
    		elem = bt_mesh_model_elem(chat.model);
    		addr = elem->addr - elem->loc + 1;
    		elem_addr = addr + elem->loc - 1;
    
    		uint16_t sub_addr = 0xc000;
    		struct bt_mesh_cfg_cli_mod_pub pub = {
    			.addr = sub_addr,
    			.app_idx = app_idx,
    			.ttl = CONFIG_BT_MESH_DEFAULT_TTL,
    			.transmit = BT_MESH_TRANSMIT(2, 10),
    		};
    
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind_vnd(net_idx, addr, elem_addr, app_idx, BT_MESH_CHAT_CLI_VENDOR_MODEL_ID, BT_MESH_CHAT_CLI_VENDOR_COMPANY_ID, NULL);
    		LOG_INF("bind res = %d, status = %d", res, status);
    		status = 0;
    		res = bt_mesh_cfg_cli_mod_pub_set_vnd(net_idx, addr, elem_addr, BT_MESH_CHAT_CLI_VENDOR_MODEL_ID, BT_MESH_CHAT_CLI_VENDOR_COMPANY_ID, &pub, NULL);
    		LOG_INF("pub res = %d, status = %d", res, status);
    		status = 0;
    		res = bt_mesh_cfg_cli_mod_sub_add_vnd(net_idx, addr, elem_addr, sub_addr, BT_MESH_CHAT_CLI_VENDOR_MODEL_ID, BT_MESH_CHAT_CLI_VENDOR_COMPANY_ID, NULL);
    		LOG_INF("sub res = %d, status = %d", res, status);
    
    		break;
    	}
    	// Light switch and Light server models #0
    	case (1):
    	{
    		elem = bt_mesh_model_elem(led_ctx[LED_IDX].srv.model);
    		addr = elem->addr - elem->loc + 1;
    		elem_addr = addr + elem->loc - 1;
    		uint16_t sub_addr = 0xc001;
    
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
    		LOG_INF("bind res = %d.", res);
    		res = bt_mesh_cfg_cli_mod_sub_add(net_idx, addr, elem_addr, sub_addr, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
    		LOG_INF("sub res = %d.", res);
    
    		elem = bt_mesh_model_elem(buttons[BUTTON_IDX].client.model);
    		addr = elem->addr - elem->loc + 1;
    		elem_addr = addr + elem->loc - 1;
    		struct bt_mesh_cfg_cli_mod_pub pub = {
    			.addr = sub_addr,
    			.app_idx = app_idx,
    			.ttl = CONFIG_BT_MESH_DEFAULT_TTL,
    			.transmit = BT_MESH_TRANSMIT(2, 10),
    		};
    
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, NULL);
    		LOG_INF("bind res = %d.", res);
    		res = bt_mesh_cfg_cli_mod_pub_set(net_idx, addr, elem_addr, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, &pub, NULL);
    		LOG_INF("pub res = %d.", res);
    		break;
    	}
    	// Light switch and Light server models #1
    	case (3):
    	{
    		elem = bt_mesh_model_elem(led_ctx[LED_IDX2].srv.model);
    		addr = elem->addr - elem->loc + 1;
    		elem_addr = addr + elem->loc - 1;
    		uint16_t sub_addr = 0xc002;
    
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
    		LOG_INF("bind res = %d.", res);
    		res = bt_mesh_cfg_cli_mod_sub_add(net_idx, addr, elem_addr, sub_addr, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
    		LOG_INF("sub res = %d.", res);
    
    		elem = bt_mesh_model_elem(buttons[BUTTON_IDX2].client.model);
    		addr = elem->addr - elem->loc + 1;
    		elem_addr = addr + elem->loc - 1;
    		struct bt_mesh_cfg_cli_mod_pub pub = {
    			.addr = sub_addr,
    			.app_idx = app_idx,
    			.ttl = CONFIG_BT_MESH_DEFAULT_TTL,
    			.transmit = BT_MESH_TRANSMIT(2, 10),
    		};
    
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, NULL);
    		LOG_INF("bind res = %d.", res);
    		res = bt_mesh_cfg_cli_mod_pub_set(net_idx, addr, elem_addr, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, &pub, NULL);
    		LOG_INF("pub res = %d.", res);
    		break;
    	}
    	// DFU and DFD
    	case (2):
    	{
    
    		elem = bt_mesh_model_elem(dfd_srv.mod);
    		addr = elem->addr - elem->loc + 1;
    		elem_addr = addr + elem->loc - 1;
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_BLOB_CLI, NULL);
    		LOG_INF("bind res = %d, status = %d", res, status);
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_DFU_CLI, NULL);
    		LOG_INF("bind res = %d, status = %d", res, status);
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_BLOB_SRV, NULL);
    		LOG_INF("bind res = %d, status = %d", res, status);
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_DFD_SRV, NULL);
    		LOG_INF("bind res = %d, status = %d", res, status);
    
    		elem = bt_mesh_model_elem(dfu_srv.mod);
    		addr = elem->addr - elem->loc + 1;
    		elem_addr = addr + elem->loc - 1;
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_BLOB_SRV, NULL);
    		LOG_INF("bind res = %d, status = %d", res, status);
    		LOG_INF("addr = %d - elem_addr = %d - net_idx = %d - app_idx = %d", addr, elem_addr, net_idx, app_idx);
    		res = bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, elem_addr, app_idx, BT_MESH_MODEL_ID_DFU_SRV, NULL);
    		LOG_INF("bind res = %d, status = %d", res, status);
    
    		break;
    	}
    
    	default:
    	{
    		LOG_ERR("Unforseen AppKey idx %d", app_idx);
    	}
    	}
    }
    
    void on_app_key_event(uint16_t app_idx, uint16_t net_idx, enum bt_mesh_key_evt evt)
    {
    	switch (evt)
    	{
    	case BT_MESH_KEY_ADDED:
    	{
    
    		on_app_key_added(app_idx, net_idx);
    
    		break;
    	}
    	case BT_MESH_KEY_DELETED:
    	{
    
    		break;
    	}
    	case BT_MESH_KEY_UPDATED:
    	{
    
    		break;
    	}
    	case BT_MESH_KEY_SWAPPED:
    	{
    
    		break;
    	}
    	case BT_MESH_KEY_REVOKED:
    	{
    
    		break;
    	}
    	}
    
    	// LOG_INF("AppKey event: AppIDX=%d - NetIDX=%d - evt=%d", app_idx, net_idx, evt);
    }
    
    BT_MESH_APP_KEY_CB_DEFINE(on_app_key_event);

    Hint: The program freezes when it enters case '3' of switch(app_key) and I don't know why

  • Another hint: it seems that the instruction which is responsible of the problem is:

        elem = bt_mesh_model_elem(led_ctx[LED_IDX2].srv.model); (case '3' of switch(app_key)

    Note that the same instruction, but with different arguments, does not give any problem inside other cases of switch(app_key)

Related