Move the TAG definition of each example to the corresponding source file (previously it is defined in the common example intialization header file), which can avoid the redefinition of TAG in some situations.
641 lines
23 KiB
C
641 lines
23 KiB
C
/* main.c - Application main entry point */
|
|
|
|
/*
|
|
* Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "esp_log.h"
|
|
#include "nvs_flash.h"
|
|
|
|
#include "esp_ble_mesh_defs.h"
|
|
#include "esp_ble_mesh_common_api.h"
|
|
#include "esp_ble_mesh_provisioning_api.h"
|
|
#include "esp_ble_mesh_networking_api.h"
|
|
#include "esp_ble_mesh_config_model_api.h"
|
|
#include "esp_ble_mesh_generic_model_api.h"
|
|
|
|
#include "ble_mesh_example_init.h"
|
|
|
|
#define TAG "EXAMPLE"
|
|
|
|
#define LED_OFF 0x0
|
|
#define LED_ON 0x1
|
|
|
|
#define CID_ESP 0x02E5
|
|
|
|
#define PROV_OWN_ADDR 0x0001
|
|
|
|
#define MSG_SEND_TTL 3
|
|
#define MSG_SEND_REL false
|
|
#define MSG_TIMEOUT 0
|
|
#define MSG_ROLE ROLE_PROVISIONER
|
|
|
|
#define COMP_DATA_PAGE_0 0x00
|
|
|
|
#define APP_KEY_IDX 0x0000
|
|
#define APP_KEY_OCTET 0x12
|
|
|
|
static uint8_t dev_uuid[16];
|
|
|
|
typedef struct {
|
|
uint8_t uuid[16];
|
|
uint16_t unicast;
|
|
uint8_t elem_num;
|
|
uint8_t onoff;
|
|
} esp_ble_mesh_node_info_t;
|
|
|
|
static esp_ble_mesh_node_info_t nodes[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
|
|
[0 ... (CONFIG_BLE_MESH_MAX_PROV_NODES - 1)] = {
|
|
.unicast = ESP_BLE_MESH_ADDR_UNASSIGNED,
|
|
.elem_num = 0,
|
|
.onoff = LED_OFF,
|
|
}
|
|
};
|
|
|
|
static struct esp_ble_mesh_key {
|
|
uint16_t net_idx;
|
|
uint16_t app_idx;
|
|
uint8_t app_key[16];
|
|
} prov_key;
|
|
|
|
static esp_ble_mesh_client_t config_client;
|
|
static esp_ble_mesh_client_t onoff_client;
|
|
|
|
static esp_ble_mesh_cfg_srv_t config_server = {
|
|
.relay = ESP_BLE_MESH_RELAY_DISABLED,
|
|
.beacon = ESP_BLE_MESH_BEACON_ENABLED,
|
|
#if defined(CONFIG_BLE_MESH_FRIEND)
|
|
.friend_state = ESP_BLE_MESH_FRIEND_ENABLED,
|
|
#else
|
|
.friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED,
|
|
#endif
|
|
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
|
|
.gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED,
|
|
#else
|
|
.gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED,
|
|
#endif
|
|
.default_ttl = 7,
|
|
/* 3 transmissions with 20ms interval */
|
|
.net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20),
|
|
.relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20),
|
|
};
|
|
|
|
static esp_ble_mesh_model_t root_models[] = {
|
|
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
|
|
ESP_BLE_MESH_MODEL_CFG_CLI(&config_client),
|
|
ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI(NULL, &onoff_client),
|
|
};
|
|
|
|
static esp_ble_mesh_elem_t elements[] = {
|
|
ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE),
|
|
};
|
|
|
|
static esp_ble_mesh_comp_t composition = {
|
|
.cid = CID_ESP,
|
|
.elements = elements,
|
|
.element_count = ARRAY_SIZE(elements),
|
|
};
|
|
|
|
static esp_ble_mesh_prov_t provision = {
|
|
.prov_uuid = dev_uuid,
|
|
.prov_unicast_addr = PROV_OWN_ADDR,
|
|
.prov_start_address = 0x0005,
|
|
.prov_attention = 0x00,
|
|
.prov_algorithm = 0x00,
|
|
.prov_pub_key_oob = 0x00,
|
|
.prov_static_oob_val = NULL,
|
|
.prov_static_oob_len = 0x00,
|
|
.flags = 0x00,
|
|
.iv_index = 0x00,
|
|
};
|
|
|
|
static esp_err_t example_ble_mesh_store_node_info(const uint8_t uuid[16], uint16_t unicast,
|
|
uint8_t elem_num, uint8_t onoff_state)
|
|
{
|
|
int i;
|
|
|
|
if (!uuid || !ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
/* Judge if the device has been provisioned before */
|
|
for (i = 0; i < ARRAY_SIZE(nodes); i++) {
|
|
if (!memcmp(nodes[i].uuid, uuid, 16)) {
|
|
ESP_LOGW(TAG, "%s: reprovisioned device 0x%04x", __func__, unicast);
|
|
nodes[i].unicast = unicast;
|
|
nodes[i].elem_num = elem_num;
|
|
nodes[i].onoff = onoff_state;
|
|
return ESP_OK;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(nodes); i++) {
|
|
if (nodes[i].unicast == ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
|
memcpy(nodes[i].uuid, uuid, 16);
|
|
nodes[i].unicast = unicast;
|
|
nodes[i].elem_num = elem_num;
|
|
nodes[i].onoff = onoff_state;
|
|
return ESP_OK;
|
|
}
|
|
}
|
|
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
static esp_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast)
|
|
{
|
|
int i;
|
|
|
|
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(nodes); i++) {
|
|
if (nodes[i].unicast <= unicast &&
|
|
nodes[i].unicast + nodes[i].elem_num > unicast) {
|
|
return &nodes[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static esp_err_t example_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common,
|
|
esp_ble_mesh_node_info_t *node,
|
|
esp_ble_mesh_model_t *model, uint32_t opcode)
|
|
{
|
|
if (!common || !node || !model) {
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
common->opcode = opcode;
|
|
common->model = model;
|
|
common->ctx.net_idx = prov_key.net_idx;
|
|
common->ctx.app_idx = prov_key.app_idx;
|
|
common->ctx.addr = node->unicast;
|
|
common->ctx.send_ttl = MSG_SEND_TTL;
|
|
common->ctx.send_rel = MSG_SEND_REL;
|
|
common->msg_timeout = MSG_TIMEOUT;
|
|
common->msg_role = MSG_ROLE;
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_err_t prov_complete(int node_idx, const esp_ble_mesh_octet16_t uuid,
|
|
uint16_t unicast, uint8_t elem_num, uint16_t net_idx)
|
|
{
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
esp_ble_mesh_cfg_client_get_state_t get_state = {0};
|
|
esp_ble_mesh_node_info_t *node = NULL;
|
|
char name[11] = {0};
|
|
int err;
|
|
|
|
ESP_LOGI(TAG, "node index: 0x%x, unicast address: 0x%02x, element num: %d, netkey index: 0x%02x",
|
|
node_idx, unicast, elem_num, net_idx);
|
|
ESP_LOGI(TAG, "device uuid: %s", bt_hex(uuid, 16));
|
|
|
|
sprintf(name, "%s%d", "NODE-", node_idx);
|
|
err = esp_ble_mesh_provisioner_set_node_name(node_idx, name);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Set node name failed", __func__);
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
err = example_ble_mesh_store_node_info(uuid, unicast, elem_num, LED_OFF);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Store node info failed", __func__);
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
node = example_ble_mesh_get_node_info(unicast);
|
|
if (!node) {
|
|
ESP_LOGE(TAG, "%s: Get node info failed", __func__);
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
|
|
get_state.comp_data_get.page = COMP_DATA_PAGE_0;
|
|
err = esp_ble_mesh_config_client_get_state(&common, &get_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Send config comp data get failed", __func__);
|
|
return ESP_FAIL;
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
static void prov_link_open(esp_ble_mesh_prov_bearer_t bearer)
|
|
{
|
|
ESP_LOGI(TAG, "%s link open", bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
|
}
|
|
|
|
static void prov_link_close(esp_ble_mesh_prov_bearer_t bearer, uint8_t reason)
|
|
{
|
|
ESP_LOGI(TAG, "%s link close, reason 0x%02x",
|
|
bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT", reason);
|
|
}
|
|
|
|
static void recv_unprov_adv_pkt(uint8_t dev_uuid[16], uint8_t addr[BD_ADDR_LEN],
|
|
esp_ble_mesh_addr_type_t addr_type, uint16_t oob_info,
|
|
uint8_t adv_type, esp_ble_mesh_prov_bearer_t bearer)
|
|
{
|
|
esp_ble_mesh_unprov_dev_add_t add_dev = {0};
|
|
int err;
|
|
|
|
/* Due to the API esp_ble_mesh_provisioner_set_dev_uuid_match, Provisioner will only
|
|
* use this callback to report the devices, whose device UUID starts with 0xdd & 0xdd,
|
|
* to the application layer.
|
|
*/
|
|
|
|
ESP_LOGI(TAG, "address: %s, address type: %d, adv type: %d", bt_hex(addr, BD_ADDR_LEN), addr_type, adv_type);
|
|
ESP_LOGI(TAG, "device uuid: %s", bt_hex(dev_uuid, 16));
|
|
ESP_LOGI(TAG, "oob info: %d, bearer: %s", oob_info, (bearer & ESP_BLE_MESH_PROV_ADV) ? "PB-ADV" : "PB-GATT");
|
|
|
|
memcpy(add_dev.addr, addr, BD_ADDR_LEN);
|
|
add_dev.addr_type = (uint8_t)addr_type;
|
|
memcpy(add_dev.uuid, dev_uuid, 16);
|
|
add_dev.oob_info = oob_info;
|
|
add_dev.bearer = (uint8_t)bearer;
|
|
/* Note: If unprovisioned device adv packets have not been received, we should not add
|
|
device with ADD_DEV_START_PROV_NOW_FLAG set. */
|
|
err = esp_ble_mesh_provisioner_add_unprov_dev(&add_dev,
|
|
ADD_DEV_RM_AFTER_PROV_FLAG | ADD_DEV_START_PROV_NOW_FLAG | ADD_DEV_FLUSHABLE_DEV_FLAG);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Add unprovisioned device into queue failed", __func__);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
|
|
esp_ble_mesh_prov_cb_param_t *param)
|
|
{
|
|
switch (event) {
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT, err_code %d", param->provisioner_prov_enable_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT, err_code %d", param->provisioner_prov_disable_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT");
|
|
recv_unprov_adv_pkt(param->provisioner_recv_unprov_adv_pkt.dev_uuid, param->provisioner_recv_unprov_adv_pkt.addr,
|
|
param->provisioner_recv_unprov_adv_pkt.addr_type, param->provisioner_recv_unprov_adv_pkt.oob_info,
|
|
param->provisioner_recv_unprov_adv_pkt.adv_type, param->provisioner_recv_unprov_adv_pkt.bearer);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_LINK_OPEN_EVT:
|
|
prov_link_open(param->provisioner_prov_link_open.bearer);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT:
|
|
prov_link_close(param->provisioner_prov_link_close.bearer, param->provisioner_prov_link_close.reason);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT:
|
|
prov_complete(param->provisioner_prov_complete.node_idx, param->provisioner_prov_complete.device_uuid,
|
|
param->provisioner_prov_complete.unicast_addr, param->provisioner_prov_complete.element_num,
|
|
param->provisioner_prov_complete.netkey_idx);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT, err_code %d", param->provisioner_add_unprov_dev_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT, err_code %d", param->provisioner_set_dev_uuid_match_comp.err_code);
|
|
break;
|
|
case ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT: {
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT, err_code %d", param->provisioner_set_node_name_comp.err_code);
|
|
if (param->provisioner_set_node_name_comp.err_code == ESP_OK) {
|
|
const char *name = NULL;
|
|
name = esp_ble_mesh_provisioner_get_node_name(param->provisioner_set_node_name_comp.node_index);
|
|
if (!name) {
|
|
ESP_LOGE(TAG, "Get node name failed");
|
|
return;
|
|
}
|
|
ESP_LOGI(TAG, "Node %d name is: %s", param->provisioner_set_node_name_comp.node_index, name);
|
|
}
|
|
break;
|
|
}
|
|
case ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT: {
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT, err_code %d", param->provisioner_add_app_key_comp.err_code);
|
|
if (param->provisioner_add_app_key_comp.err_code == ESP_OK) {
|
|
esp_err_t err = 0;
|
|
prov_key.app_idx = param->provisioner_add_app_key_comp.app_idx;
|
|
err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(PROV_OWN_ADDR, prov_key.app_idx,
|
|
ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI, ESP_BLE_MESH_CID_NVAL);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "Provisioner bind local model appkey failed");
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT:
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT, err_code %d", param->provisioner_bind_app_key_to_model_comp.err_code);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t event,
|
|
esp_ble_mesh_cfg_client_cb_param_t *param)
|
|
{
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
esp_ble_mesh_node_info_t *node = NULL;
|
|
uint32_t opcode;
|
|
uint16_t addr;
|
|
int err;
|
|
|
|
opcode = param->params->opcode;
|
|
addr = param->params->ctx.addr;
|
|
|
|
ESP_LOGI(TAG, "%s, error_code = 0x%02x, event = 0x%02x, addr: 0x%04x, opcode: 0x%04x",
|
|
__func__, param->error_code, event, param->params->ctx.addr, opcode);
|
|
|
|
if (param->error_code) {
|
|
ESP_LOGE(TAG, "Send config client message failed, opcode 0x%04x", opcode);
|
|
return;
|
|
}
|
|
|
|
node = example_ble_mesh_get_node_info(addr);
|
|
if (!node) {
|
|
ESP_LOGE(TAG, "%s: Get node info failed", __func__);
|
|
return;
|
|
}
|
|
|
|
switch (event) {
|
|
case ESP_BLE_MESH_CFG_CLIENT_GET_STATE_EVT:
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
|
|
ESP_LOGI(TAG, "composition data %s", bt_hex(param->status_cb.comp_data_status.composition_data->data,
|
|
param->status_cb.comp_data_status.composition_data->len));
|
|
esp_ble_mesh_cfg_client_set_state_t set_state = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
|
set_state.app_key_add.net_idx = prov_key.net_idx;
|
|
set_state.app_key_add.app_idx = prov_key.app_idx;
|
|
memcpy(set_state.app_key_add.app_key, prov_key.app_key, 16);
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Config AppKey Add failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_CFG_CLIENT_SET_STATE_EVT:
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
|
|
esp_ble_mesh_cfg_client_set_state_t set_state = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
|
set_state.model_app_bind.element_addr = node->unicast;
|
|
set_state.model_app_bind.model_app_idx = prov_key.app_idx;
|
|
set_state.model_app_bind.model_id = ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV;
|
|
set_state.model_app_bind.company_id = ESP_BLE_MESH_CID_NVAL;
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Config Model App Bind failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
|
|
esp_ble_mesh_generic_client_get_state_t get_state = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET);
|
|
err = esp_ble_mesh_generic_client_get_state(&common, &get_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Generic OnOff Get failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_CFG_CLIENT_PUBLISH_EVT:
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_STATUS:
|
|
ESP_LOG_BUFFER_HEX("composition data %s", param->status_cb.comp_data_status.composition_data->data,
|
|
param->status_cb.comp_data_status.composition_data->len);
|
|
break;
|
|
case ESP_BLE_MESH_MODEL_OP_APP_KEY_STATUS:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_CFG_CLIENT_TIMEOUT_EVT:
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
|
|
esp_ble_mesh_cfg_client_get_state_t get_state = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
|
|
get_state.comp_data_get.page = COMP_DATA_PAGE_0;
|
|
err = esp_ble_mesh_config_client_get_state(&common, &get_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Config Composition Data Get failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
|
|
esp_ble_mesh_cfg_client_set_state_t set_state = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
|
set_state.app_key_add.net_idx = prov_key.net_idx;
|
|
set_state.app_key_add.app_idx = prov_key.app_idx;
|
|
memcpy(set_state.app_key_add.app_key, prov_key.app_key, 16);
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Config AppKey Add failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
|
|
esp_ble_mesh_cfg_client_set_state_t set_state = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
|
set_state.model_app_bind.element_addr = node->unicast;
|
|
set_state.model_app_bind.model_app_idx = prov_key.app_idx;
|
|
set_state.model_app_bind.model_id = ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV;
|
|
set_state.model_app_bind.company_id = ESP_BLE_MESH_CID_NVAL;
|
|
err = esp_ble_mesh_config_client_set_state(&common, &set_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Config Model App Bind failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
ESP_LOGE(TAG, "Not a config client status message event");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void example_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_t event,
|
|
esp_ble_mesh_generic_client_cb_param_t *param)
|
|
{
|
|
esp_ble_mesh_client_common_param_t common = {0};
|
|
esp_ble_mesh_node_info_t *node = NULL;
|
|
uint32_t opcode;
|
|
uint16_t addr;
|
|
int err;
|
|
|
|
opcode = param->params->opcode;
|
|
addr = param->params->ctx.addr;
|
|
|
|
ESP_LOGI(TAG, "%s, error_code = 0x%02x, event = 0x%02x, addr: 0x%04x, opcode: 0x%04x",
|
|
__func__, param->error_code, event, param->params->ctx.addr, opcode);
|
|
|
|
if (param->error_code) {
|
|
ESP_LOGE(TAG, "Send generic client message failed, opcode 0x%04x", opcode);
|
|
return;
|
|
}
|
|
|
|
node = example_ble_mesh_get_node_info(addr);
|
|
if (!node) {
|
|
ESP_LOGE(TAG, "%s: Get node info failed", __func__);
|
|
return;
|
|
}
|
|
|
|
switch (event) {
|
|
case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT:
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: {
|
|
esp_ble_mesh_generic_client_set_state_t set_state = {0};
|
|
node->onoff = param->status_cb.onoff_status.present_onoff;
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET onoff: 0x%02x", node->onoff);
|
|
/* After Generic OnOff Status for Generic OnOff Get is received, Generic OnOff Set will be sent */
|
|
example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);
|
|
set_state.onoff_set.op_en = false;
|
|
set_state.onoff_set.onoff = !node->onoff;
|
|
set_state.onoff_set.tid = 0;
|
|
err = esp_ble_mesh_generic_client_set_state(&common, &set_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT:
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
|
|
node->onoff = param->status_cb.onoff_status.present_onoff;
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET onoff: 0x%02x", node->onoff);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT:
|
|
break;
|
|
case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT:
|
|
/* If failed to receive the responses, these messages will be resend */
|
|
switch (opcode) {
|
|
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: {
|
|
esp_ble_mesh_generic_client_get_state_t get_state = {0};
|
|
example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET);
|
|
err = esp_ble_mesh_generic_client_get_state(&common, &get_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Generic OnOff Get failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: {
|
|
esp_ble_mesh_generic_client_set_state_t set_state = {0};
|
|
node->onoff = param->status_cb.onoff_status.present_onoff;
|
|
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET onoff: 0x%02x", node->onoff);
|
|
example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);
|
|
set_state.onoff_set.op_en = false;
|
|
set_state.onoff_set.onoff = !node->onoff;
|
|
set_state.onoff_set.tid = 0;
|
|
err = esp_ble_mesh_generic_client_set_state(&common, &set_state);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
ESP_LOGE(TAG, "Not a generic client status message event");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static esp_err_t ble_mesh_init(void)
|
|
{
|
|
uint8_t match[2] = {0xdd, 0xdd};
|
|
esp_err_t err;
|
|
|
|
prov_key.net_idx = ESP_BLE_MESH_KEY_PRIMARY;
|
|
prov_key.app_idx = APP_KEY_IDX;
|
|
memset(prov_key.app_key, APP_KEY_OCTET, sizeof(prov_key.app_key));
|
|
|
|
esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);
|
|
esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb);
|
|
esp_ble_mesh_register_generic_client_callback(example_ble_mesh_generic_client_cb);
|
|
|
|
|
|
err = esp_ble_mesh_init(&provision, &composition);
|
|
if (err) {
|
|
ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err);
|
|
return err;
|
|
}
|
|
|
|
esp_ble_mesh_provisioner_set_dev_uuid_match(match, sizeof(match), 0x0, false);
|
|
|
|
esp_ble_mesh_provisioner_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
|
|
|
|
esp_ble_mesh_provisioner_add_local_app_key(prov_key.app_key, prov_key.net_idx, prov_key.app_idx);
|
|
|
|
ESP_LOGI(TAG, "BLE Mesh Provisioner initialized");
|
|
|
|
return err;
|
|
}
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_err_t err;
|
|
|
|
ESP_LOGI(TAG, "Initializing...");
|
|
|
|
err = nvs_flash_init();
|
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
|
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
err = nvs_flash_init();
|
|
}
|
|
ESP_ERROR_CHECK(err);
|
|
|
|
err = bluetooth_init();
|
|
if (err) {
|
|
ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err);
|
|
return;
|
|
}
|
|
|
|
ble_mesh_get_dev_uuid(dev_uuid);
|
|
|
|
/* Initialize the Bluetooth Mesh Subsystem */
|
|
err = ble_mesh_init();
|
|
if (err) {
|
|
ESP_LOGE(TAG, "Bluetooth mesh init failed (err %d)", err);
|
|
}
|
|
}
|