feat(zigbee): upgrade zigbee example to v2.0

This commit is contained in:
xieqinan@espressif.com
2026-09-09 11:34:28 +08:00
parent a8a5106421
commit 256403fe73
53 changed files with 1880 additions and 1251 deletions
@@ -0,0 +1,13 @@
include($ENV{IDF_PATH}/tools/cmake/version.cmake)
set(public_requires "freertos")
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
list(APPEND public_requires "esp_driver_gpio")
else()
list(APPEND public_requires "driver")
endif()
idf_component_register(SRC_DIRS "src"
INCLUDE_DIRS "include"
REQUIRES ${public_requires})
@@ -0,0 +1,27 @@
menu "ESP Zigbee DevKit GPIO Configuration"
config GPIO_BOOT_ON_DEVKIT
int "BOOT GPIO on devkit"
default 9 if IDF_TARGET_ESP32H2
default 9 if IDF_TARGET_ESP32C6
default 28 if IDF_TARGET_ESP32C5
default 9
help
The GPIO connected to the BOOT button on the devkits
config GPIO_EXT1_WAKEUP_SOURCE
int "External wakeup GPIO"
default 9 if IDF_TARGET_ESP32H2
default 7 if IDF_TARGET_ESP32C6
default 7 if IDF_TARGET_ESP32S31
default 6 if IDF_TARGET_ESP32C5
range 7 14 if IDF_TARGET_ESP32H2
range 0 7 if IDF_TARGET_ESP32C6
range 0 7 if IDF_TARGET_ESP32S31
range 0 6 if IDF_TARGET_ESP32C5
default 9
help
The GPIO can be used as external wake up source for sleep device
endmenu
@@ -0,0 +1,79 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: LicenseRef-Included
*
* Zigbee switch driver
*
* This driver reads a physical GPIO switch/button (e.g. BOOT button on devkit),
* uses GPIO interrupt and a queue to report press/release events to the application
* via a callback. Typical use: Zigbee HA On/Off Switch sending commands on button press.
*
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*/
#pragma once
#include <stdbool.h>
#include "driver/gpio.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Opaque handle for the switch driver instance.
*/
typedef void* switch_driver_handle_t;
/**
* @brief Invalid handle value.
*/
#define SWITCH_INV_HANDLE NULL
/**
* @brief Callback invoked from GPIO ISR (low-level) when the switch level changes.
*
* Runs in interrupt context: keep it minimal (e.g. set a flag or post to a queue).
* Do not block or call blocking / non-ISR-safe APIs.
*
* @param user_ctx User context passed at init
*/
typedef void (*switch_event_cb_t)(switch_driver_handle_t handle);
/**
* @brief Switch driver configuration.
*/
typedef struct {
gpio_num_t gpio_num; /*!< GPIO number used as switch input (e.g. BOOT button) */
switch_event_cb_t event_cb; /*!< Callback on level change (invoked from ISR); may be NULL if only polling */
} switch_driver_config_t;
/**
* @brief Initialize the switch driver.
*
* Configures the GPIO in switch_driver_init() as input with pull-up enabled,
* installs the GPIO ISR, and hooks the callback. The callback is triggered in low-level
* (GPIO ISR) context on level change.
*
* @param config Driver configuration (gpio_num required; event_cb optional)
* @return Handle
*/
switch_driver_handle_t switch_driver_init(const switch_driver_config_t *config);
/**
* @brief Deinitialize the switch driver.
*
* Removes ISR handler and resets GPIO.
*
* @param handle Handle from switch_driver_init; may be NULL
*/
void switch_driver_deinit(switch_driver_handle_t handle);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,116 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: LicenseRef-Included
*
* Zigbee switch driver
*
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdlib.h>
#include <string.h>
#include "switch_driver.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "esp_attr.h"
#include "esp_log.h"
static QueueHandle_t gpio_event_queue = NULL;
static void switch_driver_gpio_intr_enabled(gpio_num_t gpio_num, bool enabled)
{
if (enabled) {
gpio_intr_enable(gpio_num);
} else {
gpio_intr_disable(gpio_num);
}
}
static void IRAM_ATTR gpio_isr_handler(void *arg)
{
switch_driver_config_t *config = (switch_driver_config_t *)arg;
switch_driver_gpio_intr_enabled(config->gpio_num, false);
xQueueSendFromISR(gpio_event_queue, &config, NULL);
}
static void switch_driver_button_detected(void *arg)
{
(void)arg;
switch_driver_config_t *config = NULL;
while (1) {
if (xQueueReceive(gpio_event_queue, &config, portMAX_DELAY) == pdTRUE) {
if (config) {
if (config->event_cb) {
config->event_cb(config);
}
}
}
vTaskDelay(pdMS_TO_TICKS(200));
switch_driver_gpio_intr_enabled(config->gpio_num, true);
}
}
switch_driver_handle_t switch_driver_init(const switch_driver_config_t *config)
{
if (config == NULL || config->gpio_num < 0) {
return NULL;
}
switch_driver_config_t *handle = (switch_driver_config_t *)malloc(sizeof(switch_driver_config_t));
if (handle == NULL) {
return NULL;
}
memcpy(handle, (void *)config, sizeof(switch_driver_config_t));
/* Configure GPIO in init: input, pull-up, and negative-edge interrupt */
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << config->gpio_num),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_LOW_LEVEL,
};
esp_err_t ret = gpio_config(&io_conf);
if (ret != ESP_OK) {
free(handle);
return NULL;
}
gpio_event_queue = xQueueCreate(10, sizeof(switch_driver_config_t *));
if (gpio_event_queue == 0) {
gpio_reset_pin(config->gpio_num);
free(handle);
return NULL;
}
xTaskCreate(switch_driver_button_detected, "button_detected", 4096, NULL, 10, NULL);
ret = gpio_install_isr_service(0);
if (ret != ESP_OK) {
gpio_reset_pin(config->gpio_num);
free(handle);
return NULL;
}
ret = gpio_isr_handler_add(config->gpio_num, gpio_isr_handler, (void *)handle);
if (ret != ESP_OK) {
gpio_reset_pin(config->gpio_num);
free(handle);
return NULL;
}
return handle;
}
void switch_driver_deinit(switch_driver_handle_t handle)
{
if (handle == NULL) {
return;
}
switch_driver_config_t *config = (switch_driver_config_t *)handle;
gpio_isr_handler_remove(config->gpio_num);
gpio_reset_pin(config->gpio_num);
free(config);
}