ble mesh: update ble mesh console example

This commit is contained in:
Chen Sheng 2020-03-22 18:34:39 +08:00 committed by He Yin Ling
parent 6330b3345e
commit f3986bca71
23 changed files with 764 additions and 162 deletions

View file

@ -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 ".")

View file

@ -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:

View file

@ -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),
};

View file

@ -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);

View file

@ -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;
}

View file

@ -74,6 +74,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;
}
@ -90,6 +92,8 @@ void app_main(void)
}
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
const char* prompt = LOG_COLOR_I "esp32> " LOG_RESET_COLOR;
repl_config.prompt = prompt;
#if CONFIG_STORE_HISTORY
initialize_filesystem();
repl_config.his_save_path = HISTORY_PATH;
@ -101,6 +105,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
// start console REPL
ESP_ERROR_CHECK(esp_console_repl_start());

View file

@ -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

View file

@ -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);

View file

@ -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 = {

View file

@ -14,10 +14,7 @@ CONFIG_BT_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_ESP_CONSOLE_UART_BAUDRATE=921600
CONFIG_ESPTOOLPY_BAUD_921600B=y
CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B=y
CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y

View file

@ -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"

View file

@ -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;
}

View file

@ -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 { \

View file

@ -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[] = {

View file

@ -77,6 +77,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;
}
@ -93,6 +96,8 @@ void app_main(void)
}
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
const char* prompt = LOG_COLOR_I "esp32> " LOG_RESET_COLOR;
repl_config.prompt = prompt;
#if CONFIG_STORE_HISTORY
initialize_filesystem();
repl_config.his_save_path = HISTORY_PATH;

View file

@ -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) {

View file

@ -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");

View file

@ -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) {

View file

@ -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;

View file

@ -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");

View file

@ -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]);
}
}

View file

@ -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__ */

View file

@ -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