Move the TAG definition of each example to the corresponding source file (previously it is defined in the common example intialization header file), which can avoid the redefinition of TAG in some situations.
592 lines
23 KiB
C
592 lines
23 KiB
C
/* main.c - Application main entry point */
|
|
|
|
/*
|
|
* Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "esp_log.h"
|
|
#include "nvs_flash.h"
|
|
#include "esp_bt.h"
|
|
|
|
#include "esp_ble_mesh_defs.h"
|
|
#include "esp_ble_mesh_common_api.h"
|
|
#include "esp_ble_mesh_provisioning_api.h"
|
|
#include "esp_ble_mesh_networking_api.h"
|
|
#include "esp_ble_mesh_config_model_api.h"
|
|
|
|
#include "ble_mesh_example_init.h"
|
|
#include "ble_mesh_example_nvs.h"
|
|
#include "board.h"
|
|
|
|
#define TAG "EXAMPLE"
|
|
|
|
#define CID_ESP 0x02E5
|
|
|
|
#define PROV_OWN_ADDR 0x0001
|
|
|
|
#define MSG_SEND_TTL 3
|
|
#define MSG_SEND_REL false
|
|
#define MSG_TIMEOUT 0
|
|
#define MSG_ROLE ROLE_PROVISIONER
|
|
|
|
#define COMP_DATA_PAGE_0 0x00
|
|
|
|
#define APP_KEY_IDX 0x0000
|
|
#define APP_KEY_OCTET 0x12
|
|
|
|
#define COMP_DATA_1_OCTET(msg, offset) (msg[offset])
|
|
#define COMP_DATA_2_OCTET(msg, offset) (msg[offset + 1] << 8 | msg[offset])
|
|
|
|
#define ESP_BLE_MESH_VND_MODEL_ID_CLIENT 0x0000
|
|
#define ESP_BLE_MESH_VND_MODEL_ID_SERVER 0x0001
|
|
|
|
#define ESP_BLE_MESH_VND_MODEL_OP_SEND ESP_BLE_MESH_MODEL_OP_3(0x00, CID_ESP)
|
|
#define ESP_BLE_MESH_VND_MODEL_OP_STATUS ESP_BLE_MESH_MODEL_OP_3(0x01, CID_ESP)
|
|
|
|
static uint8_t dev_uuid[ESP_BLE_MESH_OCTET16_LEN];
|
|
|
|
static struct example_info_store {
|
|
uint16_t server_addr; /* Vendor server unicast address */
|
|
uint16_t vnd_tid; /* TID contained in the vendor message */
|
|
} store = {
|
|
.server_addr = ESP_BLE_MESH_ADDR_UNASSIGNED,
|
|
.vnd_tid = 0,
|
|
};
|
|
|
|
static nvs_handle NVS_HANDLE;
|
|
static const char * NVS_KEY = "vendor_client";
|
|
|
|
static struct esp_ble_mesh_key {
|
|
uint16_t net_idx;
|
|
uint16_t app_idx;
|
|
uint8_t app_key[ESP_BLE_MESH_OCTET16_LEN];
|
|
} prov_key;
|
|
|
|
static esp_ble_mesh_cfg_srv_t config_server = {
|
|
.beacon = ESP_BLE_MESH_BEACON_DISABLED,
|
|
#if defined(CONFIG_BLE_MESH_FRIEND)
|
|
.friend_state = ESP_BLE_MESH_FRIEND_ENABLED,
|
|
#else
|
|
.friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED,
|
|
#endif
|
|
.default_ttl = 7,
|
|
/* 3 transmissions with 20ms interval */
|
|
.net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20),
|
|
.relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20),
|
|
};
|
|
|
|
static esp_ble_mesh_client_t config_client;
|
|
|
|
static const esp_ble_mesh_client_op_pair_t vnd_op_pair[] = {
|
|
{ ESP_BLE_MESH_VND_MODEL_OP_SEND, ESP_BLE_MESH_VND_MODEL_OP_STATUS },
|
|
};
|
|
|
|
static esp_ble_mesh_client_t vendor_client = {
|
|
.op_pair_size = ARRAY_SIZE(vnd_op_pair),
|
|
.op_pair = vnd_op_pair,
|
|
};
|
|
|
|
static esp_ble_mesh_model_op_t vnd_op[] = {
|
|
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_STATUS, 2),
|
|
ESP_BLE_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
static esp_ble_mesh_model_t root_models[] = {
|
|
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
|
|
ESP_BLE_MESH_MODEL_CFG_CLI(&config_client),
|
|
};
|
|
|
|
static esp_ble_mesh_model_t vnd_models[] = {
|
|
ESP_BLE_MESH_VENDOR_MODEL(CID_ESP, ESP_BLE_MESH_VND_MODEL_ID_CLIENT,
|
|
vnd_op, NULL, &vendor_client),
|
|
};
|
|
|
|
static esp_ble_mesh_elem_t elements[] = {
|
|
ESP_BLE_MESH_ELEMENT(0, root_models, vnd_models),
|
|
};
|
|
|
|
static esp_ble_mesh_comp_t composition = {
|
|
.cid = CID_ESP,
|
|
.elements = elements,
|
|
.element_count = ARRAY_SIZE(elements),
|
|
};
|
|
|
|
static esp_ble_mesh_prov_t provision = {
|
|
.prov_uuid = dev_uuid,
|
|
.prov_unicast_addr = PROV_OWN_ADDR,
|
|
.prov_start_address = 0x0005,
|
|
};
|
|
|
|
static void mesh_example_info_store(void)
|
|
{
|
|
ble_mesh_nvs_store(NVS_HANDLE, NVS_KEY, &store, sizeof(store));
|
|
}
|
|
|
|
static void mesh_example_info_restore(void)
|
|
{
|
|
esp_err_t err = ESP_OK;
|
|
bool exist = false;
|
|
|
|
err = ble_mesh_nvs_restore(NVS_HANDLE, NVS_KEY, &store, sizeof(store), &exist);
|
|
if (err != ESP_OK) {
|
|
return;
|
|
}
|
|
|
|
if (exist) {
|
|
ESP_LOGI(TAG, "Restore, server_addr 0x%04x, vnd_tid 0x%04x", store.server_addr, store.vnd_tid);
|
|
}
|
|
}
|
|
|
|
static void example_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common,
|
|
esp_ble_mesh_node_t *node,
|
|
esp_ble_mesh_model_t *model, uint32_t opcode)
|
|
{
|
|
common->opcode = opcode;
|
|
common->model = model;
|
|
common->ctx.net_idx = prov_key.net_idx;
|
|
common->ctx.app_idx = prov_key.app_idx;
|
|
common->ctx.addr = node->unicast_addr;
|
|
common->ctx.send_ttl = MSG_SEND_TTL;
|
|
common->ctx.send_rel = MSG_SEND_REL;
|
|
common->msg_timeout = MSG_TIMEOUT;
|
|
common->msg_role = MSG_ROLE;
|
|
}
|
|
|
|
static esp_err_t prov_complete(uint16_t node_index, const esp_ble_mesh_octet16_t uuid,
|
|
uint16_t primary_addr, uint8_t element_num, uint16_t net_idx)
|
|
{
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
esp_ble_mesh_cfg_client_get_state_t get = {0};
|
|
esp_ble_mesh_node_t *node = NULL;
|
|
char name[10] = {'\0'};
|
|
esp_err_t err;
|
|
|
|
ESP_LOGI(TAG, "node_index %u, primary_addr 0x%04x, element_num %u, net_idx 0x%03x",
|
|
node_index, primary_addr, element_num, net_idx);
|
|
ESP_LOG_BUFFER_HEX("uuid", uuid, ESP_BLE_MESH_OCTET16_LEN);
|
|
|
|
store.server_addr = primary_addr;
|
|
mesh_example_info_store(); /* Store proper mesh example info */
|
|
|
|
sprintf(name, "%s%02x", "NODE-", node_index);
|
|
err = esp_ble_mesh_provisioner_set_node_name(node_index, name);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to set node name");
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
node = esp_ble_mesh_provisioner_get_node_with_addr(primary_addr);
|
|
if (node == NULL) {
|
|
ESP_LOGE(TAG, "Failed to get node 0x%04x info", primary_addr);
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
|
|
get.comp_data_get.page = COMP_DATA_PAGE_0;
|
|
err = esp_ble_mesh_config_client_get_state(&common, &get);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to send Config Composition Data Get");
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
static void recv_unprov_adv_pkt(uint8_t dev_uuid[ESP_BLE_MESH_OCTET16_LEN], uint8_t addr[BD_ADDR_LEN],
|
|
esp_ble_mesh_addr_type_t addr_type, uint16_t oob_info,
|
|
uint8_t adv_type, esp_ble_mesh_prov_bearer_t bearer)
|
|
{
|
|
esp_ble_mesh_unprov_dev_add_t add_dev = {0};
|
|
esp_err_t err;
|
|
|
|
/* Due to the API esp_ble_mesh_provisioner_set_dev_uuid_match, Provisioner will only
|
|
* use this callback to report the devices, whose device UUID starts with 0xdd & 0xdd,
|
|
* to the application layer.
|
|
*/
|
|
|
|
ESP_LOG_BUFFER_HEX("Device address", addr, BD_ADDR_LEN);
|
|
ESP_LOGI(TAG, "Address type 0x%02x, adv type 0x%02x", addr_type, adv_type);
|
|
ESP_LOG_BUFFER_HEX("Device UUID", dev_uuid, ESP_BLE_MESH_OCTET16_LEN);
|
|
ESP_LOGI(TAG, "oob info 0x%04x, bearer %s", oob_info, (bearer & ESP_BLE_MESH_PROV_ADV) ? "PB-ADV" : "PB-GATT");
|
|
|
|
memcpy(add_dev.addr, addr, BD_ADDR_LEN);
|
|
add_dev.addr_type = (uint8_t)addr_type;
|
|
memcpy(add_dev.uuid, dev_uuid, ESP_BLE_MESH_OCTET16_LEN);
|
|
add_dev.oob_info = oob_info;
|
|
add_dev.bearer = (uint8_t)bearer;
|
|
/* Note: If unprovisioned device adv packets have not been received, we should not add
|
|
device with ADD_DEV_START_PROV_NOW_FLAG set. */
|
|
err = esp_ble_mesh_provisioner_add_unprov_dev(&add_dev,
|
|
ADD_DEV_RM_AFTER_PROV_FLAG | ADD_DEV_START_PROV_NOW_FLAG | ADD_DEV_FLUSHABLE_DEV_FLAG);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to start provisioning device");
|
|
}
|
|
}
|
|
|
|
static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
|
|
esp_ble_mesh_prov_cb_param_t *param)
|
|
{
|
|
switch (event) {
|
|
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code);
|
|
mesh_example_info_restore(); /* Restore proper mesh example info */
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT, err_code %d", param->provisioner_prov_enable_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT, err_code %d", param->provisioner_prov_disable_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT");
|
|
recv_unprov_adv_pkt(param->provisioner_recv_unprov_adv_pkt.dev_uuid, param->provisioner_recv_unprov_adv_pkt.addr,
|
|
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;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_LINK_OPEN_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_LINK_OPEN_EVT, bearer %s",
|
|
param->provisioner_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT, bearer %s, reason 0x%02x",
|
|
param->provisioner_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT", param->provisioner_prov_link_close.reason);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT:
|
|
prov_complete(param->provisioner_prov_complete.node_idx, param->provisioner_prov_complete.device_uuid,
|
|
param->provisioner_prov_complete.unicast_addr, param->provisioner_prov_complete.element_num,
|
|
param->provisioner_prov_complete.netkey_idx);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT, err_code %d", param->provisioner_add_unprov_dev_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT, err_code %d", param->provisioner_set_dev_uuid_match_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT, err_code %d", param->provisioner_set_node_name_comp.err_code);
|
|
if (param->provisioner_set_node_name_comp.err_code == 0) {
|
|
const char *name = esp_ble_mesh_provisioner_get_node_name(param->provisioner_set_node_name_comp.node_index);
|
|
if (name) {
|
|
ESP_LOGI(TAG, "Node %d name %s", param->provisioner_set_node_name_comp.node_index, name);
|
|
}
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT, err_code %d", param->provisioner_add_app_key_comp.err_code);
|
|
if (param->provisioner_add_app_key_comp.err_code == 0) {
|
|
prov_key.app_idx = param->provisioner_add_app_key_comp.app_idx;
|
|
esp_err_t err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(PROV_OWN_ADDR, prov_key.app_idx,
|
|
ESP_BLE_MESH_VND_MODEL_ID_CLIENT, CID_ESP);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to bind AppKey to vendor client");
|
|
}
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT, err_code %d", param->provisioner_bind_app_key_to_model_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_STORE_NODE_COMP_DATA_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_STORE_NODE_COMP_DATA_COMP_EVT, err_code %d", param->provisioner_store_node_comp_data_comp.err_code);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void example_ble_mesh_parse_node_comp_data(const uint8_t *data, uint16_t length)
|
|
{
|
|
uint16_t cid, pid, vid, crpl, feat;
|
|
uint16_t loc, model_id, company_id;
|
|
uint8_t nums, numv;
|
|
uint16_t offset;
|
|
int i;
|
|
|
|
cid = COMP_DATA_2_OCTET(data, 0);
|
|
pid = COMP_DATA_2_OCTET(data, 2);
|
|
vid = COMP_DATA_2_OCTET(data, 4);
|
|
crpl = COMP_DATA_2_OCTET(data, 6);
|
|
feat = COMP_DATA_2_OCTET(data, 8);
|
|
offset = 10;
|
|
|
|
ESP_LOGI(TAG, "********************** Composition Data Start **********************");
|
|
ESP_LOGI(TAG, "* CID 0x%04x, PID 0x%04x, VID 0x%04x, CRPL 0x%04x, Features 0x%04x *", cid, pid, vid, crpl, feat);
|
|
for (; offset < length; ) {
|
|
loc = COMP_DATA_2_OCTET(data, offset);
|
|
nums = COMP_DATA_1_OCTET(data, offset + 2);
|
|
numv = COMP_DATA_1_OCTET(data, offset + 3);
|
|
offset += 4;
|
|
ESP_LOGI(TAG, "* Loc 0x%04x, NumS 0x%02x, NumV 0x%02x *", loc, nums, numv);
|
|
for (i = 0; i < nums; i++) {
|
|
model_id = COMP_DATA_2_OCTET(data, offset);
|
|
ESP_LOGI(TAG, "* SIG Model ID 0x%04x *", model_id);
|
|
offset += 2;
|
|
}
|
|
for (i = 0; i < numv; i++) {
|
|
company_id = COMP_DATA_2_OCTET(data, offset);
|
|
model_id = COMP_DATA_2_OCTET(data, offset + 2);
|
|
ESP_LOGI(TAG, "* Vendor Model ID 0x%04x, Company ID 0x%04x *", model_id, company_id);
|
|
offset += 4;
|
|
}
|
|
}
|
|
ESP_LOGI(TAG, "*********************** Composition Data End ***********************");
|
|
}
|
|
|
|
static void example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t event,
|
|
esp_ble_mesh_cfg_client_cb_param_t *param)
|
|
{
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
esp_ble_mesh_cfg_client_set_state_t set = {0};
|
|
esp_ble_mesh_node_t *node = NULL;
|
|
esp_err_t err;
|
|
|
|
ESP_LOGI(TAG, "Config client, err_code %d, event %u, addr 0x%04x, opcode 0x%04x",
|
|
param->error_code, event, param->params->ctx.addr, param->params->opcode);
|
|
|
|
if (param->error_code) {
|
|
ESP_LOGE(TAG, "Send config client message failed, opcode 0x%04x", param->params->opcode);
|
|
return;
|
|
}
|
|
|
|
node = esp_ble_mesh_provisioner_get_node_with_addr(param->params->ctx.addr);
|
|
if (!node) {
|
|
ESP_LOGE(TAG, "Failed to get node 0x%04x info", param->params->ctx.addr);
|
|
return;
|
|
}
|
|
|
|
switch (event) {
|
|
case ESP_BLE_MESH_CFG_CLIENT_GET_STATE_EVT:
|
|
if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET) {
|
|
ESP_LOG_BUFFER_HEX("Composition data", param->status_cb.comp_data_status.composition_data->data,
|
|
param->status_cb.comp_data_status.composition_data->len);
|
|
example_ble_mesh_parse_node_comp_data(param->status_cb.comp_data_status.composition_data->data,
|
|
param->status_cb.comp_data_status.composition_data->len);
|
|
err = esp_ble_mesh_provisioner_store_node_comp_data(param->params->ctx.addr,
|
|
param->status_cb.comp_data_status.composition_data->data,
|
|
param->status_cb.comp_data_status.composition_data->len);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to store node composition data");
|
|
break;
|
|
}
|
|
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
|
set.app_key_add.net_idx = prov_key.net_idx;
|
|
set.app_key_add.app_idx = prov_key.app_idx;
|
|
memcpy(set.app_key_add.app_key, prov_key.app_key, ESP_BLE_MESH_OCTET16_LEN);
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to send Config AppKey Add");
|
|
}
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_CFG_CLIENT_SET_STATE_EVT:
|
|
if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD) {
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
|
set.model_app_bind.element_addr = node->unicast_addr;
|
|
set.model_app_bind.model_app_idx = prov_key.app_idx;
|
|
set.model_app_bind.model_id = ESP_BLE_MESH_VND_MODEL_ID_SERVER;
|
|
set.model_app_bind.company_id = CID_ESP;
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to send Config Model App Bind");
|
|
}
|
|
} else if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND) {
|
|
ESP_LOGW(TAG, "%s, Provision and config successfully", __func__);
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_CFG_CLIENT_PUBLISH_EVT:
|
|
if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_STATUS) {
|
|
ESP_LOG_BUFFER_HEX("Composition data", param->status_cb.comp_data_status.composition_data->data,
|
|
param->status_cb.comp_data_status.composition_data->len);
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_CFG_CLIENT_TIMEOUT_EVT:
|
|
switch (param->params->opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
|
|
esp_ble_mesh_cfg_client_get_state_t get = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
|
|
get.comp_data_get.page = COMP_DATA_PAGE_0;
|
|
err = esp_ble_mesh_config_client_get_state(&common, &get);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to send Config Composition Data Get");
|
|
}
|
|
break;
|
|
}
|
|
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD:
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
|
set.app_key_add.net_idx = prov_key.net_idx;
|
|
set.app_key_add.app_idx = prov_key.app_idx;
|
|
memcpy(set.app_key_add.app_key, prov_key.app_key, ESP_BLE_MESH_OCTET16_LEN);
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to send Config AppKey Add");
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND:
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
|
set.model_app_bind.element_addr = node->unicast_addr;
|
|
set.model_app_bind.model_app_idx = prov_key.app_idx;
|
|
set.model_app_bind.model_id = ESP_BLE_MESH_VND_MODEL_ID_SERVER;
|
|
set.model_app_bind.company_id = CID_ESP;
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to send Config Model App Bind");
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
ESP_LOGE(TAG, "Invalid config client event %u", event);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void example_ble_mesh_send_vendor_message(bool resend)
|
|
{
|
|
esp_ble_mesh_msg_ctx_t ctx = {0};
|
|
uint32_t opcode;
|
|
esp_err_t err;
|
|
|
|
ctx.net_idx = prov_key.net_idx;
|
|
ctx.app_idx = prov_key.app_idx;
|
|
ctx.addr = store.server_addr;
|
|
ctx.send_ttl = MSG_SEND_TTL;
|
|
ctx.send_rel = MSG_SEND_REL;
|
|
opcode = ESP_BLE_MESH_VND_MODEL_OP_SEND;
|
|
|
|
if (resend == false) {
|
|
store.vnd_tid++;
|
|
}
|
|
|
|
err = esp_ble_mesh_client_model_send_msg(vendor_client.model, &ctx, opcode,
|
|
sizeof(store.vnd_tid), (uint8_t *)&store.vnd_tid, MSG_TIMEOUT, true, MSG_ROLE);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to send vendor message 0x%06x", opcode);
|
|
return;
|
|
}
|
|
|
|
mesh_example_info_store(); /* Store proper mesh example info */
|
|
}
|
|
|
|
static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event,
|
|
esp_ble_mesh_model_cb_param_t *param)
|
|
{
|
|
static int64_t start_time;
|
|
|
|
switch (event) {
|
|
case ESP_BLE_MESH_MODEL_OPERATION_EVT:
|
|
if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_STATUS) {
|
|
int64_t end_time = esp_timer_get_time();
|
|
ESP_LOGI(TAG, "Recv 0x%06x, tid 0x%04x, time %lldus",
|
|
param->model_operation.opcode, store.vnd_tid, end_time - start_time);
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_MODEL_SEND_COMP_EVT:
|
|
if (param->model_send_comp.err_code) {
|
|
ESP_LOGE(TAG, "Failed to send message 0x%06x", param->model_send_comp.opcode);
|
|
break;
|
|
}
|
|
start_time = esp_timer_get_time();
|
|
ESP_LOGI(TAG, "Send 0x%06x", param->model_send_comp.opcode);
|
|
break;
|
|
case ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT:
|
|
ESP_LOGI(TAG, "Receive publish message 0x%06x", param->client_recv_publish_msg.opcode);
|
|
break;
|
|
case ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT:
|
|
ESP_LOGW(TAG, "Client message 0x%06x timeout", param->client_send_timeout.opcode);
|
|
example_ble_mesh_send_vendor_message(true);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static esp_err_t ble_mesh_init(void)
|
|
{
|
|
uint8_t match[2] = { 0x32, 0x10 };
|
|
esp_err_t err;
|
|
|
|
prov_key.net_idx = ESP_BLE_MESH_KEY_PRIMARY;
|
|
prov_key.app_idx = APP_KEY_IDX;
|
|
memset(prov_key.app_key, APP_KEY_OCTET, sizeof(prov_key.app_key));
|
|
|
|
esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);
|
|
esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb);
|
|
esp_ble_mesh_register_custom_model_callback(example_ble_mesh_custom_model_cb);
|
|
|
|
err = esp_ble_mesh_init(&provision, &composition);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to initialize mesh stack");
|
|
return err;
|
|
}
|
|
|
|
err = esp_ble_mesh_client_model_init(&vnd_models[0]);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "Failed to initialize vendor client");
|
|
return err;
|
|
}
|
|
|
|
err = esp_ble_mesh_provisioner_set_dev_uuid_match(match, sizeof(match), 0x0, false);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to set matching device uuid");
|
|
return err;
|
|
}
|
|
|
|
err = esp_ble_mesh_provisioner_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to enable mesh provisioner");
|
|
return err;
|
|
}
|
|
|
|
err = esp_ble_mesh_provisioner_add_local_app_key(prov_key.app_key, prov_key.net_idx, prov_key.app_idx);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to add local AppKey");
|
|
return err;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "ESP BLE Mesh Provisioner initialized");
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_err_t err;
|
|
|
|
ESP_LOGI(TAG, "Initializing...");
|
|
|
|
err = nvs_flash_init();
|
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
|
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
err = nvs_flash_init();
|
|
}
|
|
ESP_ERROR_CHECK(err);
|
|
|
|
board_init();
|
|
|
|
err = bluetooth_init();
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err);
|
|
return;
|
|
}
|
|
|
|
/* Open nvs namespace for storing/restoring mesh example info */
|
|
err = ble_mesh_nvs_open(&NVS_HANDLE);
|
|
if (err) {
|
|
return;
|
|
}
|
|
|
|
ble_mesh_get_dev_uuid(dev_uuid);
|
|
|
|
/* Initialize the Bluetooth Mesh Subsystem */
|
|
err = ble_mesh_init();
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Bluetooth mesh init failed (err %d)", err);
|
|
}
|
|
}
|