mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ble_mesh: update ble mesh examples
This commit is contained in:
parent
a302d210b9
commit
e0e62232e0
@ -1,496 +0,0 @@
|
||||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional 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_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 "board.h"
|
||||
#include "ble_mesh_demo_init.h"
|
||||
|
||||
#define CID_ESP 0x02E5
|
||||
|
||||
#define MSG_SEND_TTL 3
|
||||
#define MSG_SEND_REL false
|
||||
#define MSG_TIMEOUT 0 /* 0 indicates that timeout value from menuconfig will be used */
|
||||
#define MSG_ROLE ROLE_NODE
|
||||
|
||||
extern struct _led_state led_state[3];
|
||||
|
||||
static uint8_t dev_uuid[16] = { 0xdd, 0xdd };
|
||||
static uint16_t node_net_idx = ESP_BLE_MESH_KEY_UNUSED;
|
||||
static uint16_t node_app_idx = ESP_BLE_MESH_KEY_UNUSED;
|
||||
static uint8_t remote_onoff = LED_OFF;
|
||||
|
||||
/* The remote node address shall be input through UART1, see board.c */
|
||||
uint16_t remote_addr = ESP_BLE_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_srv_pub, 2 + 1, MSG_ROLE);
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_cli_pub, 2 + 1, MSG_ROLE);
|
||||
|
||||
static esp_ble_mesh_model_op_t onoff_op[] = {
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2),
|
||||
/* Each model operation struct array must use this terminator
|
||||
* as the end tag of the operation uint. */
|
||||
ESP_BLE_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t root_models[] = {
|
||||
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
|
||||
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op,
|
||||
&onoff_srv_pub, &led_state[0]),
|
||||
ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI(&onoff_cli_pub, &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),
|
||||
};
|
||||
|
||||
/* Disable OOB security for SILabs Android app */
|
||||
static esp_ble_mesh_prov_t provision = {
|
||||
.uuid = dev_uuid,
|
||||
#if 0
|
||||
.output_size = 4,
|
||||
.output_actions = ESP_BLE_MESH_DISPLAY_NUMBER,
|
||||
.input_actions = ESP_BLE_MESH_PUSH,
|
||||
.input_size = 4,
|
||||
#else
|
||||
.output_size = 0,
|
||||
.output_actions = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int output_number(esp_ble_mesh_output_action_t action, uint32_t number)
|
||||
{
|
||||
board_output_number(action, number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
||||
{
|
||||
ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr);
|
||||
ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index);
|
||||
board_prov_complete();
|
||||
node_net_idx = net_idx;
|
||||
}
|
||||
|
||||
static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t length, uint8_t *data)
|
||||
{
|
||||
struct _led_state *led = (struct _led_state *)model->user_data;
|
||||
uint8_t send_data;
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
|
||||
|
||||
send_data = led->current;
|
||||
/* Send Generic OnOff Status as a response to Generic OnOff Get */
|
||||
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t length, uint8_t *data)
|
||||
{
|
||||
struct _led_state *led = (struct _led_state *)model->user_data;
|
||||
uint8_t prev_onoff;
|
||||
esp_err_t err;
|
||||
|
||||
prev_onoff = led->previous;
|
||||
led->current = data[0];
|
||||
remote_onoff = led->current;
|
||||
|
||||
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
|
||||
|
||||
board_led_operation(led->pin, led->current);
|
||||
|
||||
/* If Generic OnOff state is changed, and the publish address of Generic OnOff Server
|
||||
* model is valid, Generic OnOff Status will be published.
|
||||
*/
|
||||
if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
||||
ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current);
|
||||
err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(led->current), &led->current, ROLE_NODE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t length, uint8_t *data)
|
||||
{
|
||||
struct net_buf_simple *msg = model->pub->msg;
|
||||
struct _led_state *led = (struct _led_state *)model->user_data;
|
||||
uint8_t prev_onoff, send_data;
|
||||
esp_err_t err;
|
||||
|
||||
prev_onoff = led->previous;
|
||||
led->current = data[0];
|
||||
remote_onoff = led->current;
|
||||
|
||||
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
|
||||
|
||||
board_led_operation(led->pin, led->current);
|
||||
|
||||
send_data = led->current;
|
||||
/* Send Generic OnOff Status as a response to Generic OnOff Get */
|
||||
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If Generic OnOff state is changed, and the publish address of Generic OnOff Server
|
||||
* model is valid, Generic OnOff Status will be published.
|
||||
*/
|
||||
if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
||||
ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current);
|
||||
bt_mesh_model_msg_init(msg, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS);
|
||||
err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data, ROLE_NODE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *esp_ble_mesh_prov_event_to_str(esp_ble_mesh_prov_cb_event_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
||||
return "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_INPUT_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_INPUT_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_RESET_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_RESET_EVT";
|
||||
default:
|
||||
return "Invalid BLE Mesh provision event";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event,
|
||||
esp_ble_mesh_prov_cb_param_t *param)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s, event = %s", __func__, esp_ble_mesh_prov_event_to_str(event));
|
||||
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT, bearer %s",
|
||||
param->node_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT, bearer %s",
|
||||
param->node_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT:
|
||||
output_number(param->node_prov_output_num.action, param->node_prov_output_num.number);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_INPUT_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
|
||||
prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr,
|
||||
param->node_prov_complete.flags, param->node_prov_complete.iv_index);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_RESET_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT, err_code %d", param->node_set_unprov_dev_name_comp.err_code);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static esp_err_t esp_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common,
|
||||
esp_ble_mesh_generic_client_set_state_t *set,
|
||||
esp_ble_mesh_model_t *model, uint32_t opcode,
|
||||
uint8_t onoff)
|
||||
{
|
||||
if (!common || !set || !model) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
common->opcode = opcode;
|
||||
common->model = model;
|
||||
common->ctx.net_idx = node_net_idx;
|
||||
common->ctx.app_idx = node_app_idx;
|
||||
common->ctx.addr = remote_addr;
|
||||
common->ctx.send_ttl = MSG_SEND_TTL;
|
||||
common->ctx.send_rel = MSG_SEND_REL;
|
||||
common->msg_timeout = MSG_TIMEOUT;
|
||||
common->msg_role = MSG_ROLE;
|
||||
set->onoff_set.op_en = false;
|
||||
set->onoff_set.onoff = onoff;
|
||||
set->onoff_set.tid = 0x0;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static void esp_ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event,
|
||||
esp_ble_mesh_model_cb_param_t *param)
|
||||
{
|
||||
esp_ble_mesh_client_common_param_t common = {0};
|
||||
int err;
|
||||
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_MODEL_OPERATION_EVT: {
|
||||
if (!param->model_operation.model || !param->model_operation.model->op || !param->model_operation.ctx) {
|
||||
ESP_LOGE(TAG, "ESP_BLE_MESH_MODEL_OPERATION_EVT parameter is NULL");
|
||||
return;
|
||||
}
|
||||
if (node_app_idx == ESP_BLE_MESH_KEY_UNUSED) {
|
||||
/* Generic OnOff Server/Client Models need to bind with the same app key */
|
||||
node_app_idx = param->model_operation.ctx->app_idx;
|
||||
}
|
||||
switch (param->model_operation.opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
|
||||
gen_onoff_get_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: {
|
||||
esp_ble_mesh_generic_client_set_state_t set_state = {0};
|
||||
gen_onoff_set_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
/* This node has a Generic OnOff Client and Server Model.
|
||||
* When Generic OnOff Server Model receives a Generic OnOff Set message, after
|
||||
* this message is been handled, the Generic OnOff Client Model will send the
|
||||
* Generic OnOff Set message to another node(contains Generic OnOff Server Model)
|
||||
* identified by the remote_addr.
|
||||
*/
|
||||
esp_ble_mesh_set_msg_common(&common, &set_state, onoff_client.model,
|
||||
ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, remote_onoff);
|
||||
err = esp_ble_mesh_generic_client_set_state(&common, &set_state);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK: {
|
||||
esp_ble_mesh_generic_client_set_state_t set_state = {0};
|
||||
gen_onoff_set_unack_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
/* This node has a Generic OnOff Client and Server Model.
|
||||
* When Generic OnOff Client Model receives a Generic OnOff Set Unack message,
|
||||
* after this message is been handled, the Generic OnOff Client Model will send
|
||||
* the Generic OnOff Set Unack message to another node(contains Generic OnOff
|
||||
* Server Model) identified by the remote_addr.
|
||||
*/
|
||||
esp_ble_mesh_set_msg_common(&common, &set_state, onoff_client.model,
|
||||
ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, remote_onoff);
|
||||
err = esp_ble_mesh_generic_client_set_state(&common, &set_state);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Set Unack failed", __func__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_MODEL_SEND_COMP_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_generic_cb(esp_ble_mesh_generic_client_cb_event_t event,
|
||||
esp_ble_mesh_generic_client_cb_param_t *param)
|
||||
{
|
||||
uint32_t opcode;
|
||||
int err;
|
||||
|
||||
ESP_LOGI(TAG, "%s: event is %d, error code is %d, opcode is 0x%x",
|
||||
__func__, event, param->error_code, param->params->opcode);
|
||||
|
||||
opcode = param->params->opcode;
|
||||
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT");
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: onoff %d", param->status_cb.onoff_status.present_onoff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT");
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: onoff %d", param->status_cb.onoff_status.present_onoff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT");
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT: {
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT");
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: {
|
||||
esp_ble_mesh_client_common_param_t common = {0};
|
||||
esp_ble_mesh_generic_client_set_state_t set_state = {0};
|
||||
/* If failed to get the response of Generic OnOff Set, resend Generic OnOff Set */
|
||||
esp_ble_mesh_set_msg_common(&common, &set_state, onoff_client.model,
|
||||
ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, remote_onoff);
|
||||
err = esp_ble_mesh_generic_client_set_state(&common, &set_state);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int ble_mesh_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
esp_ble_mesh_register_prov_callback(esp_ble_mesh_prov_cb);
|
||||
esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb);
|
||||
esp_ble_mesh_register_generic_client_callback(esp_ble_mesh_generic_cb);
|
||||
|
||||
err = esp_ble_mesh_init(&provision, &composition);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
|
||||
|
||||
ESP_LOGI(TAG, "BLE Mesh Node initialized");
|
||||
|
||||
board_led_operation(LED_G, LED_ON);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing...");
|
||||
|
||||
board_init();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/* board.c - Board-specific hooks */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_ble_mesh_provisioning_api.h"
|
||||
#include "board.h"
|
||||
|
||||
#define TAG "BOARD"
|
||||
|
||||
#define MESH_UART_NUM UART_NUM_1
|
||||
#define MESH_UART (&UART1)
|
||||
|
||||
#define UART_BUF_SIZE 128
|
||||
|
||||
#define UART1_TX_PIN GPIO_NUM_16
|
||||
#define UART1_RX_PIN GPIO_NUM_17
|
||||
|
||||
extern uint16_t remote_addr;
|
||||
|
||||
struct _led_state led_state[3] = {
|
||||
{ LED_OFF, LED_OFF, LED_R, "red" },
|
||||
{ LED_OFF, LED_OFF, LED_G, "green" },
|
||||
{ LED_OFF, LED_OFF, LED_B, "blue" },
|
||||
};
|
||||
|
||||
void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number)
|
||||
{
|
||||
ESP_LOGI(TAG, "Board output number %d", number);
|
||||
}
|
||||
|
||||
void board_prov_complete(void)
|
||||
{
|
||||
board_led_operation(LED_G, LED_OFF);
|
||||
}
|
||||
|
||||
void board_led_operation(uint8_t pin, uint8_t onoff)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(led_state); i++) {
|
||||
if (led_state[i].pin != pin) {
|
||||
continue;
|
||||
}
|
||||
if (onoff == led_state[i].previous) {
|
||||
ESP_LOGW(TAG, "led %s is already %s",
|
||||
led_state[i].name, (onoff ? "on" : "off"));
|
||||
return;
|
||||
}
|
||||
gpio_set_level(pin, onoff);
|
||||
led_state[i].previous = onoff;
|
||||
return;
|
||||
}
|
||||
ESP_LOGE(TAG, "LED is not found!");
|
||||
}
|
||||
|
||||
static void board_uart_task(void *p)
|
||||
{
|
||||
uint8_t *data = calloc(1, UART_BUF_SIZE);
|
||||
uint32_t input;
|
||||
|
||||
while (1) {
|
||||
int len = uart_read_bytes(MESH_UART_NUM, data, UART_BUF_SIZE, 100 / portTICK_RATE_MS);
|
||||
if (len > 0) {
|
||||
input = strtoul((const char *)data, NULL, 16);
|
||||
remote_addr = input & 0xFFFF;
|
||||
ESP_LOGI(TAG, "%s: input 0x%08x, remote_addr 0x%04x", __func__, input, remote_addr);
|
||||
memset(data, 0, UART_BUF_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void board_led_init(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(led_state); i++) {
|
||||
gpio_pad_select_gpio(led_state[i].pin);
|
||||
gpio_set_direction(led_state[i].pin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(led_state[i].pin, LED_OFF);
|
||||
led_state[i].previous = LED_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void board_uart_init(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
|
||||
};
|
||||
uart_param_config(MESH_UART_NUM, &uart_config);
|
||||
uart_set_pin(MESH_UART_NUM, UART1_TX_PIN, UART1_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
uart_driver_install(MESH_UART_NUM, UART_BUF_SIZE * 2, 0, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
board_led_init();
|
||||
board_uart_init();
|
||||
xTaskCreate(board_uart_task, "board_uart_task", 2048, NULL, 5, NULL);
|
||||
}
|
@ -574,7 +574,7 @@ static esp_err_t ble_mesh_init(void)
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
int err;
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing...");
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#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 "board.h"
|
||||
#include "esp_fast_prov_operation.h"
|
||||
@ -95,15 +96,12 @@ example_fast_prov_server_t fast_prov_server = {
|
||||
.state = STATE_IDLE,
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_op_t onoff_op[] = {
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2),
|
||||
ESP_BLE_MESH_MODEL_OP_END,
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 3, ROLE_FAST_PROV);
|
||||
static esp_ble_mesh_gen_onoff_srv_t onoff_server = {
|
||||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 1, ROLE_FAST_PROV);
|
||||
|
||||
static esp_ble_mesh_model_op_t fast_prov_srv_op[] = {
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET, 3),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD, 16),
|
||||
@ -124,8 +122,7 @@ static esp_ble_mesh_model_op_t fast_prov_cli_op[] = {
|
||||
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_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op,
|
||||
&onoff_pub, &led_state[1]),
|
||||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub, &onoff_server),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t vnd_models[] = {
|
||||
@ -158,29 +155,11 @@ static esp_ble_mesh_prov_t prov = {
|
||||
.iv_index = 0x00,
|
||||
};
|
||||
|
||||
static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, uint8_t *data)
|
||||
static void example_change_led_state(uint8_t onoff)
|
||||
{
|
||||
struct _led_state *led = NULL;
|
||||
uint8_t send_data;
|
||||
esp_err_t err;
|
||||
struct _led_state *led = &led_state[1];
|
||||
|
||||
led = (struct _led_state *)model->user_data;
|
||||
if (!led) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get generic onoff server model user_data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
send_data = led->current;
|
||||
|
||||
/* Sends Generic OnOff Status as a reponse to Generic OnOff Get */
|
||||
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Generic OnOff Status message", __func__);
|
||||
return;
|
||||
}
|
||||
board_led_operation(led->pin, onoff);
|
||||
|
||||
/* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will
|
||||
* start the timer used to disable fast provisioning functionality.
|
||||
@ -190,37 +169,6 @@ static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, uint8_t *data)
|
||||
{
|
||||
struct _led_state *led = NULL;
|
||||
|
||||
led = (struct _led_state *)model->user_data;
|
||||
if (!led) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get generic onoff server model user_data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
led->current = data[0];
|
||||
gpio_set_level(led->pin, led->current);
|
||||
|
||||
/* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will
|
||||
* start the timer used to disable fast provisioning functionality.
|
||||
*/
|
||||
if (!bt_mesh_atomic_test_and_set_bit(fast_prov_server.srv_flags, DISABLE_FAST_PROV_START)) {
|
||||
k_delayed_work_submit(&fast_prov_server.disable_fast_prov_timer, DISABLE_FAST_PROV_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, uint8_t *data)
|
||||
{
|
||||
gen_onoff_set_unack_handler(model, ctx, len, data);
|
||||
gen_onoff_get_handler(model, ctx, len, data);
|
||||
}
|
||||
|
||||
static void node_prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
||||
{
|
||||
ESP_LOGI(TAG, "net_idx: 0x%04x, unicast_addr: 0x%04x", net_idx, addr);
|
||||
@ -484,14 +432,6 @@ static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event
|
||||
}
|
||||
opcode = param->model_operation.opcode;
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
|
||||
gen_onoff_set_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK:
|
||||
gen_onoff_set_unack_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET:
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD:
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR:
|
||||
@ -724,6 +664,27 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t
|
||||
}
|
||||
}
|
||||
|
||||
static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event,
|
||||
esp_ble_mesh_generic_server_cb_param_t *param)
|
||||
{
|
||||
ESP_LOGI(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x",
|
||||
event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst);
|
||||
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT");
|
||||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||
|
||||
param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
|
||||
ESP_LOGI(TAG, "onoff 0x%02x", param->value.state_change.onoff_set.onoff);
|
||||
example_change_led_state(param->value.state_change.onoff_set.onoff);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Unknown Generic Server event 0x%02x", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ble_mesh_init(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
@ -732,6 +693,7 @@ static esp_err_t ble_mesh_init(void)
|
||||
esp_ble_mesh_register_custom_model_callback(example_ble_mesh_custom_model_cb);
|
||||
esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb);
|
||||
esp_ble_mesh_register_config_server_callback(example_ble_mesh_config_server_cb);
|
||||
esp_ble_mesh_register_generic_server_callback(example_ble_mesh_generic_server_cb);
|
||||
|
||||
err = esp_ble_mesh_init(&prov, &comp);
|
||||
if (err != ESP_OK) {
|
||||
|
@ -1,358 +0,0 @@
|
||||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional 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_networking_api.h"
|
||||
#include "esp_ble_mesh_provisioning_api.h"
|
||||
#include "esp_ble_mesh_config_model_api.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "ble_mesh_demo_init.h"
|
||||
|
||||
#define CID_ESP 0x02E5
|
||||
|
||||
extern struct _led_state led_state[3];
|
||||
|
||||
static uint8_t dev_uuid[16] = { 0xdd, 0xdd };
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 1, ROLE_NODE);
|
||||
|
||||
static esp_ble_mesh_model_op_t onoff_op[] = {
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2),
|
||||
/* Each model operation struct array must use this terminator
|
||||
* as the end tag of the operation uint. */
|
||||
ESP_BLE_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t root_models[] = {
|
||||
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
|
||||
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op,
|
||||
&onoff_pub, &led_state[0]),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t extend_model_0[] = {
|
||||
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op,
|
||||
&onoff_pub, &led_state[1]),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t extend_model_1[] = {
|
||||
ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op,
|
||||
&onoff_pub, &led_state[2]),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_elem_t elements[] = {
|
||||
ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE),
|
||||
ESP_BLE_MESH_ELEMENT(0, extend_model_0, ESP_BLE_MESH_MODEL_NONE),
|
||||
ESP_BLE_MESH_ELEMENT(0, extend_model_1, ESP_BLE_MESH_MODEL_NONE),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_comp_t composition = {
|
||||
.cid = CID_ESP,
|
||||
.elements = elements,
|
||||
.element_count = ARRAY_SIZE(elements),
|
||||
};
|
||||
|
||||
/* Disable OOB security for SILabs Android app */
|
||||
static esp_ble_mesh_prov_t provision = {
|
||||
.uuid = dev_uuid,
|
||||
#if 0
|
||||
.output_size = 4,
|
||||
.output_actions = ESP_BLE_MESH_DISPLAY_NUMBER,
|
||||
.input_actions = ESP_BLE_MESH_PUSH,
|
||||
.input_size = 4,
|
||||
#else
|
||||
.output_size = 0,
|
||||
.output_actions = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int output_number(esp_ble_mesh_output_action_t action, uint32_t number)
|
||||
{
|
||||
board_output_number(action, number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
||||
{
|
||||
ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr);
|
||||
ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index);
|
||||
board_prov_complete();
|
||||
}
|
||||
|
||||
static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t length, uint8_t *data)
|
||||
{
|
||||
struct _led_state *led = (struct _led_state *)model->user_data;
|
||||
uint8_t send_data;
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
|
||||
|
||||
send_data = led->current;
|
||||
/* Send Generic OnOff Status as a response to Generic OnOff Get */
|
||||
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t length, uint8_t *data)
|
||||
{
|
||||
struct _led_state *led = (struct _led_state *)model->user_data;
|
||||
uint8_t prev_onoff;
|
||||
esp_err_t err;
|
||||
|
||||
prev_onoff = led->previous;
|
||||
led->current = data[0];
|
||||
|
||||
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
|
||||
|
||||
board_led_operation(led->pin, led->current);
|
||||
|
||||
/* If Generic OnOff state is changed, and the publish address of Generic OnOff Server
|
||||
* model is valid, Generic OnOff Status will be published.
|
||||
*/
|
||||
if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
||||
ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current);
|
||||
err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(led->current), &led->current, ROLE_NODE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t length, uint8_t *data)
|
||||
{
|
||||
struct _led_state *led = (struct _led_state *)model->user_data;
|
||||
uint8_t prev_onoff, send_data;
|
||||
esp_err_t err;
|
||||
|
||||
prev_onoff = led->previous;
|
||||
led->current = data[0];
|
||||
|
||||
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
|
||||
|
||||
board_led_operation(led->pin, led->current);
|
||||
|
||||
send_data = led->current;
|
||||
/* Send Generic OnOff Status as a response to Generic OnOff Get */
|
||||
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If Generic OnOff state is changed, and the publish address of Generic OnOff Server
|
||||
* model is valid, Generic OnOff Status will be published.
|
||||
*/
|
||||
if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) {
|
||||
ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current);
|
||||
err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data, ROLE_NODE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *esp_ble_mesh_prov_event_to_str(esp_ble_mesh_prov_cb_event_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
||||
return "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_INPUT_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_INPUT_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT";
|
||||
case ESP_BLE_MESH_NODE_PROV_RESET_EVT:
|
||||
return "ESP_BLE_MESH_NODE_PROV_RESET_EVT";
|
||||
default:
|
||||
return "Invalid BLE Mesh provision event";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event,
|
||||
esp_ble_mesh_prov_cb_param_t *param)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s, event = %s", __func__, esp_ble_mesh_prov_event_to_str(event));
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT, bearer %s",
|
||||
param->node_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT, bearer %s",
|
||||
param->node_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT:
|
||||
output_number(param->node_prov_output_num.action, param->node_prov_output_num.number);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_INPUT_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
|
||||
prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr,
|
||||
param->node_prov_complete.flags, param->node_prov_complete.iv_index);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_RESET_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT, err_code %d", param->node_set_unprov_dev_name_comp.err_code);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event,
|
||||
esp_ble_mesh_model_cb_param_t *param)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_MODEL_OPERATION_EVT: {
|
||||
if (!param->model_operation.model || !param->model_operation.model->op || !param->model_operation.ctx) {
|
||||
ESP_LOGE(TAG, "ESP_BLE_MESH_MODEL_OPERATION_EVT parameter is NULL");
|
||||
return;
|
||||
}
|
||||
switch (param->model_operation.opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
|
||||
gen_onoff_get_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
|
||||
gen_onoff_set_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK:
|
||||
gen_onoff_set_unack_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_MESH_MODEL_SEND_COMP_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ble_mesh_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
esp_ble_mesh_register_prov_callback(esp_ble_mesh_prov_cb);
|
||||
esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb);
|
||||
|
||||
err = esp_ble_mesh_init(&provision, &composition);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
|
||||
|
||||
ESP_LOGI(TAG, "BLE Mesh Node initialized");
|
||||
|
||||
board_led_operation(LED_G, LED_ON);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing...");
|
||||
|
||||
board_init();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
/* board.c - Board-specific hooks */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "board.h"
|
||||
#include "esp_ble_mesh_provisioning_api.h"
|
||||
|
||||
#define TAG "BOARD"
|
||||
|
||||
#define INTR_FLAG_DEFAULT 0
|
||||
|
||||
static xQueueHandle s_evt_queue;
|
||||
|
||||
struct _led_state led_state[3] = {
|
||||
{ LED_OFF, LED_OFF, LED_R, "red" },
|
||||
{ LED_OFF, LED_OFF, LED_G, "green" },
|
||||
{ LED_OFF, LED_OFF, LED_B, "blue" },
|
||||
};
|
||||
|
||||
void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number)
|
||||
{
|
||||
ESP_LOGI(TAG, "Board output number %d", number);
|
||||
}
|
||||
|
||||
void board_prov_complete(void)
|
||||
{
|
||||
board_led_operation(LED_G, LED_OFF);
|
||||
}
|
||||
|
||||
void board_led_operation(uint8_t pin, uint8_t onoff)
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (led_state[i].pin != pin) {
|
||||
continue;
|
||||
}
|
||||
if (onoff == led_state[i].previous) {
|
||||
ESP_LOGW(TAG, "led %s is already %s",
|
||||
led_state[i].name, (onoff ? "on" : "off"));
|
||||
return;
|
||||
}
|
||||
gpio_set_level(pin, onoff);
|
||||
led_state[i].previous = onoff;
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "LED is not found!");
|
||||
}
|
||||
|
||||
static void board_led_init(void)
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
gpio_pad_select_gpio(led_state[i].pin);
|
||||
gpio_set_direction(led_state[i].pin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(led_state[i].pin, LED_OFF);
|
||||
led_state[i].previous = LED_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR switch_isr_handler(void *arg)
|
||||
{
|
||||
uint32_t gpio_num = (uint32_t) arg;
|
||||
xQueueSendFromISR(s_evt_queue, &gpio_num, NULL);
|
||||
}
|
||||
|
||||
static void switch_key_init(uint32_t key)
|
||||
{
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_NEGEDGE;
|
||||
io_conf.pin_bit_mask = 1 << key;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_up_en = 1;
|
||||
io_conf.pull_down_en = 0;
|
||||
gpio_config(&io_conf);
|
||||
|
||||
gpio_set_intr_type(key, GPIO_INTR_NEGEDGE);
|
||||
gpio_install_isr_service(INTR_FLAG_DEFAULT);
|
||||
gpio_isr_handler_add(key, switch_isr_handler, (void *)key);
|
||||
}
|
||||
|
||||
static void switch_task_entry(void *arg)
|
||||
{
|
||||
while (1) {
|
||||
uint32_t io_num;
|
||||
if (xQueueReceive(s_evt_queue, &io_num, portMAX_DELAY) == pdTRUE) {
|
||||
uint8_t onoff = led_state[0].previous;
|
||||
ESP_LOGI(TAG, "GPIO[%d] intr, val: %d", io_num, gpio_get_level(io_num));
|
||||
board_led_operation(LED_R, !onoff);
|
||||
led_state[0].previous = !onoff;
|
||||
//TODO: publish state change message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void switch_init(gpio_num_t gpio_num)
|
||||
{
|
||||
s_evt_queue = xQueueCreate(3, sizeof(uint32_t));
|
||||
if (!s_evt_queue) {
|
||||
return;
|
||||
}
|
||||
|
||||
BaseType_t ret = xTaskCreate(switch_task_entry, "switch", 4096, NULL, 4, NULL);
|
||||
if (ret == pdFAIL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch_key_init(gpio_num);
|
||||
return;
|
||||
|
||||
fail:
|
||||
vQueueDelete(s_evt_queue);
|
||||
}
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
board_led_init();
|
||||
switch_init(GPIO_NUM_18);
|
||||
}
|
@ -3,4 +3,4 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(ble_mesh_node)
|
||||
project(onoff_client)
|
@ -3,7 +3,7 @@
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := ble_mesh_node
|
||||
PROJECT_NAME := onoff_client
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := components/include
|
||||
|
@ -0,0 +1,7 @@
|
||||
|
||||
set(COMPONENT_SRCS "button.c"
|
||||
"button_obj.cpp")
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ". include")
|
||||
|
||||
register_component()
|
@ -0,0 +1,21 @@
|
||||
menu "Button"
|
||||
|
||||
choice BUTTON_TIMER_IMPLEMENT
|
||||
bool "Button Timer Mode"
|
||||
default BUTTON_USE_ESP_TIMER
|
||||
help
|
||||
Choose a implementation of timer for button instance.
|
||||
|
||||
config BUTTON_USE_RTOS_TIMER
|
||||
bool "Use FreeRTOS Timer"
|
||||
|
||||
config BUTTON_USE_ESP_TIMER
|
||||
bool "Use ESP Timer"
|
||||
endchoice
|
||||
|
||||
config BUTTON_IO_GLITCH_FILTER_TIME_MS
|
||||
int "IO glitch filter timer ms (10~100)"
|
||||
range 10 100
|
||||
default 50
|
||||
|
||||
endmenu
|
@ -0,0 +1,47 @@
|
||||
# Component: Button
|
||||
|
||||
* This component defines a button as a well encapsulated object.
|
||||
* A button device is defined by:
|
||||
* GPIO number on which the button is attached.
|
||||
* Active level which decided by peripheral hardware.
|
||||
* Trigger mode which decides whether to call serial trigger callback during pressing
|
||||
* Serial threshold seconds which decides that serial trigger callback will be called after how many seconds' pressing
|
||||
* A button device can provide:
|
||||
* One push event callback
|
||||
* One release event callback
|
||||
* One short-time tap event callback
|
||||
* One serial trigger event callback
|
||||
* Several long-time press event callback
|
||||
We can set different jitter filters for all the events.
|
||||
Once any of the long press callback is triggered, the short tap event will not be triggered.
|
||||
This components are based on GPIO provided by idf and soft timer provided by FreeRTOS.
|
||||
|
||||
* To use the button device, you need to :
|
||||
* create a button object returned by iot_button_create().
|
||||
* Then hook different event callbacks to the button object.
|
||||
* To free the object, you can call iot_button_delete to delete the button object and free the memory that used.
|
||||
|
||||
* Todo:
|
||||
* Add hardware timer mode(because sometimes soft-timer callback function is limited)
|
||||
|
||||
### NOTE:
|
||||
> All the event callback function are realized by FreeRTOS soft timer APIs, the callback must follow the rule:
|
||||
|
||||
|
||||
|
||||
```
|
||||
Button callback functions execute in the context of the timer service task.
|
||||
It is therefore essential that button callback functions never attempt to block.
|
||||
For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(), or specify a non zero block time when accessing a queue or a semaphore.
|
||||
```
|
||||
|
||||
> In addition:
|
||||
> You can adjust the following macros within FreeRTOS to adjust the stack depth/queue length/task priority of the timer service.
|
||||
|
||||
|
||||
```
|
||||
#define configUSE_TIMERS //enable soft-timer
|
||||
#define configTIMER_TASK_PRIORITY // priority of the timers service task
|
||||
#define configQueue_LENGTH // length of timer command queue
|
||||
#define configTIMER_TASK_STACK_DEPTH // stack depth of the soft-timer
|
||||
```
|
@ -0,0 +1,434 @@
|
||||
// Copyright 2015-2016 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 "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "iot_button.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#define USE_ESP_TIMER CONFIG_BUTTON_USE_ESP_TIMER
|
||||
#if USE_ESP_TIMER
|
||||
#define STOP_TIMER(tmr) esp_timer_stop(tmr)
|
||||
#define DELETE_TIMER(tmr) esp_timer_delete(tmr)
|
||||
#else
|
||||
#define STOP_TIMER(tmr) xTimerStop(tmr, portMAX_DELAY)
|
||||
#define DELETE_TIMER(tmr) xTimerDelete(tmr, portMAX_DELAY);
|
||||
#endif
|
||||
|
||||
#define IOT_CHECK(tag, a, ret) if(!(a)) { \
|
||||
ESP_LOGE(tag,"%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__); \
|
||||
return (ret); \
|
||||
}
|
||||
#define ERR_ASSERT(tag, param) IOT_CHECK(tag, (param) == ESP_OK, ESP_FAIL)
|
||||
#define POINT_ASSERT(tag, param, ret) IOT_CHECK(tag, (param) != NULL, (ret))
|
||||
|
||||
typedef enum {
|
||||
BUTTON_STATE_IDLE = 0,
|
||||
BUTTON_STATE_PUSH,
|
||||
BUTTON_STATE_PRESSED,
|
||||
} button_status_t;
|
||||
|
||||
typedef struct button_dev button_dev_t;
|
||||
typedef struct btn_cb button_cb_t;
|
||||
|
||||
struct btn_cb{
|
||||
TickType_t interval;
|
||||
button_cb cb;
|
||||
void* arg;
|
||||
#if !USE_ESP_TIMER
|
||||
TimerHandle_t tmr;
|
||||
#else
|
||||
esp_timer_handle_t tmr;
|
||||
#endif
|
||||
button_dev_t *pbtn;
|
||||
button_cb_t *next_cb;
|
||||
};
|
||||
|
||||
struct button_dev{
|
||||
uint8_t io_num;
|
||||
uint8_t active_level;
|
||||
uint32_t serial_thres_sec;
|
||||
button_status_t state;
|
||||
button_cb_t tap_short_cb;
|
||||
button_cb_t tap_psh_cb;
|
||||
button_cb_t tap_rls_cb;
|
||||
button_cb_t press_serial_cb;
|
||||
button_cb_t* cb_head;
|
||||
};
|
||||
|
||||
#define BUTTON_GLITCH_FILTER_TIME_MS CONFIG_BUTTON_IO_GLITCH_FILTER_TIME_MS
|
||||
static const char* TAG = "button";
|
||||
|
||||
// static void button_press_cb(xTimerHandle tmr)
|
||||
static void button_press_cb(void* tmr)
|
||||
{
|
||||
#if !USE_ESP_TIMER
|
||||
button_cb_t* btn_cb = (button_cb_t*) pvTimerGetTimerID(tmr);
|
||||
#else
|
||||
button_cb_t* btn_cb = (button_cb_t*)(tmr);
|
||||
#endif
|
||||
|
||||
button_dev_t* btn = btn_cb->pbtn;
|
||||
// low, then restart
|
||||
if (btn->active_level == gpio_get_level(btn->io_num)) {
|
||||
btn->state = BUTTON_STATE_PRESSED;
|
||||
if (btn_cb->cb) {
|
||||
btn_cb->cb(btn_cb->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static void button_tap_psh_cb(xTimerHandle tmr)
|
||||
static void button_tap_psh_cb(void* tmr)
|
||||
{
|
||||
#if !USE_ESP_TIMER
|
||||
button_cb_t* btn_cb = (button_cb_t*) pvTimerGetTimerID(tmr);
|
||||
#else
|
||||
button_cb_t* btn_cb = (button_cb_t*)(tmr);
|
||||
#endif
|
||||
|
||||
button_dev_t* btn = btn_cb->pbtn;
|
||||
STOP_TIMER(btn->tap_rls_cb.tmr);
|
||||
|
||||
int lv = gpio_get_level(btn->io_num);
|
||||
|
||||
if (btn->active_level == lv) {
|
||||
// high, then key is up
|
||||
btn->state = BUTTON_STATE_PUSH;
|
||||
if (btn->press_serial_cb.tmr) {
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerChangePeriod(btn->press_serial_cb.tmr, btn->serial_thres_sec*1000 / portTICK_PERIOD_MS, portMAX_DELAY);
|
||||
xTimerReset(btn->press_serial_cb.tmr, portMAX_DELAY);
|
||||
#else
|
||||
esp_timer_stop(btn->press_serial_cb.tmr);
|
||||
esp_timer_start_once(btn->press_serial_cb.tmr, btn->serial_thres_sec * 1000 * 1000);
|
||||
#endif
|
||||
|
||||
}
|
||||
if (btn->tap_psh_cb.cb) {
|
||||
btn->tap_psh_cb.cb(btn->tap_psh_cb.arg);
|
||||
}
|
||||
} else {
|
||||
// 50ms, check if this is a real key up
|
||||
if (btn->tap_rls_cb.tmr) {
|
||||
STOP_TIMER(btn->tap_rls_cb.tmr);
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerReset(btn->tap_rls_cb.tmr, portMAX_DELAY);
|
||||
#else
|
||||
esp_timer_start_once(btn->tap_rls_cb.tmr, btn->tap_rls_cb.interval * portTICK_PERIOD_MS * 1000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void button_tap_rls_cb(void* tmr)
|
||||
{
|
||||
#if !USE_ESP_TIMER
|
||||
button_cb_t* btn_cb = (button_cb_t*) pvTimerGetTimerID(tmr);
|
||||
#else
|
||||
button_cb_t* btn_cb = (button_cb_t*)(tmr);
|
||||
#endif
|
||||
button_dev_t* btn = btn_cb->pbtn;
|
||||
STOP_TIMER(btn->tap_rls_cb.tmr);
|
||||
|
||||
if (btn->active_level == gpio_get_level(btn->io_num)) {
|
||||
|
||||
} else {
|
||||
// high, then key is up
|
||||
button_cb_t *pcb = btn->cb_head;
|
||||
while (pcb != NULL) {
|
||||
if (pcb->tmr != NULL) {
|
||||
STOP_TIMER(pcb->tmr);
|
||||
}
|
||||
pcb = pcb->next_cb;
|
||||
}
|
||||
if (btn->press_serial_cb.tmr && btn->press_serial_cb.tmr != NULL) {
|
||||
STOP_TIMER(btn->press_serial_cb.tmr);
|
||||
}
|
||||
if (btn->tap_short_cb.cb && btn->state == BUTTON_STATE_PUSH) {
|
||||
btn->tap_short_cb.cb(btn->tap_short_cb.arg);
|
||||
}
|
||||
if(btn->tap_rls_cb.cb && btn->state != BUTTON_STATE_IDLE) {
|
||||
btn->tap_rls_cb.cb(btn->tap_rls_cb.arg);
|
||||
}
|
||||
btn->state = BUTTON_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void button_press_serial_cb(void* tmr)
|
||||
{
|
||||
#if !USE_ESP_TIMER
|
||||
button_dev_t* btn = (button_dev_t*) pvTimerGetTimerID(tmr);
|
||||
#else
|
||||
button_dev_t* btn = (button_dev_t*)(tmr);
|
||||
#endif
|
||||
|
||||
if (btn->press_serial_cb.cb) {
|
||||
btn->press_serial_cb.cb(btn->press_serial_cb.arg);
|
||||
}
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerChangePeriod(btn->press_serial_cb.tmr, btn->press_serial_cb.interval, portMAX_DELAY);
|
||||
xTimerReset(btn->press_serial_cb.tmr, portMAX_DELAY);
|
||||
#else
|
||||
esp_timer_stop(btn->press_serial_cb.tmr);
|
||||
esp_timer_start_once(btn->press_serial_cb.tmr, btn->press_serial_cb.interval * portTICK_PERIOD_MS * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void button_gpio_isr_handler(void* arg)
|
||||
{
|
||||
button_dev_t* btn = (button_dev_t*) arg;
|
||||
portBASE_TYPE HPTaskAwoken = pdFALSE;
|
||||
int level = gpio_get_level(btn->io_num);
|
||||
if (level == btn->active_level) {
|
||||
if (btn->tap_psh_cb.tmr) {
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerStopFromISR(btn->tap_psh_cb.tmr, &HPTaskAwoken);
|
||||
xTimerResetFromISR(btn->tap_psh_cb.tmr, &HPTaskAwoken);
|
||||
#else
|
||||
esp_timer_stop(btn->tap_psh_cb.tmr);
|
||||
esp_timer_start_once(btn->tap_psh_cb.tmr, btn->tap_psh_cb.interval * portTICK_PERIOD_MS * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
button_cb_t *pcb = btn->cb_head;
|
||||
while (pcb != NULL) {
|
||||
if (pcb->tmr != NULL) {
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerStopFromISR(pcb->tmr, &HPTaskAwoken);
|
||||
xTimerResetFromISR(pcb->tmr, &HPTaskAwoken);
|
||||
#else
|
||||
esp_timer_stop(pcb->tmr);
|
||||
esp_timer_start_once(pcb->tmr, pcb->interval * portTICK_PERIOD_MS * 1000);
|
||||
#endif
|
||||
}
|
||||
pcb = pcb->next_cb;
|
||||
}
|
||||
} else {
|
||||
// 50ms, check if this is a real key up
|
||||
if (btn->tap_rls_cb.tmr) {
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerStopFromISR(btn->tap_rls_cb.tmr, &HPTaskAwoken);
|
||||
xTimerResetFromISR(btn->tap_rls_cb.tmr, &HPTaskAwoken);
|
||||
#else
|
||||
esp_timer_stop(btn->tap_rls_cb.tmr);
|
||||
esp_timer_start_once(btn->tap_rls_cb.tmr, btn->tap_rls_cb.interval * portTICK_PERIOD_MS * 1000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
#if !USE_ESP_TIMER
|
||||
static void button_free_tmr(xTimerHandle* tmr)
|
||||
#else
|
||||
static void button_free_tmr(esp_timer_handle_t *tmr)
|
||||
#endif
|
||||
{
|
||||
if (tmr && *tmr) {
|
||||
STOP_TIMER(*tmr);
|
||||
DELETE_TIMER(*tmr);
|
||||
*tmr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t iot_button_delete(button_handle_t btn_handle)
|
||||
{
|
||||
POINT_ASSERT(TAG, btn_handle, ESP_ERR_INVALID_ARG);
|
||||
button_dev_t* btn = (button_dev_t*) btn_handle;
|
||||
gpio_set_intr_type(btn->io_num, GPIO_INTR_DISABLE);
|
||||
gpio_isr_handler_remove(btn->io_num);
|
||||
|
||||
button_free_tmr(&btn->tap_rls_cb.tmr);
|
||||
button_free_tmr(&btn->tap_psh_cb.tmr);
|
||||
button_free_tmr(&btn->tap_short_cb.tmr);
|
||||
button_free_tmr(&btn->press_serial_cb.tmr);
|
||||
|
||||
button_cb_t *pcb = btn->cb_head;
|
||||
while (pcb != NULL) {
|
||||
button_cb_t *cb_next = pcb->next_cb;
|
||||
button_free_tmr(&pcb->tmr);
|
||||
free(pcb);
|
||||
pcb = cb_next;
|
||||
}
|
||||
free(btn);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
button_handle_t iot_button_create(gpio_num_t gpio_num, button_active_t active_level)
|
||||
{
|
||||
#if USE_ESP_TIMER
|
||||
ets_printf("use esp timer !!!\n");
|
||||
esp_timer_init();
|
||||
#endif
|
||||
|
||||
IOT_CHECK(TAG, gpio_num < GPIO_NUM_MAX, NULL);
|
||||
button_dev_t* btn = (button_dev_t*) calloc(1, sizeof(button_dev_t));
|
||||
POINT_ASSERT(TAG, btn, NULL);
|
||||
btn->active_level = active_level;
|
||||
btn->io_num = gpio_num;
|
||||
btn->state = BUTTON_STATE_IDLE;
|
||||
btn->tap_rls_cb.arg = NULL;
|
||||
btn->tap_rls_cb.cb = NULL;
|
||||
btn->tap_rls_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_PERIOD_MS;
|
||||
btn->tap_rls_cb.pbtn = btn;
|
||||
#if !USE_ESP_TIMER
|
||||
btn->tap_rls_cb.tmr = xTimerCreate("btn_rls_tmr", btn->tap_rls_cb.interval, pdFALSE,
|
||||
&btn->tap_rls_cb, button_tap_rls_cb);
|
||||
#else
|
||||
esp_timer_create_args_t tmr_param_rls;
|
||||
tmr_param_rls.arg = &btn->tap_rls_cb;
|
||||
tmr_param_rls.callback = button_tap_rls_cb;
|
||||
tmr_param_rls.dispatch_method = ESP_TIMER_TASK;
|
||||
tmr_param_rls.name = "btn_rls_tmr";
|
||||
esp_timer_create(&tmr_param_rls, &btn->tap_rls_cb.tmr);
|
||||
#endif
|
||||
|
||||
btn->tap_psh_cb.arg = NULL;
|
||||
btn->tap_psh_cb.cb = NULL;
|
||||
btn->tap_psh_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_PERIOD_MS;
|
||||
btn->tap_psh_cb.pbtn = btn;
|
||||
#if !USE_ESP_TIMER
|
||||
btn->tap_psh_cb.tmr = xTimerCreate("btn_psh_tmr", btn->tap_psh_cb.interval, pdFALSE,
|
||||
&btn->tap_psh_cb, button_tap_psh_cb);
|
||||
#else
|
||||
esp_timer_create_args_t tmr_param_psh;
|
||||
tmr_param_psh.arg = &btn->tap_psh_cb;
|
||||
tmr_param_psh.callback = button_tap_psh_cb;
|
||||
tmr_param_psh.dispatch_method = ESP_TIMER_TASK;
|
||||
tmr_param_psh.name = "btn_psh_tmr";
|
||||
esp_timer_create(&tmr_param_psh, &btn->tap_psh_cb.tmr);
|
||||
#endif
|
||||
gpio_install_isr_service(0);
|
||||
gpio_config_t gpio_conf;
|
||||
gpio_conf.intr_type = GPIO_INTR_ANYEDGE;
|
||||
gpio_conf.mode = GPIO_MODE_INPUT;
|
||||
gpio_conf.pin_bit_mask = (1ULL << gpio_num);
|
||||
gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&gpio_conf);
|
||||
gpio_isr_handler_add(gpio_num, button_gpio_isr_handler, btn);
|
||||
return (button_handle_t) btn;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_rm_cb(button_handle_t btn_handle, button_cb_type_t type)
|
||||
{
|
||||
button_dev_t* btn = (button_dev_t*) btn_handle;
|
||||
button_cb_t* btn_cb = NULL;
|
||||
if (type == BUTTON_CB_PUSH) {
|
||||
btn_cb = &btn->tap_psh_cb;
|
||||
} else if (type == BUTTON_CB_RELEASE) {
|
||||
btn_cb = &btn->tap_rls_cb;
|
||||
} else if (type == BUTTON_CB_TAP) {
|
||||
btn_cb = &btn->tap_short_cb;
|
||||
} else if (type == BUTTON_CB_SERIAL) {
|
||||
btn_cb = &btn->press_serial_cb;
|
||||
}
|
||||
btn_cb->cb = NULL;
|
||||
btn_cb->arg = NULL;
|
||||
btn_cb->pbtn = btn;
|
||||
button_free_tmr(&btn_cb->tmr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_set_serial_cb(button_handle_t btn_handle, uint32_t start_after_sec, TickType_t interval_tick, button_cb cb, void* arg)
|
||||
{
|
||||
button_dev_t* btn = (button_dev_t*) btn_handle;
|
||||
btn->serial_thres_sec = start_after_sec;
|
||||
|
||||
if (btn->press_serial_cb.tmr == NULL) {
|
||||
#if !USE_ESP_TIMER
|
||||
btn->press_serial_cb.tmr = xTimerCreate("btn_serial_tmr", btn->serial_thres_sec*1000 / portTICK_PERIOD_MS,
|
||||
pdFALSE, btn, button_press_serial_cb);
|
||||
#else
|
||||
esp_timer_create_args_t tmr_param_ser;
|
||||
tmr_param_ser.arg = btn;
|
||||
tmr_param_ser.callback = button_press_serial_cb;
|
||||
tmr_param_ser.dispatch_method = ESP_TIMER_TASK;
|
||||
tmr_param_ser.name = "btn_serial_tmr";
|
||||
esp_timer_create(&tmr_param_ser, &btn->press_serial_cb.tmr);
|
||||
#endif
|
||||
}
|
||||
btn->press_serial_cb.arg = arg;
|
||||
btn->press_serial_cb.cb = cb;
|
||||
btn->press_serial_cb.interval = interval_tick;
|
||||
btn->press_serial_cb.pbtn = btn;
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerChangePeriod(btn->press_serial_cb.tmr, btn->serial_thres_sec*1000 / portTICK_PERIOD_MS, portMAX_DELAY);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_set_evt_cb(button_handle_t btn_handle, button_cb_type_t type, button_cb cb, void* arg)
|
||||
{
|
||||
POINT_ASSERT(TAG, btn_handle, ESP_ERR_INVALID_ARG);
|
||||
button_dev_t* btn = (button_dev_t*) btn_handle;
|
||||
if (type == BUTTON_CB_PUSH) {
|
||||
btn->tap_psh_cb.arg = arg;
|
||||
btn->tap_psh_cb.cb = cb;
|
||||
btn->tap_psh_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_RATE_MS;
|
||||
btn->tap_psh_cb.pbtn = btn;
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerChangePeriod(btn->tap_psh_cb.tmr, btn->tap_psh_cb.interval, portMAX_DELAY);
|
||||
#endif
|
||||
} else if (type == BUTTON_CB_RELEASE) {
|
||||
btn->tap_rls_cb.arg = arg;
|
||||
btn->tap_rls_cb.cb = cb;
|
||||
btn->tap_rls_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_RATE_MS;
|
||||
btn->tap_rls_cb.pbtn = btn;
|
||||
#if !USE_ESP_TIMER
|
||||
xTimerChangePeriod(btn->tap_rls_cb.tmr, btn->tap_psh_cb.interval, portMAX_DELAY);
|
||||
#endif
|
||||
} else if (type == BUTTON_CB_TAP) {
|
||||
btn->tap_short_cb.arg = arg;
|
||||
btn->tap_short_cb.cb = cb;
|
||||
btn->tap_short_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_RATE_MS;
|
||||
btn->tap_short_cb.pbtn = btn;
|
||||
} else if (type == BUTTON_CB_SERIAL) {
|
||||
iot_button_set_serial_cb(btn_handle, 1, 1000 / portTICK_RATE_MS, cb, arg);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_add_custom_cb(button_handle_t btn_handle, uint32_t press_sec, button_cb cb, void* arg)
|
||||
{
|
||||
POINT_ASSERT(TAG, btn_handle, ESP_ERR_INVALID_ARG);
|
||||
IOT_CHECK(TAG, press_sec != 0, ESP_ERR_INVALID_ARG);
|
||||
button_dev_t* btn = (button_dev_t*) btn_handle;
|
||||
button_cb_t* cb_new = (button_cb_t*) calloc(1, sizeof(button_cb_t));
|
||||
POINT_ASSERT(TAG, cb_new, ESP_FAIL);
|
||||
cb_new->arg = arg;
|
||||
cb_new->cb = cb;
|
||||
cb_new->interval = press_sec * 1000 / portTICK_PERIOD_MS;
|
||||
cb_new->pbtn = btn;
|
||||
#if !USE_ESP_TIMER
|
||||
cb_new->tmr = xTimerCreate("btn_press_tmr", cb_new->interval, pdFALSE, cb_new, button_press_cb);
|
||||
#else
|
||||
esp_timer_create_args_t tmr_param_cus;
|
||||
tmr_param_cus.arg = cb_new;
|
||||
tmr_param_cus.callback = button_press_cb;
|
||||
tmr_param_cus.dispatch_method = ESP_TIMER_TASK;
|
||||
tmr_param_cus.name = "btn_press_custom_tmr";
|
||||
esp_timer_create(&tmr_param_cus, &cb_new->tmr);
|
||||
#endif
|
||||
cb_new->next_cb = btn->cb_head;
|
||||
btn->cb_head = cb_new;
|
||||
return ESP_OK;
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// Copyright 2015-2016 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 "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "iot_button.h"
|
||||
|
||||
CButton::CButton(gpio_num_t gpio_num, button_active_t active_level)
|
||||
{
|
||||
m_btn_handle = iot_button_create(gpio_num, active_level);
|
||||
}
|
||||
|
||||
CButton::~CButton()
|
||||
{
|
||||
iot_button_delete(m_btn_handle);
|
||||
m_btn_handle = NULL;
|
||||
}
|
||||
|
||||
esp_err_t CButton::set_evt_cb(button_cb_type_t type, button_cb cb, void* arg)
|
||||
{
|
||||
return iot_button_set_evt_cb(m_btn_handle, type, cb, arg);
|
||||
}
|
||||
|
||||
esp_err_t CButton::set_serial_cb(button_cb cb, void* arg, TickType_t interval_tick, uint32_t start_after_sec)
|
||||
{
|
||||
return iot_button_set_serial_cb(m_btn_handle, start_after_sec, interval_tick, cb, arg);
|
||||
}
|
||||
|
||||
esp_err_t CButton::add_custom_cb(uint32_t press_sec, button_cb cb, void* arg)
|
||||
{
|
||||
return iot_button_add_custom_cb(m_btn_handle, press_sec, cb, arg);
|
||||
}
|
||||
|
||||
esp_err_t CButton::rm_cb(button_cb_type_t type)
|
||||
{
|
||||
return iot_button_rm_cb(m_btn_handle, type);
|
||||
}
|
@ -0,0 +1,230 @@
|
||||
// Copyright 2015-2016 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 _IOT_BUTTON_H_
|
||||
#define _IOT_BUTTON_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/portmacro.h"
|
||||
typedef void (* button_cb)(void*);
|
||||
typedef void* button_handle_t;
|
||||
|
||||
typedef enum {
|
||||
BUTTON_ACTIVE_HIGH = 1, /*!<button active level: high level*/
|
||||
BUTTON_ACTIVE_LOW = 0, /*!<button active level: low level*/
|
||||
} button_active_t;
|
||||
|
||||
typedef enum {
|
||||
BUTTON_CB_PUSH = 0, /*!<button push callback event */
|
||||
BUTTON_CB_RELEASE, /*!<button release callback event */
|
||||
BUTTON_CB_TAP, /*!<button quick tap callback event(will not trigger if there already is a "PRESS" event) */
|
||||
BUTTON_CB_SERIAL, /*!<button serial trigger callback event */
|
||||
} button_cb_type_t;
|
||||
|
||||
/**
|
||||
* @brief Init button functions
|
||||
*
|
||||
* @param gpio_num GPIO index of the pin that the button uses
|
||||
* @param active_level button hardware active level.
|
||||
* For "BUTTON_ACTIVE_LOW" it means when the button pressed, the GPIO will read low level.
|
||||
*
|
||||
* @return A button_handle_t handle to the created button object, or NULL in case of error.
|
||||
*/
|
||||
button_handle_t iot_button_create(gpio_num_t gpio_num, button_active_t active_level);
|
||||
|
||||
/**
|
||||
* @brief Register a callback function for a serial trigger event.
|
||||
*
|
||||
* @param btn_handle handle of the button object
|
||||
* @start_after_sec define the time after which to start serial trigger action
|
||||
* @interval_tick serial trigger interval
|
||||
* @cb callback function for "TAP" action.
|
||||
* @arg Parameter for callback function
|
||||
* @note
|
||||
* Button callback functions execute in the context of the timer service task.
|
||||
* It is therefore essential that button callback functions never attempt to block.
|
||||
* For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(),
|
||||
* or specify a non zero block time when accessing a queue or a semaphore.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t iot_button_set_serial_cb(button_handle_t btn_handle, uint32_t start_after_sec, TickType_t interval_tick, button_cb cb, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Register a callback function for a button_cb_type_t action.
|
||||
*
|
||||
* @param btn_handle handle of the button object
|
||||
* @param type callback function type
|
||||
* @param cb callback function for "TAP" action.
|
||||
* @param arg Parameter for callback function
|
||||
* @note
|
||||
* Button callback functions execute in the context of the timer service task.
|
||||
* It is therefore essential that button callback functions never attempt to block.
|
||||
* For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(),
|
||||
* or specify a non zero block time when accessing a queue or a semaphore.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t iot_button_set_evt_cb(button_handle_t btn_handle, button_cb_type_t type, button_cb cb, void* arg);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param btn_handle handle of the button object
|
||||
* @param press_sec the callback function would be called if you press the button for a specified period of time
|
||||
* @param cb callback function for "PRESS" action.
|
||||
* @param arg Parameter for callback function
|
||||
*
|
||||
* @note
|
||||
* Button callback functions execute in the context of the timer service task.
|
||||
* It is therefore essential that button callback functions never attempt to block.
|
||||
* For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(),
|
||||
* or specify a non zero block time when accessing a queue or a semaphore.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t iot_button_add_custom_cb(button_handle_t btn_handle, uint32_t press_sec, button_cb cb, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Delete button object and free memory
|
||||
* @param btn_handle handle of the button object
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t iot_button_delete(button_handle_t btn_handle);
|
||||
|
||||
/**
|
||||
* @brief Remove callback
|
||||
*
|
||||
* @param btn_handle The handle of the button object
|
||||
* @param type callback function event type
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t iot_button_rm_cb(button_handle_t btn_handle, button_cb_type_t type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/**
|
||||
* class of button
|
||||
* simple usage:
|
||||
* CButton* btn = new CButton(BUTTON_IO_NUM, BUTTON_ACTIVE_LEVEL, BUTTON_SERIAL_TRIGGER, 3);
|
||||
* btn->add_cb(BUTTON_CB_PUSH, button_tap_cb, (void*) push, 50 / portTICK_PERIOD_MS);
|
||||
* btn->add_custom_cb(5, button_press_5s_cb, NULL);
|
||||
* ......
|
||||
* delete btn;
|
||||
*/
|
||||
class CButton
|
||||
{
|
||||
private:
|
||||
button_handle_t m_btn_handle;
|
||||
|
||||
/**
|
||||
* prevent copy constructing
|
||||
*/
|
||||
CButton(const CButton&);
|
||||
CButton& operator = (const CButton&);
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief constructor of CButton
|
||||
*
|
||||
* @param gpio_num GPIO index of the pin that the button uses
|
||||
* @param active_level button hardware active level.
|
||||
* For "BUTTON_ACTIVE_LOW" it means when the button pressed, the GPIO will read low level.
|
||||
*/
|
||||
CButton(gpio_num_t gpio_num, button_active_t active_level = BUTTON_ACTIVE_LOW);
|
||||
|
||||
~CButton();
|
||||
|
||||
/**
|
||||
* @brief Register a callback function for a button_cb_type_t action.
|
||||
*
|
||||
* @param type callback function type
|
||||
* @param cb callback function for "TAP" action.
|
||||
* @param arg Parameter for callback function
|
||||
* @note
|
||||
* Button callback functions execute in the context of the timer service task.
|
||||
* It is therefore essential that button callback functions never attempt to block.
|
||||
* For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(),
|
||||
* or specify a non zero block time when accessing a queue or a semaphore.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t set_evt_cb(button_cb_type_t type, button_cb cb, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Register a callback function for a serial trigger event.
|
||||
*
|
||||
* @param btn_handle handle of the button object
|
||||
* @start_after_sec define the time after which to start serial trigger action
|
||||
* @interval_tick serial trigger interval
|
||||
* @cb callback function for "TAP" action.
|
||||
* @arg Parameter for callback function
|
||||
* @note
|
||||
* Button callback functions execute in the context of the timer service task.
|
||||
* It is therefore essential that button callback functions never attempt to block.
|
||||
* For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(),
|
||||
* or specify a non zero block time when accessing a queue or a semaphore.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t set_serial_cb(button_cb cb, void* arg, TickType_t interval_tick, uint32_t start_after_sec);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param press_sec the callback function would be called if you press the button for a specified period of time
|
||||
* @param cb callback function for "PRESS" action.
|
||||
* @param arg Parameter for callback function
|
||||
*
|
||||
* @note
|
||||
* Button callback functions execute in the context of the timer service task.
|
||||
* It is therefore essential that button callback functions never attempt to block.
|
||||
* For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(),
|
||||
* or specify a non zero block time when accessing a queue or a semaphore.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t add_custom_cb(uint32_t press_sec, button_cb cb, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Remove callback
|
||||
*
|
||||
* @param type callback function event type
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t rm_cb(button_cb_type_t type);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
@ -9,7 +9,7 @@
|
||||
#ifndef _BLE_MESH_DEMO_INIT_H_
|
||||
#define _BLE_MESH_DEMO_INIT_H_
|
||||
|
||||
#define TAG "ble_mesh_node"
|
||||
#define TAG "onoff_client"
|
||||
|
||||
void ble_mesh_get_dev_uuid(uint8_t *dev_uuid);
|
||||
|
@ -0,0 +1,272 @@
|
||||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional 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_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 "board.h"
|
||||
#include "ble_mesh_demo_init.h"
|
||||
|
||||
#define CID_ESP 0x02E5
|
||||
|
||||
static uint8_t dev_uuid[16] = { 0xdd, 0xdd };
|
||||
static uint16_t node_net_idx = ESP_BLE_MESH_KEY_UNUSED;
|
||||
static uint16_t node_app_idx = ESP_BLE_MESH_KEY_UNUSED;
|
||||
static uint8_t remote_onoff = LED_OFF;
|
||||
static uint8_t msg_tid = 0x0;
|
||||
|
||||
/* The remote node address shall be input through UART1, see board.c */
|
||||
uint16_t remote_addr = ESP_BLE_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_cli_pub, 2 + 1, ROLE_NODE);
|
||||
|
||||
static esp_ble_mesh_model_t root_models[] = {
|
||||
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
|
||||
ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI(&onoff_cli_pub, &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),
|
||||
};
|
||||
|
||||
/* Disable OOB security for SILabs Android app */
|
||||
static esp_ble_mesh_prov_t provision = {
|
||||
.uuid = dev_uuid,
|
||||
#if 0
|
||||
.output_size = 4,
|
||||
.output_actions = ESP_BLE_MESH_DISPLAY_NUMBER,
|
||||
.input_actions = ESP_BLE_MESH_PUSH,
|
||||
.input_size = 4,
|
||||
#else
|
||||
.output_size = 0,
|
||||
.output_actions = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
||||
{
|
||||
ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr);
|
||||
ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index);
|
||||
board_led_operation(LED_G, LED_OFF);
|
||||
node_net_idx = net_idx;
|
||||
}
|
||||
|
||||
static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
|
||||
esp_ble_mesh_prov_cb_param_t *param)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT, bearer %s",
|
||||
param->node_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT, bearer %s",
|
||||
param->node_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT");
|
||||
prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr,
|
||||
param->node_prov_complete.flags, param->node_prov_complete.iv_index);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_RESET_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT, err_code %d", param->node_set_unprov_dev_name_comp.err_code);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void example_ble_mesh_send_gen_onoff_set(void)
|
||||
{
|
||||
esp_ble_mesh_generic_client_set_state_t set = {0};
|
||||
esp_ble_mesh_client_common_param_t common = {0};
|
||||
esp_err_t err;
|
||||
|
||||
common.opcode = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK;
|
||||
common.model = onoff_client.model;
|
||||
common.ctx.net_idx = node_net_idx;
|
||||
common.ctx.app_idx = node_app_idx;
|
||||
common.ctx.addr = 0xFFFF; /* to all nodes */
|
||||
common.ctx.send_ttl = 3;
|
||||
common.ctx.send_rel = false;
|
||||
common.msg_timeout = 0; /* 0 indicates that timeout value from menuconfig will be used */
|
||||
common.msg_role = ROLE_NODE;
|
||||
|
||||
set.onoff_set.op_en = false;
|
||||
set.onoff_set.onoff = remote_onoff;
|
||||
set.onoff_set.tid = msg_tid++;
|
||||
|
||||
err = esp_ble_mesh_generic_client_set_state(&common, &set);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);
|
||||
} else {
|
||||
remote_onoff = !remote_onoff;
|
||||
}
|
||||
}
|
||||
|
||||
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_LOGI(TAG, "%s: event is %d, error code is %d, opcode is 0x%x",
|
||||
__func__, event, param->error_code, param->params->opcode);
|
||||
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT");
|
||||
if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET) {
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, onoff %d", param->status_cb.onoff_status.present_onoff);
|
||||
}
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT");
|
||||
if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, onoff %d", param->status_cb.onoff_status.present_onoff);
|
||||
}
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT");
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT");
|
||||
if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
|
||||
/* If failed to get the response of Generic OnOff Set, resend Generic OnOff Set */
|
||||
example_ble_mesh_send_gen_onoff_set();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t event,
|
||||
esp_ble_mesh_cfg_server_cb_param_t *param)
|
||||
{
|
||||
if (event == ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT) {
|
||||
switch (param->ctx.recv_op) {
|
||||
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD");
|
||||
ESP_LOGI(TAG, "net_idx 0x%04x, app_idx 0x%04x",
|
||||
param->value.state_change.appkey_add.net_idx,
|
||||
param->value.state_change.appkey_add.app_idx);
|
||||
ESP_LOG_BUFFER_HEX("AppKey", param->value.state_change.appkey_add.app_key, 16);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND");
|
||||
ESP_LOGI(TAG, "elem_addr 0x%04x, app_idx 0x%04x, cid 0x%04x, mod_id 0x%04x",
|
||||
param->value.state_change.mod_app_bind.element_addr,
|
||||
param->value.state_change.mod_app_bind.app_idx,
|
||||
param->value.state_change.mod_app_bind.company_id,
|
||||
param->value.state_change.mod_app_bind.model_id);
|
||||
if (param->value.state_change.mod_app_bind.company_id == 0xFFFF &&
|
||||
param->value.state_change.mod_app_bind.model_id == ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI) {
|
||||
node_app_idx = param->value.state_change.mod_app_bind.app_idx;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ble_mesh_init(void)
|
||||
{
|
||||
esp_err_t err = 0;
|
||||
|
||||
esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);
|
||||
esp_ble_mesh_register_generic_client_callback(example_ble_mesh_generic_client_cb);
|
||||
esp_ble_mesh_register_config_server_callback(example_ble_mesh_config_server_cb);
|
||||
|
||||
err = esp_ble_mesh_init(&provision, &composition);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
|
||||
|
||||
ESP_LOGI(TAG, "BLE Mesh Node initialized");
|
||||
|
||||
board_led_operation(LED_G, LED_ON);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing...");
|
||||
|
||||
board_init();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/* board.c - Board-specific hooks */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "iot_button.h"
|
||||
#include "board.h"
|
||||
|
||||
#define TAG "BOARD"
|
||||
|
||||
#define BUTTON_IO_NUM 0
|
||||
#define BUTTON_ACTIVE_LEVEL 0
|
||||
|
||||
extern void example_ble_mesh_send_gen_onoff_set(void);
|
||||
|
||||
struct _led_state led_state[3] = {
|
||||
{ LED_OFF, LED_OFF, LED_R, "red" },
|
||||
{ LED_OFF, LED_OFF, LED_G, "green" },
|
||||
{ LED_OFF, LED_OFF, LED_B, "blue" },
|
||||
};
|
||||
|
||||
void board_led_operation(uint8_t pin, uint8_t onoff)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(led_state); i++) {
|
||||
if (led_state[i].pin != pin) {
|
||||
continue;
|
||||
}
|
||||
if (onoff == led_state[i].previous) {
|
||||
ESP_LOGW(TAG, "led %s is already %s",
|
||||
led_state[i].name, (onoff ? "on" : "off"));
|
||||
return;
|
||||
}
|
||||
gpio_set_level(pin, onoff);
|
||||
led_state[i].previous = onoff;
|
||||
return;
|
||||
}
|
||||
ESP_LOGE(TAG, "LED is not found!");
|
||||
}
|
||||
|
||||
static void board_led_init(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(led_state); i++) {
|
||||
gpio_pad_select_gpio(led_state[i].pin);
|
||||
gpio_set_direction(led_state[i].pin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(led_state[i].pin, LED_OFF);
|
||||
led_state[i].previous = LED_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void button_tap_cb(void* arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "tap cb (%s)", (char *)arg);
|
||||
|
||||
example_ble_mesh_send_gen_onoff_set();
|
||||
}
|
||||
|
||||
static void board_button_init(void)
|
||||
{
|
||||
button_handle_t btn_handle = iot_button_create(BUTTON_IO_NUM, BUTTON_ACTIVE_LEVEL);
|
||||
if (btn_handle) {
|
||||
iot_button_set_evt_cb(btn_handle, BUTTON_CB_RELEASE, button_tap_cb, "RELEASE");
|
||||
}
|
||||
}
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
board_led_init();
|
||||
board_button_init();
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -31,10 +32,6 @@ struct _led_state {
|
||||
char *name;
|
||||
};
|
||||
|
||||
void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number);
|
||||
|
||||
void board_prov_complete(void);
|
||||
|
||||
void board_led_operation(uint8_t pin, uint8_t onoff);
|
||||
|
||||
void board_init(void);
|
Before Width: | Height: | Size: 433 KiB After Width: | Height: | Size: 433 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@ -3,4 +3,4 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(ble_mesh_client_model)
|
||||
project(onoff_server)
|
@ -3,7 +3,7 @@
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := ble_mesh_client_model
|
||||
PROJECT_NAME := onoff_server
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := components/include
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef _BLE_MESH_DEMO_INIT_H_
|
||||
#define _BLE_MESH_DEMO_INIT_H_
|
||||
|
||||
#define TAG "ble_mesh_client"
|
||||
#define TAG "onoff_server"
|
||||
|
||||
void ble_mesh_get_dev_uuid(uint8_t *dev_uuid);
|
||||
|
@ -0,0 +1,332 @@
|
||||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional 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_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 "board.h"
|
||||
#include "ble_mesh_demo_init.h"
|
||||
|
||||
#define CID_ESP 0x02E5
|
||||
|
||||
extern struct _led_state led_state[3];
|
||||
|
||||
static uint8_t dev_uuid[16] = { 0xdd, 0xdd };
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_0, 2 + 3, ROLE_NODE);
|
||||
static esp_ble_mesh_gen_onoff_srv_t onoff_server_0 = {
|
||||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_1, 2 + 3, ROLE_NODE);
|
||||
static esp_ble_mesh_gen_onoff_srv_t onoff_server_1 = {
|
||||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
|
||||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_2, 2 + 3, ROLE_NODE);
|
||||
static esp_ble_mesh_gen_onoff_srv_t onoff_server_2 = {
|
||||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t root_models[] = {
|
||||
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
|
||||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_0, &onoff_server_0),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t extend_model_0[] = {
|
||||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_1, &onoff_server_1),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t extend_model_1[] = {
|
||||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_2, &onoff_server_2),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_elem_t elements[] = {
|
||||
ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE),
|
||||
ESP_BLE_MESH_ELEMENT(0, extend_model_0, ESP_BLE_MESH_MODEL_NONE),
|
||||
ESP_BLE_MESH_ELEMENT(0, extend_model_1, ESP_BLE_MESH_MODEL_NONE),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_comp_t composition = {
|
||||
.cid = CID_ESP,
|
||||
.elements = elements,
|
||||
.element_count = ARRAY_SIZE(elements),
|
||||
};
|
||||
|
||||
/* Disable OOB security for SILabs Android app */
|
||||
static esp_ble_mesh_prov_t provision = {
|
||||
.uuid = dev_uuid,
|
||||
#if 0
|
||||
.output_size = 4,
|
||||
.output_actions = ESP_BLE_MESH_DISPLAY_NUMBER,
|
||||
.input_actions = ESP_BLE_MESH_PUSH,
|
||||
.input_size = 4,
|
||||
#else
|
||||
.output_size = 0,
|
||||
.output_actions = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
||||
{
|
||||
ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr);
|
||||
ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index);
|
||||
board_led_operation(LED_G, LED_OFF);
|
||||
}
|
||||
|
||||
static void example_change_led_state(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx, uint8_t onoff)
|
||||
{
|
||||
uint16_t primary_addr = esp_ble_mesh_get_primary_element_address();
|
||||
uint8_t elem_count = esp_ble_mesh_get_element_count();
|
||||
struct _led_state *led = NULL;
|
||||
uint8_t i;
|
||||
|
||||
if (ESP_BLE_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) {
|
||||
for (i = 0; i < elem_count; i++) {
|
||||
if (ctx->recv_dst == (primary_addr + i)) {
|
||||
led = &led_state[i];
|
||||
board_led_operation(led->pin, onoff);
|
||||
}
|
||||
}
|
||||
} else if (ESP_BLE_MESH_ADDR_IS_GROUP(ctx->recv_dst)) {
|
||||
if (esp_ble_mesh_is_model_subscribed_to_group(model, ctx->recv_dst)) {
|
||||
led = &led_state[model->element->element_addr - primary_addr];
|
||||
board_led_operation(led->pin, onoff);
|
||||
}
|
||||
} else if (ctx->recv_dst == 0xFFFF) {
|
||||
led = &led_state[model->element->element_addr - primary_addr];
|
||||
board_led_operation(led->pin, onoff);
|
||||
}
|
||||
}
|
||||
|
||||
static void example_handle_gen_onoff_msg(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
esp_ble_mesh_server_recv_gen_onoff_set_t *set)
|
||||
{
|
||||
esp_ble_mesh_gen_onoff_srv_t *srv = model->user_data;
|
||||
|
||||
switch (ctx->recv_op) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
|
||||
esp_ble_mesh_server_model_send_msg(model, ctx,
|
||||
ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, sizeof(srv->state.onoff), &srv->state.onoff);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK:
|
||||
if (set->op_en == false) {
|
||||
srv->state.onoff = set->onoff;
|
||||
} else {
|
||||
/* TODO: Delay and state transition */
|
||||
srv->state.onoff = set->onoff;
|
||||
}
|
||||
if (ctx->recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
|
||||
esp_ble_mesh_server_model_send_msg(model, ctx,
|
||||
ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, sizeof(srv->state.onoff), &srv->state.onoff);
|
||||
}
|
||||
esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(srv->state.onoff), &srv->state.onoff, ROLE_NODE);
|
||||
example_change_led_state(model, ctx, srv->state.onoff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
|
||||
esp_ble_mesh_prov_cb_param_t *param)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT, bearer %s",
|
||||
param->node_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT, bearer %s",
|
||||
param->node_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT");
|
||||
prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr,
|
||||
param->node_prov_complete.flags, param->node_prov_complete.iv_index);
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_PROV_RESET_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_RESET_EVT");
|
||||
break;
|
||||
case ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT, err_code %d", param->node_set_unprov_dev_name_comp.err_code);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event,
|
||||
esp_ble_mesh_generic_server_cb_param_t *param)
|
||||
{
|
||||
ESP_LOGI(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x",
|
||||
event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst);
|
||||
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT");
|
||||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||
|
||||
param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
|
||||
ESP_LOGI(TAG, "onoff 0x%02x", param->value.state_change.onoff_set.onoff);
|
||||
example_change_led_state(param->model, ¶m->ctx, param->value.state_change.onoff_set.onoff);
|
||||
}
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT");
|
||||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET) {
|
||||
example_handle_gen_onoff_msg(param->model, ¶m->ctx, NULL);
|
||||
}
|
||||
break;
|
||||
case ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT");
|
||||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||
|
||||
param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
|
||||
ESP_LOGI(TAG, "onoff 0x%02x, tid 0x%02x", param->value.set.onoff.onoff, param->value.set.onoff.tid);
|
||||
if (param->value.set.onoff.op_en) {
|
||||
ESP_LOGI(TAG, "trans_time 0x%02x, delay 0x%02x",
|
||||
param->value.set.onoff.trans_time, param->value.set.onoff.delay);
|
||||
}
|
||||
example_handle_gen_onoff_msg(param->model, ¶m->ctx, ¶m->value.set.onoff);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unknown Generic Server event 0x%02x", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t event,
|
||||
esp_ble_mesh_cfg_server_cb_param_t *param)
|
||||
{
|
||||
if (event == ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT) {
|
||||
switch (param->ctx.recv_op) {
|
||||
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD");
|
||||
ESP_LOGI(TAG, "net_idx 0x%04x, app_idx 0x%04x",
|
||||
param->value.state_change.appkey_add.net_idx,
|
||||
param->value.state_change.appkey_add.app_idx);
|
||||
ESP_LOG_BUFFER_HEX("AppKey", param->value.state_change.appkey_add.app_key, 16);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND");
|
||||
ESP_LOGI(TAG, "elem_addr 0x%04x, app_idx 0x%04x, cid 0x%04x, mod_id 0x%04x",
|
||||
param->value.state_change.mod_app_bind.element_addr,
|
||||
param->value.state_change.mod_app_bind.app_idx,
|
||||
param->value.state_change.mod_app_bind.company_id,
|
||||
param->value.state_change.mod_app_bind.model_id);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD");
|
||||
ESP_LOGI(TAG, "elem_addr 0x%04x, sub_addr 0x%04x, cid 0x%04x, mod_id 0x%04x",
|
||||
param->value.state_change.mod_sub_add.element_addr,
|
||||
param->value.state_change.mod_sub_add.sub_addr,
|
||||
param->value.state_change.mod_sub_add.company_id,
|
||||
param->value.state_change.mod_sub_add.model_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ble_mesh_init(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);
|
||||
esp_ble_mesh_register_config_server_callback(example_ble_mesh_config_server_cb);
|
||||
esp_ble_mesh_register_generic_server_callback(example_ble_mesh_generic_server_cb);
|
||||
|
||||
err = esp_ble_mesh_init(&provision, &composition);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
|
||||
|
||||
ESP_LOGI(TAG, "BLE Mesh Node initialized");
|
||||
|
||||
board_led_operation(LED_G, LED_ON);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing...");
|
||||
|
||||
board_init();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/* board.c - Board-specific hooks */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "board.h"
|
||||
|
||||
#define TAG "BOARD"
|
||||
|
||||
struct _led_state led_state[3] = {
|
||||
{ LED_OFF, LED_OFF, LED_R, "red" },
|
||||
{ LED_OFF, LED_OFF, LED_G, "green" },
|
||||
{ LED_OFF, LED_OFF, LED_B, "blue" },
|
||||
};
|
||||
|
||||
void board_led_operation(uint8_t pin, uint8_t onoff)
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (led_state[i].pin != pin) {
|
||||
continue;
|
||||
}
|
||||
if (onoff == led_state[i].previous) {
|
||||
ESP_LOGW(TAG, "led %s is already %s",
|
||||
led_state[i].name, (onoff ? "on" : "off"));
|
||||
return;
|
||||
}
|
||||
gpio_set_level(pin, onoff);
|
||||
led_state[i].previous = onoff;
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "LED is not found!");
|
||||
}
|
||||
|
||||
static void board_led_init(void)
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
gpio_pad_select_gpio(led_state[i].pin);
|
||||
gpio_set_direction(led_state[i].pin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(led_state[i].pin, LED_OFF);
|
||||
led_state[i].previous = LED_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
board_led_init();
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -9,7 +10,6 @@
|
||||
#define _BOARD_H_
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#if defined(CONFIG_BLE_MESH_ESP_WROOM_32)
|
||||
#define LED_R GPIO_NUM_25
|
||||
@ -31,10 +31,6 @@ struct _led_state {
|
||||
char *name;
|
||||
};
|
||||
|
||||
void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number);
|
||||
|
||||
void board_prov_complete(void);
|
||||
|
||||
void board_led_operation(uint8_t pin, uint8_t onoff);
|
||||
|
||||
void board_init(void);
|
@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
@ -113,8 +113,8 @@ static esp_ble_mesh_prov_t provision = {
|
||||
.iv_index = 0x00,
|
||||
};
|
||||
|
||||
static esp_err_t esp_ble_mesh_store_node_info(const uint8_t uuid[16], uint16_t unicast,
|
||||
uint8_t elem_num, uint8_t onoff_state)
|
||||
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;
|
||||
|
||||
@ -146,7 +146,7 @@ static esp_err_t esp_ble_mesh_store_node_info(const uint8_t uuid[16], uint16_t u
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static esp_ble_mesh_node_info_t *esp_ble_mesh_get_node_info(uint16_t unicast)
|
||||
static esp_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -164,9 +164,9 @@ static esp_ble_mesh_node_info_t *esp_ble_mesh_get_node_info(uint16_t unicast)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static esp_err_t esp_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)
|
||||
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;
|
||||
@ -205,19 +205,19 @@ static esp_err_t prov_complete(int node_idx, const esp_ble_mesh_octet16_t uuid,
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = esp_ble_mesh_store_node_info(uuid, unicast, elem_num, LED_OFF);
|
||||
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 = esp_ble_mesh_get_node_info(unicast);
|
||||
node = example_ble_mesh_get_node_info(unicast);
|
||||
if (!node) {
|
||||
ESP_LOGE(TAG, "%s: Get node info failed", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
|
||||
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) {
|
||||
@ -271,8 +271,8 @@ static void recv_unprov_adv_pkt(uint8_t dev_uuid[16], uint8_t addr[BD_ADDR_LEN],
|
||||
return;
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event,
|
||||
esp_ble_mesh_prov_cb_param_t *param)
|
||||
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:
|
||||
@ -341,23 +341,8 @@ static void esp_ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event,
|
||||
return;
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event,
|
||||
esp_ble_mesh_model_cb_param_t *param)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_MODEL_OPERATION_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_SEND_COMP_EVT:
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t event,
|
||||
esp_ble_mesh_cfg_client_cb_param_t *param)
|
||||
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;
|
||||
@ -376,7 +361,7 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
return;
|
||||
}
|
||||
|
||||
node = esp_ble_mesh_get_node_info(addr);
|
||||
node = example_ble_mesh_get_node_info(addr);
|
||||
if (!node) {
|
||||
ESP_LOGE(TAG, "%s: Get node info failed", __func__);
|
||||
return;
|
||||
@ -389,7 +374,7 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
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};
|
||||
esp_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
||||
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
||||
set_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);
|
||||
@ -408,7 +393,7 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
|
||||
esp_ble_mesh_cfg_client_set_state_t set_state = {0};
|
||||
esp_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
||||
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
||||
set_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;
|
||||
@ -422,7 +407,7 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
}
|
||||
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
|
||||
esp_ble_mesh_generic_client_get_state_t get_state = {0};
|
||||
esp_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET);
|
||||
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__);
|
||||
@ -450,7 +435,7 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
|
||||
esp_ble_mesh_cfg_client_get_state_t get_state = {0};
|
||||
esp_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
|
||||
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) {
|
||||
@ -461,7 +446,7 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
}
|
||||
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
|
||||
esp_ble_mesh_cfg_client_set_state_t set_state = {0};
|
||||
esp_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
||||
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
|
||||
set_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);
|
||||
@ -474,7 +459,7 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
}
|
||||
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
|
||||
esp_ble_mesh_cfg_client_set_state_t set_state = {0};
|
||||
esp_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
||||
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
|
||||
set_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;
|
||||
@ -496,8 +481,8 @@ static void esp_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t eve
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_t event,
|
||||
esp_ble_mesh_generic_client_cb_param_t *param)
|
||||
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;
|
||||
@ -516,7 +501,7 @@ static void esp_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_
|
||||
return;
|
||||
}
|
||||
|
||||
node = esp_ble_mesh_get_node_info(addr);
|
||||
node = example_ble_mesh_get_node_info(addr);
|
||||
if (!node) {
|
||||
ESP_LOGE(TAG, "%s: Get node info failed", __func__);
|
||||
return;
|
||||
@ -530,7 +515,7 @@ static void esp_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_
|
||||
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 */
|
||||
esp_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);
|
||||
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;
|
||||
@ -562,7 +547,7 @@ static void esp_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: {
|
||||
esp_ble_mesh_generic_client_get_state_t get_state = {0};
|
||||
esp_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET);
|
||||
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__);
|
||||
@ -574,7 +559,7 @@ static void esp_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_
|
||||
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);
|
||||
esp_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);
|
||||
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;
|
||||
@ -595,19 +580,18 @@ static void esp_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_
|
||||
}
|
||||
}
|
||||
|
||||
static int ble_mesh_init(void)
|
||||
static esp_err_t ble_mesh_init(void)
|
||||
{
|
||||
uint8_t match[2] = {0xdd, 0xdd};
|
||||
int err = 0;
|
||||
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(esp_ble_mesh_prov_cb);
|
||||
esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb);
|
||||
esp_ble_mesh_register_config_client_callback(esp_ble_mesh_config_client_cb);
|
||||
esp_ble_mesh_register_generic_client_callback(esp_ble_mesh_generic_client_cb);
|
||||
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);
|
||||
@ -629,7 +613,7 @@ static int ble_mesh_init(void)
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
int err;
|
||||
esp_err_t err;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing...");
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#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 "board.h"
|
||||
#include "esp_fast_prov_operation.h"
|
||||
@ -107,15 +108,12 @@ example_fast_prov_server_t fast_prov_server = {
|
||||
.state = STATE_IDLE,
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_op_t onoff_op[] = {
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2),
|
||||
ESP_BLE_MESH_MODEL_OP_END,
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 3, ROLE_FAST_PROV);
|
||||
static esp_ble_mesh_gen_onoff_srv_t onoff_server = {
|
||||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||||
};
|
||||
|
||||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 1, ROLE_FAST_PROV);
|
||||
|
||||
static esp_ble_mesh_model_op_t fast_prov_srv_op[] = {
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET, 3),
|
||||
ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD, 16),
|
||||
@ -136,8 +134,7 @@ static esp_ble_mesh_model_op_t fast_prov_cli_op[] = {
|
||||
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_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op,
|
||||
&onoff_pub, &led_state[1]),
|
||||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub, &onoff_server),
|
||||
};
|
||||
|
||||
static esp_ble_mesh_model_t vnd_models[] = {
|
||||
@ -170,29 +167,11 @@ static esp_ble_mesh_prov_t prov = {
|
||||
.iv_index = 0x00,
|
||||
};
|
||||
|
||||
static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, uint8_t *data)
|
||||
static void example_change_led_state(uint8_t onoff)
|
||||
{
|
||||
struct _led_state *led = NULL;
|
||||
uint8_t send_data;
|
||||
esp_err_t err;
|
||||
struct _led_state *led = &led_state[1];
|
||||
|
||||
led = (struct _led_state *)model->user_data;
|
||||
if (!led) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get generic onoff server model user_data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
send_data = led->current;
|
||||
|
||||
/* Sends Generic OnOff Status as a reponse to Generic OnOff Get */
|
||||
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
|
||||
sizeof(send_data), &send_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Failed to send Generic OnOff Status message", __func__);
|
||||
return;
|
||||
}
|
||||
board_led_operation(led->pin, onoff);
|
||||
|
||||
/* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will
|
||||
* start the timer used to disable fast provisioning functionality.
|
||||
@ -202,37 +181,6 @@ static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, uint8_t *data)
|
||||
{
|
||||
struct _led_state *led = NULL;
|
||||
|
||||
led = (struct _led_state *)model->user_data;
|
||||
if (!led) {
|
||||
ESP_LOGE(TAG, "%s: Failed to get generic onoff server model user_data", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
led->current = data[0];
|
||||
gpio_set_level(led->pin, led->current);
|
||||
|
||||
/* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will
|
||||
* start the timer used to disable fast provisioning functionality.
|
||||
*/
|
||||
if (!bt_mesh_atomic_test_and_set_bit(fast_prov_server.srv_flags, DISABLE_FAST_PROV_START)) {
|
||||
k_delayed_work_submit(&fast_prov_server.disable_fast_prov_timer, DISABLE_FAST_PROV_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_onoff_set_handler(esp_ble_mesh_model_t *model,
|
||||
esp_ble_mesh_msg_ctx_t *ctx,
|
||||
uint16_t len, uint8_t *data)
|
||||
{
|
||||
gen_onoff_set_unack_handler(model, ctx, len, data);
|
||||
gen_onoff_get_handler(model, ctx, len, data);
|
||||
}
|
||||
|
||||
static void node_prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
||||
{
|
||||
ESP_LOGI(TAG, "net_idx: 0x%04x, unicast_addr: 0x%04x", net_idx, addr);
|
||||
@ -496,14 +444,6 @@ static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event
|
||||
}
|
||||
opcode = param->model_operation.opcode;
|
||||
switch (opcode) {
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
|
||||
gen_onoff_set_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK:
|
||||
gen_onoff_set_unack_handler(param->model_operation.model, param->model_operation.ctx,
|
||||
param->model_operation.length, param->model_operation.msg);
|
||||
break;
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET:
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD:
|
||||
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR:
|
||||
@ -736,6 +676,27 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t
|
||||
}
|
||||
}
|
||||
|
||||
static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event,
|
||||
esp_ble_mesh_generic_server_cb_param_t *param)
|
||||
{
|
||||
ESP_LOGI(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x",
|
||||
event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst);
|
||||
|
||||
switch (event) {
|
||||
case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT");
|
||||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||
|
||||
param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
|
||||
ESP_LOGI(TAG, "onoff 0x%02x", param->value.state_change.onoff_set.onoff);
|
||||
example_change_led_state(param->value.state_change.onoff_set.onoff);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Unknown Generic Server event 0x%02x", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ble_mesh_init(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
@ -744,6 +705,7 @@ static esp_err_t ble_mesh_init(void)
|
||||
esp_ble_mesh_register_custom_model_callback(example_ble_mesh_custom_model_cb);
|
||||
esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb);
|
||||
esp_ble_mesh_register_config_server_callback(example_ble_mesh_config_server_cb);
|
||||
esp_ble_mesh_register_generic_server_callback(example_ble_mesh_generic_server_cb);
|
||||
|
||||
err = esp_ble_mesh_init(&prov, &comp);
|
||||
if (err != ESP_OK) {
|
||||
|
Loading…
Reference in New Issue
Block a user