Răsfoiți Sursa

ble mesh: update ble mesh console example(backport v3.3)

Chen Sheng 5 ani în urmă
părinte
comite
9fc2212e16
23 a modificat fișierele cu 760 adăugiri și 162 ștergeri
  1. 1 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/CMakeLists.txt
  2. 2 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.c
  3. 8 9
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_cfg_srv_model.c
  4. 5 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_decl.h
  5. 9 5
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_lib.c
  6. 5 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_main.c
  7. 180 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_reg_gen_onoff_client_cmd.c
  8. 80 24
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_node_cmd.c
  9. 29 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_server_cmd.c
  10. 3 6
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/sdkconfig.defaults
  11. 1 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/CMakeLists.txt
  12. 4 23
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.c
  13. 4 12
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.h
  14. 7 7
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_cfg_srv_model.c
  15. 3 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_main.c
  16. 2 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_cfg_client_cmd.c
  17. 4 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_gen_onoff_client_cmd.c
  18. 7 8
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_test_perf_client_cmd.c
  19. 31 16
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_node_cmd.c
  20. 14 47
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_provisioner_cmd.c
  21. 266 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/transaction.c
  22. 88 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/transaction.h
  23. 7 3
      examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/sdkconfig.defaults

+ 1 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/CMakeLists.txt

@@ -5,6 +5,7 @@ set(COMPONENT_SRCS "ble_mesh_adapter.c"
                    "ble_mesh_console_system.c"
                    "ble_mesh_register_node_cmd.c"
                    "ble_mesh_register_server_cmd.c"
+                   "ble_mesh_reg_gen_onoff_client_cmd.c"
                    "register_bluetooth.c")
 
 set(COMPONENT_ADD_INCLUDEDIRS ".")

+ 2 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.c

@@ -29,8 +29,9 @@ esp_ble_mesh_model_t *ble_mesh_get_model(uint16_t model_id)
         model = &gen_onoff_srv_models[1];
         break;
 #if (CONFIG_BLE_MESH_GENERIC_ONOFF_CLI)
+    // as server
     case ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI:
-        model = &gen_onoff_cli_models[1];
+        model = &gen_onoff_cli_models[2];
         break;
 #endif
     case ESP_BLE_MESH_VND_MODEL_ID_TEST_PERF_CLI:

+ 8 - 9
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_cfg_srv_model.c

@@ -13,7 +13,7 @@
 // limitations under the License.
 
 #include "ble_mesh_cfg_srv_model.h"
-
+#include "esp_ble_mesh_generic_model_api.h"
 uint8_t dev_uuid[16] = {0xdd, 0xdd};
 
 #if CONFIG_BLE_MESH_NODE
@@ -40,9 +40,8 @@ esp_ble_mesh_prov_t prov = {
 };
 #endif //CONFIG_BLE_MESH_PROVISIONER
 
-ESP_BLE_MESH_MODEL_PUB_DEFINE(model_pub_config, 2 + 1, ROLE_NODE);
-
 esp_ble_mesh_model_pub_t vendor_model_pub_config;
+ESP_BLE_MESH_MODEL_PUB_DEFINE(model_pub_config, 2 + 1, ROLE_NODE);
 
 // configure server module
 esp_ble_mesh_cfg_srv_t cfg_srv = {
@@ -96,16 +95,15 @@ esp_ble_mesh_comp_t config_client_comp = {
 };
 
 // configure special module
-esp_ble_mesh_model_op_t gen_onoff_srv_model_op_config[] = {
-    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET,       0),
-    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET,       2),
-    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2),
-    ESP_BLE_MESH_MODEL_OP_END,
+ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_0, 2 + 3, ROLE_NODE);
+static esp_ble_mesh_gen_onoff_srv_t onoff_server = {
+    .rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
+    .rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
 };
 
 esp_ble_mesh_model_t gen_onoff_srv_models[] = {
     ESP_BLE_MESH_MODEL_CFG_SRV(&cfg_srv),
-    ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_model_op_config, &model_pub_config, NULL),
+    ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_0, &onoff_server),
 };
 
 esp_ble_mesh_elem_t gen_onoff_srv_elements[] = {
@@ -126,6 +124,7 @@ esp_ble_mesh_client_t gen_onoff_cli;
 esp_ble_mesh_model_t gen_onoff_cli_models[] = {
     ESP_BLE_MESH_MODEL_CFG_SRV(&cfg_srv),
     ESP_BLE_MESH_MODEL_CFG_CLI(&cfg_cli),
+    ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_0, &onoff_server),
     ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI(&model_pub_config, &gen_onoff_cli),
 };
 

+ 5 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_decl.h

@@ -22,6 +22,11 @@ void ble_mesh_register_mesh_node(void);
 // Register mesh config server and generic server operation cmd
 void ble_mesh_register_server(void);
 
+#if (CONFIG_BLE_MESH_GENERIC_ONOFF_CLI)
+// Register mesh client operation cmd
+void ble_mesh_register_gen_onoff_client(void);
+#endif
+
 #if (CONFIG_BLE_MESH_CFG_CLI)
 // Register mesh config client operation cmd
 void ble_mesh_register_configuration_client_model(void);

+ 9 - 5
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_lib.c

@@ -66,10 +66,16 @@ int hexstr_2_bin(const char *hex, uint8_t *buf, uint32_t len)
 int get_value_string(char *value_in, char *buf)
 {
     int result = -1;
-
+    uint8_t loop = 0;
     uint16_t length = strlen(value_in);
-    for(int i = 0; i<length; i++) {
-        printf("%c", value_in[i]);
+
+    // address string, need sepcial test
+    for (loop = 0; loop < 17 ; loop++) {
+        if (loop % 3 == 2) {
+            if (value_in[loop] == ':') {
+                return result;
+            }
+        }
     }
 
     if (length > 2) {
@@ -85,7 +91,6 @@ int get_value_string(char *value_in, char *buf)
         strcpy(buf, value_in);
         result = 0;
     }
-
     return result;
 }
 
@@ -104,7 +109,6 @@ bool str_2_mac(uint8_t *str, uint8_t *dest)
             if (src_p[loop] != ':') {
                 return false;
             }
-
             continue;
         }
 

+ 5 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_main.c

@@ -126,6 +126,8 @@ esp_err_t bluetooth_init(void)
         return ret;
     }
 
+    esp_log_level_set("*", ESP_LOG_ERROR);
+    esp_log_level_set("ble_mesh_node_console", ESP_LOG_INFO);
     return ret;
 }
 
@@ -153,6 +155,9 @@ void app_main(void)
     register_bluetooth();
     ble_mesh_register_mesh_node();
     ble_mesh_register_server();
+#if (CONFIG_BLE_MESH_GENERIC_ONOFF_CLI)
+    ble_mesh_register_gen_onoff_client();
+#endif
 
     /* Prompt to be printed before each line.
      * This can be customized, made dynamic, etc.

+ 180 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_reg_gen_onoff_client_cmd.c

@@ -0,0 +1,180 @@
+// Copyright 2017-2019 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 "esp_timer.h"
+#include "ble_mesh_adapter.h"
+
+#if (CONFIG_BLE_MESH_GENERIC_ONOFF_CLI)
+typedef struct {
+    struct arg_str *action_type;
+    struct arg_int *op_en;
+    struct arg_int *unicast_address;
+    struct arg_int *onoff_state;
+    struct arg_int *trans_id;
+    struct arg_int *trans_time;
+    struct arg_int *delay;
+    struct arg_int *opcode;
+    struct arg_int *appkey_idx;
+    struct arg_int *role;
+    struct arg_int *net_idx;
+    struct arg_end *end;
+} ble_mesh_gen_onoff_state_t;
+ble_mesh_gen_onoff_state_t gen_onoff_state;
+
+void ble_mesh_register_gen_onoff_client_command(void);
+void ble_mesh_generic_onoff_client_model_cb(esp_ble_mesh_generic_client_cb_event_t event,
+        esp_ble_mesh_generic_client_cb_param_t *param);
+
+void ble_mesh_register_gen_onoff_client(void)
+{
+    ble_mesh_register_gen_onoff_client_command();
+}
+
+void ble_mesh_generic_onoff_client_model_cb(esp_ble_mesh_generic_client_cb_event_t event,
+        esp_ble_mesh_generic_client_cb_param_t *param)
+{
+    uint32_t opcode = param->params->opcode;
+
+    ESP_LOGD(TAG, "enter %s: event is %d, error code is %d, opcode is 0x%x\n",
+             __func__, event, param->error_code, opcode);
+
+    switch (event) {
+    case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT: {
+        switch (opcode) {
+        case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
+            if (param->error_code == ESP_OK) {
+                ESP_LOGI(TAG, "GenOnOffClient:GetStatus,OK,%d", param->status_cb.onoff_status.present_onoff);
+            } else {
+                ESP_LOGE(TAG, "GenOnOffClient:GetStatus,Fail,%d", param->error_code);
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    }
+    case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT: {
+        switch (opcode) {
+        case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
+            if (param->error_code == ESP_OK) {
+                ESP_LOGI(TAG, "GenOnOffClient:SetStatus,OK,%d", param->status_cb.onoff_status.present_onoff);
+            } else {
+                ESP_LOGE(TAG, "GenOnOffClient:SetStatus,Fail,%d", param->error_code);
+            }
+            break;
+        case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK:
+            if (param->error_code == ESP_OK) {
+                ESP_LOGI(TAG, "GenOnOffClient:SetUNACK,OK");
+            } else {
+                ESP_LOGE(TAG, "GenOnOffClient:SetUNACK,Fail,%d", param->error_code);
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    }
+    case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT: {
+        if (param->error_code == ESP_OK) {
+            ESP_LOGI(TAG, "GenOnOffClient:Publish,OK");
+        } else {
+            ESP_LOGE(TAG, "GenOnOffClient:Publish,Fail,%d", param->error_code);
+        }
+        break;
+    }
+    case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT:
+        ESP_LOGE(TAG, "GenOnOffClient:TimeOut,%d", param->error_code);
+        break;
+    case ESP_BLE_MESH_GENERIC_CLIENT_EVT_MAX:
+        ESP_LOGE(TAG, "GenONOFFClient:InvalidEvt,%d", param->error_code);
+        break;
+    default:
+        break;
+    }
+    ESP_LOGD(TAG, "exit %s \n", __func__);
+}
+
+int ble_mesh_generic_onoff_client_model(int argc, char **argv)
+{
+    int err = ESP_OK;
+    esp_ble_mesh_generic_client_set_state_t gen_client_set;
+    esp_ble_mesh_generic_client_get_state_t gen_client_get;
+    esp_ble_mesh_client_common_param_t onoff_common = {
+        .msg_timeout = 0,
+        .ctx.send_ttl = 7,
+    };
+
+    ESP_LOGD(TAG, "enter %s\n", __func__);
+
+    int nerrors = arg_parse(argc, argv, (void **) &gen_onoff_state);
+    if (nerrors != 0) {
+        arg_print_errors(stderr, gen_onoff_state.end, argv[0]);
+        return 1;
+    }
+
+    onoff_common.model = ble_mesh_get_model(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI);
+
+    arg_int_to_value(gen_onoff_state.appkey_idx, onoff_common.ctx.app_idx, "appkey_index");
+    arg_int_to_value(gen_onoff_state.opcode, onoff_common.opcode, "opcode");
+    arg_int_to_value(gen_onoff_state.role, onoff_common.msg_role, "role");
+    arg_int_to_value(gen_onoff_state.unicast_address, onoff_common.ctx.addr, "address");
+    arg_int_to_value(gen_onoff_state.net_idx, onoff_common.ctx.net_idx, "network key index");
+    arg_int_to_value(gen_onoff_state.op_en, gen_client_set.onoff_set.op_en, "op_en");
+    arg_int_to_value(gen_onoff_state.onoff_state, gen_client_set.onoff_set.onoff, "onoff");
+    arg_int_to_value(gen_onoff_state.trans_id, gen_client_set.onoff_set.tid, "tid");
+    arg_int_to_value(gen_onoff_state.trans_time, gen_client_set.onoff_set.trans_time, "trans_time");
+    arg_int_to_value(gen_onoff_state.delay, gen_client_set.onoff_set.delay, "delay");
+
+    if (gen_onoff_state.action_type->count != 0) {
+        if (strcmp(gen_onoff_state.action_type->sval[0], "get") == 0) {
+            err = esp_ble_mesh_generic_client_get_state(&onoff_common, &gen_client_get);
+        } else if (strcmp(gen_onoff_state.action_type->sval[0], "set") == 0) {
+            err = esp_ble_mesh_generic_client_set_state(&onoff_common, &gen_client_set);
+        } else if (strcmp(gen_onoff_state.action_type->sval[0], "reg") == 0) {
+            err = esp_ble_mesh_register_generic_client_callback(ble_mesh_generic_onoff_client_model_cb);
+            if (err == ESP_OK) {
+                ESP_LOGI(TAG, "GenONOFFClient:Reg,OK");
+            }
+        }
+    }
+    ESP_LOGD(TAG, "exit %s\n", __func__);
+    return err;
+}
+
+void ble_mesh_register_gen_onoff_client_command(void)
+{
+    gen_onoff_state.action_type = arg_str1("z", NULL, "<action>", "action type");
+    gen_onoff_state.opcode = arg_int0("o", NULL, "<opcode>", "message opcode");
+    gen_onoff_state.appkey_idx = arg_int0("a", NULL, "<appkey>", "appkey index");
+    gen_onoff_state.role = arg_int0("r", NULL, "<role>", "role");
+    gen_onoff_state.unicast_address = arg_int0("u", NULL, "<address>", "unicast address");
+    gen_onoff_state.net_idx = arg_int0("n", NULL, "<netkey index>", "network key index");
+    gen_onoff_state.op_en = arg_int0("e", NULL, "<optional>", "whether optional parameters included");
+    gen_onoff_state.onoff_state = arg_int0("s", NULL, "<state>", "present onoff state");
+    gen_onoff_state.trans_id = arg_int0("i", NULL, "<identifier>", "transaction identifier");
+    gen_onoff_state.trans_time = arg_int0("t", NULL, "<time>", "time to complete state transition");
+    gen_onoff_state.delay = arg_int0("d", NULL, "<delay>", "indicate message execution delay");
+    gen_onoff_state.end = arg_end(1);
+
+    const esp_console_cmd_t gen_onoff_state_cmd = {
+        .command = "bmgocm",
+        .help = "ble mesh generic onoff client model",
+        .hint = NULL,
+        .func = &ble_mesh_generic_onoff_client_model,
+        .argtable = &gen_onoff_state,
+    };
+    ESP_ERROR_CHECK(esp_console_cmd_register(&gen_onoff_state_cmd));
+}
+
+#endif

+ 80 - 24
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_node_cmd.c

@@ -22,6 +22,7 @@
 #include "esp_ble_mesh_defs.h"
 #include "esp_ble_mesh_common_api.h"
 #include "esp_ble_mesh_provisioning_api.h"
+#include "esp_ble_mesh_generic_model_api.h"
 
 #include "ble_mesh_console_lib.h"
 #include "ble_mesh_adapter.h"
@@ -90,6 +91,8 @@ void ble_mesh_register_node_cmd(void);
 // Register callback function
 void ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_param_t *param);
 void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_cb_param_t *param);
+void ble_mesh_generic_server_model_cb(esp_ble_mesh_generic_server_cb_event_t event,
+        esp_ble_mesh_generic_server_cb_param_t *param);
 
 
 void ble_mesh_register_mesh_node(void)
@@ -103,14 +106,81 @@ int ble_mesh_register_node_cb(int argc, char** argv)
     ble_mesh_node_init();
     esp_ble_mesh_register_prov_callback(ble_mesh_prov_cb);
     esp_ble_mesh_register_custom_model_callback(ble_mesh_model_cb);
+    esp_ble_mesh_register_generic_server_callback(ble_mesh_generic_server_model_cb);
     ESP_LOGI(TAG, "Node:Reg,OK");
     ESP_LOGD(TAG, "exit %s\n", __func__);
     return 0;
 }
 
+void ble_mesh_generic_server_model_cb(esp_ble_mesh_generic_server_cb_event_t event,
+        esp_ble_mesh_generic_server_cb_param_t *param)
+{
+    uint32_t opcode = param->ctx.recv_op;
+    uint8_t status;
+
+    ESP_LOGD(TAG, "enter %s: event is %d, opcode is 0x%x\n", __func__, event, opcode);
+
+    switch (event) {
+        case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
+            if (opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
+                ESP_LOGI(TAG, "GenOnOffServer:SetStatus,OK,%d", param->value.state_change.onoff_set.onoff);
+                ble_mesh_node_set_state(param->value.state_change.onoff_set.onoff);
+            } else if (opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
+                ESP_LOGI(TAG, "GenOnOffServer:SetUnAck,OK,%d", param->value.state_change.onoff_set.onoff);
+                ble_mesh_node_set_state(param->value.state_change.onoff_set.onoff);
+            }
+            break;
+    case ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT: {
+        switch (opcode) {
+        case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
+            ESP_LOGI(TAG, "GenOnOffServer:GetStatus,OK");
+            ble_mesh_node_get_state(status);
+            esp_ble_mesh_server_model_send_msg(param->model, &param->ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
+                                                   sizeof(status), &status);
+            break;
+        default:
+            break;
+        }
+        break;
+    }
+    case ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT: {
+        if (opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET || opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
+            esp_ble_mesh_gen_onoff_srv_t *srv = param->model->user_data;
+            if (param->value.set.onoff.op_en == false) {
+                srv->state.onoff = param->value.set.onoff.onoff;
+            } else {
+                /* TODO: Delay and state transition */
+               srv->state.onoff = param->value.set.onoff.onoff;
+            }
+        }
+       
+        switch (opcode) {
+            case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
+                ESP_LOGI(TAG, "GenOnOffServer:SetStatus,OK,%d", param->value.set.onoff.onoff);
+                ble_mesh_node_set_state(param->value.set.onoff.onoff);
+                ble_mesh_node_get_state(status);
+                esp_ble_mesh_server_model_send_msg(param->model, &param->ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
+                                                   sizeof(status), &status);
+                break;
+            case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK:
+                ble_mesh_node_set_state(param->value.set.onoff.onoff);
+                ESP_LOGI(TAG, "GenOnOffServer:SetUNACK,OK,%d", param->value.set.onoff.onoff);
+                break;
+            default:
+                break;
+        }
+        break;
+    }
+    default:
+        break;
+    }
+    ESP_LOGD(TAG, "exit %s \n", __func__);
+}
+
 void ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_param_t *param)
 {
     ESP_LOGD(TAG, "enter %s, event = %d", __func__, event);
+
     switch (event) {
     case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
         ble_mesh_callback_check_err_code(param->prov_register_comp.err_code, "Provisioning:Register");
@@ -169,32 +239,15 @@ void ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_p
 
 void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_cb_param_t *param)
 {
-    uint8_t status;
     uint16_t result;
     uint8_t data[4];
     
     ESP_LOGD(TAG, "enter %s, event=%x\n", __func__, event);
-    printf("enter %s, event=%x\n", __func__, event);
+
     switch (event) {
     case ESP_BLE_MESH_MODEL_OPERATION_EVT:
         if (param->model_operation.model != NULL && param->model_operation.model->op != NULL) {
-            if (param->model_operation.opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET) {
-                ESP_LOGI(TAG, "Node:GetStatus,Success");
-                ble_mesh_node_get_state(status);
-                esp_ble_mesh_server_model_send_msg(param->model_operation.model, param->model_operation.ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
-                                                   sizeof(status), &status);
-            } else if (param->model_operation.opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
-                ESP_LOGI(TAG, "Node:SetAck,Success,%d,%d,%d", param->model_operation.msg[0], param->model_operation.ctx->recv_ttl, param->model_operation.length);
-                ble_mesh_node_set_state(param->model_operation.msg[0]);
-                ble_mesh_node_get_state(status);
-                esp_ble_mesh_server_model_send_msg(param->model_operation.model, param->model_operation.ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
-                                                   sizeof(status), &status);
-            } else if (param->model_operation.opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
-                ble_mesh_node_set_state(param->model_operation.msg[0]);
-                ESP_LOGI(TAG, "Node:SetUnAck,Success,%d,%d", param->model_operation.msg[0], param->model_operation.ctx->recv_ttl);
-            } else if (param->model_operation.opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS) {
-                ESP_LOGI(TAG, "Node:Status,Success,%d", param->model_operation.length);
-            } else if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET) {
+             if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET) {
                 ESP_LOGI(TAG, "VendorModel:SetAck,Success,%d", param->model_operation.ctx->recv_ttl);
                 data[0] = param->model_operation.msg[0];
                 data[1] = param->model_operation.msg[1];
@@ -316,14 +369,17 @@ int ble_mesh_init(int argc, char **argv)
     local_component = ble_mesh_get_component(component.model_type->ival[0]);
 
     if (component.dev_uuid->count != 0) {
-        device_uuid = malloc((16 + 1) * sizeof(uint8_t));
+        device_uuid = malloc((ESP_BLE_MESH_OCTET16_LEN + 1) * sizeof(uint8_t));
         if (device_uuid == NULL) {
             ESP_LOGE(TAG, "ble mesh malloc failed, %d\n", __LINE__);
         }
-        get_value_string((char *)component.dev_uuid->sval[0], (char *) device_uuid);
-        memcpy(dev_uuid, device_uuid, 16);
-    } else {
-        memcpy(dev_uuid, esp_bt_dev_get_address(), 6);
+        err = get_value_string((char *)component.dev_uuid->sval[0], (char *) device_uuid);
+        if (err == ESP_OK) {
+            memcpy(dev_uuid, device_uuid, ESP_BLE_MESH_OCTET16_LEN);
+        } else {
+            str_2_mac((uint8_t *)component.dev_uuid->sval[0], device_uuid);
+            memcpy(dev_uuid, device_uuid, BD_ADDR_LEN);
+        }
     }
 
     err = esp_ble_mesh_init(&prov, local_component);

+ 29 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_server_cmd.c

@@ -25,6 +25,9 @@ typedef struct {
     struct arg_int *opcode;
     struct arg_int *model;
     struct arg_int *role;
+    struct arg_int *pub_addr;
+    struct arg_int *app_index;
+    struct arg_int *period;
     struct arg_end *end;
 } ble_mesh_publish_message;
 ble_mesh_publish_message msg_publish;
@@ -55,6 +58,29 @@ int ble_mesh_module_publish_message(int argc, char **argv)
 
     arg_int_to_value(msg_publish.role, device_role, "device role");
     model = ble_mesh_get_model(msg_publish.model->ival[0]);
+    if (msg_publish.role->count != 0) {
+        device_role = msg_publish.role->ival[0];
+    }
+
+    if (msg_publish.pub_addr->count != 0) {
+        model->pub->publish_addr = msg_publish.pub_addr->ival[0];
+    }
+
+    if (msg_publish.period->count != 0) {
+        model->pub->period = msg_publish.period->ival[0];
+    }
+
+    if (msg_publish.app_index->count != 0) {
+        model->pub->app_idx = msg_publish.app_index->ival[0];
+    }
+
+    if (msg_publish.data->count != 0) {
+        length = strlen(msg_publish.data->sval[0]);
+        data = malloc((length + 1) * sizeof(uint8_t));
+        if (data != NULL) {
+            err = get_value_string((char *)msg_publish.data->sval[0], (char *) data);
+        }
+    }
 
     err = esp_ble_mesh_model_publish(model, msg_publish.opcode->ival[0], length, data, device_role);
 
@@ -69,6 +95,9 @@ void ble_mesh_register_server_operation(void)
     msg_publish.opcode = arg_int1("o", NULL, "<opcode>", "operation opcode");
     msg_publish.model = arg_int1("m", NULL, "<module>", "module published to");
     msg_publish.role = arg_int1("r", NULL, "<role>", "device role");
+    msg_publish.pub_addr = arg_int1("a", NULL, "<address>", "unicast address");
+    msg_publish.app_index = arg_int1("i", NULL, "<app key>", "app key index");
+    msg_publish.period = arg_int1("p", NULL, "<period>", "period");
     msg_publish.end = arg_end(1);
 
     const esp_console_cmd_t msg_publish_cmd = {

+ 3 - 6
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/sdkconfig.defaults

@@ -14,10 +14,7 @@ CONFIG_BTU_TASK_STACK_SIZE=4512
 CONFIG_BLE_MESH=y
 CONFIG_BLE_MESH_NODE=y
 CONFIG_BLE_MESH_PB_GATT=y
-CONFIG_BLE_MESH_TX_SEG_MSG_COUNT=10
-CONFIG_BLE_MESH_RX_SEG_MSG_COUNT=10
+CONFIG_BLE_MESH_TX_SEG_MSG_COUNT=3
+CONFIG_BLE_MESH_RX_SEG_MSG_COUNT=3
 CONFIG_BLE_MESH_CFG_CLI=y
-
-CONFIG_CONSOLE_UART_BAUDRATE=921600
-CONFIG_ESPTOOLPY_BAUD_921600B=y
-CONFIG_MONITOR_BAUD_921600B=y
+CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y

+ 1 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/CMakeLists.txt

@@ -1,4 +1,5 @@
 set(COMPONENT_SRCS "ble_mesh_adapter.c"
+                   "transaction.c"
                    "ble_mesh_cfg_srv_model.c"
                    "ble_mesh_console_lib.c"
                    "ble_mesh_console_main.c"

+ 4 - 23
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.c

@@ -82,27 +82,21 @@ void ble_mesh_node_init(void)
     uint16_t i;
 
     for (i = 0; i < NODE_MAX_GROUP_CONFIG; i++) {
-        ble_mesh_node_prestore_params[i].net_idx = 0xFFFF;
-        ble_mesh_node_prestore_params[i].unicast_addr = 0xFFFF;
-    }
-
-    ble_mesh_node_sema = xSemaphoreCreateMutex();
-    if (!ble_mesh_node_sema) {
-        ESP_LOGE(TAG, "%s failed to init, failed to create mesh node semaphore", __func__);
+        ble_mesh_node_prestore_params[i].net_idx = ESP_BLE_MESH_KEY_UNUSED;
+        ble_mesh_node_prestore_params[i].unicast_addr = ESP_BLE_MESH_ADDR_UNASSIGNED;
     }
 }
 
 void ble_mesh_set_node_prestore_params(uint16_t netkey_index, uint16_t unicast_addr)
 {
     uint16_t i;
-    xSemaphoreTake(ble_mesh_node_sema, portMAX_DELAY);
     for (i = 0; i < NODE_MAX_GROUP_CONFIG; i++) {
-        if (ble_mesh_node_prestore_params[i].net_idx != 0xFFFF && ble_mesh_node_prestore_params[i].unicast_addr != 0xFFFF) {
+        if (ble_mesh_node_prestore_params[i].net_idx != ESP_BLE_MESH_KEY_UNUSED 
+                            && ble_mesh_node_prestore_params[i].unicast_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) {
             ble_mesh_node_prestore_params[i].net_idx = netkey_index;
             ble_mesh_node_prestore_params[i].unicast_addr = unicast_addr;
         }
     }
-    xSemaphoreGive(ble_mesh_node_sema);
 }
 
 void ble_mesh_create_send_data(char *data, uint16_t byte_num, uint16_t sequence_num, uint32_t opcode)
@@ -134,8 +128,6 @@ void ble_mesh_test_performance_client_model_get(void)
     uint32_t i, j;
     uint32_t sum_time = 0;
 
-    xSemaphoreTake(ble_mesh_test_perf_sema, portMAX_DELAY);
-
     for (i = 0, j = 0; i < test_perf_statistics.test_num; i++) {
         if (test_perf_statistics.time[i] != 0) {
             sum_time += test_perf_statistics.time[i];
@@ -151,8 +143,6 @@ void ble_mesh_test_performance_client_model_get(void)
 
     ESP_LOGI(TAG, "VendorModel:Statistics,%d,%d\n",
              test_perf_statistics.statistics, (sum_time / (j + 1)));
-
-    xSemaphoreGive(ble_mesh_test_perf_sema);
 }
 
 void ble_mesh_test_performance_client_model_get_received_percent(void)
@@ -167,8 +157,6 @@ void ble_mesh_test_performance_client_model_get_received_percent(void)
     } statistics_time_performance;
     statistics_time_performance *statistics_time_percent;
 
-    xSemaphoreTake(ble_mesh_test_perf_sema, portMAX_DELAY);
-
     time_level_num = ((max_time - min_time) / 50 + 1);
     statistics_time_percent = malloc(sizeof(statistics_time_performance) * time_level_num);
 
@@ -199,14 +187,11 @@ void ble_mesh_test_performance_client_model_get_received_percent(void)
     printf("\n");
 
     free(statistics_time_percent);
-    xSemaphoreGive(ble_mesh_test_perf_sema);
 }
 
 void ble_mesh_test_performance_client_model_accumulate_statistics(uint32_t value)
 {
-    xSemaphoreTake(ble_mesh_test_perf_sema, portMAX_DELAY);
     test_perf_statistics.statistics += value;
-    xSemaphoreGive(ble_mesh_test_perf_sema);
 }
 
 int ble_mesh_test_performance_client_model_accumulate_time(uint16_t time, uint8_t *data, uint8_t ack_ttl, uint16_t length)
@@ -214,11 +199,9 @@ int ble_mesh_test_performance_client_model_accumulate_time(uint16_t time, uint8_
     uint16_t i;
     uint16_t sequence_num = 0;
     uint16_t node_received_ttl = 0;
-    xSemaphoreTake(ble_mesh_test_perf_sema, portMAX_DELAY);
 
     // received fail
     if (length != test_perf_statistics.test_length) {
-        xSemaphoreGive(ble_mesh_test_perf_sema);
         return 1;
     }
 
@@ -231,7 +214,6 @@ int ble_mesh_test_performance_client_model_accumulate_time(uint16_t time, uint8_
 
     for (i = 0; i < test_perf_statistics.test_num; i++) {
         if (test_perf_statistics.package_index[i] == sequence_num) {
-            xSemaphoreGive(ble_mesh_test_perf_sema);
             return 1;
         }
     }
@@ -252,7 +234,6 @@ int ble_mesh_test_performance_client_model_accumulate_time(uint16_t time, uint8_
         }
     }
 
-    xSemaphoreGive(ble_mesh_test_perf_sema);
     return 0;
 }
 

+ 4 - 12
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.h

@@ -23,7 +23,10 @@
 
 #define TAG "ble_mesh_prov_console"
 
-uint64_t start_time;
+#define TRANS_TYPE_MESH_PERF 0x01
+#define TRANS_MESH_SEND_MESSAGE 0x01
+#define TRANS_MESH_SEND_MESSAGE_EVT 0x01
+
 typedef enum {
     VENDOR_MODEL_PERF_OPERATION_TYPE_GET = 1,
     VENDOR_MODEL_PERF_OPERATION_TYPE_SET,
@@ -62,40 +65,29 @@ ble_mesh_performance_statistics_t test_perf_statistics;
 
 #define SEND_MESSAGE_TIMEOUT (30000/portTICK_RATE_MS)
 
-extern SemaphoreHandle_t ble_mesh_node_sema;
-extern SemaphoreHandle_t ble_mesh_test_perf_send_sema;
-extern SemaphoreHandle_t ble_mesh_test_perf_sema;
-
 #define arg_int_to_value(src_msg, dst_msg, message) do { \
     if (src_msg->count != 0) {\
-        ESP_LOGD(TAG, " %s, %s\n", __func__, message);\
         dst_msg = src_msg->ival[0];\
     } \
 } while(0) \
 
 #define ble_mesh_node_get_value(index, key, value) do { \
     uint16_t _index = 0; \
-    xSemaphoreTake(ble_mesh_node_sema, portMAX_DELAY); \
     for (_index = 0; _index < NODE_MAX_GROUP_CONFIG; _index) { \
         if (node_set_prestore_params[_index].key == value) { \
             break; \
         } \
     } \
     index = _index; \
-    xSemaphoreGive(ble_mesh_node_sema); \
 } while(0) \
 
 #define ble_mesh_node_set_state(status) do { \
-    xSemaphoreTake(ble_mesh_node_sema, portMAX_DELAY); \
     node_status.previous = node_status.current; \
     node_status.current = status; \
-    xSemaphoreGive(ble_mesh_node_sema); \
 }while(0) \
 
 #define ble_mesh_node_get_state(status) do { \
-    xSemaphoreTake(ble_mesh_node_sema, portMAX_DELAY); \
     status = node_status.previous; \
-    xSemaphoreGive(ble_mesh_node_sema); \
 }while(0) \
 
 #define ble_mesh_callback_check_err_code(err_code, message) do { \

+ 7 - 7
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_cfg_srv_model.c

@@ -93,16 +93,16 @@ esp_ble_mesh_comp_t config_client_comp = {
 };
 
 // configure special module
-esp_ble_mesh_model_op_t gen_onoff_srv_model_op_config[] = {
-    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET,       0),
-    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET,       2),
-    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2),
-    ESP_BLE_MESH_MODEL_OP_END,
-};
+ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_0, 2 + 3, ROLE_NODE);
+static esp_ble_mesh_gen_onoff_srv_t onoff_server = {
+    .rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
+    .rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
+ };
+
 
 esp_ble_mesh_model_t gen_onoff_srv_models[] = {
     ESP_BLE_MESH_MODEL_CFG_SRV(&cfg_srv),
-    ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_model_op_config, &model_pub_config, NULL),
+    ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_0, &onoff_server),
 };
 
 esp_ble_mesh_elem_t gen_onoff_srv_elements[] = {

+ 3 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_main.c

@@ -129,6 +129,9 @@ esp_err_t bluetooth_init(void)
         return ret;
     }
 
+    esp_log_level_set("*", ESP_LOG_ERROR);
+    esp_log_level_set("ble_mesh_prov_console", ESP_LOG_INFO);
+
     return ret;
 }
 

+ 2 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_cfg_client_cmd.c

@@ -344,6 +344,8 @@ int ble_mesh_configuration_client_model_operation(int argc, char **argv)
                     err = esp_ble_mesh_config_client_set_state(&client_common, (esp_ble_mesh_cfg_client_set_state_t *)&relay_set);
                 } else if (strcmp(configuration_client_model_operation.set_state->sval[0], "pubset") == 0) {
                     err = esp_ble_mesh_config_client_set_state(&client_common, (esp_ble_mesh_cfg_client_set_state_t *)&mod_pub_set);
+                } else if (strcmp(configuration_client_model_operation.set_state->sval[0], "reset") == 0) {
+                    err = esp_ble_mesh_config_client_set_state(&client_common, NULL);
                 }
             }
         } else if (strcmp(configuration_client_model_operation.action_type->sval[0], "reg") == 0) {

+ 4 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_gen_onoff_client_cmd.c

@@ -30,7 +30,7 @@ typedef struct {
     struct arg_int *net_idx;
     struct arg_end *end;
 } ble_mesh_gen_onoff_state_t;
-ble_mesh_gen_onoff_state_t gen_onoff_state;
+static ble_mesh_gen_onoff_state_t gen_onoff_state;
 
 void ble_mesh_register_gen_onoff_client_command(void);
 void ble_mesh_generic_onoff_client_model_cb(esp_ble_mesh_generic_client_cb_event_t event,
@@ -124,6 +124,9 @@ int ble_mesh_generic_onoff_client_model(int argc, char **argv)
     }
 
     onoff_common.model = ble_mesh_get_model(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI);
+    if (onoff_common.model == NULL) {
+        ESP_LOGI(TAG, "GenONOFFClient:LoadModel,Fail");
+    }
 
     arg_int_to_value(gen_onoff_state.appkey_idx, onoff_common.ctx.app_idx, "appkey_index");
     arg_int_to_value(gen_onoff_state.opcode, onoff_common.opcode, "opcode");

+ 7 - 8
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_test_perf_client_cmd.c

@@ -20,9 +20,7 @@
 
 #include "esp_ble_mesh_networking_api.h"
 #include "ble_mesh_adapter.h"
-
-SemaphoreHandle_t ble_mesh_test_perf_send_sema;
-SemaphoreHandle_t ble_mesh_test_perf_sema;
+#include "transaction.h"
 
 typedef struct {
     struct arg_str *action_type;
@@ -58,7 +56,9 @@ void ble_mesh_test_performance_client_model_throughput(void *params)
 {
     uint16_t i;
     uint8_t *data = NULL;
+    uint64_t start_time;
     esp_ble_mesh_msg_ctx_t ctx;
+    transaction_t *trans = NULL;
     ble_mesh_test_perf_throughput_data *profile_context = (ble_mesh_test_perf_throughput_data *)params;
 
     ESP_LOGD(TAG, "enter %s\n", __func__);
@@ -77,16 +77,15 @@ void ble_mesh_test_performance_client_model_throughput(void *params)
         ESP_LOGE(TAG, " %s, %d, malloc fail\n", __func__, __LINE__);
     }
 
-    ble_mesh_test_perf_send_sema = xSemaphoreCreateMutex();
-    xSemaphoreTake(ble_mesh_test_perf_send_sema, SEND_MESSAGE_TIMEOUT);
-
+    TRANSACTION_INIT(&trans, TRANS_TYPE_MESH_PERF, TRANS_MESH_SEND_MESSAGE,
+                    TRANS_MESH_SEND_MESSAGE_EVT, SEND_MESSAGE_TIMEOUT, &start_time, NULL);
     for (i = 1; i <= profile_context->test_num; i++) {
         ble_mesh_create_send_data((char *)data, profile_context->length, i, profile_context->opcode);
         start_time = esp_timer_get_time();
         esp_ble_mesh_client_model_send_msg(profile_context->model, &ctx, profile_context->opcode,
                                            profile_context->length, data, 8000, profile_context->need_ack, profile_context->device_role);
         ble_mesh_test_performance_client_model_accumulate_statistics(profile_context->length);
-        xSemaphoreTake(ble_mesh_test_perf_send_sema, SEND_MESSAGE_TIMEOUT);
+        transaction_run(trans);
     }
 
     ESP_LOGI(TAG, "VendorModel:SendPackage,Finish");
@@ -111,7 +110,6 @@ int ble_mesh_test_performance_client_model(int argc, char **argv)
     model = ble_mesh_get_model(ESP_BLE_MESH_VND_MODEL_ID_TEST_PERF_CLI);
 
     if (strcmp(test_perf_client_model.action_type->sval[0], "init") == 0) {
-        ble_mesh_test_perf_sema = xSemaphoreCreateMutex();
         result = esp_ble_mesh_client_model_init(model);
         if (result == ESP_OK) {
             ESP_LOGI(TAG, "VendorClientModel:Init,OK");
@@ -158,6 +156,7 @@ int ble_mesh_test_performance_client_model_performance(int argc, char **argv)
     }
 
     if (strcmp(test_perf_client_model_statistics.action_type->sval[0], "init") == 0) {
+        init_transactions();
         result = ble_mesh_test_performance_client_model_init(test_perf_client_model_statistics.node_num->ival[0],
                  test_perf_client_model_statistics.test_size->ival[0], test_perf_client_model_statistics.ttl->ival[0]);
         if (result == 0) {

+ 31 - 16
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_node_cmd.c

@@ -23,6 +23,7 @@
 #include "esp_ble_mesh_config_model_api.h"
 
 #include "ble_mesh_adapter.h"
+#include "transaction.h"
 
 typedef struct {
     struct arg_str *static_val;
@@ -63,8 +64,6 @@ ble_mesh_node_status node_status = {
     .current = 0x0,
 };
 
-SemaphoreHandle_t ble_mesh_node_sema;
-
 void ble_mesh_register_node_cmd(void);
 // Register callback function
 void ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_param_t *param);
@@ -142,10 +141,10 @@ void ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_p
         break;
 #if (CONFIG_BLE_MESH_PROVISIONER)
     case ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT:
-        ESP_LOGI(TAG, "Provisioner recv unprovisioned device beacon:");
+        ESP_LOGD(TAG, "Provisioner recv unprovisioned device beacon:");
         ESP_LOG_BUFFER_HEX("Device UUID %s", param->provisioner_recv_unprov_adv_pkt.dev_uuid, 16);
         ESP_LOG_BUFFER_HEX("Address %s", param->provisioner_recv_unprov_adv_pkt.addr, 6);
-        ESP_LOGI(TAG, "Address type 0x%x, oob_info 0x%04x, adv_type 0x%x, bearer 0x%x",
+        ESP_LOGD(TAG, "Address type 0x%x, oob_info 0x%04x, adv_type 0x%x, bearer 0x%x",
             param->provisioner_recv_unprov_adv_pkt.addr_type, param->provisioner_recv_unprov_adv_pkt.oob_info,
             param->provisioner_recv_unprov_adv_pkt.adv_type, param->provisioner_recv_unprov_adv_pkt.bearer);
         break;
@@ -200,8 +199,17 @@ void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_c
 {
     esp_err_t result = ESP_OK;
     uint8_t status;
+    uint64_t *start_time = NULL;
+    transaction_t *trans = NULL;
 
     ESP_LOGD(TAG, "enter %s, event=%x\n", __func__, event);
+    do {
+        trans = transaction_get(TRANS_TYPE_MESH_PERF, TRANS_MESH_SEND_MESSAGE, trans);
+        if (trans) {
+            start_time = (uint64_t *)trans->input;
+            break;
+        }
+    }while(trans);
 
     switch (event) {
     case ESP_BLE_MESH_MODEL_OPERATION_EVT:
@@ -211,11 +219,17 @@ void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_c
                 ble_mesh_node_get_state(status);
                 result = esp_ble_mesh_server_model_send_msg(param->model_operation.model, param->model_operation.ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
                          sizeof(status), &status);
+                if (result != ESP_OK) {
+                    ESP_LOGE(TAG, "Node:SendMsg,Fal");
+                }
             } else if (param->model_operation.opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
                 ble_mesh_node_set_state(param->model_operation.msg[0]);
                 ESP_LOGI(TAG, "Node:SetAck,OK,%d,%d", param->model_operation.msg[0], param->model_operation.ctx->recv_ttl);
                 result = esp_ble_mesh_server_model_send_msg(param->model_operation.model, param->model_operation.ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
                          sizeof(status), param->model_operation.msg);
+                if (result != ESP_OK) {
+                    ESP_LOGE(TAG, "Node:SendMsg,Fal");
+                }
             } else if (param->model_operation.opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
                 ble_mesh_node_set_state(param->model_operation.msg[0]);
                 ESP_LOGI(TAG, "Node:SetUnAck,OK,%d,%d", param->model_operation.msg[0], param->model_operation.ctx->recv_ttl);
@@ -224,11 +238,12 @@ void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_c
             } else if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_SET) {
                 ESP_LOGI(TAG, "VendorModel:SetAck,OK,%d", param->model_operation.ctx->recv_ttl);
             } else if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_TEST_PERF_STATUS) {
-                uint64_t current_time = esp_timer_get_time();
-                result = ble_mesh_test_performance_client_model_accumulate_time(((uint32_t)(current_time - start_time) / 1000), param->model_operation.msg, param->model_operation.ctx->recv_ttl, param->model_operation.length);
                 ESP_LOGI(TAG, "VendorModel:Status,OK,%d", param->model_operation.ctx->recv_ttl);
-                if (ble_mesh_test_perf_send_sema != NULL && result == ESP_OK) {
-                    xSemaphoreGive(ble_mesh_test_perf_send_sema);
+                if (trans) {
+                    uint64_t current_time = esp_timer_get_time();
+                    result = ble_mesh_test_performance_client_model_accumulate_time(((uint32_t)(current_time - *start_time) / 1000), param->model_operation.msg,
+                        param->model_operation.ctx->recv_ttl, param->model_operation.length);
+                    transaction_set_events(trans, TRANS_MESH_SEND_MESSAGE_EVT);
                 }
             }
         }
@@ -245,10 +260,11 @@ void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_c
         break;
     case ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT:
         ESP_LOGI(TAG, "Node:PublishReceive,OK,0x%04X,%d,%d", param->client_recv_publish_msg.opcode, param->client_recv_publish_msg.length, param->client_recv_publish_msg.msg[1]);
-        uint64_t current_time = esp_timer_get_time();
-        result = ble_mesh_test_performance_client_model_accumulate_time(((uint32_t)(current_time - start_time) / 2000), param->client_recv_publish_msg.msg, param->client_recv_publish_msg.ctx->recv_ttl, param->client_recv_publish_msg.length);
-        if (ble_mesh_test_perf_send_sema != NULL && param->client_recv_publish_msg.msg[2] == VENDOR_MODEL_PERF_OPERATION_TYPE_SET_UNACK && result == ESP_OK) {
-            xSemaphoreGive(ble_mesh_test_perf_send_sema);
+        if (trans) {
+            uint64_t current_time = esp_timer_get_time();
+            result = ble_mesh_test_performance_client_model_accumulate_time(((uint32_t)(current_time - *start_time) / 2000), param->client_recv_publish_msg.msg,
+                param->client_recv_publish_msg.ctx->recv_ttl, param->client_recv_publish_msg.length);
+            transaction_set_events(trans, TRANS_MESH_SEND_MESSAGE_EVT);
         }
         break;
     case ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT:
@@ -256,8 +272,8 @@ void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_c
         break;
     case ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT:
         ESP_LOGI(TAG, "Node:TimeOut, 0x%04X", param->client_send_timeout.opcode);
-        if (ble_mesh_test_perf_send_sema != NULL) {
-            xSemaphoreGive(ble_mesh_test_perf_send_sema);
+        if (trans) {
+            transaction_set_events(trans, TRANS_MESH_SEND_MESSAGE_EVT);
         }
         break;
     case ESP_BLE_MESH_MODEL_EVT_MAX:
@@ -317,7 +333,7 @@ static int ble_mesh_load_oob(int argc, char **argv)
     //parsing prov
 #if CONFIG_BLE_MESH_NODE
     prov.uuid = dev_uuid;
-    memcpy(dev_uuid, esp_bt_dev_get_address(), 6);
+    memcpy(dev_uuid, esp_bt_dev_get_address(), BD_ADDR_LEN);
     if (oob.static_val->count != 0) {
         static_val = malloc(oob.static_val_len->ival[0] + 1);
         if (static_val == NULL) {
@@ -353,7 +369,6 @@ static int ble_mesh_load_oob(int argc, char **argv)
     return 0;
 }
 
-
 int ble_mesh_init(int argc, char **argv)
 {
     int err;

+ 14 - 47
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_provisioner_cmd.c

@@ -82,34 +82,11 @@ ble_mesh_provisioner_add_key_t provisioner_add_key;
 
 void ble_mesh_regist_provisioner_cmd(void);
 
-void ble_mesh_prov_adv_cb(const esp_ble_mesh_bd_addr_t addr, const esp_ble_mesh_addr_type_t addr_type, const uint8_t adv_type,
-                          const uint8_t *dev_uuid, uint16_t oob_info, esp_ble_mesh_prov_bearer_t bearer);
-
 void ble_mesh_register_mesh_provisioner(void)
 {
     ble_mesh_regist_provisioner_cmd();
 }
 
-void ble_mesh_prov_adv_cb(const esp_ble_mesh_bd_addr_t addr, const esp_ble_mesh_addr_type_t addr_type, const uint8_t adv_type,
-                          const uint8_t *dev_uuid, uint16_t oob_info, esp_ble_mesh_prov_bearer_t bearer)
-{
-    ESP_LOGD(TAG, "enter %s\n", __func__);
-    ESP_LOGI(TAG, "scan device address:");
-    esp_log_buffer_hex(TAG, addr, sizeof(esp_ble_mesh_bd_addr_t));
-    ESP_LOGI(TAG, "scan device uuid:");
-    esp_log_buffer_hex(TAG, dev_uuid, 16);
-    ESP_LOGD(TAG, "exit %s\n", __func__);
-}
-
-int ble_mesh_provisioner_register(int argc, char** argv)
-{
-    ESP_LOGD(TAG, "enter %s \n", __func__);
-    // esp_ble_mesh_register_unprov_adv_pkt_callback(ble_mesh_prov_adv_cb);
-    ESP_LOGI(TAG, "Provisioner:Reg,OK");
-    ESP_LOGD(TAG, "exit %s \n", __func__);
-    return 0;
-}
-
 int ble_mesh_provision_address(int argc, char **argv)
 {
     esp_err_t err = ESP_OK;
@@ -126,27 +103,17 @@ int ble_mesh_provision_address(int argc, char **argv)
         arg_print_errors(stderr, provisioner_addr.end, argv[0]);
         return 1;
     }
-    
+
+    memcpy(device_addr.uuid, preset_addr_uuid, BD_ADDR_LEN);
     if (provisioner_addr.device_addr->count != 0) {
-        if (provisioner_addr.device_uuid->count != 0) {
-            del_dev.flag = BIT(0) | BIT(1);
-            str_2_mac((uint8_t *)provisioner_addr.device_addr->sval[0], device_addr.uuid);
-            str_2_mac((uint8_t *)provisioner_addr.device_addr->sval[0], del_dev.uuid); 
-        } else {
-            del_dev.flag = BIT(0);
-            memcpy(device_addr.uuid, preset_addr_uuid, 16);
-            memcpy(del_dev.uuid, preset_addr_uuid, 16);
-        }
         str_2_mac((uint8_t *)provisioner_addr.device_addr->sval[0], device_addr.addr);
         str_2_mac((uint8_t *)provisioner_addr.device_addr->sval[0], del_dev.addr);
         arg_int_to_value(provisioner_addr.addr_type, device_addr.addr_type, "address type");
         arg_int_to_value(provisioner_addr.addr_type, del_dev.addr_type, "address type");
     } else if (provisioner_addr.device_uuid->count != 0) {
+        get_value_string((char *)provisioner_addr.device_uuid->sval[0], (char *)device_addr.uuid);
+        get_value_string((char *)provisioner_addr.device_uuid->sval[0], (char *)del_dev.uuid);
         del_dev.flag = BIT(1);
-        memcpy(device_addr.addr, preset_addr_uuid, 6);
-        memcpy(del_dev.addr, preset_addr_uuid, 6);
-        str_2_mac((uint8_t *)provisioner_addr.device_addr->sval[0], device_addr.uuid);
-        str_2_mac((uint8_t *)provisioner_addr.device_addr->sval[0], del_dev.uuid); 
     }
 
     if (strcmp(provisioner_addr.add_del->sval[0], "add") == 0) {
@@ -157,6 +124,12 @@ int ble_mesh_provision_address(int argc, char **argv)
         err = esp_ble_mesh_provisioner_delete_dev(&del_dev);
     }
 
+    if (err != ESP_OK) {
+        ESP_LOGI(TAG, "Provisioner:AddDelAddr,Fail,%d", err);
+    } else {
+        ESP_LOGI(TAG, "Provisioner:AddDelAddr,OK");
+    }
+
     ESP_LOGD(TAG, "exit %s \n", __func__);
     return err;
 }
@@ -249,6 +222,8 @@ int ble_mesh_provisioner_add_node(int argc, char **argv)
     result = bt_mesh_provisioner_store_node_info(&node_info);
     if (result == ESP_OK) {
         ESP_LOGI(TAG, "Provisioner:AddNodeInfo,OK\n");
+    } else {
+        ESP_LOGI(TAG, "Provisioner:AddNodeInfo,ERROR,%d\n", result);
     }
 
     ESP_LOGD(TAG, "exit %s\n", __func__);
@@ -282,7 +257,7 @@ int ble_mesh_provisioner_add_key(int argc, char **argv)
     }
 
     if (err != ESP_OK) {
-        ESP_LOGI(TAG, "Provisioner:KeyAction,Fail");
+        ESP_LOGI(TAG, "Provisioner:KeyAction,Fail,%d", err);
     } else {
         ESP_LOGI(TAG, "Provisioner:KeyAction,OK");
     }
@@ -314,7 +289,7 @@ int ble_mesh_provision_bind_local_model(int argc, char **argv)
     err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(element_addr, app_idx, model_id, company_id);
 
     if (err != ESP_OK) {
-        ESP_LOGE(TAG, "Provisioner:BindModel,Fail,%x\n", err);
+        ESP_LOGE(TAG, "Provisioner:BindModel,Fail,%d\n", err);
     } else {
         ESP_LOGI(TAG, "Provisioner:BindModel,OK\n");
     }
@@ -324,14 +299,6 @@ int ble_mesh_provision_bind_local_model(int argc, char **argv)
 
 void ble_mesh_regist_provisioner_cmd(void)
 {
-    const esp_console_cmd_t prov_register = {
-        .command = "bmpreg",
-        .help = "ble mesh provisioner: register callback",
-        .hint = NULL,
-        .func = &ble_mesh_provisioner_register,
-    };
-    ESP_ERROR_CHECK(esp_console_cmd_register(&prov_register));
-
     provisioner_addr.add_del = arg_str1("z", NULL, "<add/delete>", "action type");
     provisioner_addr.device_addr = arg_str0("d", NULL, "<address>", "device address");
     provisioner_addr.device_uuid = arg_str0("u", NULL, "<uuid>", "device uuid");

+ 266 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/transaction.c

@@ -0,0 +1,266 @@
+#include <stdio.h>
+
+#include "sdkconfig.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/event_groups.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+
+#include "esp_timer.h"
+#include "esp_log.h"
+#include "esp_err.h"
+
+#include "transaction.h"
+
+
+#define TAG    "TRANS"
+
+static transaction_t transactions[MAX_TRANSACTION_COUNT];
+static SemaphoreHandle_t trans_mutex;
+
+static uint32_t utils_get_system_ts(void)
+{
+    return esp_log_timestamp();
+}
+
+static void transaction_reset(transaction_t *trans)
+{
+    EventBits_t bits;
+
+    ESP_LOGV(TAG, "transaction reset: %x", (uint32_t) trans);
+    // set to inactive state and clear all bits of the transaction
+    xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+    trans->type = 0;
+    trans->sub_type = 0;
+    trans->current_bits = 0;
+    bits = xEventGroupGetBits(trans->event_group);
+    xEventGroupClearBits(trans->event_group, bits);
+    trans->state = TRANSACTION_INACTIVE;
+    trans->ret = ESP_OK;
+    xSemaphoreGiveRecursive(trans_mutex);
+}
+
+void transaction_deinit(transaction_t *trans)
+{
+    if (trans != NULL) {
+        transaction_reset(trans);
+    }
+}
+
+esp_err_t transaction_set_events(transaction_t *trans, EventBits_t events)
+{
+    esp_err_t ret = ESP_OK;
+    xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+    if (trans) {
+        if (trans->state == TRANSACTION_INACTIVE) {
+            ret = TRANS_RET_STATE_ERR;
+        } else {
+            // if the task (task A) setting current bits is with higher priority than the task (task B) run transaction,
+            // current_bits might not be updated until task A yield (not it's only update in run_transaction function).
+            // If task A set events and immediately use current_bits, current_bits is not correct.
+            // update current_bits here to make sure it's updated
+            trans->current_bits |= events;
+            xEventGroupSetBits(trans->event_group, events);
+        }
+        ESP_LOGD(TAG, "transactions set events: %x, %x, %x, %x; ret: %x", (uint32_t) trans, trans->type, trans->sub_type, events, ret);
+    } else {
+        ret = TRANS_RET_INVALID_TRNSACTION;
+    }
+    xSemaphoreGiveRecursive(trans_mutex);
+    return ret;
+}
+
+esp_err_t transaction_test_events(transaction_t *trans, EventBits_t events)
+{
+    esp_err_t ret = TRANS_RET_TEST_EVENT_FAILED;
+
+    xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+    if (trans) {
+        if (trans->state == TRANSACTION_INACTIVE) {
+            ret = TRANS_RET_STATE_ERR;
+        } else {
+            if ((trans->current_bits & events) == events) {
+                ret = ESP_OK;
+            }
+        }
+        ESP_LOGV(TAG, "transactions test events: %x, %x; ret: %x", (uint32_t) trans, events, ret);
+    } else {
+        ret = TRANS_RET_INVALID_TRNSACTION;
+    }
+    xSemaphoreGiveRecursive(trans_mutex);
+    return ret;
+}
+
+esp_err_t transaction_clear_events(transaction_t *trans, EventBits_t events)
+{
+    esp_err_t ret = ESP_OK;
+    xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+    if (trans) {
+        if (trans->state == TRANSACTION_INACTIVE) {
+            ret = TRANS_RET_STATE_ERR;
+        } else {
+            trans->current_bits &= ~events;
+            xEventGroupClearBits(trans->event_group, events);
+        }
+        ESP_LOGD(TAG, "transactions clear events: %x, %x, %x, %x; ret: %x", (uint32_t) trans, trans->type, trans->sub_type, events, ret);
+    } else {
+        ret = TRANS_RET_INVALID_TRNSACTION;
+    }
+    xSemaphoreGiveRecursive(trans_mutex);
+    return ret;
+}
+
+esp_err_t transaction_abort(transaction_t *trans, esp_err_t reason)
+{
+    esp_err_t ret = ESP_OK;
+    xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+    if (trans) {
+        if (trans->state == TRANSACTION_INACTIVE) {
+            ret = TRANS_RET_STATE_ERR;
+        } else {
+            trans->ret = reason;
+            xEventGroupSetBits(trans->event_group, TRANSACTION_ABORT_EVENT);
+        }
+        ESP_LOGD(TAG, "transactions abort: %x, %x, %x, %x; ret: %x", (uint32_t) trans, trans->type, trans->sub_type, reason, ret);
+    } else {
+        ret = TRANS_RET_INVALID_TRNSACTION;
+    }
+    xSemaphoreGiveRecursive(trans_mutex);
+    return ret;
+}
+
+esp_err_t transaction_init(transaction_t **trans, uint8_t type, uint32_t sub_type, EventBits_t wait_events, uint32_t timeout, void *input, void *output)
+{
+    esp_err_t ret = ESP_OK;
+    uint8_t i;
+
+    if ((wait_events & TRANSACTION_EVENT_MASK)
+            && wait_events != TRANSACTION_TIMEOUT_EVENT) {
+        ret = TRANS_RET_EVENTS_CONFLICT;
+        return ret;
+    }
+
+    xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+    for (i = 0; i < MAX_TRANSACTION_COUNT; i++) {
+        if ( transactions[i].state == TRANSACTION_INACTIVE ) {
+            transactions[i].state = TRANSACTION_ACTIVE;
+            *trans = &transactions[i];
+            break;
+        }
+    }
+
+    if ( i == MAX_TRANSACTION_COUNT ) {
+        ret = TRANS_RET_FAILED_TO_ALLOCATE;
+    } else {
+        // init transaction
+        transactions[i].type = type;
+        transactions[i].wait_events = wait_events;
+        transactions[i].sub_type = sub_type;
+        transactions[i].timeout = timeout;
+        transactions[i].ret = ESP_OK;
+        transactions[i].input = input;
+        transactions[i].output = output;
+    }
+    xSemaphoreGiveRecursive(trans_mutex);
+
+    if (ret == ESP_OK) {
+        ESP_LOGD(TAG, "transaction created: %x, %x, %x; ret: %x", type, sub_type, (uint32_t) *trans, ret);
+    }
+    return ret;
+}
+
+esp_err_t transaction_run(transaction_t *trans)
+{
+    esp_err_t ret = ESP_OK;
+    uint32_t start_time;
+    int32_t wait_time;
+    EventBits_t current_bits;
+
+    if (trans) {
+        start_time = utils_get_system_ts();
+
+        // wait for wait events
+        while (1) {
+            //TODO: we didn't handle ts overflow
+            wait_time = start_time + trans->timeout - utils_get_system_ts();
+
+            if ( wait_time < 0 ) {
+                ESP_LOGI(TAG, "transaction timeout: %x, %x, %x, %x, %x", (uint32_t) trans, trans->type, trans->sub_type, trans->wait_events, trans->current_bits);
+                ret = TRANS_RET_TIMEOUT;
+                break;
+            }
+
+            // trans->event_group and trans->wait_events will not be changed once trans is created, so we don't need protect them
+            current_bits = xEventGroupWaitBits(trans->event_group, trans->wait_events | TRANSACTION_ABORT_EVENT,
+                    1, 0, wait_time/portTICK_RATE_MS);
+
+            xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+            trans->current_bits |= current_bits;
+
+            if (trans->current_bits == trans->wait_events) {
+                // wait succeeded, we copy the trans->ret as ret of run transaction. This value could be changed by
+                ret = trans->ret;
+                xSemaphoreGiveRecursive(trans_mutex);
+                break;
+            } else if ( trans->current_bits & TRANSACTION_ABORT_EVENT ) {
+                if ( trans->ret ) {
+                    // copy user defined ret value if it's set
+                    ret = trans->ret;
+                } else {
+                    ret = TRANS_RET_ABORTED;
+                }
+                xSemaphoreGiveRecursive(trans_mutex);
+                break;
+            }
+            xSemaphoreGiveRecursive(trans_mutex);
+        }
+        ESP_LOGD(TAG, "transaction run: %x, %x, %x; ret: %x", (uint32_t) trans, trans->type, trans->sub_type, ret);
+        // reset after it's finished
+        transaction_reset(trans);
+    } else {
+        ESP_LOGD(TAG, "transaction run: %x; ret: %x", (uint32_t) trans, ret);
+        ret = TRANS_RET_INVALID_TRNSACTION;
+    }
+
+    return ret;
+}
+
+transaction_t *transaction_get(uint8_t type, uint32_t sub_type, transaction_t *start)
+{
+    uint8_t i, start_index;
+    transaction_t *trans = NULL;
+
+    if ( start == NULL ) {
+        start_index = 0;
+    } else {
+        start_index = (start - transactions) + 1;
+    }
+
+    xSemaphoreTakeRecursive(trans_mutex, portMAX_DELAY);
+    for (i = start_index; i < MAX_TRANSACTION_COUNT; i++) {
+        if ( transactions[i].state == TRANSACTION_ACTIVE ) {
+            if ( (transactions[i].type == type) && (transactions[i].sub_type & sub_type) ) {
+                trans = &transactions[i];
+                break;
+            }
+        }
+    }
+    xSemaphoreGiveRecursive(trans_mutex);
+
+    ESP_LOGV(TAG, "transaction get: %x, %x, %x, %x", type, sub_type, (uint32_t) start, (uint32_t) trans);
+    return trans;
+}
+
+void init_transactions(void)
+{
+    uint8_t i;
+
+    ESP_LOGI(TAG, "init transactions");
+
+    trans_mutex = xSemaphoreCreateRecursiveMutex();
+
+    for (i = 0; i < MAX_TRANSACTION_COUNT; i++) {
+        transactions[i].event_group = xEventGroupCreate();
+        transaction_reset(&transactions[i]);
+    }
+}

+ 88 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/transaction.h

@@ -0,0 +1,88 @@
+#ifndef __SSC_NIMBLE_TRANSACTION_H__
+#define __SSC_NIMBLE_TRANSACTION_H__
+
+/* In esp-idf, bluetooth and wifi stack APIs are async (using callbacks).
+ * transaction module provides a common method to let user transfer async APIs to sync transactions.
+ */
+
+#include "sdkconfig.h"
+#include "esp_err.h"
+#include "freertos/event_groups.h"
+
+#define MAX_TRANSACTION_COUNT           5
+
+#define TRANSACTION_TYPE_ALL            0xFF
+
+#define TRANSACTION_SUB_TYPE_ALL        0xFFFFFFFF
+
+// The higher 12 bits of event is reversed for event group or transaction module.
+// Application can only use lower 20 bits of the event.
+#define TRANSACTION_TIMEOUT_EVENT           0x00100000UL  // only wait for timeout
+#define TRANSACTION_ABORT_EVENT             0x00800000UL  // this event is reserved for internal use only
+#define TRANSACTION_EVENT_MASK              0xFFF00000UL
+
+
+enum {
+    TRANS_RET_ERROR_START = 0x10000,
+    TRANS_RET_FAILED_TO_ALLOCATE,
+    TRANS_RET_STATE_ERR,
+    TRANS_RET_TEST_EVENT_FAILED,
+    TRANS_RET_EVENTS_CONFLICT,    // events bit conflicts with TRANSACTION_ABORT_EVENT
+    TRANS_RET_INVALID_TRNSACTION,
+    TRANS_RET_TIMEOUT,
+    TRANS_RET_ABORTED
+};
+
+typedef enum {
+    TRANSACTION_INACTIVE,
+    TRANSACTION_ACTIVE,
+} transaction_state_t;
+
+typedef struct {
+    /* input data passed to callback */
+    void                *input;
+    /* output data from callback */
+    void                *output;
+    /* retrun value, can be set by callback or transaction module (like timeout, or other common errors)
+     * transaction_run will return this member by default. */
+    esp_err_t           ret;
+    // private member
+    transaction_state_t state;
+    uint8_t             type;
+    uint32_t            sub_type;
+    uint32_t            timeout;
+    EventBits_t         wait_events;
+    EventGroupHandle_t  event_group;
+    EventBits_t         current_bits;
+} transaction_t;
+
+
+void init_transactions(void);
+
+esp_err_t transaction_init(transaction_t **trans, uint8_t type, uint32_t sub_type, EventBits_t wait_events, uint32_t timeout, void *input, void *output);
+esp_err_t transaction_run(transaction_t *trans);
+
+transaction_t *transaction_get(uint8_t type, uint32_t sub_type, transaction_t *start);
+
+esp_err_t transaction_set_events(transaction_t *trans, EventBits_t events);
+esp_err_t transaction_test_events(transaction_t *trans, EventBits_t events);
+esp_err_t transaction_clear_events(transaction_t *trans, EventBits_t events);
+
+esp_err_t transaction_abort(transaction_t *trans, esp_err_t reason);
+
+#define TRANSACTION_INIT(trans, type, sub_type, wait_events, timeout, input, output) \
+    ESP_ERROR_CHECK(transaction_init(trans, type, sub_type, wait_events, timeout, input, output))
+
+
+#define transaction_get_first(type, sub_type) transaction_get(type, sub_type, NULL)
+
+
+/* We declare all transaction type / sub type below */
+#define TRANS_TYPE_BLE_GAP        0x01
+#define TRANS_TYPE_BLE_GATTC      0x02
+#define TRANS_TYPE_BLE_GATTS      0x03
+#define TRANS_TYPE_WIFI           0x04
+#define TRANS_TYPE_BT             0x05
+
+
+#endif /* __SSC_NIMBLE_TRANSACTION_H__ */

+ 7 - 3
examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/sdkconfig.defaults

@@ -15,7 +15,11 @@ CONFIG_BLE_MESH_PROVISIONER=y
 CONFIG_BLE_MESH_PB_GATT=y
 CONFIG_BLE_MESH_PBA_SAME_TIME=10
 CONFIG_BLE_MESH_PBG_SAME_TIME=3
-CONFIG_BLE_MESH_TX_SEG_MSG_COUNT=10
-CONFIG_BLE_MESH_RX_SEG_MSG_COUNT=10
+CONFIG_BLE_MESH_TX_SEG_MSG_COUNT=3
+CONFIG_BLE_MESH_RX_SEG_MSG_COUNT=3
 CONFIG_BLE_MESH_CFG_CLI=y
-CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y
+CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y
+CONFIG_BLE_MESH_MAX_STORED_NODES=40
+CONFIG_BLE_MESH_MSG_CACHE_SIZE=60
+CONFIG_BLE_MESH_ADV_BUF_COUNT=200
+