mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-25 09:42:35 +00:00
ble_mesh: Rename common_vendor_models to common_components
Since the scripts of CI will bypass common_components when trying to get ALL_EXAMPLES, and these BLE Mesh components will only be used by other mesh examples, i.e. no need to be compiled as a single example, so we rename the folder to common_componnets.
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
set(srcs "esp_fast_prov_client_model.c"
|
||||
"esp_fast_prov_server_model.c"
|
||||
"esp_fast_prov_operation.c")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES bt)
|
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
#
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
@@ -0,0 +1,407 @@
|
||||
// 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_defs.h"
|
||||
#include "esp_ble_mesh_local_data_operation_api.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_CLIENT"
|
||||
|
||||
/* Note: these variables are used by ble_mesh_fast_prov_client demo */
|
||||
|
||||
#define GET_ALL_NODE_ADDR_TIMEOUT K_SECONDS(60)
|
||||
|
||||
/* Timer used to send Fast Prov All Node Addr Get message */
|
||||
#if !defined(CONFIG_BLE_MESH_FAST_PROV)
|
||||
static struct k_delayed_work get_all_node_addr_timer;
|
||||
#endif
|
||||
|
||||
/* Unicast address of the Primary Provisioner */
|
||||
static uint16_t prim_prov_addr;
|
||||
|
||||
/* Note: these variables are used by ble_mesh_fast_prov_server demo */
|
||||
|
||||
/* Send 4 node addresses (8 octets) most each time to prevent segmentation */
|
||||
#define NODE_ADDR_SEND_MAX_LEN 8
|
||||
|
||||
/* Timer used to send self-provisioned node addresses to Primary Provisioner */
|
||||
struct k_delayed_work send_self_prov_node_addr_timer;
|
||||
bt_mesh_atomic_t fast_prov_cli_flags;
|
||||
|
||||
/* Self-provisioned node addresses that are being sent */
|
||||
typedef struct {
|
||||
struct net_buf_simple *addr; /* Unicast addresses of self-provisioned nodes being sent */
|
||||
bool send_succeed; /* Indicate if sent operation is successful */
|
||||
bool ack_received; /* Indicate if sent address has been acked */
|
||||
} example_send_prov_node_addr_t;
|
||||
|
||||
NET_BUF_SIMPLE_DEFINE_STATIC(send_addr, NODE_ADDR_SEND_MAX_LEN);
|
||||
static example_send_prov_node_addr_t node_addr_send = {
|
||||
.addr = &send_addr,
|
||||
.send_succeed = true,
|
||||
.ack_received = true,
|
||||
};
|
||||
|
||||
/* Self-provisioned node addresses that have been sent successfully */
|
||||
uint16_t addr_already_sent[CONFIG_BLE_MESH_MAX_PROV_NODES];
|
||||
|
||||
static example_fast_prov_server_t *get_fast_prov_srv_user_data(void)
|
||||
{
|
||||
esp_ble_mesh_model_t *model = NULL;
|
||||
|
||||
model = example_find_model(esp_ble_mesh_get_primary_element_address(),
|
||||
ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_SRV, CID_ESP);
|
||||
if (!model) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get config server model", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (example_fast_prov_server_t *)(model->user_data);
|
||||
}
|
||||
|
||||
/* Timeout handler for send_self_prov_node_addr_timer */
|
||||
void example_send_self_prov_node_addr(struct k_work *work)
|
||||
{
|
||||
example_fast_prov_server_t *fast_prov_srv = NULL;
|
||||
esp_ble_mesh_model_t *model = NULL;
|
||||
int i, j, err;
|
||||
|
||||
bt_mesh_atomic_test_and_clear_bit(&fast_prov_cli_flags, SEND_SELF_PROV_NODE_ADDR_START);
|
||||
|
||||
fast_prov_srv = get_fast_prov_srv_user_data();
|
||||
if (!fast_prov_srv) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get fast prov server model user_data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
model = example_find_model(esp_ble_mesh_get_primary_element_address(),
|
||||
ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI, CID_ESP);
|
||||
if (!model) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get fast prov client model", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node_addr_send.send_succeed == true && node_addr_send.ack_received == false) {
|
||||
ESP_LOGW(TAG, "%s: Previous node address message is being sent", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node_addr_send.send_succeed == true) {
|
||||
/* If the previous node address message has been sent successfully, and when
|
||||
* timeout event comes, we will update the send buffer (node_addr_send).
|
||||
*/
|
||||
net_buf_simple_reset(node_addr_send.addr);
|
||||
for (i = 0; i < CONFIG_BLE_MESH_MAX_PROV_NODES; i++) {
|
||||
uint16_t addr = example_get_node_address(i);
|
||||
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(addr)) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < ARRAY_SIZE(addr_already_sent); j++) {
|
||||
if (addr == addr_already_sent[j]) {
|
||||
ESP_LOGW(TAG, "%s: node addr 0x%04x has already been sent", __func__, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j != ARRAY_SIZE(addr_already_sent)) {
|
||||
continue;
|
||||
}
|
||||
net_buf_simple_add_le16(node_addr_send.addr, addr);
|
||||
if (node_addr_send.addr->len == NODE_ADDR_SEND_MAX_LEN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node_addr_send.addr->len) {
|
||||
example_msg_common_info_t info = {
|
||||
.net_idx = fast_prov_srv->net_idx,
|
||||
.app_idx = fast_prov_srv->app_idx,
|
||||
.dst = fast_prov_srv->prim_prov_addr,
|
||||
.timeout = 0,
|
||||
.role = ROLE_FAST_PROV,
|
||||
};
|
||||
err = example_send_fast_prov_self_prov_node_addr(model, &info, node_addr_send.addr);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send node address", __func__);
|
||||
node_addr_send.send_succeed = false;
|
||||
} else {
|
||||
node_addr_send.send_succeed = true;
|
||||
}
|
||||
node_addr_send.ack_received = false;
|
||||
}
|
||||
|
||||
/* If sending node addresses failed, the Provisioner will start the timer in case
|
||||
* no other devices will be provisioned and the timer will never start.
|
||||
*/
|
||||
if (node_addr_send.send_succeed == false && node_addr_send.ack_received == false) {
|
||||
if (!bt_mesh_atomic_test_and_set_bit(&fast_prov_cli_flags, SEND_SELF_PROV_NODE_ADDR_START)) {
|
||||
k_delayed_work_submit(&send_self_prov_node_addr_timer, SEND_SELF_PROV_NODE_ADDR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_BLE_MESH_FAST_PROV)
|
||||
/* Timeout handler for get_all_node_addr_timer */
|
||||
static void example_get_all_node_addr(struct k_work *work)
|
||||
{
|
||||
esp_ble_mesh_model_t *model = NULL;
|
||||
example_node_info_t *node = NULL;
|
||||
esp_err_t err;
|
||||
|
||||
node = example_get_node_info(prim_prov_addr);
|
||||
if (!node) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get node info", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
model = example_find_model(esp_ble_mesh_get_primary_element_address(),
|
||||
ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI, CID_ESP);
|
||||
if (!model) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get model info", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
example_msg_common_info_t info = {
|
||||
.net_idx = node->net_idx,
|
||||
.app_idx = node->app_idx,
|
||||
.dst = node->unicast_addr,
|
||||
.timeout = 10000,
|
||||
.role = ROLE_PROVISIONER,
|
||||
};
|
||||
err = example_send_fast_prov_all_node_addr_get(model, &info);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Fast Prov Node Address Get message", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t example_fast_prov_client_recv_timeout(uint32_t opcode, esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx)
|
||||
{
|
||||
#if defined(CONFIG_BLE_MESH_FAST_PROV)
|
||||
example_fast_prov_server_t *fast_prov_srv = NULL;
|
||||
#endif
|
||||
example_node_info_t *node = NULL;
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGW(TAG, "%s: Receive fast prov server status timeout", __func__);
|
||||
|
||||
if (!model || !ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLE_MESH_FAST_PROV)
|
||||
fast_prov_srv = get_fast_prov_srv_user_data();
|
||||
if (!fast_prov_srv) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get fast prov server model user_data", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET: {
|
||||
example_fast_prov_info_set_t set = {0};
|
||||
node = example_get_node_info(ctx->addr);
|
||||
if (!node) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
example_msg_common_info_t info = {
|
||||
.net_idx = node->net_idx,
|
||||
.app_idx = node->app_idx,
|
||||
.dst = node->unicast_addr,
|
||||
.timeout = 0,
|
||||
};
|
||||
#if defined(CONFIG_BLE_MESH_FAST_PROV)
|
||||
if (node->lack_of_addr == false) {
|
||||
set.ctx_flags = 0x03FE;
|
||||
memcpy(&set.unicast_min, &node->unicast_min,
|
||||
sizeof(example_node_info_t) - offsetof(example_node_info_t, unicast_min));
|
||||
} else {
|
||||
set.ctx_flags = BIT(6);
|
||||
set.group_addr = fast_prov_srv->group_addr;
|
||||
}
|
||||
info.role = ROLE_FAST_PROV;
|
||||
#else
|
||||
set.ctx_flags = 0x037F;
|
||||
memcpy(&set.node_addr_cnt, &node->node_addr_cnt,
|
||||
sizeof(example_node_info_t) - offsetof(example_node_info_t, node_addr_cnt));
|
||||
info.role = ROLE_PROVISIONER;
|
||||
#endif
|
||||
err = example_send_fast_prov_info_set(model, &info, &set);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Fast Prov Info Set message", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD:
|
||||
break;
|
||||
#if defined(CONFIG_BLE_MESH_FAST_PROV)
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR:
|
||||
if (node_addr_send.addr->len) {
|
||||
example_msg_common_info_t info = {
|
||||
.net_idx = fast_prov_srv->net_idx,
|
||||
.app_idx = fast_prov_srv->app_idx,
|
||||
.dst = fast_prov_srv->prim_prov_addr,
|
||||
.timeout = 0,
|
||||
.role = ROLE_FAST_PROV,
|
||||
};
|
||||
err = example_send_fast_prov_self_prov_node_addr(model, &info, node_addr_send.addr);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Fast Prov Node Addr message", __func__);
|
||||
node_addr_send.send_succeed = false;
|
||||
} else {
|
||||
node_addr_send.send_succeed = true;
|
||||
}
|
||||
node_addr_send.ack_received = false;
|
||||
}
|
||||
if (node_addr_send.send_succeed == false && node_addr_send.ack_received == false) {
|
||||
if (!bt_mesh_atomic_test_and_set_bit(&fast_prov_cli_flags, SEND_SELF_PROV_NODE_ADDR_START)) {
|
||||
k_delayed_work_submit(&send_self_prov_node_addr_timer, SEND_SELF_PROV_NODE_ADDR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET: {
|
||||
node = example_get_node_info(ctx->addr);
|
||||
if (!node) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
example_msg_common_info_t info = {
|
||||
.net_idx = node->net_idx,
|
||||
.app_idx = node->app_idx,
|
||||
.dst = node->unicast_addr,
|
||||
.timeout = 10000,
|
||||
.role = ROLE_PROVISIONER,
|
||||
};
|
||||
err = example_send_fast_prov_all_node_addr_get(model, &info);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Fast Prov Node Address message", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t example_fast_prov_client_recv_status(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, const uint8_t *data)
|
||||
{
|
||||
if (!model || !ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ESP_LOG_BUFFER_HEX("fast prov client receives", data, len);
|
||||
|
||||
switch (ctx->recv_op) {
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS:
|
||||
ESP_LOG_BUFFER_HEX("fast prov info status", data, len);
|
||||
#if !defined(CONFIG_BLE_MESH_FAST_PROV)
|
||||
prim_prov_addr = ctx->addr;
|
||||
k_delayed_work_init(&get_all_node_addr_timer, example_get_all_node_addr);
|
||||
k_delayed_work_submit(&get_all_node_addr_timer, GET_ALL_NODE_ADDR_TIMEOUT);
|
||||
#endif
|
||||
break;
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS:
|
||||
ESP_LOGI(TAG, "status_key: 0x%02x, status_act: 0x%02x", data[0], data[1]);
|
||||
break;
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK: {
|
||||
/* node address message has been acked */
|
||||
int i, j;
|
||||
uint8_t length = node_addr_send.addr->len;
|
||||
node_addr_send.send_succeed = true;
|
||||
node_addr_send.ack_received = true;
|
||||
for (i = 0; i < (length >> 1); i++) {
|
||||
uint16_t addr = net_buf_simple_pull_le16(node_addr_send.addr);
|
||||
if (ESP_BLE_MESH_ADDR_IS_UNICAST(addr)) {
|
||||
for (j = 0; j < ARRAY_SIZE(addr_already_sent); j++) {
|
||||
if (addr_already_sent[j] == addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j != ARRAY_SIZE(addr_already_sent)) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < ARRAY_SIZE(addr_already_sent); j++) {
|
||||
if (addr_already_sent[j] == ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
||||
addr_already_sent[j] = addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == ARRAY_SIZE(addr_already_sent)) {
|
||||
ESP_LOGE(TAG, "%s: No place to store the sent node address", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* In case spending too much time on the first node address message(i.e. failed
|
||||
* to receive ack), and the timer for the second or further messages is timeout,
|
||||
* thus the Provisioner will never be able to send other addresses.
|
||||
*/
|
||||
if (!bt_mesh_atomic_test_and_set_bit(&fast_prov_cli_flags, SEND_SELF_PROV_NODE_ADDR_START)) {
|
||||
k_delayed_work_submit(&send_self_prov_node_addr_timer, SEND_SELF_PROV_NODE_ADDR_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS: {
|
||||
ESP_LOG_BUFFER_HEX("Node address", data, len);
|
||||
esp_ble_mesh_model_t *cli_model = NULL;
|
||||
example_node_info_t *node = NULL;
|
||||
esp_err_t err;
|
||||
node = example_get_node_info(prim_prov_addr);
|
||||
if (!node) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get node info", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
cli_model = example_find_model(esp_ble_mesh_get_primary_element_address(),
|
||||
ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI, CID_NVAL);
|
||||
if (!cli_model) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get Generic OnOff Client Model info", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
example_msg_common_info_t info = {
|
||||
.net_idx = node->net_idx,
|
||||
.app_idx = node->app_idx,
|
||||
.dst = node->group_addr,
|
||||
.timeout = 0,
|
||||
.role = ROLE_PROVISIONER,
|
||||
};
|
||||
err = example_send_generic_onoff_set(cli_model, &info, LED_ON, 0x00, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Generic OnOff Set Unack message", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ESP_LOGE(TAG, "%s: Invalid fast prov status opcode", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP_FAST_PROV_CLIENT_MODEL_H
|
||||
#define _ESP_FAST_PROV_CLIENT_MODEL_H
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
enum {
|
||||
SEND_SELF_PROV_NODE_ADDR_START, /* Flag indicates the timer used to send self-provisioned node addresses has been started */
|
||||
CLI_MAX_FLAGS,
|
||||
};
|
||||
|
||||
#define SEND_SELF_PROV_NODE_ADDR_TIMEOUT K_SECONDS(5)
|
||||
|
||||
void example_send_self_prov_node_addr(struct k_work *work);
|
||||
|
||||
esp_err_t example_fast_prov_client_recv_timeout(uint32_t opcode, esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx);
|
||||
|
||||
esp_err_t example_fast_prov_client_recv_status(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, const uint8_t *data);
|
||||
|
||||
#endif /* _ESP_FAST_PROV_CLIENT_MODEL_H */
|
@@ -0,0 +1,121 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP_FAST_PROV_COMMON_H
|
||||
#define _ESP_FAST_PROV_COMMON_H
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
#include "esp_ble_mesh_config_model_api.h"
|
||||
|
||||
#define LED_OFF 0x00
|
||||
#define LED_ON 0x01
|
||||
|
||||
#define CID_ESP 0x02E5
|
||||
#define CID_NVAL 0xFFFF
|
||||
|
||||
/* Fast Prov Model ID */
|
||||
#define ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI 0x0000
|
||||
#define ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_SRV 0x0001
|
||||
|
||||
/* Fast Prov Message Opcode */
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET ESP_BLE_MESH_MODEL_OP_3(0x00, CID_ESP)
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS ESP_BLE_MESH_MODEL_OP_3(0x01, CID_ESP)
|
||||
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD ESP_BLE_MESH_MODEL_OP_3(0x02, CID_ESP)
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS ESP_BLE_MESH_MODEL_OP_3(0x03, CID_ESP)
|
||||
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR ESP_BLE_MESH_MODEL_OP_3(0x04, CID_ESP)
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK ESP_BLE_MESH_MODEL_OP_3(0x05, CID_ESP)
|
||||
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET ESP_BLE_MESH_MODEL_OP_3(0x06, CID_ESP)
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS ESP_BLE_MESH_MODEL_OP_3(0x07, CID_ESP)
|
||||
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD ESP_BLE_MESH_MODEL_OP_3(0x08, CID_ESP)
|
||||
|
||||
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE ESP_BLE_MESH_MODEL_OP_3(0x09, CID_ESP)
|
||||
|
||||
typedef struct {
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
uint16_t dst;
|
||||
int32_t timeout;
|
||||
esp_ble_mesh_dev_role_t role;
|
||||
} example_msg_common_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
uint8_t app_key[16];
|
||||
|
||||
uint16_t node_addr_cnt; /* Number of BLE Mesh nodes in the network */
|
||||
uint16_t unicast_min; /* Minimum unicast address to be assigned to the nodes in the network */
|
||||
uint16_t unicast_max; /* Maximum unicast address to be assigned to the nodes in the network */
|
||||
uint16_t group_addr; /* Group address which will be subscribed by the nodes in the network */
|
||||
uint8_t match_val[16]; /* Match value used by Fast Provisoning Provisioner */
|
||||
uint8_t match_len;
|
||||
|
||||
uint8_t max_node_num; /* Maximum number of nodes can be provisioned by the client */
|
||||
} __attribute__((packed)) example_prov_info_t;
|
||||
|
||||
/* Fast Prov Info Set Message Context */
|
||||
typedef struct {
|
||||
uint16_t ctx_flags; /* Flags indicate which part of context exists */
|
||||
uint16_t node_addr_cnt; /* Number of the nodes going to be provisioned */
|
||||
uint16_t unicast_min; /* Assigned minimum unicast address */
|
||||
uint16_t unicast_max; /* Assigned maximum unicast address */
|
||||
uint8_t flags; /* Flags used for provisioning data */
|
||||
uint32_t iv_index; /* IV_index used for provisioning data */
|
||||
uint16_t net_idx; /* Netkey index used for provisioning data */
|
||||
uint16_t group_addr; /* Group address going to be added to model */
|
||||
uint16_t prov_addr; /* Primary Provisioner address */
|
||||
uint8_t match_val[16]; /* Match value used for provisioning */
|
||||
uint8_t match_len;
|
||||
uint8_t action; /* Action used to enbale/disable Provisioner functionality */
|
||||
} __attribute__((packed)) example_fast_prov_info_set_t;
|
||||
|
||||
typedef struct {
|
||||
/* The following is the basic information of a node */
|
||||
bool reprov;
|
||||
uint8_t uuid[16];
|
||||
uint16_t unicast_addr;
|
||||
uint8_t element_num;
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
uint8_t onoff;
|
||||
|
||||
/* The following is the information which will be/has been sent to the node */
|
||||
bool lack_of_addr;
|
||||
uint16_t node_addr_cnt;
|
||||
uint16_t unicast_min;
|
||||
uint16_t unicast_max;
|
||||
uint8_t flags;
|
||||
uint32_t iv_index;
|
||||
uint16_t fp_net_idx;
|
||||
uint16_t group_addr;
|
||||
uint16_t prov_addr;
|
||||
uint8_t match_val[16];
|
||||
uint8_t match_len;
|
||||
uint8_t action;
|
||||
} __attribute__((packed)) example_node_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t net_key[16]; /* Network key going to be added */
|
||||
} example_fast_prov_net_key_add_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status_key; /* Indicate the result of adding network key */
|
||||
uint8_t status_act; /* Indicate the result of action */
|
||||
} example_fast_prov_net_key_status_t;
|
||||
|
||||
#endif /* _ESP_FAST_PROV_COMMON_H */
|
@@ -0,0 +1,577 @@
|
||||
// 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);
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP_FAST_PROV_OPERATION_H
|
||||
#define _ESP_FAST_PROV_OPERATION_H
|
||||
|
||||
#include "esp_fast_prov_common.h"
|
||||
|
||||
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 *example_get_node_info(uint16_t node_addr);
|
||||
|
||||
bool example_is_node_exist(const uint8_t uuid[16]);
|
||||
|
||||
uint16_t example_get_node_address(int node_idx);
|
||||
|
||||
esp_ble_mesh_model_t *example_find_model(uint16_t element_addr, uint16_t model_id,
|
||||
uint16_t company_id);
|
||||
|
||||
esp_err_t example_handle_config_app_key_add_evt(uint16_t app_idx);
|
||||
|
||||
esp_err_t example_add_fast_prov_group_address(uint16_t model_id, uint16_t group_addr);
|
||||
|
||||
esp_err_t example_delete_fast_prov_group_address(uint16_t model_id, uint16_t group_addr);
|
||||
|
||||
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_err_t example_send_generic_onoff_get(esp_ble_mesh_model_t *model,
|
||||
example_msg_common_info_t *info);
|
||||
|
||||
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_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);
|
||||
|
||||
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]);
|
||||
|
||||
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);
|
||||
|
||||
esp_err_t example_send_fast_prov_all_node_addr_get(esp_ble_mesh_model_t *model,
|
||||
example_msg_common_info_t *info);
|
||||
|
||||
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);
|
||||
|
||||
#endif /* _ESP_FAST_PROV_OPERATION_H */
|
@@ -0,0 +1,637 @@
|
||||
// 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_defs.h"
|
||||
#include "esp_ble_mesh_local_data_operation_api.h"
|
||||
#include "esp_ble_mesh_provisioning_api.h"
|
||||
#include "esp_ble_mesh_networking_api.h"
|
||||
#include "esp_ble_mesh_proxy_api.h"
|
||||
#include "esp_ble_mesh_config_model_api.h"
|
||||
|
||||
#include "esp_fast_prov_operation.h"
|
||||
#include "esp_fast_prov_server_model.h"
|
||||
|
||||
#define TAG "FAST_PROV_SERVER"
|
||||
|
||||
/* Array used to store all node addresses */
|
||||
static uint16_t all_node_addr[120];
|
||||
static uint16_t all_node_addr_cnt;
|
||||
|
||||
esp_err_t example_store_remote_node_address(uint16_t node_addr)
|
||||
{
|
||||
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(node_addr)) {
|
||||
ESP_LOGE(TAG, "%s: Not a unicast address", __func__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(all_node_addr); i++) {
|
||||
if (all_node_addr[i] == node_addr) {
|
||||
ESP_LOGW(TAG, "%s: Node address 0x%04x already exists", __func__, node_addr);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(all_node_addr); i++) {
|
||||
if (all_node_addr[i] == ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
||||
all_node_addr[i] = node_addr;
|
||||
all_node_addr_cnt++;
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "%s: remote node address queue is full", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_ble_mesh_cfg_srv_t *get_cfg_srv_user_data(void)
|
||||
{
|
||||
esp_ble_mesh_model_t *model = NULL;
|
||||
|
||||
model = example_find_model(esp_ble_mesh_get_primary_element_address(),
|
||||
ESP_BLE_MESH_MODEL_ID_CONFIG_SRV, CID_NVAL);
|
||||
if (!model) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get config server model", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (esp_ble_mesh_cfg_srv_t *)(model->user_data);
|
||||
}
|
||||
|
||||
/* Timeout handler for disable_fast_prov_timer */
|
||||
static void disable_fast_prov_cb(struct k_work *work)
|
||||
{
|
||||
example_fast_prov_server_t *srv = NULL;
|
||||
|
||||
srv = CONTAINER_OF(work, example_fast_prov_server_t, disable_fast_prov_timer.work);
|
||||
if (!srv) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get fast prov server model user_data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (esp_ble_mesh_set_fast_prov_action(FAST_PROV_ACT_SUSPEND)) {
|
||||
ESP_LOGE(TAG, "%s: Failed to disable fast provisioning", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Timeout handler for gatt_proxy_enable_timer */
|
||||
static void enable_gatt_proxy_cb(struct k_work *work)
|
||||
{
|
||||
example_fast_prov_server_t *srv = NULL;
|
||||
|
||||
srv = CONTAINER_OF(work, example_fast_prov_server_t, gatt_proxy_enable_timer.work);
|
||||
if (!srv) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get fast prov server model user_data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_atomic_test_and_clear_bit(srv->srv_flags, RELAY_PROXY_DISABLED)) {
|
||||
ESP_LOGI(TAG, "%s: Enable BLE Mesh Relay & GATT Proxy", __func__);
|
||||
/* For Primary Provisioner, Relay will not be enabled */
|
||||
esp_ble_mesh_proxy_gatt_enable();
|
||||
esp_ble_mesh_proxy_identity_enable();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void example_free_set_info(example_fast_prov_server_t *srv)
|
||||
{
|
||||
if (srv && srv->set_info) {
|
||||
bt_mesh_free(srv->set_info);
|
||||
srv->set_info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx, struct net_buf_simple *buf)
|
||||
{
|
||||
example_fast_prov_server_t *srv = NULL;
|
||||
struct net_buf_simple *msg = NULL;
|
||||
uint32_t opcode = 0;
|
||||
esp_err_t err;
|
||||
|
||||
if (!model || !model->user_data || !ctx || !buf) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
srv = (example_fast_prov_server_t *)model->user_data;
|
||||
|
||||
ESP_LOG_BUFFER_HEX("fast prov server recv", buf->data, buf->len);
|
||||
|
||||
switch (ctx->recv_op) {
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET: {
|
||||
/* fast prov info status (maximum 9 octets):
|
||||
* status_bit_mask (2) + status_ctx_flag (1) + status_unicast (1) + status_net_idx (1) +
|
||||
* status_group (1) + status_pri_prov (1) + status_match (1) + status_action (1).
|
||||
*/
|
||||
uint8_t match_len = 0, match_val[16] = {0};
|
||||
uint8_t status_unicast = 0;
|
||||
uint8_t flags = 0;
|
||||
|
||||
msg = bt_mesh_alloc_buf(9);
|
||||
opcode = ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS;
|
||||
|
||||
if (srv->set_info) {
|
||||
ESP_LOGW(TAG, "%s: Set fast prov info is already in progress", __func__);
|
||||
net_buf_simple_add_le16(msg, 0xFFFF);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If fast prov server state is pending, can not set fast prov info,
|
||||
* and send response message with all status set to 0x01 (i.e. fail).
|
||||
*/
|
||||
if (srv->state == STATE_PEND) {
|
||||
uint8_t val[7] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
|
||||
net_buf_simple_add_le16(msg, 0x7f);
|
||||
net_buf_simple_add_mem(msg, val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t ctx_flags = net_buf_simple_pull_le16(buf);
|
||||
if (ctx_flags == 0) {
|
||||
net_buf_simple_add_le16(msg, BIT(0));
|
||||
net_buf_simple_add_u8(msg, 0x01); /* invalid ctx_flags */
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t node_addr_cnt = (ctx_flags & BIT(0)) ? net_buf_simple_pull_le16(buf) : 0x0;
|
||||
uint16_t unicast_min = (ctx_flags & BIT(1)) ? net_buf_simple_pull_le16(buf) : (esp_ble_mesh_get_primary_element_address() + esp_ble_mesh_get_element_count());
|
||||
uint16_t unicast_max = (ctx_flags & BIT(2)) ? net_buf_simple_pull_le16(buf) : 0x7FFF;
|
||||
if (ctx_flags & BIT(3)) {
|
||||
flags = net_buf_simple_pull_u8(buf);
|
||||
} else {
|
||||
flags = (uint8_t)bt_mesh.sub[0].kr_flag;
|
||||
if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS)) {
|
||||
flags |= BLE_MESH_NET_FLAG_IVU;
|
||||
}
|
||||
}
|
||||
uint32_t iv_index = (ctx_flags & BIT(4)) ? net_buf_simple_pull_le32(buf) : bt_mesh.iv_index;
|
||||
uint16_t net_idx = (ctx_flags & BIT(5)) ? net_buf_simple_pull_le16(buf) : srv->net_idx;
|
||||
uint16_t group_addr = (ctx_flags & BIT(6)) ? net_buf_simple_pull_le16(buf) : ESP_BLE_MESH_ADDR_UNASSIGNED;
|
||||
uint16_t pri_prov_addr = (ctx_flags & BIT(7)) ? net_buf_simple_pull_le16(buf) : ESP_BLE_MESH_ADDR_UNASSIGNED;
|
||||
if (ctx_flags & BIT(8)) {
|
||||
match_len = buf->len - ((ctx_flags & BIT(9)) ? 1 : 0);
|
||||
if (match_len > ESP_BLE_MESH_OCTET16_LEN) {
|
||||
net_buf_simple_add_le16(msg, BIT(5));
|
||||
net_buf_simple_add_u8(msg, 0x01); /* too large match value length */
|
||||
break;
|
||||
}
|
||||
memcpy(match_val, buf->data, match_len);
|
||||
net_buf_simple_pull(buf, match_len);
|
||||
}
|
||||
uint8_t action = (ctx_flags & BIT(9)) ? net_buf_simple_pull_u8(buf) : FAST_PROV_ACT_NONE;
|
||||
|
||||
/* If fast prov server state is active, the device can only suspend or exit fast provisioning */
|
||||
if (srv->state == STATE_ACTIVE) {
|
||||
net_buf_simple_add_le16(msg, BIT(6));
|
||||
switch (action & BIT_MASK(2)) {
|
||||
case FAST_PROV_ACT_SUSPEND:
|
||||
case FAST_PROV_ACT_EXIT:
|
||||
srv->pend_act = action & BIT_MASK(2);
|
||||
if (!bt_mesh_atomic_test_and_set_bit(srv->srv_flags, DISABLE_FAST_PROV_START)) {
|
||||
k_delayed_work_submit(&srv->disable_fast_prov_timer, DISABLE_FAST_PROV_TIMEOUT);
|
||||
}
|
||||
net_buf_simple_add_u8(msg, 0x00); /* action succeed */
|
||||
break;
|
||||
default:
|
||||
net_buf_simple_add_u8(msg, 0x04); /* action already in progress */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ctx_flags & BIT(1)) || (ctx_flags & BIT(2))) {
|
||||
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_min) || !ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_max)) {
|
||||
status_unicast = 0x01; /* not a unicast address */
|
||||
} else if (unicast_min > unicast_max) {
|
||||
status_unicast = 0x02; /* min bigger than max */
|
||||
} else if (unicast_min < (esp_ble_mesh_get_primary_element_address() + esp_ble_mesh_get_element_count())) {
|
||||
status_unicast = 0x04; /* overlap with own element address */
|
||||
}
|
||||
if (status_unicast) {
|
||||
net_buf_simple_add_le16(msg, BIT(1));
|
||||
net_buf_simple_add_u8(msg, status_unicast);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx_flags & BIT(6)) {
|
||||
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
|
||||
net_buf_simple_add_le16(msg, BIT(3));
|
||||
net_buf_simple_add_u8(msg, 0x01); /* not a group address */
|
||||
break;
|
||||
}
|
||||
err = example_add_fast_prov_group_address(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, group_addr);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to add group address 0x%04x", __func__, group_addr);
|
||||
net_buf_simple_add_le16(msg, BIT(3));
|
||||
net_buf_simple_add_u8(msg, 0x02); /* add group address failed */
|
||||
break;
|
||||
}
|
||||
srv->group_addr = group_addr;
|
||||
}
|
||||
|
||||
if (ctx_flags & BIT(7)) {
|
||||
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(pri_prov_addr)) {
|
||||
net_buf_simple_add_le16(msg, BIT(4));
|
||||
net_buf_simple_add_u8(msg, 0x01); /* not a unicast address */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx_flags & BIT(9)) {
|
||||
if ((action & BIT_MASK(2)) != FAST_PROV_ACT_ENTER) {
|
||||
net_buf_simple_add_le16(msg, BIT(6));
|
||||
net_buf_simple_add_u8(msg, 0x01); /* action failed */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
net_buf_simple_add_le16(msg, BIT(6));
|
||||
net_buf_simple_add_u8(msg, 0x03); /* none action */
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&srv->ctx, ctx, sizeof(esp_ble_mesh_msg_ctx_t));
|
||||
srv->set_info = bt_mesh_calloc(sizeof(struct fast_prov_info_set));
|
||||
if (!srv->set_info) {
|
||||
ESP_LOGE(TAG, "%s: Failed to allocate memory", __func__);
|
||||
bt_mesh_free_buf(msg);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (unicast_max < unicast_min + srv->max_node_num - 1) {
|
||||
srv->max_node_num = unicast_max - unicast_min + 1;
|
||||
}
|
||||
|
||||
srv->set_info->set_succeed = false;
|
||||
srv->set_info->node_addr_cnt = node_addr_cnt;
|
||||
srv->set_info->unicast_min = unicast_min;
|
||||
srv->set_info->unicast_max = unicast_max;
|
||||
srv->set_info->flags = flags;
|
||||
srv->set_info->iv_index = iv_index;
|
||||
srv->set_info->net_idx = net_idx;
|
||||
srv->set_info->pri_prov_addr = pri_prov_addr;
|
||||
srv->set_info->match_len = match_len;
|
||||
memcpy(srv->set_info->match_val, match_val, match_len);
|
||||
srv->set_info->action = action;
|
||||
|
||||
esp_ble_mesh_fast_prov_info_t info_set = {
|
||||
.unicast_min = unicast_min,
|
||||
.unicast_max = unicast_min + srv->max_node_num - 1,
|
||||
.flags = flags,
|
||||
.iv_index = iv_index,
|
||||
.net_idx = net_idx,
|
||||
.offset = 0x00,
|
||||
.match_len = match_len,
|
||||
};
|
||||
memcpy(info_set.match_val, match_val, match_len);
|
||||
err = esp_ble_mesh_set_fast_prov_info(&info_set);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to set fast prov info", __func__);
|
||||
net_buf_simple_add_le16(msg, BIT(5) | BIT(2) | BIT(1));
|
||||
net_buf_simple_add_u8(msg, 0x01); /* set unicast failed */
|
||||
net_buf_simple_add_u8(msg, 0x01); /* set net_idx failed */
|
||||
net_buf_simple_add_u8(msg, 0x01); /* set UUID match failed */
|
||||
break;
|
||||
}
|
||||
/* If setting fast prov info successfully, wait for the event callback */
|
||||
bt_mesh_free_buf(msg);
|
||||
return ESP_OK;
|
||||
}
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD: {
|
||||
uint8_t status_net_key, status_action;
|
||||
|
||||
msg = bt_mesh_alloc_buf(2);
|
||||
|
||||
if (srv->state == STATE_PEND) {
|
||||
/* Add fast prov net_key, wait for event callback and call esp_ble_mesh_set_fast_prov_act() to set action */
|
||||
} else {
|
||||
/* If state is not pending, can not add net_key */
|
||||
status_net_key = 0x01; /* status_net_key: fail */
|
||||
status_action = 0x01; /* status_action: fail */
|
||||
}
|
||||
|
||||
opcode = ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS;
|
||||
net_buf_simple_add_u8(msg, status_net_key);
|
||||
net_buf_simple_add_u8(msg, status_action);
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR: {
|
||||
if (buf->len % 2) {
|
||||
ESP_LOGE(TAG, "%s: Invalid Fast Prov Node Addr message length", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (bt_mesh_atomic_test_and_clear_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
|
||||
k_delayed_work_cancel(&srv->gatt_proxy_enable_timer);
|
||||
}
|
||||
|
||||
for (; buf->len; ) {
|
||||
uint16_t node_addr = net_buf_simple_pull_le16(buf);
|
||||
ESP_LOGI(TAG, "Node address: 0x%04x", node_addr);
|
||||
err = example_store_remote_node_address(node_addr);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to store node address 0x%04x", __func__, node_addr);
|
||||
}
|
||||
}
|
||||
|
||||
opcode = ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK;
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET: {
|
||||
/* Top device (e.g. phone) tries to get all node addresses */
|
||||
msg = bt_mesh_alloc_buf(all_node_addr_cnt * 2);
|
||||
if (!msg) {
|
||||
ESP_LOGE(TAG, "%s: Failed to allocate memory", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < all_node_addr_cnt; i++) {
|
||||
net_buf_simple_add_le16(msg, all_node_addr[i]);
|
||||
}
|
||||
ESP_LOG_BUFFER_HEX("All node address", msg->data, msg->len);
|
||||
|
||||
opcode = ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS;
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD: {
|
||||
uint16_t own_addr = esp_ble_mesh_get_primary_element_address();
|
||||
uint16_t group_addr = net_buf_simple_pull_le16(buf);
|
||||
ESP_LOGI(TAG, "%s, group address 0x%04x", __func__, group_addr);
|
||||
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
for (; buf->len; ) {
|
||||
uint16_t dst = net_buf_simple_pull_le16(buf);
|
||||
ESP_LOGI(TAG, "%s, dst 0x%04x, own address 0x%04x", __func__, dst, own_addr);
|
||||
if (dst == own_addr) {
|
||||
err = example_add_fast_prov_group_address(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, group_addr);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to add group address 0x%04x", __func__, group_addr);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE: {
|
||||
uint16_t own_addr = esp_ble_mesh_get_primary_element_address();
|
||||
uint16_t group_addr = net_buf_simple_pull_le16(buf);
|
||||
ESP_LOGI(TAG, "%s, group address 0x%04x", __func__, group_addr);
|
||||
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
for (; buf->len; ) {
|
||||
uint16_t dst = net_buf_simple_pull_le16(buf);
|
||||
ESP_LOGI(TAG, "%s, dst 0x%04x, own address 0x%04x", __func__, dst, own_addr);
|
||||
if (dst == own_addr) {
|
||||
err = example_delete_fast_prov_group_address(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, group_addr);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to delete group address 0x%04x", __func__, group_addr);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
default:
|
||||
ESP_LOGW(TAG, "%s: Not a Fast Prov Client message opcode", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = example_send_fast_prov_status_msg(model, ctx, opcode, msg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Fast Prov Status message", __func__);
|
||||
example_free_set_info(srv);
|
||||
}
|
||||
|
||||
bt_mesh_free_buf(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t example_handle_fast_prov_info_set_comp_evt(esp_ble_mesh_model_t *model, uint8_t status_unicast,
|
||||
uint8_t status_net_idx, uint8_t status_match)
|
||||
{
|
||||
example_fast_prov_server_t *srv = NULL;
|
||||
struct net_buf_simple *msg = NULL;
|
||||
esp_err_t err;
|
||||
|
||||
if (!model || !model->user_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
srv = (example_fast_prov_server_t *)model->user_data;
|
||||
if (!srv->set_info) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
msg = bt_mesh_alloc_buf(9);
|
||||
|
||||
if (status_unicast || status_match) {
|
||||
net_buf_simple_add_le16(msg, BIT(5) | BIT(1));
|
||||
net_buf_simple_add_u8(msg, status_unicast);
|
||||
net_buf_simple_add_u8(msg, status_match);
|
||||
goto send;
|
||||
}
|
||||
|
||||
/* Update Fast Prov Server Model user_data */
|
||||
srv->unicast_min = srv->set_info->unicast_min + srv->max_node_num;
|
||||
srv->unicast_max = srv->set_info->unicast_max;
|
||||
srv->unicast_cur = srv->set_info->unicast_min + srv->max_node_num;
|
||||
if (srv->unicast_max <= srv->unicast_min) {
|
||||
srv->unicast_step = 0;
|
||||
} else {
|
||||
srv->unicast_step = (srv->unicast_max - srv->unicast_min) / srv->max_node_num;
|
||||
}
|
||||
srv->flags = srv->set_info->flags;
|
||||
srv->iv_index = srv->set_info->iv_index;
|
||||
srv->net_idx = srv->set_info->net_idx;
|
||||
if (srv->set_info->action & BIT(7)) {
|
||||
srv->primary_role = true;
|
||||
srv->node_addr_cnt = srv->set_info->node_addr_cnt;
|
||||
srv->prim_prov_addr = esp_ble_mesh_get_primary_element_address();
|
||||
srv->top_address = srv->ctx.addr;
|
||||
} else {
|
||||
srv->primary_role = false;
|
||||
srv->prim_prov_addr = srv->set_info->pri_prov_addr;
|
||||
}
|
||||
srv->match_len = srv->set_info->match_len;
|
||||
memcpy(srv->match_val, srv->set_info->match_val, srv->set_info->match_len);
|
||||
|
||||
if (status_net_idx) {
|
||||
ESP_LOGW(TAG, "%s: Wait for fast prov netkey to be added", __func__);
|
||||
srv->pend_act = FAST_PROV_ACT_ENTER;
|
||||
srv->state = STATE_PEND;
|
||||
net_buf_simple_add_le16(msg, BIT(6) | BIT(2));
|
||||
net_buf_simple_add_u8(msg, status_net_idx); /* wait for net_key */
|
||||
net_buf_simple_add_u8(msg, 0x02); /* pending action */
|
||||
goto send;
|
||||
}
|
||||
|
||||
/* Sets fast prov action */
|
||||
err = esp_ble_mesh_set_fast_prov_action(FAST_PROV_ACT_ENTER);
|
||||
if (err == ESP_OK) {
|
||||
bt_mesh_free_buf(msg);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "%s: Failed to set fast prov action", __func__);
|
||||
net_buf_simple_add_le16(msg, BIT(6));
|
||||
net_buf_simple_add_u8(msg, 0x01); /* action failed */
|
||||
|
||||
send:
|
||||
err = example_send_fast_prov_status_msg(model, &srv->ctx, ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS, msg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Fast Prov Status message", __func__);
|
||||
example_free_set_info(srv);
|
||||
}
|
||||
|
||||
bt_mesh_free_buf(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t example_handle_fast_prov_action_set_comp_evt(esp_ble_mesh_model_t *model, uint8_t status_action)
|
||||
{
|
||||
example_fast_prov_server_t *srv = NULL;
|
||||
struct net_buf_simple *msg = NULL;
|
||||
uint32_t opcode;
|
||||
esp_err_t err;
|
||||
|
||||
if (!model || !model->user_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
srv = (example_fast_prov_server_t *)model->user_data;
|
||||
|
||||
msg = bt_mesh_alloc_buf(9);
|
||||
|
||||
switch (srv->state) {
|
||||
case STATE_IDLE: { /* fast prov info set (enter) */
|
||||
const uint8_t zero[6] = {0};
|
||||
net_buf_simple_add_le16(msg, 0x7f);
|
||||
net_buf_simple_add_mem(msg, zero, 6);
|
||||
net_buf_simple_add_u8(msg, status_action);
|
||||
opcode = ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS;
|
||||
/**
|
||||
* Disable relay should not have a impact on Mesh Proxy PDU, and
|
||||
* we can also move "disabling relay" in the event of "disabling
|
||||
* gatt proxy" here.
|
||||
*/
|
||||
if (srv->node_addr_cnt == FAST_PROV_NODE_COUNT_MIN) {
|
||||
if (bt_mesh_atomic_test_and_clear_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
|
||||
k_delayed_work_cancel(&srv->gatt_proxy_enable_timer);
|
||||
}
|
||||
if (!bt_mesh_atomic_test_and_set_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
|
||||
k_delayed_work_submit(&srv->gatt_proxy_enable_timer, K_SECONDS(3));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STATE_ACTIVE: /* fast prov info set (suspend/exit) */
|
||||
/* Currently we only support suspend/exit fast prov after Generic
|
||||
* OnOff Set/Set Unack is received. So no fast prov status message
|
||||
* will be sent.
|
||||
*/
|
||||
case STATE_PEND: /* fast prov net_key add */
|
||||
/* In this case, we should send fast prov net_key status */
|
||||
default:
|
||||
bt_mesh_free_buf(msg);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
err = example_send_fast_prov_status_msg(model, &srv->ctx, opcode, msg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Fast Prov Status message", __func__);
|
||||
example_free_set_info(srv);
|
||||
bt_mesh_free_buf(msg);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (status_action == 0x00) {
|
||||
if (srv->state == STATE_IDLE || srv->state == STATE_PEND) {
|
||||
srv->state = STATE_ACTIVE;
|
||||
} else if (srv->state == STATE_ACTIVE) {
|
||||
srv->state = STATE_IDLE;
|
||||
}
|
||||
if (srv->set_info) {
|
||||
srv->set_info->set_succeed = true;
|
||||
}
|
||||
}
|
||||
|
||||
bt_mesh_free_buf(msg);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t example_handle_fast_prov_status_send_comp_evt(int err_code, uint32_t opcode,
|
||||
esp_ble_mesh_model_t *model, esp_ble_mesh_msg_ctx_t *ctx)
|
||||
{
|
||||
example_fast_prov_server_t *srv = NULL;
|
||||
|
||||
if (!model || !model->user_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
srv = (example_fast_prov_server_t *)model->user_data;
|
||||
|
||||
ESP_LOGI(TAG, "%s: opcode 0x%06x", __func__, opcode);
|
||||
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS:
|
||||
if (err_code == 0 && srv->set_info && srv->set_info->set_succeed == true) {
|
||||
if (!bt_mesh_atomic_test_and_set_bit(srv->srv_flags, RELAY_PROXY_DISABLED)) {
|
||||
/* For Primary Provisioner: disable Relay and GATT Proxy;
|
||||
* For other Provisioners: only disable GATT Proxy
|
||||
*/
|
||||
ESP_LOGW(TAG, "%s: Disable BLE Mesh Relay & GATT Proxy", __func__);
|
||||
esp_ble_mesh_proxy_gatt_disable();
|
||||
}
|
||||
}
|
||||
example_free_set_info(srv);
|
||||
break;
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS:
|
||||
break;
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK:
|
||||
if (!bt_mesh_atomic_test_and_set_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
|
||||
k_delayed_work_submit(&srv->gatt_proxy_enable_timer, GATT_PROXY_ENABLE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t example_fast_prov_server_init(esp_ble_mesh_model_t *model)
|
||||
{
|
||||
example_fast_prov_server_t *srv = NULL;
|
||||
|
||||
if (!model || !model->user_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
srv = (example_fast_prov_server_t *)model->user_data;
|
||||
srv->model = model;
|
||||
|
||||
k_delayed_work_init(&srv->disable_fast_prov_timer, disable_fast_prov_cb);
|
||||
k_delayed_work_init(&srv->gatt_proxy_enable_timer, enable_gatt_proxy_cb);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP_FAST_PROV_SERVER_MODEL_H
|
||||
#define _ESP_FAST_PROV_SERVER_MODEL_H
|
||||
|
||||
#include "esp_fast_prov_common.h"
|
||||
|
||||
#define DISABLE_FAST_PROV_TIMEOUT K_SECONDS(10)
|
||||
#define GATT_PROXY_ENABLE_TIMEOUT K_SECONDS(10)
|
||||
|
||||
#define FAST_PROV_NODE_COUNT_MIN 0x01
|
||||
|
||||
enum {
|
||||
DISABLE_FAST_PROV_START, /* Flag indicates the timer used to disable fast provisioning has been started */
|
||||
GATT_PROXY_ENABLE_START, /* Flag indicates the timer used to enable Mesh GATT Proxy has been started */
|
||||
RELAY_PROXY_DISABLED, /* Flag indicates if relay & proxy_adv are enabled or disabled */
|
||||
SRV_MAX_FLAGS,
|
||||
};
|
||||
|
||||
enum {
|
||||
STATE_IDLE,
|
||||
STATE_PEND,
|
||||
STATE_ACTIVE,
|
||||
STATE_MAX,
|
||||
};
|
||||
|
||||
struct fast_prov_info_set {
|
||||
bool set_succeed;
|
||||
uint16_t node_addr_cnt;
|
||||
uint16_t unicast_min;
|
||||
uint16_t unicast_max;
|
||||
uint8_t flags;
|
||||
uint32_t iv_index;
|
||||
uint16_t net_idx;
|
||||
uint16_t group_addr;
|
||||
uint16_t pri_prov_addr;
|
||||
uint8_t match_val[16];
|
||||
uint8_t match_len;
|
||||
uint8_t action;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
esp_ble_mesh_model_t *model; /* Fast Prov Server model pointer */
|
||||
BLE_MESH_ATOMIC_DEFINE(srv_flags, SRV_MAX_FLAGS);
|
||||
|
||||
bool primary_role; /* Indicate if the device is a Primary Provisioner */
|
||||
uint8_t max_node_num; /* The maximum number of devices can be provisioned by the Provisioner */
|
||||
uint8_t prov_node_cnt; /* Number of self-provisioned nodes */
|
||||
uint16_t app_idx; /* AppKey index of the application key added by other Provisioner */
|
||||
uint16_t top_address; /* Address of the device(e.g. phone) which triggers fast provisioning */
|
||||
|
||||
esp_ble_mesh_msg_ctx_t ctx; /* the context stored for sending fast prov status message */
|
||||
struct fast_prov_info_set *set_info; /* Used to store received fast prov info set context */
|
||||
|
||||
uint16_t node_addr_cnt; /* Number of node address shall be received */
|
||||
uint16_t unicast_min; /* Minimum unicast address can be send to other nodes */
|
||||
uint16_t unicast_max; /* Maximum unicast address can be send to other nodes */
|
||||
uint16_t unicast_cur; /* Current unicast address can be assigned */
|
||||
uint16_t unicast_step; /* Unicast address change step */
|
||||
uint8_t flags; /* Flags state */
|
||||
uint32_t iv_index; /* Iv_index state */
|
||||
uint16_t net_idx; /* Netkey index state */
|
||||
uint16_t group_addr; /* Subscribed group address */
|
||||
uint16_t prim_prov_addr; /* Unicast address of Primary Provisioner */
|
||||
uint8_t match_val[16]; /* Match value to be compared with unprovisioned device UUID */
|
||||
uint8_t match_len; /* Length of match value to be compared */
|
||||
|
||||
uint8_t pend_act; /* Pending action to be performed */
|
||||
uint8_t state; /* Fast prov state -> 0: idle, 1: pend, 2: active */
|
||||
|
||||
struct k_delayed_work disable_fast_prov_timer; /* Used to disable fast provisioning */
|
||||
struct k_delayed_work gatt_proxy_enable_timer; /* Used to enable Mesh GATT Proxy functionality */
|
||||
} __attribute__((packed)) example_fast_prov_server_t;
|
||||
|
||||
esp_err_t example_store_remote_node_address(uint16_t node_addr);
|
||||
|
||||
esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx, struct net_buf_simple *buf);
|
||||
|
||||
esp_err_t example_handle_fast_prov_info_set_comp_evt(esp_ble_mesh_model_t *model, uint8_t status_unicast,
|
||||
uint8_t status_net_idx, uint8_t status_match);
|
||||
|
||||
esp_err_t example_handle_fast_prov_action_set_comp_evt(esp_ble_mesh_model_t *model, uint8_t status_action);
|
||||
|
||||
esp_err_t example_handle_fast_prov_status_send_comp_evt(int err_code, uint32_t opcode,
|
||||
esp_ble_mesh_model_t *model, esp_ble_mesh_msg_ctx_t *ctx);
|
||||
|
||||
esp_err_t example_fast_prov_server_init(esp_ble_mesh_model_t *model);
|
||||
|
||||
#endif /* _ESP_FAST_PROV_SERVER_MODEL_H */
|
Reference in New Issue
Block a user