mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
feat(zigbee): upgrade zigbee example to v2.0
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRC_DIRS "src"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES esp_timer
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
menu "Zigbee Example Configuration"
|
||||
|
||||
config ZB_EXAMPLE_PRIMARY_CHANNEL
|
||||
int "Zigbee primary channel"
|
||||
range 11 26
|
||||
default 13
|
||||
|
||||
config ZB_EXAMPLE_SECONDARY_CHANNEL_MASK
|
||||
hex "Zigbee secondary channel mask"
|
||||
default 0x07FFF800
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* Alarm 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The argument type for the alarm callback.
|
||||
*
|
||||
*/
|
||||
typedef uintptr_t alarm_timer_arg_t;
|
||||
|
||||
/**
|
||||
* @brief The callback for the timer.
|
||||
*
|
||||
*/
|
||||
typedef void (*alarm_timer_callback_t)(alarm_timer_arg_t arg);
|
||||
|
||||
/**
|
||||
* @brief Schedule an alarm to fire at a given time.
|
||||
*
|
||||
* @param cb The callback to execute when the alarm fires.
|
||||
* @param arg The argument to pass to the callback.
|
||||
* @param time_ms The time to fire the timer in milliseconds.
|
||||
*
|
||||
* @return ESP_OK on success, error code otherwise.
|
||||
*/
|
||||
esp_err_t alarm_timer_schedule(alarm_timer_callback_t cb, alarm_timer_arg_t arg, uint32_t time_ms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
# This config file optimizes the mbedTLS code size by disabling
|
||||
# unused features by ESP-Zigbee-SDK.
|
||||
|
||||
#
|
||||
# mbedTLS
|
||||
#
|
||||
|
||||
# Enable required
|
||||
CONFIG_MBEDTLS_AES_C=y
|
||||
CONFIG_MBEDTLS_CCM_C=y
|
||||
|
||||
# Disable unused
|
||||
CONFIG_MBEDTLS_GCM_C=n
|
||||
CONFIG_MBEDTLS_CMAC_C=n
|
||||
CONFIG_MBEDTLS_SHA1_C=n
|
||||
CONFIG_MBEDTLS_SHA3_C=n
|
||||
CONFIG_MBEDTLS_SHA512_C=n
|
||||
CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=n
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=n
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=n
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=n
|
||||
|
||||
## v5.0
|
||||
CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=n
|
||||
CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=n
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=n
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=n
|
||||
|
||||
## v6.0
|
||||
CONFIG_MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH=y
|
||||
CONFIG_MBEDTLS_CTR_DRBG_C=y
|
||||
CONFIG_MBEDTLS_HMAC_DRBG_C=n
|
||||
CONFIG_MBEDTLS_X509_RSASSA_PSS_SUPPORT=n
|
||||
CONFIG_MBEDTLS_CIPHER_MODE_CBC=n
|
||||
CONFIG_MBEDTLS_CIPHER_MODE_CFB=n
|
||||
CONFIG_MBEDTLS_CIPHER_MODE_CTR=n
|
||||
CONFIG_MBEDTLS_CIPHER_MODE_OFB=n
|
||||
CONFIG_MBEDTLS_CIPHER_MODE_XTS=n
|
||||
# PSA_WANT_ALG_RSA_PSS needs CONFIG_MBEDTLS_RSA_C=y on ESP-IDF master
|
||||
CONFIG_MBEDTLS_RSA_C=y
|
||||
CONFIG_MBEDTLS_MD5_C=n
|
||||
CONFIG_MBEDTLS_SHA384_C=n
|
||||
|
||||
# end of mbedTLS
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* Alarm Timer
|
||||
*
|
||||
* 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 "esp_timer.h"
|
||||
|
||||
#include "alarm_timer.h"
|
||||
|
||||
typedef struct alarm_timer_s {
|
||||
esp_timer_handle_t timer;
|
||||
alarm_timer_callback_t cb;
|
||||
alarm_timer_arg_t arg;
|
||||
} alarm_timer_t;
|
||||
|
||||
static void alarm_timer_cb(void *arg)
|
||||
{
|
||||
alarm_timer_t *alarm = (alarm_timer_t *)arg;
|
||||
|
||||
esp_timer_delete(alarm->timer);
|
||||
alarm->cb(alarm->arg);
|
||||
free(alarm);
|
||||
}
|
||||
|
||||
esp_err_t alarm_timer_schedule(alarm_timer_callback_t cb, alarm_timer_arg_t arg, uint32_t time_ms)
|
||||
{
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
alarm_timer_t *alarm = malloc(sizeof(alarm_timer_t));
|
||||
if (alarm == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
alarm->cb = cb;
|
||||
alarm->arg = arg;
|
||||
alarm->timer = NULL;
|
||||
|
||||
esp_timer_create_args_t timer_args = {
|
||||
.callback = alarm_timer_cb,
|
||||
.arg = alarm,
|
||||
};
|
||||
|
||||
esp_err_t err = esp_timer_create(&timer_args, &alarm->timer);
|
||||
if (err != ESP_OK) {
|
||||
free(alarm);
|
||||
return err;
|
||||
}
|
||||
|
||||
uint64_t time_us = (uint64_t)time_ms * 1000;
|
||||
err = esp_timer_start_once(alarm->timer, time_us);
|
||||
if (err != ESP_OK) {
|
||||
esp_timer_delete(alarm->timer);
|
||||
free(alarm);
|
||||
return err;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
idf_component_register(SRCS "zcl_utility.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES espressif__esp-zigbee-lib)
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* ZCL utility functions for Zigbee examples
|
||||
*
|
||||
* This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
*
|
||||
* 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 "esp_err.h"
|
||||
#include "esp_zigbee_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! Maximum length of ManufacturerName string field */
|
||||
#define ESP_ZB_ZCL_CLUSTER_ID_BASIC_MANUFACTURER_NAME_MAX_LEN 32
|
||||
|
||||
/*! Maximum length of ModelIdentifier string field */
|
||||
#define ESP_ZB_ZCL_CLUSTER_ID_BASIC_MODEL_IDENTIFIER_MAX_LEN 32
|
||||
|
||||
/** optional basic manufacturer information */
|
||||
typedef struct zcl_basic_manufacturer_info_s {
|
||||
char *manufacturer_name;
|
||||
char *model_identifier;
|
||||
} zcl_basic_manufacturer_info_t;
|
||||
|
||||
/**
|
||||
* @brief Adds manufacturer information to the ZCL basic cluster of endpoint
|
||||
*
|
||||
* @param ep_list The pointer to the endpoint list with @p endpoint_id
|
||||
* @param endpoint_id The endpoint identifier indicating where the ZCL basic cluster resides
|
||||
* @param info The pointer to the basic manufacturer information, @see zcl_basic_manufacturer_info_t
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
*/
|
||||
esp_err_t esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, uint8_t endpoint_id, zcl_basic_manufacturer_info_t *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* ZCL utility functions for Zigbee examples
|
||||
*
|
||||
* This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_zigbee_core.h"
|
||||
|
||||
#include "zcl_utility.h"
|
||||
|
||||
static const char *TAG = "ZCL_UTILITY";
|
||||
|
||||
esp_err_t esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, uint8_t endpoint_id, zcl_basic_manufacturer_info_t *info)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_zb_cluster_list_t *cluster_list = NULL;
|
||||
esp_zb_attribute_list_t *basic_cluster = NULL;
|
||||
|
||||
cluster_list = esp_zb_ep_list_get_ep(ep_list, endpoint_id);
|
||||
ESP_RETURN_ON_FALSE(cluster_list, ESP_ERR_INVALID_ARG, TAG, "Failed to find endpoint id: %d in list: %p", endpoint_id, ep_list);
|
||||
basic_cluster = esp_zb_cluster_list_get_cluster(cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
|
||||
ESP_RETURN_ON_FALSE(basic_cluster, ESP_ERR_INVALID_ARG, TAG, "Failed to find basic cluster in endpoint: %d", endpoint_id);
|
||||
ESP_RETURN_ON_FALSE((info && info->manufacturer_name), ESP_ERR_INVALID_ARG, TAG, "Invalid manufacturer name");
|
||||
ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, info->manufacturer_name));
|
||||
ESP_RETURN_ON_FALSE((info && info->model_identifier), ESP_ERR_INVALID_ARG, TAG, "Invalid model identifier");
|
||||
ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, info->model_identifier));
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRC_DIRS "src"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES led_strip)
|
||||
@@ -0,0 +1,13 @@
|
||||
menu "ESP Zigbee DevKit LED Configuration"
|
||||
|
||||
config GPIO_LED_ON_DEVKIT
|
||||
int "LED GPIO on devkit"
|
||||
default 8 if IDF_TARGET_ESP32H2
|
||||
default 8 if IDF_TARGET_ESP32C6
|
||||
default 27 if IDF_TARGET_ESP32C5
|
||||
default 8
|
||||
|
||||
help
|
||||
The GPIO connected to the LED on the devkits
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,3 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/led_strip: "~3.0.0"
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* Zigbee light driver example
|
||||
*
|
||||
* This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
*
|
||||
* 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 <math.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* light intensity level */
|
||||
#define LIGHT_DEFAULT_ON 1
|
||||
#define LIGHT_DEFAULT_OFF 0
|
||||
|
||||
/* LED strip configuration */
|
||||
#define CONFIG_EXAMPLE_STRIP_LED_GPIO CONFIG_GPIO_LED_ON_DEVKIT
|
||||
#define CONFIG_EXAMPLE_STRIP_LED_NUMBER 1
|
||||
|
||||
/** Convert Hue,Saturation,V to RGB
|
||||
* RGB - [0..0xffff]
|
||||
* hue - [0..0xff]
|
||||
* Sat - [0..0xff]
|
||||
* V always = (ZB_UINT16_MAX-1)
|
||||
*/
|
||||
#define HSV_to_RGB(h, s, v, r, g, b) \
|
||||
{ \
|
||||
uint8_t i; \
|
||||
uint8_t sector = UINT8_MAX / 6; \
|
||||
float f, p, q, t; \
|
||||
if (s == 0) { /* achromatic (grey)*/ \
|
||||
r = g = b = (v); \
|
||||
} else { \
|
||||
i = h / sector; /* sector 0 to 5 */ \
|
||||
f = h % sector; /* factorial part of h*/ \
|
||||
p = (float)(v * (1.0 - (float)s / UINT8_MAX)); \
|
||||
q = (float)(v * (1.0 - (float)s / UINT8_MAX * f / (float)sector)); \
|
||||
t = (float)(v * (1.0 - (float)s / UINT8_MAX * (1 - f / (float)sector))); \
|
||||
switch (i) { \
|
||||
case 0: \
|
||||
r = (v); \
|
||||
g = t; \
|
||||
b = p; \
|
||||
break; \
|
||||
case 1: \
|
||||
r = q; \
|
||||
g = (v); \
|
||||
b = p; \
|
||||
break; \
|
||||
case 2: \
|
||||
r = p; \
|
||||
g = (v); \
|
||||
b = t; \
|
||||
break; \
|
||||
case 3: \
|
||||
r = p; \
|
||||
g = q; \
|
||||
b = (v); \
|
||||
break; \
|
||||
case 4: \
|
||||
r = t; \
|
||||
g = p; \
|
||||
b = (v); \
|
||||
break; \
|
||||
case 5: \
|
||||
default: \
|
||||
r = (v); \
|
||||
g = p; \
|
||||
b = q; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define XYZ_to_RGB(X, Y, Z, r, g, b) \
|
||||
{ \
|
||||
r = (float)(3.240479 * (X)-1.537150 * (Y)-0.498535 * (Z)); \
|
||||
g = (float)(-0.969256 * (X) + 1.875992 * (Y) + 0.041556 * (Z)); \
|
||||
b = (float)(0.055648 * (X)-0.204043 * (Y) + 1.057311 * (Z)); \
|
||||
if (r > 1) { \
|
||||
r = 1; \
|
||||
} \
|
||||
if (g > 1) { \
|
||||
g = 1; \
|
||||
} \
|
||||
if (b > 1) { \
|
||||
b = 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set light power (on/off).
|
||||
*
|
||||
* @param power The light power value to be set
|
||||
*/
|
||||
void light_driver_set_power(bool power);
|
||||
|
||||
/**
|
||||
* @brief color light driver init, be invoked where you want to use color light
|
||||
*
|
||||
* @param power power on/off
|
||||
*/
|
||||
void light_driver_init(bool power);
|
||||
|
||||
/**
|
||||
* @brief Set light level
|
||||
*
|
||||
* @param level The light level value to be set
|
||||
*/
|
||||
void light_driver_set_level(uint8_t level);
|
||||
|
||||
/**
|
||||
* @brief Set light color from RGB
|
||||
*
|
||||
* @param red The red color value to be set
|
||||
* @param green The green color value to be set
|
||||
* @param blue The blue color value to be set
|
||||
*/
|
||||
void light_driver_set_color_RGB(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
/**
|
||||
* @brief Set light color from color xy
|
||||
*
|
||||
* @param color_current_x The color x value to be set
|
||||
* @param color_current_y The color y value to be set
|
||||
*/
|
||||
void light_driver_set_color_xy(uint16_t color_current_x, uint16_t color_current_y);
|
||||
|
||||
/**
|
||||
* @brief Set light color from hue saturation
|
||||
*
|
||||
* @param hue The hue value to be set
|
||||
* @param sat The saturation value to be set
|
||||
*/
|
||||
void light_driver_set_color_hue_sat(uint8_t hue, uint8_t sat);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* Zigbee light driver example
|
||||
*
|
||||
* This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
*
|
||||
* 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 "led_strip.h"
|
||||
#include "light_driver.h"
|
||||
|
||||
static led_strip_handle_t s_led_strip;
|
||||
static uint8_t s_red = 255, s_green = 255, s_blue = 255, s_level = 255;
|
||||
|
||||
void light_driver_set_color_xy(uint16_t color_current_x, uint16_t color_current_y)
|
||||
{
|
||||
float red_f = 0, green_f = 0, blue_f = 0, color_x, color_y;
|
||||
color_x = (float)color_current_x / 65535;
|
||||
color_y = (float)color_current_y / 65535;
|
||||
/* assume color_Y is full light level value 1 (0-1.0) */
|
||||
float color_X = color_x / color_y;
|
||||
float color_Z = (1 - color_x - color_y) / color_y;
|
||||
/* change from xy to linear RGB NOT sRGB */
|
||||
XYZ_to_RGB(color_X, 1, color_Z, red_f, green_f, blue_f);
|
||||
float ratio = (float)s_level / 255;
|
||||
s_red = (uint8_t)(red_f * (float)255);
|
||||
s_green = (uint8_t)(green_f * (float)255);
|
||||
s_blue = (uint8_t)(blue_f * (float)255);
|
||||
ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * ratio, s_green * ratio, s_blue * ratio));
|
||||
ESP_ERROR_CHECK(led_strip_refresh(s_led_strip));
|
||||
}
|
||||
|
||||
void light_driver_set_color_hue_sat(uint8_t hue, uint8_t sat)
|
||||
{
|
||||
float red_f, green_f, blue_f;
|
||||
HSV_to_RGB(hue, sat, UINT8_MAX, red_f, green_f, blue_f);
|
||||
float ratio = (float)s_level / 255;
|
||||
s_red = (uint8_t)red_f;
|
||||
s_green = (uint8_t)green_f;
|
||||
s_blue = (uint8_t)blue_f;
|
||||
ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * ratio, s_green * ratio, s_blue * ratio));
|
||||
ESP_ERROR_CHECK(led_strip_refresh(s_led_strip));
|
||||
}
|
||||
|
||||
void light_driver_set_color_RGB(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
float ratio = (float)s_level / 255;
|
||||
s_red = red;
|
||||
s_green = green;
|
||||
s_blue = blue;
|
||||
ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, red * ratio, green * ratio, blue * ratio));
|
||||
ESP_ERROR_CHECK(led_strip_refresh(s_led_strip));
|
||||
}
|
||||
|
||||
void light_driver_set_power(bool power)
|
||||
{
|
||||
ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * power, s_green * power, s_blue * power));
|
||||
ESP_ERROR_CHECK(led_strip_refresh(s_led_strip));
|
||||
}
|
||||
|
||||
void light_driver_set_level(uint8_t level)
|
||||
{
|
||||
s_level = level;
|
||||
float ratio = (float)s_level / 255;
|
||||
ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * ratio, s_green * ratio, s_blue * ratio));
|
||||
ESP_ERROR_CHECK(led_strip_refresh(s_led_strip));
|
||||
}
|
||||
|
||||
void light_driver_init(bool power)
|
||||
{
|
||||
led_strip_config_t led_strip_conf = {
|
||||
.max_leds = CONFIG_EXAMPLE_STRIP_LED_NUMBER,
|
||||
.strip_gpio_num = CONFIG_EXAMPLE_STRIP_LED_GPIO,
|
||||
};
|
||||
led_strip_rmt_config_t rmt_conf = {
|
||||
.resolution_hz = 10 * 1000 * 1000, // 10MHz
|
||||
};
|
||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&led_strip_conf, &rmt_conf, &s_led_strip));
|
||||
|
||||
light_driver_set_power(power);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user