From 5d72e0c33c1d9c33b2f4d45c8b2e5fa585e7d4bc Mon Sep 17 00:00:00 2001 From: lly Date: Mon, 1 Jun 2020 09:34:40 +0800 Subject: [PATCH] ble_mesh: Add nvs operations for examples - Store onoff_client example proper mesh info - Store vendor_client example proper mesh info Closes https://github.com/espressif/esp-idf/issues/5359 --- .../ble_mesh_node/onoff_client/CMakeLists.txt | 3 +- .../ble_mesh_node/onoff_client/Makefile | 3 +- .../ble_mesh_node/onoff_client/main/main.c | 89 ++++++++++++++----- .../vendor_client/CMakeLists.txt | 3 +- .../vendor_client/Makefile | 3 +- .../vendor_client/main/main.c | 60 +++++++++++-- 6 files changed, 128 insertions(+), 33 deletions(-) diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt index a66e04c49..ecac7d3eb 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt @@ -3,7 +3,8 @@ cmake_minimum_required(VERSION 3.5) set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/button - $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/example_init) + $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/example_init + $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/example_nvs) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(onoff_client) diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile index e4475660b..b5c5805ea 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile @@ -6,6 +6,7 @@ PROJECT_NAME := onoff_client EXTRA_COMPONENT_DIRS := $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/button \ - $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/example_init + $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/example_init \ + $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/example_nvs include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/main.c index 54f7a8ffa..ad6b5c3fa 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/main.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/main.c @@ -21,17 +21,26 @@ #include "board.h" #include "ble_mesh_example_init.h" +#include "ble_mesh_example_nvs.h" #define CID_ESP 0x02E5 static uint8_t dev_uuid[16] = { 0xdd, 0xdd }; -static uint16_t node_net_idx = ESP_BLE_MESH_KEY_UNUSED; -static uint16_t node_app_idx = ESP_BLE_MESH_KEY_UNUSED; -static uint8_t remote_onoff = LED_OFF; -static uint8_t msg_tid = 0x0; -/* The remote node address shall be input through UART1, see board.c */ -uint16_t remote_addr = ESP_BLE_MESH_ADDR_UNASSIGNED; +static struct example_info_store { + uint16_t net_idx; /* NetKey Index */ + uint16_t app_idx; /* AppKey Index */ + uint8_t onoff; /* Remote OnOff */ + uint8_t tid; /* Message TID */ +} __attribute__((packed)) store = { + .net_idx = ESP_BLE_MESH_KEY_UNUSED, + .app_idx = ESP_BLE_MESH_KEY_UNUSED, + .onoff = LED_OFF, + .tid = 0x0, +}; + +static nvs_handle NVS_HANDLE; +static const char * NVS_KEY = "onoff_client"; static esp_ble_mesh_client_t onoff_client; @@ -85,20 +94,51 @@ static esp_ble_mesh_prov_t provision = { #endif }; +static void mesh_example_info_store(void) +{ + ble_mesh_nvs_store(NVS_HANDLE, NVS_KEY, &store, sizeof(store)); +} + +static void mesh_example_info_restore(void) +{ + esp_err_t err = ESP_OK; + bool exist = false; + + err = ble_mesh_nvs_restore(NVS_HANDLE, NVS_KEY, &store, sizeof(store), &exist); + if (err != ESP_OK) { + return; + } + + if (exist) { + ESP_LOGI(TAG, "Restore, net_idx 0x%04x, app_idx 0x%04x, onoff %u, tid 0x%02x", + store.net_idx, store.app_idx, store.onoff, store.tid); + } +} + static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index) { ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr); ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index); board_led_operation(LED_G, LED_OFF); - node_net_idx = net_idx; + store.net_idx = net_idx; + /* mesh_example_info_store() shall not be invoked here, because if the device + * is restarted and goes into a provisioned state, then the following events + * will come: + * 1st: ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT + * 2nd: ESP_BLE_MESH_PROV_REGISTER_COMP_EVT + * So the store.net_idx will be updated here, and if we store the mesh example + * info here, the wrong app_idx (initialized with 0xFFFF) will be stored in nvs + * just before restoring it. + */ } static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event, - esp_ble_mesh_prov_cb_param_t *param) + esp_ble_mesh_prov_cb_param_t *param) { switch (event) { case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT: ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code); + mesh_example_info_restore(); /* Restore proper mesh example info */ break; case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT: ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code); @@ -130,12 +170,12 @@ void example_ble_mesh_send_gen_onoff_set(void) { esp_ble_mesh_generic_client_set_state_t set = {0}; esp_ble_mesh_client_common_param_t common = {0}; - esp_err_t err; + esp_err_t err = ESP_OK; common.opcode = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK; common.model = onoff_client.model; - common.ctx.net_idx = node_net_idx; - common.ctx.app_idx = node_app_idx; + common.ctx.net_idx = store.net_idx; + common.ctx.app_idx = store.app_idx; common.ctx.addr = 0xFFFF; /* to all nodes */ common.ctx.send_ttl = 3; common.ctx.send_rel = false; @@ -143,22 +183,24 @@ void example_ble_mesh_send_gen_onoff_set(void) common.msg_role = ROLE_NODE; set.onoff_set.op_en = false; - set.onoff_set.onoff = remote_onoff; - set.onoff_set.tid = msg_tid++; + set.onoff_set.onoff = store.onoff; + set.onoff_set.tid = store.tid++; err = esp_ble_mesh_generic_client_set_state(&common, &set); if (err) { - ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__); - } else { - remote_onoff = !remote_onoff; + ESP_LOGE(TAG, "Send Generic OnOff Set Unack failed"); + return; } + + store.onoff = !store.onoff; + mesh_example_info_store(); /* Store proper mesh example info */ } static void example_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_t event, esp_ble_mesh_generic_client_cb_param_t *param) { - ESP_LOGI(TAG, "%s: event is %d, error code is %d, opcode is 0x%x", - __func__, event, param->error_code, param->params->opcode); + ESP_LOGI(TAG, "Generic client, event %u, error code %d, opcode is 0x%04x", + event, param->error_code, param->params->opcode); switch (event) { case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT: @@ -209,7 +251,8 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t param->value.state_change.mod_app_bind.model_id); if (param->value.state_change.mod_app_bind.company_id == 0xFFFF && param->value.state_change.mod_app_bind.model_id == ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI) { - node_app_idx = param->value.state_change.mod_app_bind.app_idx; + store.app_idx = param->value.state_change.mod_app_bind.app_idx; + mesh_example_info_store(); /* Store proper mesh example info */ } break; default: @@ -220,7 +263,7 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t static esp_err_t ble_mesh_init(void) { - esp_err_t err = 0; + esp_err_t err = ESP_OK; esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb); esp_ble_mesh_register_generic_client_callback(example_ble_mesh_generic_client_cb); @@ -262,6 +305,12 @@ void app_main(void) return; } + /* Open nvs namespace for storing/restoring mesh example info */ + err = ble_mesh_nvs_open(&NVS_HANDLE); + if (err) { + return; + } + ble_mesh_get_dev_uuid(dev_uuid); /* Initialize the Bluetooth Mesh Subsystem */ diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/CMakeLists.txt index 89eed708c..ff84549ab 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/CMakeLists.txt +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/CMakeLists.txt @@ -3,7 +3,8 @@ cmake_minimum_required(VERSION 3.5) set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/button - $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/example_init) + $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/example_init + $ENV{IDF_PATH}/examples/bluetooth/esp_ble_mesh/components/example_nvs) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(vendor_client) diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/Makefile b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/Makefile index 5296900eb..39e10243c 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/Makefile +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/Makefile @@ -6,6 +6,7 @@ PROJECT_NAME := vendor_client EXTRA_COMPONENT_DIRS := $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/button \ - $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/example_init + $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/example_init \ + $(IDF_PATH)/examples/bluetooth/esp_ble_mesh/components/example_nvs include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/main/main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/main/main.c index 8249c008b..71645fcb9 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/main/main.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/main/main.c @@ -20,6 +20,7 @@ #include "esp_ble_mesh_config_model_api.h" #include "ble_mesh_example_init.h" +#include "ble_mesh_example_nvs.h" #include "board.h" #define CID_ESP 0x02E5 @@ -45,10 +46,18 @@ #define ESP_BLE_MESH_VND_MODEL_OP_SEND ESP_BLE_MESH_MODEL_OP_3(0x00, CID_ESP) #define ESP_BLE_MESH_VND_MODEL_OP_STATUS ESP_BLE_MESH_MODEL_OP_3(0x01, CID_ESP) -static uint8_t dev_uuid[ESP_BLE_MESH_OCTET16_LEN]; -static uint16_t server_address = ESP_BLE_MESH_ADDR_UNASSIGNED; -static uint16_t vnd_tid; -static int64_t start_time; +static uint8_t dev_uuid[ESP_BLE_MESH_OCTET16_LEN]; + +static struct example_info_store { + uint16_t server_addr; /* Vendor server unicast address */ + uint16_t vnd_tid; /* TID contained in the vendor message */ +} store = { + .server_addr = ESP_BLE_MESH_ADDR_UNASSIGNED, + .vnd_tid = 0, +}; + +static nvs_handle NVS_HANDLE; +static const char * NVS_KEY = "vendor_client"; static struct esp_ble_mesh_key { uint16_t net_idx; @@ -111,6 +120,26 @@ static esp_ble_mesh_prov_t provision = { .prov_start_address = 0x0005, }; +static void mesh_example_info_store(void) +{ + ble_mesh_nvs_store(NVS_HANDLE, NVS_KEY, &store, sizeof(store)); +} + +static void mesh_example_info_restore(void) +{ + esp_err_t err = ESP_OK; + bool exist = false; + + err = ble_mesh_nvs_restore(NVS_HANDLE, NVS_KEY, &store, sizeof(store), &exist); + if (err != ESP_OK) { + return; + } + + if (exist) { + ESP_LOGI(TAG, "Restore, server_addr 0x%04x, vnd_tid 0x%04x", store.server_addr, store.vnd_tid); + } +} + static void example_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common, esp_ble_mesh_node_t *node, esp_ble_mesh_model_t *model, uint32_t opcode) @@ -139,7 +168,8 @@ static esp_err_t prov_complete(uint16_t node_index, const esp_ble_mesh_octet16_t node_index, primary_addr, element_num, net_idx); ESP_LOG_BUFFER_HEX("uuid", uuid, ESP_BLE_MESH_OCTET16_LEN); - server_address = primary_addr; + store.server_addr = primary_addr; + mesh_example_info_store(); /* Store proper mesh example info */ sprintf(name, "%s%02x", "NODE-", node_index); err = esp_ble_mesh_provisioner_set_node_name(node_index, name); @@ -202,6 +232,7 @@ static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event, switch (event) { case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT: ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code); + mesh_example_info_restore(); /* Restore proper mesh example info */ break; case ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT: ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT, err_code %d", param->provisioner_prov_enable_comp.err_code); @@ -422,31 +453,36 @@ void example_ble_mesh_send_vendor_message(bool resend) ctx.net_idx = prov_key.net_idx; ctx.app_idx = prov_key.app_idx; - ctx.addr = server_address; + ctx.addr = store.server_addr; ctx.send_ttl = MSG_SEND_TTL; ctx.send_rel = MSG_SEND_REL; opcode = ESP_BLE_MESH_VND_MODEL_OP_SEND; if (resend == false) { - vnd_tid++; + store.vnd_tid++; } err = esp_ble_mesh_client_model_send_msg(vendor_client.model, &ctx, opcode, - sizeof(vnd_tid), (uint8_t *)&vnd_tid, MSG_TIMEOUT, true, MSG_ROLE); + sizeof(store.vnd_tid), (uint8_t *)&store.vnd_tid, MSG_TIMEOUT, true, MSG_ROLE); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to send vendor message 0x%06x", opcode); + return; } + + mesh_example_info_store(); /* Store proper mesh example info */ } static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_cb_param_t *param) { + static int64_t start_time; + switch (event) { case ESP_BLE_MESH_MODEL_OPERATION_EVT: if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_STATUS) { int64_t end_time = esp_timer_get_time(); ESP_LOGI(TAG, "Recv 0x%06x, tid 0x%04x, time %lldus", - param->model_operation.opcode, vnd_tid, end_time - start_time); + param->model_operation.opcode, store.vnd_tid, end_time - start_time); } break; case ESP_BLE_MESH_MODEL_SEND_COMP_EVT: @@ -538,6 +574,12 @@ void app_main(void) return; } + /* Open nvs namespace for storing/restoring mesh example info */ + err = ble_mesh_nvs_open(&NVS_HANDLE); + if (err) { + return; + } + ble_mesh_get_dev_uuid(dev_uuid); /* Initialize the Bluetooth Mesh Subsystem */