瀏覽代碼

Merge branch 'feat/ble_mesh_multiple_nvs_namespace' into 'master'

ble_mesh: stack: Provisioner supports multiple nvs namespaces

Closes BLEMESH-260

See merge request espressif/esp-idf!11355
Island 5 年之前
父節點
當前提交
4f082154e0

+ 1 - 0
components/bt/CMakeLists.txt

@@ -389,6 +389,7 @@ if(CONFIG_BT_ENABLED)
                     "esp_ble_mesh/mesh_core/provisioner_prov.c"
                     "esp_ble_mesh/mesh_core/proxy_client.c"
                     "esp_ble_mesh/mesh_core/proxy_server.c"
+                    "esp_ble_mesh/mesh_core/settings_uid.c"
                     "esp_ble_mesh/mesh_core/settings.c"
                     "esp_ble_mesh/mesh_core/test.c"
                     "esp_ble_mesh/mesh_core/transport.c"

+ 44 - 22
components/bt/esp_ble_mesh/Kconfig.in

@@ -320,28 +320,6 @@ if BLE_MESH
 
     if BLE_MESH_SETTINGS
 
-        config BLE_MESH_SPECIFIC_PARTITION
-            bool "Use a specific NVS partition for BLE Mesh"
-            default n
-            help
-                When selected, the mesh stack will use a specified NVS partition instead of
-                default NVS partition. Note that the specified partition must be registered
-                with NVS using nvs_flash_init_partition() API, and the partition must exists
-                in the csv file.
-                When Provisioner needs to store a large amount of nodes' information in the
-                flash (e.g. more than 20), this option is recommended to be enabled.
-
-        if BLE_MESH_SPECIFIC_PARTITION
-
-            config BLE_MESH_PARTITION_NAME
-                string "Name of the NVS partition for BLE Mesh"
-                default "ble_mesh"
-                help
-                    This value defines the name of the specified NVS partition used by the
-                    mesh stack.
-
-        endif # BLE_MESH_SPECIFIC_PARTITION
-
         config BLE_MESH_STORE_TIMEOUT
             int "Delay (in seconds) before storing anything persistently"
             range 0 1000000
@@ -407,6 +385,50 @@ if BLE_MESH
                 in advance before recovering node information and make sure the node
                 information recovering could work as expected.
 
+        config BLE_MESH_SPECIFIC_PARTITION
+            bool "Use a specific NVS partition for BLE Mesh"
+            default n
+            help
+                When selected, the mesh stack will use a specified NVS partition instead of
+                default NVS partition. Note that the specified partition must be registered
+                with NVS using nvs_flash_init_partition() API, and the partition must exists
+                in the csv file.
+                When Provisioner needs to store a large amount of nodes' information in the
+                flash (e.g. more than 20), this option is recommended to be enabled.
+
+        config BLE_MESH_PARTITION_NAME
+            string "Name of the NVS partition for BLE Mesh"
+            depends on BLE_MESH_SPECIFIC_PARTITION
+            default "ble_mesh"
+            help
+                This value defines the name of the specified NVS partition used by the
+                mesh stack.
+
+        config BLE_MESH_USE_MULTIPLE_NAMESPACE
+            bool "Support using multiple NVS namespaces by Provisioner"
+            depends on BLE_MESH_PROVISIONER
+            default n
+            help
+                When selected, Provisioner can use different NVS namespaces to store
+                different instances of mesh information.
+                For example, if in the first room, Provisioner uses NetKey A, AppKey
+                A and provisions three devices, these information will be treated as
+                mesh information instance A. When the Provisioner moves to the second
+                room, it uses NetKey B, AppKey B and provisions two devices, then the
+                information will be treated as mesh information instance B.
+                Here instance A and instance B will be stored in different namespaces.
+                With this option enabled, Provisioner needs to use specific functions
+                to open the corresponding NVS namespace, restore the mesh information,
+                release the mesh information or erase the mesh information.
+
+        config BLE_MESH_MAX_NVS_NAMESPACE
+            int "Maximum number of NVS namespaces"
+            depends on BLE_MESH_USE_MULTIPLE_NAMESPACE
+            default 2
+            range 1 255
+            help
+                This option specifies the maximum NVS namespaces supported by Provisioner.
+
     endif  # if BLE_MESH_SETTINGS
 
     config BLE_MESH_SUBNET_COUNT

+ 170 - 0
components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c

@@ -598,6 +598,176 @@ esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, esp_ble
 }
 #endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
 
+#if CONFIG_BLE_MESH_SETTINGS
+esp_err_t esp_ble_mesh_provisioner_direct_erase_settings(void)
+{
+    btc_msg_t msg = {0};
+
+    ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_PROV;
+
+    msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DIRECT_ERASE_SETTINGS;
+
+    return (btc_transfer_context(&msg, NULL, 0, NULL)
+            == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+#endif /* CONFIG_BLE_MESH_SETTINGS */
+
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+esp_err_t esp_ble_mesh_provisioner_open_settings_with_index(uint8_t index)
+{
+    btc_ble_mesh_prov_args_t arg = {0};
+    btc_msg_t msg = {0};
+
+    if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_PROV;
+    msg.act = BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_INDEX;
+
+    arg.open_settings_with_index.index = index;
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
+            == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_mesh_provisioner_open_settings_with_uid(const char *uid)
+{
+    btc_ble_mesh_prov_args_t arg = {0};
+    btc_msg_t msg = {0};
+
+    if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_PROV;
+    msg.act = BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_UID;
+
+    strncpy(arg.open_settings_with_uid.uid, uid, ESP_BLE_MESH_SETTINGS_UID_SIZE);
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
+            == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_mesh_provisioner_close_settings_with_index(uint8_t index, bool erase)
+{
+    btc_ble_mesh_prov_args_t arg = {0};
+    btc_msg_t msg = {0};
+
+    if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_PROV;
+    msg.act = BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX;
+
+    arg.close_settings_with_index.index = index;
+    arg.close_settings_with_index.erase = erase;
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
+            == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_mesh_provisioner_close_settings_with_uid(const char *uid, bool erase)
+{
+    btc_ble_mesh_prov_args_t arg = {0};
+    btc_msg_t msg = {0};
+
+    if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_PROV;
+    msg.act = BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_UID;
+
+    strncpy(arg.close_settings_with_uid.uid, uid, ESP_BLE_MESH_SETTINGS_UID_SIZE);
+    arg.close_settings_with_uid.erase = erase;
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
+            == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_mesh_provisioner_delete_settings_with_index(uint8_t index)
+{
+    btc_ble_mesh_prov_args_t arg = {0};
+    btc_msg_t msg = {0};
+
+    if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_PROV;
+    msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX;
+
+    arg.delete_settings_with_index.index = index;
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
+            == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_ble_mesh_provisioner_delete_settings_with_uid(const char *uid)
+{
+    btc_ble_mesh_prov_args_t arg = {0};
+    btc_msg_t msg = {0};
+
+    if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_PROV;
+    msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_UID;
+
+    strncpy(arg.delete_settings_with_uid.uid, uid, ESP_BLE_MESH_SETTINGS_UID_SIZE);
+
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
+            == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+const char *esp_ble_mesh_provisioner_get_settings_uid(uint8_t index)
+{
+    if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
+        return NULL;
+    }
+
+    return btc_ble_mesh_provisioner_get_settings_uid(index);
+}
+
+uint8_t esp_ble_mesh_provisioner_get_settings_index(const char *uid)
+{
+    if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
+        return ESP_BLE_MESH_INVALID_SETTINGS_IDX;
+    }
+
+    return btc_ble_mesh_provisioner_get_settings_index(uid);
+}
+
+uint8_t esp_ble_mesh_provisioner_get_free_settings_count(void)
+{
+    return btc_ble_mesh_provisioner_get_free_settings_count();
+}
+#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
+
 #endif /* CONFIG_BLE_MESH_PROVISIONER */
 
 #if (CONFIG_BLE_MESH_FAST_PROV)

+ 165 - 0
components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h

@@ -473,6 +473,171 @@ esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_type(uint8_t type);
  */
 esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, esp_ble_mesh_heartbeat_filter_info_t *info);
 
+/**
+ * @brief         This function is called by Provisioner to directly erase the mesh
+ *                information from nvs namespace.
+ *
+ * @note          This function can be invoked when the mesh stack is not initialized
+ *                or has been de-initialized.
+ *
+ * @return        ESP_OK on success or error code otherwise.
+ *
+ */
+esp_err_t esp_ble_mesh_provisioner_direct_erase_settings(void);
+
+/**
+ * @brief         This function is called by Provisioner to open a nvs namespace
+ *                for storing mesh information.
+ *
+ * @note          Before open another nvs namespace, the previously opened nvs
+ *                namespace must be closed firstly.
+ *
+ * @param[in]     index: Settings index.
+ *
+ * @return        ESP_OK on success or error code otherwise.
+ *
+ */
+esp_err_t esp_ble_mesh_provisioner_open_settings_with_index(uint8_t index);
+
+/**
+ * @brief         This function is called by Provisioner to open a nvs namespace
+ *                for storing mesh information.
+ *
+ * @note          Before open another nvs namespace, the previously opened nvs
+ *                namespace must be closed firstly.
+ *
+ * @param[in]     uid: Settings user id.
+ *
+ * @return        ESP_OK on success or error code otherwise.
+ *
+ */
+esp_err_t esp_ble_mesh_provisioner_open_settings_with_uid(const char *uid);
+
+/**
+ * @brief         This function is called by Provisioner to close a nvs namespace
+ *                which is opened previously for storing mesh information.
+ *
+ * @note          1. Before closing the nvs namespace, it must be open.
+ *                2. When the function is invoked, the Provisioner functionality
+ *                   will be disabled firstly, and:
+ *                   a) If the "erase" flag is set to false, the mesh information
+ *                      will be cleaned (e.g. removing NetKey, AppKey, nodes, etc)
+ *                      from the mesh stack.
+ *                   b) If the "erase" flag is set to true, the mesh information
+ *                      stored in the nvs namespace will also be erased besides
+ *                      been cleaned from the mesh stack.
+ *                3. If Provisioner tries to work properly again, we can invoke the
+ *                   open function to open a new nvs namespace or a previously added
+ *                   one, and restore the mesh information from it if not erased.
+ *                4. The working process shall be as following:
+ *                   a) Open settings A
+ *                   b) Start to provision and control nodes
+ *                   c) Close settings A
+ *                   d) Open settings B
+ *                   e) Start to provision and control other nodes
+ *                   f) Close settings B
+ *                   g) ......
+ *
+ * @param[in]     index: Settings index.
+ * @param[in]     erase: Indicate if erasing mesh information.
+ *
+ * @return        ESP_OK on success or error code otherwise.
+ *
+ */
+esp_err_t esp_ble_mesh_provisioner_close_settings_with_index(uint8_t index, bool erase);
+
+/**
+ * @brief         This function is called by Provisioner to close a nvs namespace
+ *                which is opened previously for storing mesh information.
+ *
+ * @note          1. Before closing the nvs namespace, it must be open.
+ *                2. When the function is invoked, the Provisioner functionality
+ *                   will be disabled firstly, and:
+ *                   a) If the "erase" flag is set to false, the mesh information
+ *                      will be cleaned (e.g. removing NetKey, AppKey, nodes, etc)
+ *                      from the mesh stack.
+ *                   b) If the "erase" flag is set to true, the mesh information
+ *                      stored in the nvs namespace will also be erased besides
+ *                      been cleaned from the mesh stack.
+ *                3. If Provisioner tries to work properly again, we can invoke the
+ *                   open function to open a new nvs namespace or a previously added
+ *                   one, and restore the mesh information from it if not erased.
+ *                4. The working process shall be as following:
+ *                   a) Open settings A
+ *                   b) Start to provision and control nodes
+ *                   c) Close settings A
+ *                   d) Open settings B
+ *                   e) Start to provision and control other nodes
+ *                   f) Close settings B
+ *                   g) ......
+ *
+ * @param[in]     uid: Settings user id.
+ * @param[in]     erase: Indicate if erasing mesh information.
+ *
+ * @return        ESP_OK on success or error code otherwise.
+ *
+ */
+esp_err_t esp_ble_mesh_provisioner_close_settings_with_uid(const char *uid, bool erase);
+
+/**
+ * @brief         This function is called by Provisioner to erase the mesh information
+ *                and settings user id from a nvs namespace.
+ *
+ * @note          When this function is called, the nvs namespace must not be open.
+ *                This function is used to erase the mesh information and settings
+ *                user id which are not used currently.
+ *
+ * @param[in]     index: Settings index.
+ *
+ * @return        ESP_OK on success or error code otherwise.
+ *
+ */
+esp_err_t esp_ble_mesh_provisioner_delete_settings_with_index(uint8_t index);
+
+/**
+ * @brief         This function is called by Provisioner to erase the mesh information
+ *                and settings user id from a nvs namespace.
+ *
+ * @note          When this function is called, the nvs namespace must not be open.
+ *                This function is used to erase the mesh information and settings
+ *                user id which are not used currently.
+ *
+ * @param[in]     uid: Settings user id.
+ *
+ * @return        ESP_OK on success or error code otherwise.
+ *
+ */
+esp_err_t esp_ble_mesh_provisioner_delete_settings_with_uid(const char *uid);
+
+/**
+ * @brief         This function is called by Provisioner to get settings user id.
+ *
+ * @param[in]     index: Settings index.
+ *
+ * @return        Setting user id on success or NULL on failure.
+ *
+ */
+const char *esp_ble_mesh_provisioner_get_settings_uid(uint8_t index);
+
+/**
+ * @brief         This function is called by Provisioner to get settings index.
+ *
+ * @param[in]     uid: Settings user id.
+ *
+ * @return        Settings index.
+ *
+ */
+uint8_t esp_ble_mesh_provisioner_get_settings_index(const char *uid);
+
+/**
+ * @brief         This function is called by Provisioner to get the number of free
+ *                settings user id.
+ *
+ * @return        Number of free settings user id.
+ *
+ */
+uint8_t esp_ble_mesh_provisioner_get_free_settings_count(void);
+
 /**
  * @brief         This function is called to get fast provisioning application key.
  *

+ 65 - 1
components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h

@@ -51,6 +51,12 @@ extern "C" {
 /*!< The maximum length of a BLE Mesh unprovisioned device name */
 #define ESP_BLE_MESH_DEVICE_NAME_MAX_LEN    DEVICE_NAME_SIZE
 
+/*!< The maximum length of settings user id */
+#define ESP_BLE_MESH_SETTINGS_UID_SIZE      20
+
+/*!< Invalid settings index */
+#define ESP_BLE_MESH_INVALID_SETTINGS_IDX   0xFF
+
 /*!< Define the BLE Mesh octet 16 bytes size */
 #define ESP_BLE_MESH_OCTET16_LEN    16
 typedef uint8_t esp_ble_mesh_octet16_t[ESP_BLE_MESH_OCTET16_LEN];
@@ -869,7 +875,14 @@ typedef enum {
     ESP_BLE_MESH_PROVISIONER_ENABLE_HEARTBEAT_RECV_COMP_EVT,     /*!< Provisioner start to receive heartbeat message completion event */
     ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT, /*!< Provisioner set the heartbeat filter type completion event */
     ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_INFO_COMP_EVT, /*!< Provisioner set the heartbeat filter information completion event */
-    ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT,        /*!< Provisioner receive heartbeat message event */
+    ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT,         /*!< Provisioner receive heartbeat message event */
+    ESP_BLE_MESH_PROVISIONER_DRIECT_ERASE_SETTINGS_COMP_EVT,        /*!< Provisioner directly erase settings completion event */
+    ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT,     /*!< Provisioner open settings with index completion event */
+    ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_UID_COMP_EVT,       /*!< Provisioner open settings with user id completion event */
+    ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT,    /*!< Provisioner close settings with index completion event */
+    ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_UID_COMP_EVT,      /*!< Provisioner close settings with user id completion event */
+    ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT,   /*!< Provisioner delete settings with index completion event */
+    ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_UID_COMP_EVT,     /*!< Provisioner delete settings with user id completion event */
     ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT,                   /*!< Set fast provisioning information (e.g. unicast address range, net_idx, etc.) completion event */
     ESP_BLE_MESH_SET_FAST_PROV_ACTION_COMP_EVT,                 /*!< Set fast provisioning action completion event */
     ESP_BLE_MESH_HEARTBEAT_MESSAGE_RECV_EVT,                    /*!< Receive Heartbeat message event */
@@ -1272,6 +1285,57 @@ typedef union {
         uint16_t feature;           /*!< Bit field of currently active features of the node */
         int8_t   rssi;              /*!< RSSI of the heartbeat message */
     } provisioner_recv_heartbeat;   /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT */
+    /**
+     * @brief ESP_BLE_MESH_PROVISIONER_DRIECT_ERASE_SETTINGS_COMP_EVT
+     */
+    struct {
+        int err_code;                           /*!< Indicate the result of directly erasing settings by the Provisioner */
+    } provisioner_direct_erase_settings_comp;   /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_DRIECT_ERASE_SETTINGS_COMP_EVT */
+    /**
+     * @brief ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT
+     */
+    struct {
+        int err_code;                               /*!< Indicate the result of opening settings with index by the Provisioner */
+        uint8_t index;                              /*!< Index of Provisioner settings */
+    } provisioner_open_settings_with_index_comp;    /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT */
+    /**
+     * @brief ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_UID_COMP_EVT
+     */
+    struct {
+        int err_code;                                   /*!< Indicate the result of opening settings with user id by the Provisioner */
+        uint8_t index;                                  /*!< Index of Provisioner settings */
+        char uid[ESP_BLE_MESH_SETTINGS_UID_SIZE + 1];   /*!< Provisioner settings user id */
+    } provisioner_open_settings_with_uid_comp;          /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_UID_COMP_EVT */
+    /**
+     * @brief ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT
+     */
+    struct {
+        int err_code;                               /*!< Indicate the result of closing settings with index by the Provisioner */
+        uint8_t index;                              /*!< Index of Provisioner settings */
+    } provisioner_close_settings_with_index_comp;   /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT */
+    /**
+     * @brief ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_UID_COMP_EVT
+     */
+    struct {
+        int err_code;                                   /*!< Indicate the result of closing settings with user id by the Provisioner */
+        uint8_t index;                                  /*!< Index of Provisioner settings */
+        char uid[ESP_BLE_MESH_SETTINGS_UID_SIZE + 1];   /*!< Provisioner settings user id */
+    } provisioner_close_settings_with_uid_comp;         /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_UID_COMP_EVT */
+    /**
+     * @brief ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT
+     */
+    struct {
+        int err_code;                               /*!< Indicate the result of deleting settings with index by the Provisioner */
+        uint8_t index;                              /*!< Index of Provisioner settings */
+    } provisioner_delete_settings_with_index_comp;  /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT */
+    /**
+     * @brief ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_UID_COMP_EVT
+     */
+    struct {
+        int err_code;                                   /*!< Indicate the result of deleting settings with user id by the Provisioner */
+        uint8_t index;                                  /*!< Index of Provisioner settings */
+        char uid[ESP_BLE_MESH_SETTINGS_UID_SIZE + 1];   /*!< Provisioner settings user id */
+    } provisioner_delete_settings_with_uid_comp;        /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_UID_COMP_EVT */
     /**
      * @brief ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT
      */

+ 70 - 0
components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c

@@ -29,6 +29,7 @@
 #include "mesh.h"
 #include "access.h"
 #include "prov.h"
+#include "settings_uid.h"
 #include "proxy_server.h"
 #include "proxy_client.h"
 #include "provisioner_prov.h"
@@ -840,6 +841,23 @@ static void btc_ble_mesh_provisioner_recv_heartbeat_cb(u16_t hb_src, u16_t hb_ds
 }
 #endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
 
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+const char *btc_ble_mesh_provisioner_get_settings_uid(uint8_t index)
+{
+    return bt_mesh_provisioner_get_settings_uid(index);
+}
+
+uint8_t btc_ble_mesh_provisioner_get_settings_index(const char *uid)
+{
+    return bt_mesh_provisioner_get_settings_index(uid);
+}
+
+uint8_t btc_ble_mesh_provisioner_get_free_settings_count(void)
+{
+    return bt_mesh_provisioner_get_free_settings_count();
+}
+#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
+
 #endif /* CONFIG_BLE_MESH_PROVISIONER */
 
 static void btc_ble_mesh_node_recv_heartbeat_cb(u8_t hops, u16_t feature)
@@ -2042,6 +2060,58 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
                                                           arg->set_heartbeat_filter_info.hb_dst);
         break;
 #endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
+#if CONFIG_BLE_MESH_SETTINGS
+    case BTC_BLE_MESH_ACT_PROVISIONER_DIRECT_ERASE_SETTINGS:
+        act = ESP_BLE_MESH_PROVISIONER_DRIECT_ERASE_SETTINGS_COMP_EVT;
+        param.provisioner_direct_erase_settings_comp.err_code = bt_mesh_provisioner_direct_erase_settings();
+        break;
+#endif /* CONFIG_BLE_MESH_SETTINGS */
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+    case BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_INDEX:
+        act = ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT;
+        param.provisioner_open_settings_with_index_comp.index = arg->open_settings_with_index.index;
+        param.provisioner_open_settings_with_index_comp.err_code =
+            bt_mesh_provisioner_open_settings_with_index(arg->open_settings_with_index.index);
+        break;
+    case BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_UID:
+        act = ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_UID_COMP_EVT;
+        strncpy(param.provisioner_open_settings_with_uid_comp.uid,
+                arg->open_settings_with_uid.uid, ESP_BLE_MESH_SETTINGS_UID_SIZE + 1);
+        param.provisioner_open_settings_with_uid_comp.err_code =
+            bt_mesh_provisioner_open_settings_with_uid(arg->open_settings_with_uid.uid,
+                                                       &param.provisioner_open_settings_with_uid_comp.index);
+        break;
+    case BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX:
+        act = ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT;
+        param.provisioner_close_settings_with_index_comp.index = arg->close_settings_with_index.index;
+        param.provisioner_close_settings_with_index_comp.err_code =
+            bt_mesh_provisioner_close_settings_with_index(arg->close_settings_with_index.index,
+                                                          arg->close_settings_with_index.erase);
+        break;
+    case BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_UID:
+        act = ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_UID_COMP_EVT;
+        strncpy(param.provisioner_close_settings_with_uid_comp.uid,
+                arg->close_settings_with_uid.uid, ESP_BLE_MESH_SETTINGS_UID_SIZE + 1);
+        param.provisioner_close_settings_with_uid_comp.err_code =
+            bt_mesh_provisioner_close_settings_with_uid(arg->close_settings_with_uid.uid,
+                                                        arg->close_settings_with_uid.erase,
+                                                        &param.provisioner_close_settings_with_uid_comp.index);
+        break;
+    case BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX:
+        act = ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT;
+        param.provisioner_delete_settings_with_index_comp.index = arg->delete_settings_with_index.index;
+        param.provisioner_delete_settings_with_index_comp.err_code =
+            bt_mesh_provisioner_delete_settings_with_index(arg->delete_settings_with_index.index);
+        break;
+    case BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_UID:
+        act = ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_UID_COMP_EVT;
+        strncpy(param.provisioner_delete_settings_with_uid_comp.uid,
+                arg->delete_settings_with_uid.uid, ESP_BLE_MESH_SETTINGS_UID_SIZE + 1);
+        param.provisioner_delete_settings_with_uid_comp.err_code =
+            bt_mesh_provisioner_delete_settings_with_uid(arg->delete_settings_with_uid.uid,
+                                                         &param.provisioner_delete_settings_with_uid_comp.index);
+        break;
+#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
 #endif /* CONFIG_BLE_MESH_PROVISIONER */
 #if CONFIG_BLE_MESH_FAST_PROV
     case BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO:

+ 33 - 0
components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h

@@ -66,6 +66,13 @@ typedef enum {
     BTC_BLE_MESH_ACT_PROVISIONER_ENABLE_HEARTBEAT_RECV,
     BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE,
     BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_INFO,
+    BTC_BLE_MESH_ACT_PROVISIONER_DIRECT_ERASE_SETTINGS,
+    BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_INDEX,
+    BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_UID,
+    BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX,
+    BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_UID,
+    BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX,
+    BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_UID,
     BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO,
     BTC_BLE_MESH_ACT_SET_FAST_PROV_ACTION,
     BTC_BLE_MESH_ACT_LPN_ENABLE,
@@ -231,6 +238,26 @@ typedef union {
         uint16_t hb_src;
         uint16_t hb_dst;
     } set_heartbeat_filter_info;
+    struct {
+        uint8_t index;
+    } open_settings_with_index;
+    struct {
+        char uid[ESP_BLE_MESH_SETTINGS_UID_SIZE + 1];
+    } open_settings_with_uid;
+    struct {
+        uint8_t index;
+        bool erase;
+    } close_settings_with_index;
+    struct {
+        char uid[ESP_BLE_MESH_SETTINGS_UID_SIZE + 1];
+        bool erase;
+    } close_settings_with_uid;
+    struct {
+        uint8_t index;
+    } delete_settings_with_index;
+    struct {
+        char uid[ESP_BLE_MESH_SETTINGS_UID_SIZE + 1];
+    } delete_settings_with_uid;
     struct ble_mesh_set_fast_prov_info_args {
         uint16_t unicast_min;
         uint16_t unicast_max;
@@ -363,6 +390,12 @@ esp_ble_mesh_model_t *btc_ble_mesh_model_find(const esp_ble_mesh_elem_t *elem, u
 
 const esp_ble_mesh_comp_t *btc_ble_mesh_comp_get(void);
 
+const char *btc_ble_mesh_provisioner_get_settings_uid(uint8_t index);
+
+uint8_t btc_ble_mesh_provisioner_get_settings_index(const char *uid);
+
+uint8_t btc_ble_mesh_provisioner_get_free_settings_count(void);
+
 void btc_ble_mesh_model_call_handler(btc_msg_t *msg);
 void btc_ble_mesh_model_cb_handler(btc_msg_t *msg);
 

+ 16 - 9
components/bt/esp_ble_mesh/mesh_core/net.c

@@ -1572,16 +1572,9 @@ void bt_mesh_net_init(void)
     k_work_init(&bt_mesh.local_work, bt_mesh_net_local);
 }
 
-#if CONFIG_BLE_MESH_DEINIT
-void bt_mesh_net_deinit(void)
+void bt_mesh_net_reset(void)
 {
-    k_delayed_work_free(&bt_mesh.ivu_timer);
-
-    k_work_init(&bt_mesh.local_work, NULL);
-
-    /* Local queue uses a while loop, currently no need
-     * to handle this.
-     */
+    k_delayed_work_cancel(&bt_mesh.ivu_timer);
 
 #if FRIEND_CRED_COUNT > 0
     memset(friend_cred, 0, sizeof(friend_cred));
@@ -1596,4 +1589,18 @@ void bt_mesh_net_deinit(void)
     bt_mesh.iv_index = 0U;
     bt_mesh.seq = 0U;
 }
+
+#if CONFIG_BLE_MESH_DEINIT
+void bt_mesh_net_deinit(void)
+{
+    bt_mesh_net_reset();
+
+    k_delayed_work_free(&bt_mesh.ivu_timer);
+
+    k_work_init(&bt_mesh.local_work, NULL);
+
+    /* Local queue uses a while loop, currently no need
+     * to handle this.
+     */
+}
 #endif /* CONFIG_BLE_MESH_DEINIT */

+ 1 - 0
components/bt/esp_ble_mesh/mesh_core/net.h

@@ -375,6 +375,7 @@ u32_t bt_mesh_next_seq(void);
 void bt_mesh_net_start(void);
 
 void bt_mesh_net_init(void);
+void bt_mesh_net_reset(void);
 void bt_mesh_net_deinit(void);
 
 void bt_mesh_net_header_parse(struct net_buf_simple *buf,

+ 6 - 3
components/bt/esp_ble_mesh/mesh_core/provisioner_main.c

@@ -161,8 +161,7 @@ done:
     return 0;
 }
 
-#if CONFIG_BLE_MESH_DEINIT
-int bt_mesh_provisioner_deinit(bool erase)
+void bt_mesh_provisioner_main_reset(bool erase)
 {
     int i;
 
@@ -192,9 +191,13 @@ int bt_mesh_provisioner_deinit(bool erase)
     }
 
     node_count = 0U;
+}
 
+#if CONFIG_BLE_MESH_DEINIT
+int bt_mesh_provisioner_deinit(bool erase)
+{
+    bt_mesh_provisioner_main_reset(erase);
     bt_mesh_provisioner_mutex_free();
-
     return 0;
 }
 #endif /* CONFIG_BLE_MESH_DEINIT */

+ 2 - 0
components/bt/esp_ble_mesh/mesh_core/provisioner_main.h

@@ -51,6 +51,8 @@ int bt_mesh_provisioner_init(void);
 
 int bt_mesh_provisioner_net_create(void);
 
+void bt_mesh_provisioner_main_reset(bool erase);
+
 int bt_mesh_provisioner_deinit(bool erase);
 
 bool bt_mesh_provisioner_check_is_addr_dup(u16_t addr, u8_t elem_num, bool comp_with_own);

+ 65 - 19
components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c

@@ -3271,8 +3271,7 @@ int bt_mesh_provisioner_prov_init(const struct bt_mesh_prov *prov_info)
     return 0;
 }
 
-#if CONFIG_BLE_MESH_DEINIT
-int bt_mesh_provisioner_prov_deinit(bool erase)
+int bt_mesh_provisioner_prov_reset(bool erase)
 {
     int i;
 
@@ -3281,20 +3280,71 @@ int bt_mesh_provisioner_prov_deinit(bool erase)
         return -EINVAL;
     }
 
-#if defined(CONFIG_BLE_MESH_PB_ADV)
-    for (i = 0; i < CONFIG_BLE_MESH_PBA_SAME_TIME; i++) {
-        prov_clear_tx(i);
-        k_delayed_work_free(&link[i].tx.retransmit);
-#if defined(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN)
-        /* Remove the link id from exceptional list */
-        bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_REMOVE,
-                                        BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link[i].link_id);
-#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */
-    }
+    for (i = 0; i < BLE_MESH_PROV_SAME_TIME; i++) {
+        k_delayed_work_cancel(&link[i].timeout);
+
+        prov_memory_free(i);
+
+        if (i < CONFIG_BLE_MESH_PBA_SAME_TIME) {
+#if CONFIG_BLE_MESH_PB_ADV
+            prov_clear_tx(i);
+#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN
+            bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_REMOVE,
+                BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link[i].link_id);
+#endif
+            memset(&link[i], 0, offsetof(struct prov_link, tx.retransmit));
+            link[i].pending_ack = XACT_NVAL;
+            link[i].rx.prev_id = XACT_NVAL;
+            link[i].rx.buf = bt_mesh_pba_get_buf(i);
 #endif /* CONFIG_BLE_MESH_PB_ADV */
+        } else {
+            memset(&link[i], 0, offsetof(struct prov_link, timeout));
+        }
+
+        if (bt_mesh_pub_key_get()) {
+            bt_mesh_atomic_set_bit(link[i].flags, LOCAL_PUB_KEY);
+        }
+    }
+
+    /* static_oob_len & static_oob_val are initialized during mesh init.
+     * When reset the Provisioner, they should not be reset. Otherwise
+     * users need to invoke the corresponding function to set the static
+     * oob information before using them.
+     */
+    memset(&prov_ctx, 0, offsetof(struct bt_mesh_prov_ctx, static_oob_len));
+    prov_ctx.match_offset = 0;
+    prov_ctx.match_length = 0;
+    prov_ctx.prov_after_match = false;
+    memset(prov_ctx.match_value, 0, sizeof(prov_ctx.match_value));
+    memset(&prov_ctx.fast_prov, 0, sizeof(prov_ctx.fast_prov));
+
+    memset(unprov_dev, 0, sizeof(unprov_dev));
+
+    if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS) && erase) {
+        bt_mesh_clear_prov_info();
+    }
+
+    return 0;
+}
+
+#if CONFIG_BLE_MESH_DEINIT
+int bt_mesh_provisioner_prov_deinit(bool erase)
+{
+    int i;
+
+    if (prov == NULL) {
+        BT_ERR("%s, No provisioning context provided", __func__);
+        return -EINVAL;
+    }
+
+    bt_mesh_provisioner_prov_reset(erase);
 
     for (i = 0; i < BLE_MESH_PROV_SAME_TIME; i++) {
-        prov_memory_free(i);
+#if defined(CONFIG_BLE_MESH_PB_ADV)
+        if (i < CONFIG_BLE_MESH_PBA_SAME_TIME) {
+            k_delayed_work_free(&link[i].tx.retransmit);
+        }
+#endif
         k_delayed_work_free(&link[i].timeout);
         memset(&link[i], 0, sizeof(link[i]));
     }
@@ -3306,17 +3356,13 @@ int bt_mesh_provisioner_prov_deinit(bool erase)
 #if defined(CONFIG_BLE_MESH_PB_GATT)
     bt_mesh_pb_gatt_mutex_free();
 #endif
-    memset(&prov_ctx, 0, sizeof(prov_ctx));
+    prov_ctx.static_oob_len = 0U;
+    memset(prov_ctx.static_oob_val, 0, sizeof(prov_ctx.static_oob_val));
 
 #if defined(CONFIG_BLE_MESH_PB_ADV)
     memset(adv_buf, 0, sizeof(adv_buf));
     memset(adv_buf_data, 0, sizeof(adv_buf_data));
 #endif
-    memset(unprov_dev, 0, sizeof(unprov_dev));
-
-    if (erase && IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
-        bt_mesh_clear_prov_info();
-    }
 
     prov = NULL;
 

+ 2 - 0
components/bt/esp_ble_mesh/mesh_core/provisioner_prov.h

@@ -142,6 +142,8 @@ int bt_mesh_provisioner_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_s
  */
 int bt_mesh_provisioner_prov_init(const struct bt_mesh_prov *prov_info);
 
+int bt_mesh_provisioner_prov_reset(bool erase);
+
 /**
  * @brief This function de-initializes provisioner's PB-GATT and PB-ADV
  *        related information.

+ 11 - 0
components/bt/esp_ble_mesh/mesh_core/settings.c

@@ -20,6 +20,7 @@
 #include "mesh_common.h"
 #include "settings_nvs.h"
 #include "settings.h"
+#include "settings_uid.h"
 #include "provisioner_main.h"
 #include "provisioner_prov.h"
 
@@ -2664,4 +2665,14 @@ int bt_mesh_settings_deinit(bool erase)
 }
 #endif /* CONFIG_BLE_MESH_DEINIT */
 
+void bt_mesh_settings_reset(bool erase)
+{
+    k_delayed_work_cancel(&pending_store);
+    if (erase) {
+        bt_mesh_clear_net();
+        bt_mesh_clear_seq();
+        bt_mesh_clear_role();
+    }
+}
+
 #endif /* CONFIG_BLE_MESH_SETTINGS */

+ 2 - 0
components/bt/esp_ble_mesh/mesh_core/settings.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018 Intel Corporation
+ * Additional Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -69,6 +70,7 @@ int settings_core_erase(void);
 
 int bt_mesh_settings_init(void);
 int bt_mesh_settings_deinit(bool erase);
+void bt_mesh_settings_reset(bool erase);
 
 #ifdef __cplusplus
 }

+ 530 - 0
components/bt/esp_ble_mesh/mesh_core/settings_uid.c

@@ -0,0 +1,530 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "mesh.h"
+#include "mesh_main.h"
+#include "mesh_common.h"
+#include "settings_nvs.h"
+#include "settings.h"
+#include "transport.h"
+#include "provisioner_prov.h"
+
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+/*
+ * key: "mesh/uid" -> write/read to set/get all the user ids.
+ * key: "mesh/id/xxxx" -> write/read to set/get the "xxxx" user id.
+ */
+#define SETTINGS_NVS_NAME_SIZE      15
+#define SETTINGS_UID_SIZE           20
+#define INVALID_SETTINGS_INDEX      0xFF
+#define INVALID_SETTINGS_HANDLE     UINT32_MAX
+
+static struct settings_uid {
+    bool open;                              /* Indicate if settings is open */
+    char id[SETTINGS_UID_SIZE + 1];         /* Settings user id */
+    char name[SETTINGS_NVS_NAME_SIZE + 1];  /* Settings nvs namespace */
+    bt_mesh_nvs_handle_t handle;            /* Core Settings nvs handle */
+} user_ids[CONFIG_BLE_MESH_MAX_NVS_NAMESPACE];
+
+static int settings_direct_erase(u8_t index);
+
+static inline bool settings_uid_empty(struct settings_uid *uid)
+{
+    return (uid->id[0] == '\0') ? true : false;
+}
+
+bt_mesh_nvs_handle_t get_core_settings_handle(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        if (user_ids[i].open) {
+            return user_ids[i].handle;
+        }
+    }
+
+    BT_ERR("No settings handle found");
+    return INVALID_SETTINGS_HANDLE;
+}
+
+int settings_uid_init(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        memset(&user_ids[i], 0, sizeof(struct settings_uid));
+        user_ids[i].handle = INVALID_SETTINGS_HANDLE;
+    }
+
+    return 0;
+}
+
+int settings_uid_load(void)
+{
+    struct net_buf_simple *buf = NULL;
+    char name[16] = {'\0'};
+    bool exist = false;
+    size_t length = 0;
+    int err = 0;
+    int i;
+
+    /* Before using user id to search settings, we need to
+     * restore all the settings user_ids properly.
+     */
+
+    buf = bt_mesh_get_uid_settings_item("mesh/uid");
+    if (!buf) {
+        return 0;
+    }
+
+    length = buf->len;
+
+    for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) {
+        u16_t index = net_buf_simple_pull_le16(buf);
+
+        sprintf(name, "mesh/id/%04x", index);
+
+        err = bt_mesh_load_uid_settings(name, (u8_t *)user_ids[index].id,
+                                        SETTINGS_UID_SIZE, &exist);
+        if (err) {
+            continue;
+        }
+
+        if (exist == false) {
+            continue;
+        }
+
+        BT_INFO("Restored settings %d, uid %s", index, user_ids[index].id);
+    }
+
+    bt_mesh_free_buf(buf);
+    return err;
+}
+
+#if CONFIG_BLE_MESH_DEINIT
+int settings_uid_deinit(bool erase)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        memset(&user_ids[i], 0, offsetof(struct settings_uid, handle));
+        /* Can not reset handle here, since it will be used
+         * in the settings_uid_erase().
+         */
+    }
+
+    return 0;
+}
+
+int settings_uid_erase(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        if (user_ids[i].open == true) {
+            /* When a nvs namespace is open, which means it is
+             * being used currently. And its information will
+             * be erased when the deinit function is invoked,
+             * no need to erase it here.
+             */
+            bt_mesh_settings_nvs_close(user_ids[i].handle);
+        } else if (settings_uid_empty(&user_ids[i]) == false) {
+            /* When a user id is not empty, which means the nvs
+             * namespace may contains mesh information, need to
+             * erase it here.
+             */
+            settings_direct_erase(i);
+        }
+
+        user_ids[i].handle = INVALID_SETTINGS_HANDLE;
+    }
+
+    bt_mesh_erase_uid_settings("mesh/uid");
+    return 0;
+}
+#endif /* CONFIG_BLE_MESH_DEINIT */
+
+static int settings_direct_erase(u8_t index)
+{
+    bt_mesh_nvs_handle_t handle = 0;
+    char name[16] = {'\0'};
+    int err = 0;
+
+    sprintf(name, "%s_%02x", "mesh_core", index);
+
+    /* Get handle for core settings */
+    err = bt_mesh_settings_nvs_open(name, &handle);
+    if (err) {
+        BT_ERR("Open nvs failed, name %s, err %d", name, err);
+        return -EIO;
+    }
+
+    /* Erase mesh information */
+    err = bt_mesh_settings_erase_all(handle);
+    if (err) {
+        BT_ERR("Erase settings failed, index %d", index);
+        return err;
+    }
+
+    bt_mesh_settings_nvs_close(handle);
+
+    /* Erase settings user id */
+    memset(name, 0, sizeof(name));
+    sprintf(name, "mesh/id/%04x", index);
+
+    bt_mesh_erase_uid_settings(name);
+    bt_mesh_remove_uid_settings_item("mesh/uid", index);
+
+    return 0;
+}
+
+static u8_t settings_index_get(const char *id, u8_t *index)
+{
+    u8_t idx = 0;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        if (strlen(user_ids[i].id) != strlen(id)) {
+            continue;
+        }
+
+        if (!strncmp(user_ids[i].id, id, strlen(id))) {
+            idx = i;
+            break;
+        }
+    }
+
+    if (i == ARRAY_SIZE(user_ids)) {
+        idx = INVALID_SETTINGS_INDEX;
+    }
+
+    if (index) {
+        *index = idx;
+    }
+    return idx;
+}
+
+static int settings_open(u8_t index)
+{
+    struct settings_uid *uid = &user_ids[index];
+    char name[16] = {'\0'};
+    int err = 0;
+    int i;
+
+    /* Check if the nvs namespace is already open */
+    if (uid->open == true) {
+        BT_WARN("Settings already open, index %d", index);
+        return -EALREADY;
+    }
+
+    /* Check if another nvs namespace is already open */
+    for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        if (i != index && user_ids[i].open == true) {
+            BT_ERR("Settings %d is open, close it first", i);
+            return -EBUSY;
+        }
+    }
+
+    memset(uid->name, 0, sizeof(uid->name));
+    sprintf(uid->name, "%s_%02x", "mesh_core", index);
+
+    err = bt_mesh_settings_nvs_open(uid->name, &uid->handle);
+    if (err) {
+        BT_ERR("Open nvs failed, name %s, err %d", uid->name, err);
+        return -EIO;
+    }
+
+    if (settings_uid_empty(uid)) {
+        /* If the settings is not open with user id, then we use
+         * the index as the user id. Or when the device restarts,
+         * the user id may be restored, in this case the user id
+         * shall not be updated.
+         */
+        sprintf(uid->id, "%04x", index);
+    }
+
+    BT_INFO("Open settings, index %d, uid %s", index, uid->id);
+
+    sprintf(name, "mesh/id/%04x", index);
+    err = bt_mesh_save_uid_settings(name, (const u8_t *)uid->id, SETTINGS_UID_SIZE);
+    if (err) {
+        BT_ERR("Save uid failed, name %s", name);
+        return err;
+    }
+
+    err = bt_mesh_add_uid_settings_item("mesh/uid", index);
+    if (err) {
+        BT_ERR("Add uid failed, index %d", index);
+        return err;
+    }
+
+    /* Mark this as open here, because we need this flag for
+     * finding nvs handle before restoring mesh information.
+     */
+    uid->open = true;
+
+    err = settings_core_load();
+    if (err) {
+        BT_ERR("Load settings failed, name %s", uid->name);
+        return err;
+    }
+
+    err = settings_core_commit();
+    if (err) {
+        BT_ERR("Commit settings failed, name %s", uid->name);
+        return err;
+    }
+
+    return 0;
+}
+
+int bt_mesh_provisioner_open_settings_with_index(u8_t index)
+{
+    if (index >= ARRAY_SIZE(user_ids)) {
+        BT_ERR("Invalid settings index %d", index);
+        return -EINVAL;
+    }
+
+    return settings_open(index);
+}
+
+int bt_mesh_provisioner_open_settings_with_uid(const char *id, u8_t *index)
+{
+    u8_t idx = 0;
+    int i;
+
+    if (!id || strlen(id) > SETTINGS_UID_SIZE) {
+        BT_ERR("Invalid settings uid");
+        return -EINVAL;
+    }
+
+    idx = settings_index_get(id, index);
+
+    /* If user id not exists, try to add this as a new one. */
+    if (idx >= ARRAY_SIZE(user_ids)) {
+        for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+            if (settings_uid_empty(&user_ids[i])) {
+                strncpy(user_ids[i].id, id, SETTINGS_UID_SIZE);
+                if (index) {
+                    *index = i;
+                }
+                break;
+            }
+        }
+
+        if (i == ARRAY_SIZE(user_ids)) {
+            BT_ERR("Settings uid is full!");
+            return -ENOMEM;
+        }
+
+        idx = i;
+    }
+
+    return settings_open(idx);
+}
+
+static int settings_close(u8_t index, bool erase)
+{
+    struct settings_uid *uid = &user_ids[index];
+    char name[16] = {'\0'};
+    int err = 0;
+
+    if (uid->open == false) {
+        BT_ERR("Settings not open, index %d", index);
+        return -EIO;
+    }
+
+    BT_INFO("Close settings, index %d, uid %s", index, uid->id);
+
+    /* Disable Provisioner firstly */
+    err = bt_mesh_provisioner_disable(BLE_MESH_PROV_ADV | BLE_MESH_PROV_GATT);
+    if (err && err != -EALREADY) {
+        BT_ERR("Disable Provisioner failed (err %d)", err);
+        return err;
+    }
+
+    /* Reset (and erase) mesh information */
+    bt_mesh_provisioner_prov_reset(erase);
+    bt_mesh_provisioner_main_reset(erase);
+    bt_mesh_net_reset();
+    bt_mesh_rx_reset(erase);
+    bt_mesh_tx_reset();
+    bt_mesh_settings_reset(erase);
+
+    if (erase == true) {
+        /* Erase and reset settings user id */
+        sprintf(name, "mesh/id/%04x", index);
+
+        bt_mesh_erase_uid_settings(name);
+        bt_mesh_remove_uid_settings_item("mesh/uid", index);
+
+        memset(uid->id, 0, sizeof(uid->id));
+    }
+
+    bt_mesh_settings_nvs_close(uid->handle);
+    uid->open = false;
+
+    return 0;
+}
+
+int bt_mesh_provisioner_close_settings_with_index(u8_t index, bool erase)
+{
+    if (index >= ARRAY_SIZE(user_ids)) {
+        BT_ERR("Invalid settings index %d", index);
+        return -EINVAL;
+    }
+
+    return settings_close(index, erase);
+}
+
+int bt_mesh_provisioner_close_settings_with_uid(const char *id, bool erase, u8_t *index)
+{
+    u8_t idx = 0;
+
+    if (!id || strlen(id) > SETTINGS_UID_SIZE) {
+        BT_ERR("Invalid settings uid");
+        return -EINVAL;
+    }
+
+    idx = settings_index_get(id, index);
+    if (idx >= ARRAY_SIZE(user_ids)) {
+        BT_ERR("Settings uid %s not exists", id);
+        return -ENODEV;
+    }
+
+    return settings_close(idx, erase);
+}
+
+static int settings_delete(u8_t index)
+{
+    /* The function is used to erase mesh information from
+     * the nvs namespace when it is not open and restored,
+     * and delete the corresponding user id.
+     */
+    struct settings_uid *uid = &user_ids[index];
+
+    if (uid->open == true) {
+        BT_ERR("Settings being used, index %d", index);
+        return -EBUSY;
+    }
+
+    BT_INFO("Delete settings, index %d, uid %s", index, uid->id);
+
+    settings_direct_erase(index);
+
+    memset(uid, 0, sizeof(struct settings_uid));
+    uid->handle = INVALID_SETTINGS_HANDLE;
+
+    return 0;
+}
+
+int bt_mesh_provisioner_delete_settings_with_index(u8_t index)
+{
+    if (index >= ARRAY_SIZE(user_ids)) {
+        BT_ERR("Invalid settings index %d", index);
+        return -EINVAL;
+    }
+
+    return settings_delete(index);
+}
+
+int bt_mesh_provisioner_delete_settings_with_uid(const char *id, u8_t *index)
+{
+    u8_t idx = 0;
+
+    if (!id || strlen(id) > SETTINGS_UID_SIZE) {
+        BT_ERR("Invalid settings uid");
+        return -EINVAL;
+    }
+
+    idx = settings_index_get(id, index);
+    if (idx >= ARRAY_SIZE(user_ids)) {
+        BT_ERR("Settings uid %s not exists", id);
+        return -ENODEV;
+    }
+
+    return settings_delete(idx);
+}
+
+const char *bt_mesh_provisioner_get_settings_uid(u8_t index)
+{
+    if (index >= ARRAY_SIZE(user_ids)) {
+        BT_ERR("Invalid settings index %d", index);
+        return NULL;
+    }
+
+    return user_ids[index].id;
+}
+
+u8_t bt_mesh_provisioner_get_settings_index(const char *id)
+{
+    u8_t idx = 0;
+
+    if (!id || strlen(id) > SETTINGS_UID_SIZE) {
+        BT_ERR("Invalid settings uid");
+        return INVALID_SETTINGS_INDEX;
+    }
+
+    idx = settings_index_get(id, NULL);
+    if (idx >= ARRAY_SIZE(user_ids)) {
+        BT_ERR("Settings uid %s not exists", id);
+    }
+
+    return idx;
+}
+
+u8_t bt_mesh_provisioner_get_free_settings_count(void)
+{
+    u8_t count = 0;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        if (settings_uid_empty(&user_ids[i])) {
+            count++;
+        }
+    }
+
+    return count;
+}
+#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
+
+#if CONFIG_BLE_MESH_SETTINGS && CONFIG_BLE_MESH_PROVISIONER
+int bt_mesh_provisioner_direct_erase_settings(void)
+{
+    bt_mesh_nvs_handle_t handle = 0;
+    int err = 0;
+
+    err = bt_mesh_settings_direct_open(&handle);
+    if (err) {
+        return err;
+    }
+
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+    for (int i = 0; i < ARRAY_SIZE(user_ids); i++) {
+        settings_direct_erase(i);
+    }
+
+    bt_mesh_erase_uid_settings("mesh/uid");
+#else
+    err = bt_mesh_settings_erase_all(handle);
+#endif
+
+    bt_mesh_settings_direct_close();
+    return err;
+}
+#endif /* CONFIG_BLE_MESH_SETTINGS && CONFIG_BLE_MESH_PROVISIONER */

+ 47 - 0
components/bt/esp_ble_mesh/mesh_core/settings_uid.h

@@ -0,0 +1,47 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _SETTINGS_UID_H_
+#define _SETTINGS_UID_H_
+
+#include "mesh_types.h"
+#include "settings_nvs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int settings_uid_init(void);
+int settings_uid_load(void);
+int settings_uid_deinit(void);
+int settings_uid_erase(void);
+
+int bt_mesh_provisioner_open_settings_with_index(u8_t index);
+int bt_mesh_provisioner_open_settings_with_uid(const char *id, u8_t *index);
+int bt_mesh_provisioner_close_settings_with_index(u8_t index, bool erase);
+int bt_mesh_provisioner_close_settings_with_uid(const char *id, bool erase, u8_t *index);
+int bt_mesh_provisioner_delete_settings_with_index(u8_t index);
+int bt_mesh_provisioner_delete_settings_with_uid(const char *id, u8_t *index);
+
+const char *bt_mesh_provisioner_get_settings_uid(u8_t index);
+u8_t bt_mesh_provisioner_get_settings_index(const char *id);
+u8_t bt_mesh_provisioner_get_free_settings_count(void);
+
+int bt_mesh_provisioner_direct_erase_settings(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SETTINGS_UID_H_ */

+ 194 - 16
components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c

@@ -16,13 +16,16 @@
 #include <errno.h>
 
 #include "mesh_common.h"
-#include "settings_nvs.h"
+#include "settings_uid.h"
 #include "settings.h"
 
 #if CONFIG_BLE_MESH_SETTINGS
 
 enum settings_type {
     SETTINGS_CORE,
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+    SETTINGS_UID,
+#endif
 };
 
 struct settings_context {
@@ -49,10 +52,36 @@ static struct settings_context settings_ctx[] = {
         .settings_erase = settings_core_erase,
 #endif /* CONFIG_BLE_MESH_DEINIT */
     },
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+    [SETTINGS_UID] = {
+        .nvs_name = "mesh_user_id",
+        .settings_init = settings_uid_init,
+        .settings_load = settings_uid_load,
+        .settings_commit = NULL,
+#if CONFIG_BLE_MESH_DEINIT
+        .settings_deinit = settings_uid_deinit,
+        .settings_erase = settings_uid_erase,
+#endif /* CONFIG_BLE_MESH_DEINIT */
+    },
+#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
 };
 
 /* API used to initialize, load and commit BLE Mesh related settings */
 
+int bt_mesh_settings_nvs_open(const char* name, bt_mesh_nvs_handle_t *handle)
+{
+#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
+    return nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, name, NVS_READWRITE, handle);
+#else
+    return nvs_open(name, NVS_READWRITE, handle);
+#endif
+}
+
+void bt_mesh_settings_nvs_close(bt_mesh_nvs_handle_t handle)
+{
+    nvs_close(handle);
+}
+
 void bt_mesh_settings_init_foreach(void)
 {
     int err = 0;
@@ -61,37 +90,49 @@ void bt_mesh_settings_init_foreach(void)
 #if CONFIG_BLE_MESH_SPECIFIC_PARTITION
     err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME);
     if (err != ESP_OK) {
-        BT_ERR("Failed to init mesh partition, name %s, err %d", CONFIG_BLE_MESH_PARTITION_NAME, err);
+        BT_ERR("Init mesh partition failed, name %s, err %d", CONFIG_BLE_MESH_PARTITION_NAME, err);
         return;
     }
-#endif
+#endif /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */
 
     for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
         struct settings_context *ctx = &settings_ctx[i];
 
-#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
-        err = nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, ctx->nvs_name, NVS_READWRITE, &ctx->handle);
-#else
-        err = nvs_open(ctx->nvs_name, NVS_READWRITE, &ctx->handle);
-#endif
-        if (err != ESP_OK) {
-            BT_ERR("Open nvs failed, name %s, err %d", ctx->nvs_name, err);
-            continue;
-        }
-
+        /* Settings initialization is always needed. */
         if (ctx->settings_init && ctx->settings_init()) {
             BT_ERR("Init settings failed, name %s", ctx->nvs_name);
+            return;
+        }
+
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+        /* If multiple nvs namespace functionality is enabled,
+         * no need to perform the following operations during
+         * initialization. And they will be performed when the
+         * application layer tries to open settings.
+         */
+        if (i != SETTINGS_UID) {
             continue;
         }
+#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
+
+        err = bt_mesh_settings_nvs_open(ctx->nvs_name, &ctx->handle);
+        if (err) {
+            BT_ERR("Open nvs failed, name %s, err %d", ctx->nvs_name, err);
+            return;
+        }
 
         if (ctx->settings_load && ctx->settings_load()) {
             BT_ERR("Load settings failed, name %s", ctx->nvs_name);
-            continue;
+            return;
         }
 
+        /* If not using multiple nvs namespaces, we will follow the normal
+         * procedure, i.e. restoring all the mesh information.
+         * If using multiple nvs namespaces, we will only restore user_id.
+         */
         if (ctx->settings_commit && ctx->settings_commit()) {
             BT_ERR("Commit settings failed, name %s", ctx->nvs_name);
-            continue;
+            return;
         }
     }
 }
@@ -114,7 +155,7 @@ void bt_mesh_settings_deinit_foreach(bool erase)
             continue;
         }
 
-        nvs_close(ctx->handle);
+        bt_mesh_settings_nvs_close(ctx->handle);
     }
 
 #if CONFIG_BLE_MESH_SPECIFIC_PARTITION
@@ -123,10 +164,59 @@ void bt_mesh_settings_deinit_foreach(bool erase)
 }
 #endif /* CONFIG_BLE_MESH_DEINIT */
 
+int bt_mesh_settings_direct_open(bt_mesh_nvs_handle_t *handle)
+{
+    int err = 0;
+    int i;
+
+#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
+    err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME);
+    if (err != ESP_OK) {
+        BT_ERR("Init mesh partition failed, name %s, err %d", CONFIG_BLE_MESH_PARTITION_NAME, err);
+        return -EIO;
+    }
+#endif /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */
+
+    for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
+        struct settings_context *ctx = &settings_ctx[i];
+
+        err = bt_mesh_settings_nvs_open(ctx->nvs_name, &ctx->handle);
+        if (err) {
+            BT_ERR("Open nvs failed, name %s, err %d", ctx->nvs_name, err);
+            return -EIO;
+        }
+
+        if (i == SETTINGS_CORE && handle) {
+            *handle = ctx->handle;
+        }
+    }
+
+    return 0;
+}
+
+void bt_mesh_settings_direct_close(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
+        bt_mesh_settings_nvs_close(settings_ctx[i].handle);
+    }
+
+#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
+    nvs_flash_deinit_partition(CONFIG_BLE_MESH_PARTITION_NAME);
+#endif
+}
+
 /* API used to get BLE Mesh related nvs handle */
 
 static inline bt_mesh_nvs_handle_t settings_get_nvs_handle(enum settings_type type)
 {
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+    if (type == SETTINGS_CORE) {
+        extern bt_mesh_nvs_handle_t get_core_settings_handle(void);
+        return get_core_settings_handle();
+    }
+#endif
     return settings_ctx[type].handle;
 }
 
@@ -183,6 +273,14 @@ int bt_mesh_save_core_settings(const char *key, const u8_t *val, size_t len)
     return bt_mesh_save_settings(handle, key, val, len);
 }
 
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+int bt_mesh_save_uid_settings(const char *key, const u8_t *val, size_t len)
+{
+    bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
+    return bt_mesh_save_settings(handle, key, val, len);
+}
+#endif
+
 int bt_mesh_erase_settings(bt_mesh_nvs_handle_t handle, const char *key)
 {
     return bt_mesh_save_settings(handle, key, NULL, 0);
@@ -193,6 +291,13 @@ int bt_mesh_erase_core_settings(const char *key)
     return bt_mesh_save_core_settings(key, NULL, 0);
 }
 
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+int bt_mesh_erase_uid_settings(const char *name)
+{
+    return bt_mesh_save_uid_settings(name, NULL, 0);
+}
+#endif
+
 /* API used to load BLE Mesh related settings */
 
 static int settings_load(bt_mesh_nvs_handle_t handle, const char *key,
@@ -237,6 +342,14 @@ int bt_mesh_load_core_settings(const char *key, u8_t *buf, size_t buf_len, bool
     return bt_mesh_load_settings(handle, key, buf, buf_len, exist);
 }
 
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+int bt_mesh_load_uid_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist)
+{
+    bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
+    return bt_mesh_load_settings(handle, key, buf, buf_len, exist);
+}
+#endif
+
 /* API used to get length of BLE Mesh related settings */
 
 static size_t settings_get_length(bt_mesh_nvs_handle_t handle, const char *key)
@@ -317,6 +430,14 @@ struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key)
     return bt_mesh_get_settings_item(handle, key);
 }
 
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+struct net_buf_simple *bt_mesh_get_uid_settings_item(const char *key)
+{
+    bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
+    return bt_mesh_get_settings_item(handle, key);
+}
+#endif
+
 /* API used to check if the settings item exists */
 
 static bool is_settings_item_exist(struct net_buf_simple *buf, const u16_t val)
@@ -398,6 +519,14 @@ int bt_mesh_add_core_settings_item(const char *key, const u16_t val)
     return bt_mesh_add_settings_item(handle, key, val);
 }
 
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+int bt_mesh_add_uid_settings_item(const char *key, const u16_t val)
+{
+    bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
+    return bt_mesh_add_settings_item(handle, key, val);
+}
+#endif
+
 /* API used to remove the settings item */
 
 static int settings_remove_item(bt_mesh_nvs_handle_t handle, const char *key, const u16_t val)
@@ -462,4 +591,53 @@ int bt_mesh_remove_core_settings_item(const char *key, const u16_t val)
     return bt_mesh_remove_settings_item(handle, key, val);
 }
 
+#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
+int bt_mesh_remove_uid_settings_item(const char *key, const u16_t val)
+{
+    bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID);
+    return bt_mesh_remove_settings_item(handle, key, val);
+}
+#endif
+
+int bt_mesh_settings_erase_key(bt_mesh_nvs_handle_t handle, const char *key)
+{
+    int err = 0;
+
+    err = nvs_erase_key(handle, key);
+    if (err != ESP_OK) {
+        if (err == ESP_ERR_NVS_NOT_FOUND) {
+            return 0;
+        }
+
+        BT_ERR("Failed to erase %s (err %d)", key, err);
+        return -EIO;
+    }
+
+    err = nvs_commit(handle);
+    if (err != ESP_OK) {
+        BT_ERR("Failed to commit nvs (err %d)", err);
+        return -EIO;
+    }
+
+    return 0;
+}
+
+int bt_mesh_settings_erase_all(bt_mesh_nvs_handle_t handle)
+{
+    int err = 0;
+
+    err = nvs_erase_all(handle);
+    if (err != ESP_OK) {
+        BT_ERR("Failed to erase all (err %d)", err);
+        return -EIO;
+    }
+
+    err = nvs_commit(handle);
+    if (err != ESP_OK) {
+        BT_ERR("Failed to commit nvs (err %d)", err);
+        return -EIO;
+    }
+
+    return 0;
+}
 #endif /* CONFIG_BLE_MESH_SETTINGS */

+ 15 - 0
components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.h

@@ -30,28 +30,43 @@ typedef nvs_handle_t    bt_mesh_nvs_handle_t;
 #define BLE_MESH_GET_MODEL_IDX(x)       ((u8_t)(x))
 #define BLE_MESH_GET_MODEL_KEY(a, b)    ((u16_t)(((u16_t)((a) << 8)) | (b)))
 
+int bt_mesh_settings_nvs_open(const char* name, bt_mesh_nvs_handle_t *handle);
+void bt_mesh_settings_nvs_close(bt_mesh_nvs_handle_t handle);
+
 void bt_mesh_settings_init_foreach(void);
 void bt_mesh_settings_deinit_foreach(bool erase);
 
+int bt_mesh_settings_direct_open(bt_mesh_nvs_handle_t *handle);
+void bt_mesh_settings_direct_close(void);
+
 int bt_mesh_save_settings(bt_mesh_nvs_handle_t handle, const char *key,
                           const u8_t *val, size_t len);
 int bt_mesh_save_core_settings(const char *key, const u8_t *val, size_t len);
+int bt_mesh_save_uid_settings(const char *key, const u8_t *val, size_t len);
 
 int bt_mesh_erase_settings(bt_mesh_nvs_handle_t handle, const char *key);
 int bt_mesh_erase_core_settings(const char *key);
+int bt_mesh_erase_uid_settings(const char *name);
 
 int bt_mesh_load_settings(bt_mesh_nvs_handle_t handle, const char *key,
                           u8_t *buf, size_t buf_len, bool *exist);
 int bt_mesh_load_core_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist);
+int bt_mesh_load_uid_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist);
 
 struct net_buf_simple *bt_mesh_get_settings_item(bt_mesh_nvs_handle_t handle, const char *key);
 struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key);
+struct net_buf_simple *bt_mesh_get_uid_settings_item(const char *key);
 
 int bt_mesh_add_settings_item(bt_mesh_nvs_handle_t handle, const char *key, const u16_t val);
 int bt_mesh_add_core_settings_item(const char *key, const u16_t val);
+int bt_mesh_add_uid_settings_item(const char *key, const u16_t val);
 
 int bt_mesh_remove_settings_item(bt_mesh_nvs_handle_t handle, const char *key, const u16_t val);
 int bt_mesh_remove_core_settings_item(const char *key, const u16_t val);
+int bt_mesh_remove_uid_settings_item(const char *key, const u16_t val);
+
+int bt_mesh_settings_erase_key(bt_mesh_nvs_handle_t handle, const char *key);
+int bt_mesh_settings_erase_all(bt_mesh_nvs_handle_t handle);
 
 #ifdef __cplusplus
 }

+ 17 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.ci.nvs00

@@ -0,0 +1,17 @@
+CONFIG_BT_ENABLED=y
+CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
+CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
+CONFIG_BTDM_CTRL_MODE_BTDM=n
+CONFIG_BTDM_MODEM_SLEEP=n
+CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE=y
+CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN=y
+CONFIG_BT_BTU_TASK_STACK_SIZE=4512
+
+CONFIG_BLE_MESH=y
+CONFIG_BLE_MESH_DEINIT=n
+CONFIG_BLE_MESH_PROVISIONER=y
+CONFIG_BLE_MESH_PB_GATT=y
+CONFIG_BLE_MESH_SETTINGS=y
+CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE=y
+CONFIG_BLE_MESH_CFG_CLI=y
+CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y

+ 16 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.ci.nvs01

@@ -0,0 +1,16 @@
+CONFIG_BT_ENABLED=y
+CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
+CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
+CONFIG_BTDM_CTRL_MODE_BTDM=n
+CONFIG_BTDM_MODEM_SLEEP=n
+CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE=y
+CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN=y
+CONFIG_BT_BTU_TASK_STACK_SIZE=4512
+
+CONFIG_BLE_MESH=y
+CONFIG_BLE_MESH_PROVISIONER=y
+CONFIG_BLE_MESH_PB_GATT=y
+CONFIG_BLE_MESH_SETTINGS=y
+CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE=y
+CONFIG_BLE_MESH_CFG_CLI=y
+CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y