1. BLE Mesh Core * Provisioning: Node Role * PB-ADV and PB-GATT * Authentication OOB * Provisioning: Provisioner Role * PB-ADV and PB-GATT * Authentication OOB * Networking * Relay * Segmentation and Reassembly * Key Refresh * IV Update * Proxy Support * Multiple Client Models Run Simultaneously * Support multiple client models send packets to different nodes simultaneously * No blocking between client model and server * NVS Storage * Store BLE Mesh node related information in flash * Store BLE Mesh Provisioner related information in flash 2. BLE Mesh Models * Foundation Models * Configuration Server Model * Configuration Client Model * Health Server Model * Health Client Model * Generic * Generic OnOff Server * Generic OnOff Client * Generic Level Server * Generic Level Client * Generic Default Transition Time Server * Generic Default Transition Time Client * Generic Power OnOff Server * Generic Power OnOff Setup Server * Generic Power OnOff Client * Generic Power Level Server * Generic Power Level Setup Server * Generic Power Level Client * Generic Battery Server * Generic Battery Client * Generic Location Server * Generic Location Setup Server * Generic Location Client * Generic Admin Property Server * Generic Manufacturer Property Server * Generic User Property Server * Generic Client Property Server * Generic Property Client * Sensor Server Model * Sensor Server * Sensor Setup Server * Sensor Client * Time and Scenes * Time Server * Time Setup Server * Time Client * Scene Server * Scene Setup Server * Scene Client * Scheduler Server * Scheduler Setup Server * Scheduler Client * Lighting * Light Lightness Server * Light Lightness Setup Server * Light Lightness Client * Light CTL Server * Light CTL Setup Server * Light CTL Client * Light CTL Temperature Server * Light HSL Server * Light HSL Setup Server * Light HSL Client * Light HSL Hue Server * Light HSL Saturation Server * Light xyL Server * Light xyL Setup Server * Light xyL Client * Light LC Server * Light LC Setup Server * Light LC Client 3. BLE Mesh Applications * BLE Mesh Node * OnOff Client Example * OnOff Server Example * BLE Mesh Provisioner * Example * Fast Provisioning * Vendor Fast Prov Server Model * Vendor Fast Prov Client Model * Examples * Wi-Fi & BLE Mesh Coexistence * Example * BLE Mesh Console Commands * Examples
577 lines
No EOL
18 KiB
C
577 lines
No EOL
18 KiB
C
// 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 <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "esp_ble_mesh_networking_api.h"
|
|
#include "esp_ble_mesh_provisioning_api.h"
|
|
#include "esp_ble_mesh_config_model_api.h"
|
|
#include "esp_ble_mesh_generic_model_api.h"
|
|
#include "esp_ble_mesh_local_data_operation_api.h"
|
|
|
|
#include "esp_fast_prov_common.h"
|
|
#include "esp_fast_prov_operation.h"
|
|
#include "esp_fast_prov_client_model.h"
|
|
#include "esp_fast_prov_server_model.h"
|
|
|
|
#define TAG "FAST_PROV_OP"
|
|
|
|
/* Provisioned node information context */
|
|
static example_node_info_t nodes_info[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
|
|
[0 ... (CONFIG_BLE_MESH_MAX_PROV_NODES - 1)] = {
|
|
.reprov = false,
|
|
.unicast_addr = ESP_BLE_MESH_ADDR_UNASSIGNED,
|
|
.element_num = 0x0,
|
|
.net_idx = ESP_BLE_MESH_KEY_UNUSED,
|
|
.app_idx = ESP_BLE_MESH_KEY_UNUSED,
|
|
.onoff = LED_OFF,
|
|
.lack_of_addr = false,
|
|
.unicast_min = ESP_BLE_MESH_ADDR_UNASSIGNED,
|
|
.unicast_max = ESP_BLE_MESH_ADDR_UNASSIGNED,
|
|
.flags = 0x0,
|
|
.iv_index = 0x0,
|
|
.group_addr = ESP_BLE_MESH_ADDR_UNASSIGNED,
|
|
.prov_addr = ESP_BLE_MESH_ADDR_UNASSIGNED,
|
|
.match_len = 0,
|
|
.action = FAST_PROV_ACT_NONE,
|
|
}
|
|
};
|
|
|
|
esp_err_t example_store_node_info(const uint8_t uuid[16], uint16_t node_addr,
|
|
uint8_t elem_num, uint16_t net_idx,
|
|
uint16_t app_idx, uint8_t onoff)
|
|
{
|
|
example_node_info_t *node = NULL;
|
|
|
|
if (!uuid || !ESP_BLE_MESH_ADDR_IS_UNICAST(node_addr) || !elem_num) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(nodes_info); i++) {
|
|
node = &nodes_info[i];
|
|
if (!memcmp(node->uuid, uuid, 16)) {
|
|
ESP_LOGW(TAG, "%s: reprovisioned node", __func__);
|
|
node->reprov = true;
|
|
node->unicast_addr = node_addr;
|
|
node->element_num = elem_num;
|
|
node->net_idx = net_idx;
|
|
node->app_idx = app_idx;
|
|
node->onoff = onoff;
|
|
return ESP_OK;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(nodes_info); i++) {
|
|
node = &nodes_info[i];
|
|
if (node->unicast_addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
|
memcpy(node->uuid, uuid, 16);
|
|
node->reprov = false;
|
|
node->unicast_addr = node_addr;
|
|
node->element_num = elem_num;
|
|
node->net_idx = net_idx;
|
|
node->app_idx = app_idx;
|
|
node->onoff = onoff;
|
|
node->lack_of_addr = false;
|
|
return ESP_OK;
|
|
}
|
|
}
|
|
|
|
ESP_LOGE(TAG, "%s: nodes_info is full", __func__);
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
example_node_info_t *example_get_node_info(uint16_t node_addr)
|
|
{
|
|
example_node_info_t *node = NULL;
|
|
|
|
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(node_addr)) {
|
|
return NULL;
|
|
}
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(nodes_info); i++) {
|
|
node = &nodes_info[i];
|
|
if (node_addr >= node->unicast_addr &&
|
|
node_addr < node->unicast_addr + node->element_num) {
|
|
return node;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool example_is_node_exist(const uint8_t uuid[16])
|
|
{
|
|
example_node_info_t *node = NULL;
|
|
|
|
if (!uuid) {
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(nodes_info); i++) {
|
|
node = &nodes_info[i];
|
|
if (ESP_BLE_MESH_ADDR_IS_UNICAST(node->unicast_addr)) {
|
|
if (!memcmp(node->uuid, uuid, 16)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
uint16_t example_get_node_address(int node_idx)
|
|
{
|
|
return nodes_info[node_idx].unicast_addr;
|
|
}
|
|
|
|
esp_ble_mesh_model_t *example_find_model(uint16_t element_addr, uint16_t model_id,
|
|
uint16_t company_id)
|
|
{
|
|
esp_ble_mesh_elem_t *element = NULL;
|
|
|
|
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr)) {
|
|
return NULL;
|
|
}
|
|
|
|
element = esp_ble_mesh_find_element(element_addr);
|
|
if (!element) {
|
|
return NULL;
|
|
}
|
|
|
|
if (company_id == CID_NVAL) {
|
|
return esp_ble_mesh_find_sig_model(element, model_id);
|
|
} else {
|
|
return esp_ble_mesh_find_vendor_model(element, company_id, model_id);
|
|
}
|
|
}
|
|
|
|
static esp_err_t example_set_app_idx_to_user_data(uint16_t app_idx)
|
|
{
|
|
example_fast_prov_server_t *srv_data = NULL;
|
|
esp_ble_mesh_model_t *srv_model = NULL;
|
|
|
|
srv_model = example_find_model(esp_ble_mesh_get_primary_element_address(),
|
|
ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_SRV, CID_ESP);
|
|
if (!srv_model) {
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
srv_data = (example_fast_prov_server_t *)(srv_model->user_data);
|
|
if (!srv_data) {
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
srv_data->app_idx = app_idx;
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t example_handle_config_app_key_add_evt(uint16_t app_idx)
|
|
{
|
|
const esp_ble_mesh_comp_t *comp = NULL;
|
|
esp_ble_mesh_elem_t *element = NULL;
|
|
esp_ble_mesh_model_t *model = NULL;
|
|
int i, j, k;
|
|
|
|
comp = esp_ble_mesh_get_composition_data();
|
|
if (!comp) {
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
for (i = 0; i < comp->element_count; i++) {
|
|
element = &comp->elements[i];
|
|
/* Bind app_idx with SIG models except the Config Client & Server models */
|
|
for (j = 0; j < element->sig_model_count; j++) {
|
|
model = &element->sig_models[j];
|
|
if (model->model_id == ESP_BLE_MESH_MODEL_ID_CONFIG_SRV ||
|
|
model->model_id == ESP_BLE_MESH_MODEL_ID_CONFIG_CLI) {
|
|
continue;
|
|
}
|
|
for (k = 0; k < ARRAY_SIZE(model->keys); k++) {
|
|
if (model->keys[k] == app_idx) {
|
|
break;
|
|
}
|
|
}
|
|
if (k != ARRAY_SIZE(model->keys)) {
|
|
continue;
|
|
}
|
|
for (k = 0; k < ARRAY_SIZE(model->keys); k++) {
|
|
if (model->keys[k] == ESP_BLE_MESH_KEY_UNUSED) {
|
|
model->keys[k] = app_idx;
|
|
break;
|
|
}
|
|
}
|
|
if (k == ARRAY_SIZE(model->keys)) {
|
|
ESP_LOGE(TAG, "%s: SIG model (model_id 0x%04x) is full of AppKey",
|
|
__func__, model->model_id);
|
|
}
|
|
}
|
|
/* Bind app_idx with Vendor models */
|
|
for (j = 0; j < element->vnd_model_count; j++) {
|
|
model = &element->vnd_models[j];
|
|
for (k = 0; k < ARRAY_SIZE(model->keys); k++) {
|
|
if (model->keys[k] == app_idx) {
|
|
break;
|
|
}
|
|
}
|
|
if (k != ARRAY_SIZE(model->keys)) {
|
|
continue;
|
|
}
|
|
for (k = 0; k < ARRAY_SIZE(model->keys); k++) {
|
|
if (model->keys[k] == ESP_BLE_MESH_KEY_UNUSED) {
|
|
model->keys[k] = app_idx;
|
|
break;
|
|
}
|
|
}
|
|
if (k == ARRAY_SIZE(model->keys)) {
|
|
ESP_LOGE(TAG, "%s: Vendor model (model_id 0x%04x, cid: 0x%04x) is full of AppKey",
|
|
__func__, model->vnd.model_id, model->vnd.company_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
return example_set_app_idx_to_user_data(app_idx);
|
|
}
|
|
|
|
esp_err_t example_add_fast_prov_group_address(uint16_t model_id, uint16_t group_addr)
|
|
{
|
|
const esp_ble_mesh_comp_t *comp = NULL;
|
|
esp_ble_mesh_elem_t *element = NULL;
|
|
esp_ble_mesh_model_t *model = NULL;
|
|
int i, j;
|
|
|
|
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
comp = esp_ble_mesh_get_composition_data();
|
|
if (!comp) {
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
for (i = 0; i < comp->element_count; i++) {
|
|
element = &comp->elements[i];
|
|
model = esp_ble_mesh_find_sig_model(element, model_id);
|
|
if (!model) {
|
|
continue;
|
|
}
|
|
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
|
|
if (model->groups[j] == group_addr) {
|
|
break;
|
|
}
|
|
}
|
|
if (j != ARRAY_SIZE(model->groups)) {
|
|
ESP_LOGW(TAG, "%s: Group address already exists, element index: %d", __func__, i);
|
|
continue;
|
|
}
|
|
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
|
|
if (model->groups[j] == ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
|
model->groups[j] = group_addr;
|
|
break;
|
|
}
|
|
}
|
|
if (j == ARRAY_SIZE(model->groups)) {
|
|
ESP_LOGE(TAG, "%s: Model is full of group address, element index: %d", __func__, i);
|
|
}
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t example_delete_fast_prov_group_address(uint16_t model_id, uint16_t group_addr)
|
|
{
|
|
const esp_ble_mesh_comp_t *comp = NULL;
|
|
esp_ble_mesh_elem_t *element = NULL;
|
|
esp_ble_mesh_model_t *model = NULL;
|
|
int i, j;
|
|
|
|
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
comp = esp_ble_mesh_get_composition_data();
|
|
if (comp == NULL) {
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
for (i = 0; i < comp->element_count; i++) {
|
|
element = &comp->elements[i];
|
|
|
|
model = esp_ble_mesh_find_sig_model(element, model_id);
|
|
if (model == NULL) {
|
|
continue;
|
|
}
|
|
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
|
|
if (model->groups[j] == group_addr) {
|
|
model->groups[j] = ESP_BLE_MESH_ADDR_UNASSIGNED;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t example_send_config_appkey_add(esp_ble_mesh_model_t *model,
|
|
example_msg_common_info_t *info,
|
|
esp_ble_mesh_cfg_app_key_add_t *add_key)
|
|
{
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
esp_ble_mesh_cfg_client_set_state_t set = {0};
|
|
const uint8_t *key = NULL;
|
|
|
|
if (!model || !info) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
if (add_key) {
|
|
set.app_key_add.net_idx = add_key->net_idx;
|
|
set.app_key_add.app_idx = add_key->app_idx;
|
|
memcpy(set.app_key_add.app_key, add_key->app_key, 16);
|
|
} else {
|
|
#if defined(CONFIG_BLE_MESH_FAST_PROV)
|
|
key = esp_ble_mesh_get_fast_prov_app_key(info->net_idx, info->app_idx);
|
|
#endif
|
|
if (!key) {
|
|
return ESP_FAIL;
|
|
}
|
|
set.app_key_add.net_idx = info->net_idx;
|
|
set.app_key_add.app_idx = info->app_idx;
|
|
memcpy(set.app_key_add.app_key, key, 16);
|
|
}
|
|
|
|
common.opcode = ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD;
|
|
common.model = model;
|
|
common.ctx.net_idx = info->net_idx;
|
|
common.ctx.app_idx = 0x0000; /* not used for config messages */
|
|
common.ctx.addr = info->dst;
|
|
common.ctx.send_rel = false;
|
|
common.ctx.send_ttl = 0;
|
|
common.msg_timeout = info->timeout;
|
|
common.msg_role = info->role;
|
|
|
|
return esp_ble_mesh_config_client_set_state(&common, &set);
|
|
}
|
|
|
|
esp_err_t example_send_generic_onoff_get(esp_ble_mesh_model_t *model,
|
|
example_msg_common_info_t *info)
|
|
{
|
|
esp_ble_mesh_generic_client_get_state_t get = {0};
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
|
|
if (!model || !info) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
common.opcode = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET;
|
|
common.model = model;
|
|
common.ctx.net_idx = info->net_idx;
|
|
common.ctx.app_idx = info->app_idx;
|
|
common.ctx.addr = info->dst;
|
|
common.ctx.send_rel = false;
|
|
common.ctx.send_ttl = 0;
|
|
common.msg_timeout = info->timeout;
|
|
common.msg_role = info->role;
|
|
|
|
return esp_ble_mesh_generic_client_get_state(&common, &get);
|
|
}
|
|
|
|
esp_err_t example_send_generic_onoff_set(esp_ble_mesh_model_t *model,
|
|
example_msg_common_info_t *info,
|
|
uint8_t onoff, uint8_t tid, bool need_ack)
|
|
{
|
|
esp_ble_mesh_generic_client_set_state_t set = {0};
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
|
|
if (!model || !info) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
set.onoff_set.onoff = onoff;
|
|
set.onoff_set.tid = tid;
|
|
set.onoff_set.op_en = false;
|
|
|
|
if (need_ack) {
|
|
common.opcode = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET;
|
|
} else {
|
|
common.opcode = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK;
|
|
}
|
|
common.model = model;
|
|
common.ctx.net_idx = info->net_idx;
|
|
common.ctx.app_idx = info->app_idx;
|
|
common.ctx.addr = info->dst;
|
|
common.ctx.send_rel = false;
|
|
common.ctx.send_ttl = 0;
|
|
common.msg_timeout = info->timeout;
|
|
common.msg_role = info->role;
|
|
|
|
return esp_ble_mesh_generic_client_set_state(&common, &set);
|
|
}
|
|
|
|
esp_err_t example_send_fast_prov_info_set(esp_ble_mesh_model_t *model,
|
|
example_msg_common_info_t *info,
|
|
example_fast_prov_info_set_t *set)
|
|
{
|
|
struct net_buf_simple *msg = NULL;
|
|
esp_err_t err;
|
|
|
|
if (!model || !set || !set->ctx_flags || !info) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "min: 0x%04x, max: 0x%04x", set->unicast_min, set->unicast_max);
|
|
ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", set->flags, set->iv_index);
|
|
ESP_LOGI(TAG, "net_idx: 0x%04x, group_addr: 0x%04x", set->net_idx, set->group_addr);
|
|
ESP_LOGI(TAG, "action: 0x%02x", set->action);
|
|
ESP_LOG_BUFFER_HEX("FAST_PROV_OP: match_val", set->match_val, set->match_len);
|
|
|
|
msg = bt_mesh_alloc_buf(18 + set->match_len);
|
|
if (!msg) {
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
net_buf_simple_add_le16(msg, set->ctx_flags);
|
|
if (set->ctx_flags & BIT(0)) {
|
|
net_buf_simple_add_le16(msg, set->node_addr_cnt);
|
|
}
|
|
if (set->ctx_flags & BIT(1)) {
|
|
net_buf_simple_add_le16(msg, set->unicast_min);
|
|
}
|
|
if (set->ctx_flags & BIT(2)) {
|
|
net_buf_simple_add_le16(msg, set->unicast_max);
|
|
}
|
|
if (set->ctx_flags & BIT(3)) {
|
|
net_buf_simple_add_u8(msg, set->flags);
|
|
}
|
|
if (set->ctx_flags & BIT(4)) {
|
|
net_buf_simple_add_le32(msg, set->iv_index);
|
|
}
|
|
if (set->ctx_flags & BIT(5)) {
|
|
net_buf_simple_add_le16(msg, set->net_idx);
|
|
}
|
|
if (set->ctx_flags & BIT(6)) {
|
|
net_buf_simple_add_le16(msg, set->group_addr);
|
|
}
|
|
if (set->ctx_flags & BIT(7)) {
|
|
net_buf_simple_add_le16(msg, set->prov_addr);
|
|
}
|
|
if (set->ctx_flags & BIT(8)) {
|
|
net_buf_simple_add_mem(msg, set->match_val, set->match_len);
|
|
}
|
|
if (set->ctx_flags & BIT(9)) {
|
|
net_buf_simple_add_u8(msg, set->action);
|
|
}
|
|
|
|
esp_ble_mesh_msg_ctx_t ctx = {
|
|
.net_idx = info->net_idx,
|
|
.app_idx = info->app_idx,
|
|
.addr = info->dst,
|
|
.send_rel = false,
|
|
.send_ttl = 0,
|
|
};
|
|
err = esp_ble_mesh_client_model_send_msg(model, &ctx,
|
|
ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET,
|
|
msg->len, msg->data, info->timeout, true, info->role);
|
|
|
|
bt_mesh_free_buf(msg);
|
|
return err;
|
|
}
|
|
|
|
esp_err_t example_send_fast_prov_net_key_add(esp_ble_mesh_model_t *model,
|
|
example_msg_common_info_t *info,
|
|
uint8_t net_key[16])
|
|
{
|
|
if (!model || !info || !net_key) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
esp_ble_mesh_msg_ctx_t ctx = {
|
|
.net_idx = info->net_idx,
|
|
.app_idx = info->app_idx,
|
|
.addr = info->dst,
|
|
.send_rel = false,
|
|
.send_ttl = 0,
|
|
};
|
|
|
|
return esp_ble_mesh_client_model_send_msg(model, &ctx,
|
|
ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD,
|
|
16, net_key, info->timeout, true, info->role);
|
|
}
|
|
|
|
esp_err_t example_send_fast_prov_self_prov_node_addr(esp_ble_mesh_model_t *model,
|
|
example_msg_common_info_t *info,
|
|
struct net_buf_simple *node_addr)
|
|
{
|
|
if (!model || !info || !node_addr || (node_addr->len % 2)) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
ESP_LOG_BUFFER_HEX("Send node address", node_addr->data, node_addr->len);
|
|
|
|
esp_ble_mesh_msg_ctx_t ctx = {
|
|
.net_idx = info->net_idx,
|
|
.app_idx = info->app_idx,
|
|
.addr = info->dst,
|
|
.send_rel = false,
|
|
.send_ttl = 0,
|
|
};
|
|
|
|
return esp_ble_mesh_client_model_send_msg(model, &ctx,
|
|
ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR,
|
|
node_addr->len, node_addr->data, info->timeout, true, info->role);
|
|
}
|
|
|
|
esp_err_t example_send_fast_prov_all_node_addr_get(esp_ble_mesh_model_t *model,
|
|
example_msg_common_info_t *info)
|
|
{
|
|
if (!model || !info) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
esp_ble_mesh_msg_ctx_t ctx = {
|
|
.net_idx = info->net_idx,
|
|
.app_idx = info->app_idx,
|
|
.addr = info->dst,
|
|
.send_rel = false,
|
|
.send_ttl = 0,
|
|
};
|
|
|
|
return esp_ble_mesh_client_model_send_msg(model, &ctx,
|
|
ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET,
|
|
0, NULL, info->timeout, true, info->role);
|
|
}
|
|
|
|
esp_err_t example_send_fast_prov_status_msg(esp_ble_mesh_model_t *model,
|
|
esp_ble_mesh_msg_ctx_t *ctx,
|
|
uint32_t opcode, struct net_buf_simple *msg)
|
|
{
|
|
if (!model || !ctx) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS:
|
|
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS:
|
|
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK:
|
|
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS:
|
|
ctx->send_ttl = 0;
|
|
ctx->send_rel = false;
|
|
break;
|
|
default:
|
|
ESP_LOGW(TAG, "%s: Invalid fast prov status opcode 0x%04x", __func__, opcode);
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
return esp_ble_mesh_server_model_send_msg(model, ctx, opcode, msg ? msg->len : 0, msg ? msg->data : NULL);
|
|
} |