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 ∁ } /**********************************************************************************/ /****************************** 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