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:
@@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "esp_zigbee_gateway.c"
|
||||
PRIV_REQUIRES ieee802154 esp_driver_usb_serial_jtag esp_coex esp_netif
|
||||
vfs esp_wifi nvs_flash esp_driver_uart
|
||||
INCLUDE_DIRS ".")
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES ieee802154 esp_driver_usb_serial_jtag esp_coex esp_netif
|
||||
vfs esp_wifi spiffs nvs_flash esp_driver_uart)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
choice ZB_GW_RCP_CHIP
|
||||
depends on AUTO_UPDATE_RCP
|
||||
prompt "Zigbee gateway RCP chip for auto update"
|
||||
default ZB_GW_RCP_CHIP_ESP32H2
|
||||
help
|
||||
Select the RCP chip connected to the Zigbee gateway.
|
||||
|
||||
config ZB_GW_RCP_CHIP_ESP32H2
|
||||
bool "ESP32-H2"
|
||||
help
|
||||
ESP32-H2 is the RCP chip connected to the Zigbee gateway.
|
||||
|
||||
config ZB_GW_RCP_CHIP_ESP32C6
|
||||
bool "ESP32-C6"
|
||||
help
|
||||
ESP32-C6 is the RCP chip connected to the Zigbee gateway.
|
||||
endchoice
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
@@ -11,172 +11,255 @@
|
||||
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/usb_serial_jtag.h"
|
||||
#include "esp_coexist.h"
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "esp_vfs_eventfd.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
#include "esp_event.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include "esp_zigbee_gateway.h"
|
||||
#include "zb_config_platform.h"
|
||||
|
||||
static const char *TAG = "ESP_ZB_GATEWAY";
|
||||
|
||||
/* Note: Please select the correct console output port based on the development board in menuconfig */
|
||||
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
esp_err_t esp_zb_gateway_console_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
/* Disable buffering on stdin */
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
|
||||
/* Minicom, screen, idf_monitor send CR when ENTER key is pressed */
|
||||
usb_serial_jtag_vfs_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
|
||||
/* Move the caret to the beginning of the next line on '\n' */
|
||||
usb_serial_jtag_vfs_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
|
||||
|
||||
/* Enable non-blocking mode on stdin and stdout */
|
||||
fcntl(fileno(stdout), F_SETFL, O_NONBLOCK);
|
||||
fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
|
||||
|
||||
usb_serial_jtag_driver_config_t usb_serial_jtag_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT();
|
||||
ret = usb_serial_jtag_driver_install(&usb_serial_jtag_config);
|
||||
usb_serial_jtag_vfs_use_driver();
|
||||
uart_vfs_dev_register();
|
||||
return ret;
|
||||
}
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
#include "esp_wifi.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask)
|
||||
#if CONFIG_AUTO_UPDATE_RCP
|
||||
#include "zigbee_rcp.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE
|
||||
#include "esp_coexist.h"
|
||||
#endif
|
||||
|
||||
#include "light_driver.h"
|
||||
#include "alarm_timer.h"
|
||||
|
||||
#include "esp_zigbee.h"
|
||||
|
||||
#include "ezbee/zha.h"
|
||||
#include "esp_zigbee_gateway.h"
|
||||
|
||||
static const char *TAG = "ZIGBEE_GATEWAY";
|
||||
|
||||
#if (CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET)
|
||||
static esp_err_t esp_zigbee_connect_netif(void)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(esp_zb_bdb_start_top_level_commissioning(mode_mask) == ESP_OK, , TAG, "Failed to start Zigbee bdb commissioning");
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
wifi_ps_type_t ps_type = WIFI_PS_NONE;
|
||||
#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE
|
||||
ps_type = WIFI_PS_MIN_MODEM;
|
||||
#endif /* CONFIG_ESP_COEX_SW_COEXIST_ENABLE */
|
||||
#endif /* CONFIG_EXAMPLE_CONNECT_WIFI */
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_netif_init(), TAG, "Failed to initialize network interface");
|
||||
ESP_RETURN_ON_ERROR(esp_event_loop_create_default(), TAG, "Failed to create event loop");
|
||||
|
||||
#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE
|
||||
esp_coex_wifi_i154_enable();
|
||||
#endif /* CONFIG_ESP_COEX_SW_COEXIST_ENABLE*/
|
||||
|
||||
ESP_RETURN_ON_ERROR(example_connect(), TAG, "Failed to connect to Network Interface");
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_set_ps(ps_type), TAG, "Failed to set power save type for Wi-Fi");
|
||||
#endif /* CONFIG_EXAMPLE_CONNECT_WIFI */
|
||||
return ret;
|
||||
}
|
||||
#endif /* (CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET) */
|
||||
|
||||
static esp_err_t deferred_driver_init(void)
|
||||
{
|
||||
static bool is_inited = false;
|
||||
|
||||
ESP_RETURN_ON_FALSE(!is_inited, ESP_OK, TAG, "Deferred driver already initialized");
|
||||
|
||||
light_driver_init(false);
|
||||
is_inited = true;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct)
|
||||
static void esp_zigbee_alarm_bdb_commissioning(alarm_timer_arg_t arg)
|
||||
{
|
||||
uint32_t *p_sg_p = signal_struct->p_app_signal;
|
||||
esp_err_t err_status = signal_struct->esp_err_status;
|
||||
esp_zb_app_signal_type_t sig_type = *p_sg_p;
|
||||
esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL;
|
||||
esp_zigbee_lock_acquire(portMAX_DELAY);
|
||||
(void)ezb_bdb_start_top_level_commissioning(arg);
|
||||
esp_zigbee_lock_release();
|
||||
}
|
||||
|
||||
switch (sig_type) {
|
||||
case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP:
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE
|
||||
esp_coex_wifi_i154_enable();
|
||||
#endif /* CONFIG_ESP_COEX_SW_COEXIST_ENABLE */
|
||||
ESP_RETURN_ON_FALSE(example_connect() == ESP_OK, , TAG, "Failed to connect to Wi-Fi");
|
||||
ESP_RETURN_ON_FALSE(esp_wifi_set_ps(WIFI_PS_MIN_MODEM) == ESP_OK, , TAG, "Failed to set Wi-Fi minimum modem power save type");
|
||||
#endif /* CONFIG_EXAMPLE_CONNECT_WIFI */
|
||||
static bool esp_zigbee_app_signal_handler(const ezb_app_signal_t *app_signal)
|
||||
{
|
||||
ezb_app_signal_type_t signal_type = ezb_app_signal_get_type(app_signal);
|
||||
|
||||
switch (signal_type) {
|
||||
case EZB_ZDO_SIGNAL_SKIP_STARTUP:
|
||||
ESP_LOGI(TAG, "Initialize Zigbee stack");
|
||||
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION);
|
||||
ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_INITIALIZATION);
|
||||
break;
|
||||
case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START:
|
||||
case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT:
|
||||
if (err_status == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non");
|
||||
if (esp_zb_bdb_is_factory_new()) {
|
||||
ESP_LOGI(TAG, "Start network formation");
|
||||
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION);
|
||||
case EZB_BDB_SIGNAL_DEVICE_FIRST_START:
|
||||
case EZB_BDB_SIGNAL_DEVICE_REBOOT: {
|
||||
ezb_bdb_comm_status_t status = *((ezb_bdb_comm_status_t *)ezb_app_signal_get_params(app_signal));
|
||||
if (status == EZB_BDB_STATUS_SUCCESS) {
|
||||
ESP_LOGI(TAG, "Deferred driver initialization %s", deferred_driver_init() ? "failed" : "successful");
|
||||
ESP_LOGI(TAG, "Device started up in%s factory-reset mode", ezb_bdb_is_factory_new() ? "" : " non");
|
||||
if (ezb_bdb_is_factory_new()) {
|
||||
ESP_ERROR_CHECK(ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_NETWORK_FORMATION));
|
||||
} else {
|
||||
esp_zb_bdb_open_network(180);
|
||||
ESP_LOGI(TAG, "Device rebooted");
|
||||
ezb_bdb_open_network(180);
|
||||
ESP_LOGI(TAG, "Device reboot");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status));
|
||||
ESP_LOGW(TAG, "The %s failed with status(0x%02x), please retry", ezb_app_signal_to_string(signal_type), status);
|
||||
alarm_timer_schedule(esp_zigbee_alarm_bdb_commissioning, EZB_BDB_MODE_INITIALIZATION, 1000);
|
||||
}
|
||||
break;
|
||||
case ESP_ZB_BDB_SIGNAL_FORMATION:
|
||||
if (err_status == ESP_OK) {
|
||||
esp_zb_ieee_addr_t ieee_address;
|
||||
esp_zb_get_long_address(ieee_address);
|
||||
ESP_LOGI(TAG, "Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)",
|
||||
ieee_address[7], ieee_address[6], ieee_address[5], ieee_address[4],
|
||||
ieee_address[3], ieee_address[2], ieee_address[1], ieee_address[0],
|
||||
esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address());
|
||||
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
|
||||
} break;
|
||||
case EZB_BDB_SIGNAL_FORMATION: {
|
||||
ezb_bdb_comm_status_t status = *((ezb_bdb_comm_status_t *)ezb_app_signal_get_params(app_signal));
|
||||
if (status == EZB_BDB_STATUS_SUCCESS) {
|
||||
ezb_extpanid_t extended_pan_id;
|
||||
ezb_nwk_get_extended_panid(&extended_pan_id);
|
||||
ESP_LOGI(TAG, "Formed network successfully: PAN ID(0x%04hx, EXT: 0x%llx), Channel(%d), Short Address(0x%04hx)",
|
||||
ezb_nwk_get_panid(), extended_pan_id.u64, ezb_nwk_get_current_channel(), ezb_nwk_get_short_address());
|
||||
ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Restart network formation (status: %s)", esp_err_to_name(err_status));
|
||||
esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000);
|
||||
ESP_LOGW(TAG, "Failed to form network with status(0x%02x)", status);
|
||||
alarm_timer_schedule(esp_zigbee_alarm_bdb_commissioning, EZB_BDB_MODE_NETWORK_FORMATION, 1000);
|
||||
}
|
||||
break;
|
||||
case ESP_ZB_BDB_SIGNAL_STEERING:
|
||||
if (err_status == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Network steering started");
|
||||
} break;
|
||||
case EZB_BDB_SIGNAL_STEERING: {
|
||||
ezb_bdb_comm_status_t status = *((ezb_bdb_comm_status_t *)ezb_app_signal_get_params(app_signal));
|
||||
if (status == EZB_BDB_STATUS_SUCCESS) {
|
||||
ESP_LOGI(TAG, "Network steering completed");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Failed to steering network with status(0x%02x)", status);
|
||||
alarm_timer_schedule(esp_zigbee_alarm_bdb_commissioning, EZB_BDB_MODE_NETWORK_FORMATION, 1000);
|
||||
}
|
||||
break;
|
||||
case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE:
|
||||
dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p);
|
||||
ESP_LOGI(TAG, "New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr);
|
||||
break;
|
||||
case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS:
|
||||
if (err_status == ESP_OK) {
|
||||
if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) {
|
||||
ESP_LOGI(TAG, "Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p));
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id());
|
||||
}
|
||||
} break;
|
||||
case EZB_ZDO_SIGNAL_DEVICE_ANNCE: {
|
||||
const ezb_zdo_signal_device_annce_params_t *dev_annce_params = ezb_app_signal_get_params(app_signal);
|
||||
ESP_LOGI(TAG, "New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->short_addr);
|
||||
} break;
|
||||
case EZB_ZDO_SIGNAL_LEAVE_INDICATION: {
|
||||
const ezb_zdo_signal_leave_indication_params_t *leave_ind_params = ezb_app_signal_get_params(app_signal);
|
||||
ESP_LOGI(TAG, "Zigbee Node(0x%04hx) is leaving network", leave_ind_params->short_addr);
|
||||
} break;
|
||||
case EZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: {
|
||||
uint8_t duration = *(uint8_t *)ezb_app_signal_get_params(app_signal);
|
||||
if (duration) {
|
||||
ESP_LOGI(TAG, "Network(0x%04hx) is open for %d seconds", ezb_nwk_get_panid(), duration);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Network(0x%04hx) closed, devices joining not allowed.", ezb_nwk_get_panid());
|
||||
}
|
||||
break;
|
||||
case ESP_ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
|
||||
ESP_LOGI(TAG, "Production configuration is %s", err_status == ESP_OK ? "ready" : "not present");
|
||||
esp_zb_set_node_descriptor_manufacturer_code(ESP_MANUFACTURER_CODE);
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type,
|
||||
esp_err_to_name(err_status));
|
||||
ESP_LOGI(TAG, "Zigbee APP Signal: %s(type: 0x%02x)", ezb_app_signal_to_string(signal_type), signal_type);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void zcl_core_set_attr_value_handler(ezb_zcl_set_attr_value_message_t *message)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(message, , TAG, "message is empty");
|
||||
ESP_LOGI(TAG, "ZCL SetAttributeValue message for endpoint(%d) cluster(0x%04x) %s with status(0x%02x)", message->info.dst_ep,
|
||||
message->info.cluster_id, message->info.cluster_role == EZB_ZCL_CLUSTER_SERVER ? "server" : "client",
|
||||
message->info.status);
|
||||
if (message->info.cluster_id == EZB_ZCL_CLUSTER_ID_ON_OFF) {
|
||||
light_driver_set_power(*(uint8_t *)message->in.attribute.data.value);
|
||||
ESP_LOGI(TAG, "Set On/Off: %d", *(uint8_t *)message->in.attribute.data.value);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unsupported cluster ID(0x%04x)", message->info.cluster_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_zigbee_zcl_core_action_handler(ezb_zcl_core_action_callback_id_t callback_id, void *message)
|
||||
{
|
||||
switch (callback_id) {
|
||||
case EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID:
|
||||
zcl_core_set_attr_value_handler(message);
|
||||
break;
|
||||
case EZB_ZCL_CORE_DEFAULT_RSP_CB_ID: {
|
||||
ezb_zcl_cmd_default_rsp_message_t *default_rsp = (ezb_zcl_cmd_default_rsp_message_t *)message;
|
||||
ESP_LOGI(TAG, "Received ZCL Default Response with status(0x%02x)", default_rsp->in.status_code);
|
||||
} break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "ZCL Core Action: ID(0x%04lx)", callback_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_zb_task(void *pvParameters)
|
||||
esp_err_t esp_zigbee_create_zha_gateway_device(void)
|
||||
{
|
||||
/* initialize Zigbee stack */
|
||||
esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG();
|
||||
esp_zb_init(&zb_nwk_cfg);
|
||||
esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK);
|
||||
esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create();
|
||||
esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create();
|
||||
esp_zb_endpoint_config_t endpoint_config = {
|
||||
.endpoint = ESP_ZB_GATEWAY_ENDPOINT,
|
||||
.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID,
|
||||
.app_device_id = ESP_ZB_HA_REMOTE_CONTROL_DEVICE_ID,
|
||||
.app_device_version = 0,
|
||||
};
|
||||
ezb_af_device_desc_t dev_desc = ezb_af_create_device_desc();
|
||||
ezb_zha_custom_gateway_config_t gateway_cfg = EZB_ZHA_CUSTOM_GATEWAY_CONFIG();
|
||||
ezb_af_ep_desc_t ep_desc = ezb_zha_create_custom_gateway(ESP_ZIGBEE_CUSTOM_GATEWAY_EP_ID, &gateway_cfg);
|
||||
ezb_zcl_cluster_desc_t basic_desc = {0};
|
||||
|
||||
basic_desc = ezb_af_endpoint_get_cluster_desc(ep_desc, EZB_ZCL_CLUSTER_ID_BASIC, EZB_ZCL_CLUSTER_SERVER);
|
||||
ezb_zcl_basic_cluster_desc_add_attr(basic_desc, EZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)ESP_MANUFACTURER_NAME);
|
||||
ezb_zcl_basic_cluster_desc_add_attr(basic_desc, EZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)ESP_MODEL_IDENTIFIER);
|
||||
ezb_af_endpoint_add_cluster_desc(ep_desc, ezb_zcl_on_off_create_cluster_desc(NULL, EZB_ZCL_CLUSTER_SERVER));
|
||||
|
||||
ESP_ERROR_CHECK(ezb_af_device_add_endpoint_desc(dev_desc, ep_desc));
|
||||
ESP_ERROR_CHECK(ezb_af_device_desc_register(dev_desc));
|
||||
|
||||
ezb_zcl_core_action_handler_register(esp_zigbee_zcl_core_action_handler);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_zigbee_setup_commissioning(void)
|
||||
{
|
||||
ezb_aps_secur_enable_distributed_security(false);
|
||||
ESP_ERROR_CHECK(ezb_bdb_set_primary_channel_set(ESP_ZIGBEE_PRIMARY_CHANNEL_MASK));
|
||||
ESP_ERROR_CHECK(ezb_bdb_set_secondary_channel_set(ESP_ZIGBEE_SECONDARY_CHANNEL_MASK));
|
||||
ESP_ERROR_CHECK(ezb_app_signal_add_handler(esp_zigbee_app_signal_handler));
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void esp_zigbee_stack_main_task(void *pvParameters)
|
||||
{
|
||||
esp_zigbee_config_t zigbee_config = ESP_ZIGBEE_DEFAULT_CONFIG();
|
||||
|
||||
#if CONFIG_AUTO_UPDATE_RCP
|
||||
esp_rcp_update_config_t rcp_config = ESP_ZIGBEE_RCP_CONFIG();
|
||||
ESP_ERROR_CHECK(esp_zigbee_rcp_init(&rcp_config));
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(esp_zigbee_init(&zigbee_config));
|
||||
|
||||
#if CONFIG_AUTO_UPDATE_RCP
|
||||
ESP_ERROR_CHECK(esp_zigbee_rcp_update());
|
||||
#endif
|
||||
|
||||
#if (CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET)
|
||||
ESP_ERROR_CHECK(esp_zigbee_connect_netif());
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(esp_zigbee_setup_commissioning());
|
||||
|
||||
ESP_ERROR_CHECK(esp_zigbee_create_zha_gateway_device());
|
||||
|
||||
ESP_ERROR_CHECK(esp_zigbee_start(false));
|
||||
|
||||
esp_zigbee_launch_mainloop();
|
||||
|
||||
esp_zigbee_deinit();
|
||||
|
||||
#if CONFIG_AUTO_UPDATE_RCP
|
||||
esp_zigbee_rcp_deinit();
|
||||
#endif
|
||||
|
||||
esp_zb_attribute_list_t *basic_cluser = esp_zb_basic_cluster_create(NULL);
|
||||
esp_zb_basic_cluster_add_attr(basic_cluser, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, ESP_MANUFACTURER_NAME);
|
||||
esp_zb_basic_cluster_add_attr(basic_cluser, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, ESP_MODEL_IDENTIFIER);
|
||||
esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluser, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
|
||||
esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
|
||||
esp_zb_ep_list_add_gateway_ep(ep_list, cluster_list, endpoint_config);
|
||||
esp_zb_device_register(ep_list);
|
||||
ESP_ERROR_CHECK(esp_zb_start(false));
|
||||
esp_zb_stack_main_loop();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_zb_platform_config_t config = {
|
||||
.radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(),
|
||||
.host_config = ESP_ZB_DEFAULT_HOST_CONFIG(),
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_zb_platform_config(&config));
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
ESP_ERROR_CHECK(esp_zb_gateway_console_init());
|
||||
#endif
|
||||
xTaskCreate(esp_zb_task, "Zigbee_main", 8192, NULL, 5, NULL);
|
||||
|
||||
ESP_LOGI(TAG, "Start ESP Zigbee Stack");
|
||||
xTaskCreate(esp_zigbee_stack_main_task, "Zigbee_main", 4096 * 2, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
@@ -12,62 +12,87 @@
|
||||
* CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_zigbee_core.h"
|
||||
#pragma once
|
||||
|
||||
/* Zigbee Configuration */
|
||||
#define MAX_CHILDREN 10 /* the max amount of connected devices */
|
||||
#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */
|
||||
#define ESP_ZB_PRIMARY_CHANNEL_MASK (1l << 13) /* Zigbee primary channel mask use in the example */
|
||||
#define ESP_ZB_GATEWAY_ENDPOINT 1 /* Gateway endpoint identifier */
|
||||
#define APP_PROD_CFG_CURRENT_VERSION 0x0001 /* Production configuration version */
|
||||
#define ESP_ZIGBEE_PRIMARY_CHANNEL_MASK (1U << CONFIG_ZB_EXAMPLE_PRIMARY_CHANNEL)
|
||||
#define ESP_ZIGBEE_SECONDARY_CHANNEL_MASK CONFIG_ZB_EXAMPLE_SECONDARY_CHANNEL_MASK
|
||||
|
||||
/* Basic manufacturer information */
|
||||
#define ESP_MANUFACTURER_CODE 0x131B /* Customized manufacturer code */
|
||||
#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF" /* Customized manufacturer name */
|
||||
#define ESP_MODEL_IDENTIFIER "\x07"CONFIG_IDF_TARGET /* Customized model identifier */
|
||||
#define ESP_ZIGBEE_CUSTOM_GATEWAY_EP_ID (10)
|
||||
|
||||
/* RCP connection pins */
|
||||
#define HOST_RX_PIN_TO_RCP_TX 4
|
||||
#define HOST_TX_PIN_TO_RCP_RX 5
|
||||
#define ESP_ZIGBEE_STORAGE_PARTITION_NAME "nvs"
|
||||
|
||||
#define ESP_ZB_ZC_CONFIG() \
|
||||
{ \
|
||||
.esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, \
|
||||
.install_code_policy = INSTALLCODE_POLICY_ENABLE, \
|
||||
.nwk_cfg.zczr_cfg = { \
|
||||
.max_children = MAX_CHILDREN, \
|
||||
}, \
|
||||
#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF"
|
||||
#define ESP_MODEL_IDENTIFIER "\x07"CONFIG_IDF_TARGET
|
||||
|
||||
#if defined(CONFIG_ZB_GW_RCP_CHIP_ESP32C6)
|
||||
#define ESP_ZIGBEE_RCP_TARGET_CHIP ESP32C6_CHIP
|
||||
#elif defined(CONFIG_ZB_GW_RCP_CHIP_ESP32H2)
|
||||
#define ESP_ZIGBEE_RCP_TARGET_CHIP ESP32H2_CHIP
|
||||
#else
|
||||
#define ESP_ZIGBEE_RCP_TARGET_CHIP ESP_UNKNOWN_CHIP
|
||||
#endif
|
||||
|
||||
#define ESP_ZIGBEE_ZC_CONFIG() \
|
||||
{ \
|
||||
.device_type = EZB_NWK_DEVICE_TYPE_COORDINATOR, \
|
||||
.install_code_policy = false, \
|
||||
.zczr_config = { \
|
||||
.max_children = 10, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#if CONFIG_ZB_RADIO_NATIVE
|
||||
#define ESP_ZB_DEFAULT_RADIO_CONFIG() \
|
||||
{ \
|
||||
.radio_mode = ZB_RADIO_MODE_NATIVE, \
|
||||
#if CONFIG_SOC_IEEE802154_SUPPORTED
|
||||
#define ESP_ZIGBEE_PLATFORM_CONFIG() \
|
||||
{ \
|
||||
.storage_partition_name = ESP_ZIGBEE_STORAGE_PARTITION_NAME, \
|
||||
.radio_config = { \
|
||||
.radio_mode = ESP_ZIGBEE_RADIO_MODE_NATIVE, \
|
||||
}, \
|
||||
}
|
||||
#else
|
||||
#define ESP_ZB_DEFAULT_RADIO_CONFIG() \
|
||||
{ \
|
||||
.radio_mode = ZB_RADIO_MODE_UART_RCP, \
|
||||
.radio_uart_config = { \
|
||||
.port = 1, \
|
||||
.uart_config = \
|
||||
{ \
|
||||
.baud_rate = 460800, \
|
||||
.data_bits = UART_DATA_8_BITS, \
|
||||
.parity = UART_PARITY_DISABLE, \
|
||||
.stop_bits = UART_STOP_BITS_1, \
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \
|
||||
.rx_flow_ctrl_thresh = 0, \
|
||||
.source_clk = UART_SCLK_DEFAULT, \
|
||||
}, \
|
||||
.rx_pin = HOST_RX_PIN_TO_RCP_TX, \
|
||||
.tx_pin = HOST_TX_PIN_TO_RCP_RX, \
|
||||
}, \
|
||||
#define ESP_ZIGBEE_UART_CONFIG() \
|
||||
{ \
|
||||
.port = 1, \
|
||||
.uart_config = \
|
||||
{ \
|
||||
.baud_rate = 460800, \
|
||||
.data_bits = UART_DATA_8_BITS, \
|
||||
.parity = UART_PARITY_DISABLE, \
|
||||
.stop_bits = UART_STOP_BITS_1, \
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \
|
||||
.rx_flow_ctrl_thresh = 0, \
|
||||
.source_clk = UART_SCLK_DEFAULT, \
|
||||
}, \
|
||||
.rx_pin = CONFIG_DEFAULT_PIN_TO_RCP_TX, \
|
||||
.tx_pin = CONFIG_DEFAULT_PIN_TO_RCP_RX, \
|
||||
}
|
||||
|
||||
#define ESP_ZIGBEE_PLATFORM_CONFIG() \
|
||||
{ \
|
||||
.storage_partition_name = ESP_ZIGBEE_STORAGE_PARTITION_NAME, \
|
||||
.radio_config = { \
|
||||
.radio_mode = ESP_ZIGBEE_RADIO_MODE_UART_RCP, \
|
||||
.radio_uart_config = ESP_ZIGBEE_UART_CONFIG(), \
|
||||
}, \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ESP_ZB_DEFAULT_HOST_CONFIG() \
|
||||
{ \
|
||||
.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, \
|
||||
}
|
||||
#define ESP_ZIGBEE_DEFAULT_CONFIG() \
|
||||
{ \
|
||||
.device_config = ESP_ZIGBEE_ZC_CONFIG(), \
|
||||
.platform_config = ESP_ZIGBEE_PLATFORM_CONFIG(), \
|
||||
};
|
||||
|
||||
#define ESP_ZIGBEE_RCP_CONFIG() \
|
||||
{ \
|
||||
.rcp_type = RCP_TYPE_UART, \
|
||||
.uart_rx_pin = CONFIG_DEFAULT_PIN_TO_RCP_TX, \
|
||||
.uart_tx_pin = CONFIG_DEFAULT_PIN_TO_RCP_RX, \
|
||||
.uart_port = 1, \
|
||||
.uart_baudrate = 115200, \
|
||||
.reset_pin = CONFIG_DEFAULT_PIN_TO_RCP_RESET, \
|
||||
.boot_pin = CONFIG_DEFAULT_PIN_TO_RCP_BOOT, \
|
||||
.update_baudrate = 460800, \
|
||||
.firmware_dir = "/" CONFIG_RCP_PARTITION_NAME "/ot_rcp", \
|
||||
.target_chip = ESP_ZIGBEE_RCP_TARGET_CHIP, \
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp-zboss-lib: "~1.6.0"
|
||||
espressif/esp-zigbee-lib: "~1.6.0"
|
||||
## Required IDF version
|
||||
espressif/esp_rcp_update: "~1.6.0"
|
||||
espressif/esp-zigbee-lib:
|
||||
version: ">=2.0.0"
|
||||
idf:
|
||||
version: ">=5.0.0"
|
||||
version: ">=5.2"
|
||||
example_common:
|
||||
path: ${IDF_PATH}/examples/zigbee/zb_common_components/example_common
|
||||
light_driver:
|
||||
path: ${IDF_PATH}/examples/zigbee/zb_common_components/light_driver
|
||||
protocol_examples_common:
|
||||
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_AUTO_UPDATE_RCP
|
||||
#include "esp_rcp_update.h"
|
||||
#include "esp_spiffs.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_OPENTHREAD_SPINEL_ONLY
|
||||
#include "esp_radio_spinel.h"
|
||||
#define ESP_ZIGBEE_RCP_VERSION_MAX_SIZE 80
|
||||
#endif
|
||||
|
||||
#include "esp_zigbee.h"
|
||||
|
||||
#include "zigbee_rcp.h"
|
||||
|
||||
#define TAG "ZIGBEE_RCP"
|
||||
|
||||
#if CONFIG_AUTO_UPDATE_RCP
|
||||
|
||||
static void rcp_update(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Update RCP");
|
||||
/* Stop Zigbee stack during RCP update */
|
||||
esp_zigbee_deinit();
|
||||
if (esp_rcp_update() != ESP_OK) {
|
||||
esp_rcp_mark_image_verified(false);
|
||||
}
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
static void rcp_fatal_failure_handler(void)
|
||||
{
|
||||
#if CONFIG_AUTO_UPDATE_RCP
|
||||
ESP_LOGW(TAG, "RCP failure, re-flashing RCP");
|
||||
rcp_update();
|
||||
#endif
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
static void rcp_failure_handler(void)
|
||||
{
|
||||
ESP_LOGW(TAG, "RCP failure, reset RCP");
|
||||
esp_rcp_reset();
|
||||
}
|
||||
|
||||
esp_err_t esp_zigbee_rcp_update(void)
|
||||
{
|
||||
char rcp_version[ESP_ZIGBEE_RCP_VERSION_MAX_SIZE] = {0};
|
||||
ESP_RETURN_ON_ERROR(esp_radio_spinel_rcp_version_get(rcp_version, ESP_RADIO_SPINEL_ZIGBEE), TAG,
|
||||
"Failed to get rcp version from radio spinel");
|
||||
#if (CONFIG_AUTO_UPDATE_RCP)
|
||||
char storage_rcp_version[ESP_ZIGBEE_RCP_VERSION_MAX_SIZE] = {0};
|
||||
if (esp_rcp_load_version_in_storage(storage_rcp_version, sizeof(storage_rcp_version)) == ESP_OK) {
|
||||
if (strcmp(storage_rcp_version, rcp_version)) {
|
||||
ESP_LOGI(TAG, "Update the RCP version from %s to %s", storage_rcp_version, rcp_version);
|
||||
rcp_update();
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Running RCP version: %s", rcp_version);
|
||||
esp_rcp_mark_image_verified(true);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "No RCP firmware found in storage, reboot to try next image");
|
||||
esp_rcp_mark_image_verified(false);
|
||||
esp_restart();
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t spiffs_init(void)
|
||||
{
|
||||
esp_vfs_spiffs_conf_t rcp_fw_conf = {
|
||||
.base_path = "/" CONFIG_RCP_PARTITION_NAME,
|
||||
.partition_label = CONFIG_RCP_PARTITION_NAME,
|
||||
.max_files = 10,
|
||||
.format_if_mount_failed = false,
|
||||
};
|
||||
return esp_vfs_spiffs_register(&rcp_fw_conf);
|
||||
}
|
||||
|
||||
static void spiffs_deinit(void)
|
||||
{
|
||||
esp_vfs_spiffs_unregister(CONFIG_RCP_PARTITION_NAME);
|
||||
}
|
||||
|
||||
esp_err_t esp_zigbee_rcp_init(esp_rcp_update_config_t *config)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(config != NULL, ESP_ERR_INVALID_ARG, TAG, "config is NULL");
|
||||
ESP_ERROR_CHECK(spiffs_init());
|
||||
ESP_ERROR_CHECK(esp_rcp_update_init(config));
|
||||
#if CONFIG_OPENTHREAD_SPINEL_ONLY
|
||||
esp_radio_spinel_register_rcp_failure_handler(rcp_failure_handler, ESP_RADIO_SPINEL_ZIGBEE);
|
||||
esp_radio_spinel_set_compatibility_error_callback(rcp_fatal_failure_handler);
|
||||
esp_radio_spinel_set_coprocessor_reset_failure_callback(rcp_fatal_failure_handler);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_zigbee_rcp_deinit(void)
|
||||
{
|
||||
#if CONFIG_OPENTHREAD_SPINEL_ONLY
|
||||
esp_radio_spinel_set_coprocessor_reset_failure_callback(NULL);
|
||||
esp_radio_spinel_set_compatibility_error_callback(NULL);
|
||||
esp_radio_spinel_register_rcp_failure_handler(NULL, ESP_RADIO_SPINEL_ZIGBEE);
|
||||
#endif
|
||||
esp_rcp_update_deinit();
|
||||
spiffs_deinit();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Included
|
||||
*
|
||||
* 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_rcp_update.h"
|
||||
|
||||
esp_err_t esp_zigbee_rcp_init(esp_rcp_update_config_t *config);
|
||||
|
||||
void esp_zigbee_rcp_deinit(void);
|
||||
|
||||
esp_err_t esp_zigbee_rcp_update(void);
|
||||
Reference in New Issue
Block a user