OVMS3-idf/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/main/ble_mesh_demo_main.c
lly b19671e0d4 ble_mesh: Add ESP BLE Mesh implementation
1. BLE Mesh Core

    * Provisioning: Node Role
        * PB-ADV and PB-GATT
        * Authentication OOB

    * Provisioning: Provisioner Role
        * PB-ADV and PB-GATT
        * Authentication OOB

    * Networking
        * Relay
        * Segmentation and Reassembly
        * Key Refresh
        * IV Update

    * Proxy Support

    * Multiple Client Models Run Simultaneously
        * Support multiple client models send packets to different nodes simultaneously
        * No blocking between client model and server

    * NVS Storage
        * Store BLE Mesh node related information in flash
        * Store BLE Mesh Provisioner related information in flash

2. BLE Mesh Models

    * Foundation Models
        * Configuration Server Model
        * Configuration Client Model
        * Health Server Model
        * Health Client Model

    * Generic
        * Generic OnOff Server
        * Generic OnOff Client
        * Generic Level Server
        * Generic Level Client
        * Generic Default Transition Time Server
        * Generic Default Transition Time Client
        * Generic Power OnOff Server
        * Generic Power OnOff Setup Server
        * Generic Power OnOff Client
        * Generic Power Level Server
        * Generic Power Level Setup Server
        * Generic Power Level Client
        * Generic Battery Server
        * Generic Battery Client
        * Generic Location Server
        * Generic Location Setup Server
        * Generic Location Client
        * Generic Admin Property Server
        * Generic Manufacturer Property Server
        * Generic User Property Server
        * Generic Client Property Server
        * Generic Property Client

    * Sensor Server Model
        * Sensor Server
        * Sensor Setup Server
        * Sensor Client

    * Time and Scenes
        * Time Server
        * Time Setup Server
        * Time Client
        * Scene Server
        * Scene Setup Server
        * Scene Client
        * Scheduler Server
        * Scheduler Setup Server
        * Scheduler Client

    * Lighting
        * Light Lightness Server
        * Light Lightness Setup Server
        * Light Lightness Client
        * Light CTL Server
        * Light CTL Setup Server
        * Light CTL Client
        * Light CTL Temperature Server
        * Light HSL Server
        * Light HSL Setup Server
        * Light HSL Client
        * Light HSL Hue Server
        * Light HSL Saturation Server
        * Light xyL Server
        * Light xyL Setup Server
        * Light xyL Client
        * Light LC Server
        * Light LC Setup Server
        * Light LC Client

3. BLE Mesh Applications

    * BLE Mesh Node
        * OnOff Client Example
        * OnOff Server Example

    * BLE Mesh Provisioner
        * Example

    * Fast Provisioning
        * Vendor Fast Prov Server Model
        * Vendor Fast Prov Client Model
        * Examples

    * Wi-Fi & BLE Mesh Coexistence
        * Example

    * BLE Mesh Console Commands
        * Examples
2020-02-03 12:03:36 +08:00

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_demo_init.h"
#define LED_OFF 0x0
#define LED_ON 0x1
#define CID_ESP 0x02E5
#define CID_NVAL 0xFFFF
#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[10];
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, 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 = 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 = 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);
}
}