Преглед изворни кода

ble_mesh: update ble mesh examples

lly пре 6 година
родитељ
комит
dfcfe467c9
44 измењених фајлова са 1632 додато и 1301 уклоњено
  1. 0 496
      examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/ble_mesh_demo_main.c
  2. 0 115
      examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/board.c
  3. 1 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/main/ble_mesh_demo_main.c
  4. 31 69
      examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/main/ble_mesh_demo_main.c
  5. 0 358
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/ble_mesh_demo_main.c
  6. 0 130
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/board.c
  7. 1 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt
  8. 1 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile
  9. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/README.md
  10. 7 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/CMakeLists.txt
  11. 21 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/Kconfig
  12. 47 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/README.md
  13. 434 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button.c
  14. 48 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button_obj.cpp
  15. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/component.mk
  16. 230 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/include/iot_button.h
  17. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/CMakeLists.txt
  18. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/Kconfig.projbuild
  19. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/ble_mesh_demo_init.c
  20. 1 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/ble_mesh_demo_init.h
  21. 272 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/ble_mesh_demo_main.c
  22. 78 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/board.c
  23. 1 4
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/board.h
  24. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/component.mk
  25. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults
  26. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/ble_mesh_client_model.md
  27. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/images/app.png
  28. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/images/message.png
  29. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/images/picture5.png
  30. 1 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/CMakeLists.txt
  31. 1 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/Makefile
  32. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/README.md
  33. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/CMakeLists.txt
  34. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/Kconfig.projbuild
  35. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/ble_mesh_demo_init.c
  36. 1 1
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/ble_mesh_demo_init.h
  37. 332 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/ble_mesh_demo_main.c
  38. 56 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/board.c
  39. 1 5
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/board.h
  40. 4 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/component.mk
  41. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults
  42. 0 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/tutorial/Ble_Mesh_Node_Example_Walkthrough.md
  43. 32 48
      examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/main/ble_mesh_demo_main.c
  44. 31 69
      examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/ble_mesh_demo_main.c

+ 0 - 496
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/ble_mesh_demo_main.c

@@ -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);
-    }
-}

+ 0 - 115
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/board.c

@@ -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);
-}

+ 1 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/main/ble_mesh_demo_main.c

@@ -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...");
 

+ 31 - 69
examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/main/ble_mesh_demo_main.c

@@ -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;
-
-    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;
+    struct _led_state *led = &led_state[1];
 
-    /* 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) {

+ 0 - 358
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/ble_mesh_demo_main.c

@@ -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);
-    }
-}

+ 0 - 130
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/board.c

@@ -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);
-}

+ 1 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_node/CMakeLists.txt → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt

@@ -4,4 +4,4 @@ cmake_minimum_required(VERSION 3.5)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 set(SUPPORTED_TARGETS esp32)
-project(ble_mesh_node)
+project(onoff_client)

+ 1 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_node/Makefile → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile

@@ -3,7 +3,7 @@
 # project subdirectory.
 #
 
-PROJECT_NAME := ble_mesh_node
+PROJECT_NAME := onoff_client
 
 COMPONENT_ADD_INCLUDEDIRS := components/include
 

+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/README.md → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/README.md


+ 7 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/CMakeLists.txt

@@ -0,0 +1,7 @@
+
+set(COMPONENT_SRCS "button.c"
+                   "button_obj.cpp")
+
+set(COMPONENT_ADD_INCLUDEDIRS ". include")
+
+register_component()

+ 21 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/Kconfig

@@ -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

+ 47 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/README.md

@@ -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
+```

+ 434 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button.c

@@ -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;
+}

+ 48 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button_obj.cpp

@@ -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
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/component.mk → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/component.mk


+ 230 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/include/iot_button.h

@@ -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

+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/CMakeLists.txt → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/CMakeLists.txt


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/Kconfig.projbuild → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/Kconfig.projbuild


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/ble_mesh_demo_init.c → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/ble_mesh_demo_init.c


+ 1 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/ble_mesh_demo_init.h → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/ble_mesh_demo_init.h

@@ -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);
 

+ 272 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/ble_mesh_demo_main.c

@@ -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);
+    }
+}

+ 78 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/board.c

@@ -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();
+}

+ 1 - 4
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/board.h → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/board.h

@@ -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);

+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/component.mk → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/main/component.mk


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/sdkconfig.defaults → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/tutorial/ble_mesh_client_model.md → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/ble_mesh_client_model.md


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/tutorial/images/app.png → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/images/app.png


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/tutorial/images/message.png → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/images/message.png


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/tutorial/images/picture5.png → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/images/picture5.png


+ 1 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/CMakeLists.txt → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/CMakeLists.txt

@@ -4,4 +4,4 @@ cmake_minimum_required(VERSION 3.5)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 set(SUPPORTED_TARGETS esp32)
-project(ble_mesh_client_model)
+project(onoff_server)

+ 1 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/Makefile → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/Makefile

@@ -3,7 +3,7 @@
 # project subdirectory.
 #
 
-PROJECT_NAME := ble_mesh_client_model
+PROJECT_NAME := onoff_server
 
 COMPONENT_ADD_INCLUDEDIRS := components/include
 

+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/README.md → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/README.md


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/CMakeLists.txt → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/CMakeLists.txt


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/Kconfig.projbuild → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/Kconfig.projbuild


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/ble_mesh_demo_init.c → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/ble_mesh_demo_init.c


+ 1 - 1
examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/ble_mesh_demo_init.h → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/ble_mesh_demo_init.h

@@ -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);
 

+ 332 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/ble_mesh_demo_main.c

@@ -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, &param->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, &param->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, &param->ctx, &param->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);
+    }
+}

+ 56 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/board.c

@@ -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();
+}

+ 1 - 5
examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/board.h → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/board.h

@@ -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);

+ 4 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/main/component.mk

@@ -0,0 +1,4 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/sdkconfig.defaults → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults


+ 0 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_node/tutorial/Ble_Mesh_Node_Example_Walkthrough.md → examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/tutorial/Ble_Mesh_Node_Example_Walkthrough.md


+ 32 - 48
examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/main/ble_mesh_demo_main.c

@@ -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...");
 

+ 31 - 69
examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/ble_mesh_demo_main.c

@@ -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;
-
-    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;
+    struct _led_state *led = &led_state[1];
 
-    /* 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) {