Просмотр исходного кода

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
lly 5 лет назад
Родитель
Сommit
5d72e0c33c

+ 2 - 1
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)

+ 2 - 1
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

+ 69 - 20
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 */

+ 2 - 1
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)

+ 2 - 1
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

+ 51 - 9
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 */