mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 10:40:47 +03:00
feat(zigbee): upgrade zigbee example to v2.0
This commit is contained in:
@@ -1,46 +1,68 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
# Gateway Example
|
||||
|
||||
This example demonstrates how to build a Zigbee Gateway device.
|
||||
This example demonstrates how to build a Zigbee Gateway device. It runs on a Wi-Fi SoC such as ESP32, ESP32-C3 and ESP32-S3, with an 802.15.4 SoC like ESP32-H2
|
||||
running [ot_rcp](https://github.com/espressif/esp-idf/tree/master/examples/openthread/ot_rcp) to provide 802.15.4 radio.
|
||||
|
||||
The ESP Zigbee SDK provides more examples and tools for productization:
|
||||
* [ESP Zigbee SDK Docs](https://docs.espressif.com/projects/esp-zigbee-sdk)
|
||||
* [ESP Zigbee SDK Repo](https://github.com/espressif/esp-zigbee-sdk)
|
||||
## Hardware Platforms
|
||||
|
||||
## Hardware Required
|
||||
### Wi-Fi based ESP Zigbee Gateway
|
||||
|
||||
By default, two SoCs are required to run this example:
|
||||
* An ESP32 series Wi-Fi SoC (ESP32, ESP32-C, ESP32-S, etc) loaded with this esp_zigbee_gateway example.
|
||||
* An ESP32-H2 802.15.4 SoC loaded with [ot_rcp](../../openthread/ot_rcp/) example
|
||||
The Wi-Fi based ESP Zigbee Gateway consists of two SoCs:
|
||||
|
||||
Connect the two SoCs via UART, below is an example setup with ESP32-DevKitC and ESP32-H2-DevKitC:
|
||||

|
||||
* An ESP32 series Wi-Fi SoC (ESP32, ESP32-C, ESP32-S, etc) loaded with this example.
|
||||
* An 802.15.4 enabled SoC (e.g., ESP32-H2 or ESP32-C6) loaded with [OpenThread RCP](https://github.com/espressif/esp-idf/tree/master/examples/openthread/ot_rcp) example.
|
||||
|
||||
#### ESP Zigbee Gateway Board
|
||||
|
||||
The ESP Zigbee gateway board provides an integrated module of an ESP32-S3 SoC and an ESP32-H2 RCP.
|
||||
|
||||

|
||||
|
||||
The two SoCs are connected with following interfaces:
|
||||
* UART for serial communication
|
||||
* RESET and BOOT pins for RCP Update
|
||||
* 3-Wires PTA for RF coexistence
|
||||
|
||||
No jumper wires needed. No `idf.py menuconfig` under menu "OpenThread RCP Update" configure to change.
|
||||
|
||||
#### Standalone Modules
|
||||
|
||||
The SDK also supports manually connecting an ESP32-H2 RCP to an ESP32 series Wi-Fi SoC. As one way of connection is following:
|
||||
|
||||
ESP32 pin | ESP32-H2 pin
|
||||
------------- |-------------
|
||||
GND | G
|
||||
GPIO4 (RX) | TX
|
||||
GPIO5 (TX) | RX
|
||||
GPI017 | RST
|
||||
GPIO18 | GPIO9(BOOT)
|
||||
|
||||
* TX, RX pin can be also configured by user in esp_zigbee_gateway.h
|
||||
TX, RX, RST and BOOT pin from ESP32 side can be configured by user in `idf.py menuconfig` under menu "ESP Zigbee gateway rcp update".
|
||||
|
||||
The example could also run on a single SoC which supports both Wi-Fi and Zigbee (e.g., ESP32-C6), but since there is only one RF path in ESP32-C6, which means Wi-Fi and Zigbee can't receive simultaneously, it has a significant impact on performance. Hence the two SoCs solution is recommended.
|
||||
TX, RX pins from ESP32-H2 should be configured in [ot_rcp example](https://github.com/espressif/esp-idf/tree/master/examples/openthread/ot_rcp) via "OpenThread RCP Example > Configure RCP UART pin manually" options.
|
||||
|
||||
## Configure the RCP
|
||||
Other pin number is also available for user to configure if needed.
|
||||
|
||||
The `OPENTHREAD_NCP_VENDOR_HOOK` of `ot_rcp` should be selected via menuconfig when the [ot_rcp](../../openthread/ot_rcp/) example is built. Then use `idf.py -p PORT erase-flash` to flash the RCP firmware to ESP32-H2-DevKitC.
|
||||
The following image shows an example connection between ESP32 DevKitC and ESP32-H2 DevKitC:
|
||||
|
||||
## Configure the project
|
||||

|
||||
|
||||
Before project configuration and build, make sure to set the correct chip target using `idf.py set-target <chip_name>`.
|
||||
## Erase the NVRAM
|
||||
|
||||
In order to run the example on single SoC which supports both Wi-Fi and Thread, the option `CONFIG_ESP_COEX_SW_COEXIST_ENABLE` and option `CONFIG_ZB_RADIO_NATIVE` should be enabled. The two options are enabled by default for ESP32-C6 target.
|
||||
Before flash it to the board, it is recommended to erase NVRAM if user doesn't want to keep the previous examples or other projects stored info
|
||||
using `idf.py -p PORT erase-flash`
|
||||
|
||||
## Erase the NVRAM
|
||||
## Create the RCP firmware image
|
||||
|
||||
Before flash it to the board, it is recommended to erase NVRAM if user doesn't want to keep the previous examples or other projects stored info using `idf.py -p PORT erase-flash`
|
||||
The esp_zigbee_gateway supports updating the RCP image. Generate rcp image before building the esp_zigbee_gateway example.
|
||||
|
||||
Build the [ot_rcp](https://github.com/espressif/esp-idf/tree/master/examples/openthread/ot_rcp) example. Later in the esp_zigbee_gateway building process, the built RCP image will be automatically packed into the esp_zigbee_gateway firmware. See detail in [CMakeLists.txt](main/CMakeLists.txt).
|
||||
|
||||
Notes:
|
||||
- `OPENTHREAD_NCP_VENDOR_HOOK` of `ot_rcp` should be selected via menuconfig.
|
||||
|
||||
## Build and Flash
|
||||
|
||||
@@ -48,86 +70,94 @@ Build the project, flash it to the board, and start the monitor tool to view the
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
## Example Output
|
||||
## Application Functions
|
||||
|
||||
As you run the example, you will see the following log:
|
||||
|
||||
esp_zigbee_gateway:
|
||||
- When the program starts, the board will attempt to read the RCP version from the remote radio via UART.
|
||||
```
|
||||
I (499) main_task: Calling app_main()
|
||||
I (519) ESP_RADIO_SPINEL: spinel UART interface initialization completed
|
||||
I (519) ESP_RADIO_SPINEL: Spinel UART interface has been successfully enabled
|
||||
I (519) ZB_ESP_SPINEL: Spinel UART interface enable successfully
|
||||
I (529) main_task: Returned from app_main()
|
||||
I(529) OPENTHREAD:[I] P-RadioSpinel-: RCP reset: RESET_POWER_ON
|
||||
I(539) OPENTHREAD:[I] P-RadioSpinel-: Software reset RCP successfully
|
||||
I (569) ZB_ESP_SPINEL: Radio spinel workflow register successfully
|
||||
I (769) ESP_ZB_GATEWAY: Production configuration is ready
|
||||
W (769) ESP_ZB_GATEWAY: Production configuration is not present
|
||||
I (769) example_connect: Start example_connect.
|
||||
I (779) pp: pp rom version: e7ae62f
|
||||
I (779) net80211: net80211 rom version: e7ae62f
|
||||
I (799) wifi:wifi driver task: 3fca80d8, prio:23, stack:6656, core=0
|
||||
I (799) wifi:wifi firmware version: 3ce09e5
|
||||
I (799) wifi:wifi certification version: v7.0
|
||||
I (799) wifi:config NVS flash: enabled
|
||||
I (799) wifi:config nano formatting: disabled
|
||||
I (809) wifi:Init data frame dynamic rx buffer num: 32
|
||||
I (809) wifi:Init static rx mgmt buffer num: 5
|
||||
I (819) wifi:Init management short buffer num: 32
|
||||
I (819) wifi:Init dynamic tx buffer num: 32
|
||||
I (819) wifi:Init static tx FG buffer num: 2
|
||||
I (829) wifi:Init static rx buffer size: 1600
|
||||
I (829) wifi:Init static rx buffer num: 10
|
||||
I (839) wifi:Init dynamic rx buffer num: 32
|
||||
I (839) wifi_init: rx ba win: 6
|
||||
I (839) wifi_init: tcpip mbox: 32
|
||||
I (849) wifi_init: udp mbox: 6
|
||||
I (849) wifi_init: tcp mbox: 6
|
||||
I (849) wifi_init: tcp tx win: 5760
|
||||
I (859) wifi_init: tcp rx win: 5760
|
||||
I (859) wifi_init: tcp mss: 1440
|
||||
I (869) wifi_init: WiFi IRAM OP enabled
|
||||
I (869) wifi_init: WiFi RX IRAM OP enabled
|
||||
I (879) phy_init: phy_version 670,b7bc9b9,Apr 30 2024,10:54:13
|
||||
W (879) phy_init: failed to load RF calibration data (0x1102), falling back to full calibration
|
||||
I (989) wifi:mode : sta (f4:12:fa:41:a7:f4)
|
||||
I (989) wifi:enable tsf
|
||||
I (999) example_connect: Connecting to esp-office-2.4G...
|
||||
I (999) example_connect: Waiting for IP(s)
|
||||
I (3409) wifi:new:<13,0>, old:<1,0>, ap:<255,255>, sta:<13,0>, prof:1
|
||||
I (3649) wifi:state: init -> auth (b0)
|
||||
I (3719) wifi:state: auth -> assoc (0)
|
||||
I (3759) wifi:state: assoc -> run (10)
|
||||
I (3769) wifi:connected with esp-office-2.4G, aid = 1, channel 13, BW20, bssid = 9c:3a:9a:04:18:92
|
||||
I (3769) wifi:security: WPA2-PSK, phy: bgn, rssi: -42
|
||||
I (3769) wifi:pm start, type: 1
|
||||
|
||||
I (3779) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
|
||||
I (3789) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000
|
||||
I (3819) wifi:AP's beacon interval = 102400 us, DTIM period = 1
|
||||
I (3849) wifi:<ba-add>idx:0 (ifx:0, 9c:3a:9a:04:18:92), tid:0, ssn:0, winSize:64
|
||||
I (4799) esp_netif_handlers: example_netif_sta ip: 192.168.200.133, mask: 255.255.252.0, gw: 192.168.200.1
|
||||
I (4799) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.200.133
|
||||
I (5509) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:f612:faff:fe41:a7f4, type: ESP_IP6_ADDR_IS_LINK_LOCAL
|
||||
I (5509) example_common: Connected to example_netif_sta
|
||||
I (5519) example_common: - IPv4 address: 192.168.200.133,
|
||||
I (5519) example_common: - IPv6 address: fe80:0000:0000:0000:f612:faff:fe41:a7f4, type: ESP_IP6_ADDR_IS_LINK_LOCAL
|
||||
I (5529) wifi:Set ps type: 0, coexist: 0
|
||||
|
||||
I (5539) ESP_ZB_GATEWAY: Initialize Zigbee stack
|
||||
I (5549) ESP_ZB_GATEWAY: Device started up in factory-reset mode
|
||||
I (5549) ESP_ZB_GATEWAY: Start network formation
|
||||
W (5729) ESP_ZB_GATEWAY: Network(0xb8e9) closed, devices joining not allowed.
|
||||
I (5729) ESP_ZB_GATEWAY: Formed network successfully (Extended PAN ID: 60:55:f9:ff:fe:f7:73:e8, PAN ID: 0xb8e9, Channel:13, Short Address: 0x0000)
|
||||
I (6339) ESP_ZB_GATEWAY: Network(0xb8e9) is open for 180 seconds
|
||||
I (6339) ESP_ZB_GATEWAY: Network steering started
|
||||
I (433) main_task: Started on CPU0
|
||||
I (443) main_task: Calling app_main()
|
||||
I (453) ZIGBEE_GATEWAY: Start ESP Zigbee Stack
|
||||
I (493) main_task: Returned from app_main()
|
||||
I (503) RCP_UPDATE: RCP: using update sequence 0
|
||||
I (503) ESP_RADIO_SPINEL: spinel UART interface initialization completed
|
||||
I (503) ESP_RADIO_SPINEL: Spinel UART interface has been successfully enabled
|
||||
I (503) ESP_ZIGBEE_RADIO_SPINEL_UART: Spinel UART interface enable successfully
|
||||
I(513) OPENTHREAD:[I] P-SpinelDrive-: co-processor reset: RESET_POWER_ON
|
||||
E(523) OPENTHREAD:[C] P-SpinelDrive-: Software reset co-processor successfully
|
||||
I (573) ESP_ZIGBEE_RCP: Running RCP version: openthread-esp32/fcae32885b029-b945928d7; esp32h2; 2026-03-11 02:30:22 UTC
|
||||
```
|
||||
|
||||
## Gateway Functions
|
||||
- If `CONFIG_AUTO_UPDATE_RCP` is enabled and the version does not match the stored one, the board will automatically update the RCP using the stored version.
|
||||
|
||||
* When the device starts up, it will attempt to connect to a Wi-Fi network and then interface with the OT-RCP via UART to form a Zigbee network.
|
||||
* For more Gateway functionalities, please refer to [matter zigbee bridge](https://github.com/espressif/esp-matter/tree/main/examples/bridge_apps/zigbee_bridge/) and [Rainmaker Zigbee Gateway](https://github.com/espressif/esp-rainmaker/tree/master/examples/zigbee_gateway) examples.
|
||||
- After confirming that the remote radio is functioning properly, the board will connect to Wi-Fi as configured in menuconfig.
|
||||
```
|
||||
|
||||
I (573) example_connect: Start example_connect.
|
||||
I (583) pp: pp rom version: e7ae62f
|
||||
I (583) net80211: net80211 rom version: e7ae62f
|
||||
I (593) wifi:wifi driver task: 3fcb86d0, prio:23, stack:6656, core=0
|
||||
I (593) wifi:wifi firmware version: 14da9b7
|
||||
I (593) wifi:wifi certification version: v7.0
|
||||
I (603) wifi:config NVS flash: enabled
|
||||
I (603) wifi:config nano formatting: disabled
|
||||
I (603) wifi:Init data frame dynamic rx buffer num: 32
|
||||
I (613) wifi:Init static rx mgmt buffer num: 5
|
||||
I (613) wifi:Init management short buffer num: 32
|
||||
I (623) wifi:Init dynamic tx buffer num: 32
|
||||
I (623) wifi:Init static tx FG buffer num: 2
|
||||
I (633) wifi:Init static rx buffer size: 1600
|
||||
I (633) wifi:Init static rx buffer num: 10
|
||||
I (633) wifi:Init dynamic rx buffer num: 32
|
||||
I (643) wifi_init: rx ba win: 6
|
||||
I (643) wifi_init: accept mbox: 6
|
||||
I (643) wifi_init: tcpip mbox: 32
|
||||
I (653) wifi_init: udp mbox: 6
|
||||
I (653) wifi_init: tcp mbox: 6
|
||||
I (653) wifi_init: tcp tx win: 5760
|
||||
I (663) wifi_init: tcp rx win: 5760
|
||||
I (663) wifi_init: tcp mss: 1440
|
||||
I (663) wifi_init: WiFi IRAM OP enabled
|
||||
I (673) wifi_init: WiFi RX IRAM OP enabled
|
||||
I (673) phy_init: phy_version 701,f4f1da3a,Mar 3 2025,15:50:10
|
||||
W (673) phy_init: failed to load RF calibration data (0x1102), falling back to full calibration
|
||||
I (783) phy_init: Saving new calibration data due to checksum failure or outdated calibration data, mode(2)
|
||||
I (793) wifi:mode : sta (48:27:e2:14:43:38)
|
||||
I (793) wifi:enable tsf
|
||||
I (793) example_connect: Connecting to esp-guest...
|
||||
W (793) wifi:Password length matches WPA2 standards, authmode threshold changes from OPEN to WPA2
|
||||
I (803) example_connect: Waiting for IP(s)
|
||||
I (3293) wifi:new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:1, snd_ch_cfg:0x0
|
||||
I (3303) wifi:state: init -> auth (0xb0)
|
||||
I (3303) wifi:state: auth -> assoc (0x0)
|
||||
I (3323) wifi:state: assoc -> run (0x10)
|
||||
I (3413) wifi:connected with esp-guest, aid = 1, channel 6, BW20, bssid = 84:78:48:86:87:31
|
||||
I (3423) wifi:security: WPA2-PSK, phy: bgn, rssi: -30
|
||||
I (3423) wifi:pm start, type: 1
|
||||
|
||||
I (3423) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
|
||||
I (3433) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000
|
||||
I (3453) wifi:AP's beacon interval = 102400 us, DTIM period = 1
|
||||
I (3503) wifi:<ba-add>idx:0 (ifx:0, 84:78:48:86:87:31), tid:0, ssn:0, winSize:64
|
||||
I (4573) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:4a27:e2ff:fe14:4338, type: ESP_IP6_ADDR_IS_LINK_LOCAL
|
||||
I (4843) esp_netif_handlers: example_netif_sta ip: 10.18.40.174, mask: 255.255.255.0, gw: 10.18.40.1
|
||||
I (4843) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 10.18.40.174
|
||||
I (4843) example_common: Connected to example_netif_sta
|
||||
I (4853) example_common: - IPv4 address: 10.18.40.174,
|
||||
I (4853) example_common: - IPv6 address: fe80:0000:0000:0000:4a27:e2ff:fe14:4338, type: ESP_IP6_ADDR_IS_LINK_LOCAL
|
||||
I (4863) wifi:Set ps type: 0, coexist: 0
|
||||
```
|
||||
|
||||
- Finally, the board will act as the `Zigbee Gateway`, forming a network and handling commands from the network.
|
||||
```
|
||||
I (4883) ZIGBEE_GATEWAY: Initialize Zigbee stack
|
||||
I (4883) ZIGBEE_GATEWAY: Deferred driver initialization successful
|
||||
I (4883) ZIGBEE_GATEWAY: Device started up in factory-reset mode
|
||||
I (5303) ZIGBEE_GATEWAY: Formed network successfully: PAN ID(0x4494, EXT: 0x6055f9fffef7a2ad), Channel(13), Short Address(0x0000)
|
||||
I (5573) ZIGBEE_GATEWAY: Network(0x4494) is open for 180 seconds
|
||||
I (5573) ZIGBEE_GATEWAY: Network steering completed
|
||||
```
|
||||
|
||||
- Gateway functionalities supporting Wi-Fi interaction will be added in future updates.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -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);
|
||||
@@ -1,8 +1,8 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1400K,
|
||||
zb_storage, data, fat, 0x16e000,16K,
|
||||
zb_fct, data, fat, 0x172000,1K,
|
||||
rcp_fw, data, spiffs, 0x173000,500k,
|
||||
nvs, data, nvs, , 0x6000,
|
||||
otadata, data, ota, , 0x2000,
|
||||
phy_init, data, phy, , 0x1000,
|
||||
factory, app, factory, , 1708K,
|
||||
zb_fct, data, fat, , 1K,
|
||||
rcp_fw, data, spiffs, , 640k,
|
||||
|
||||
|
@@ -8,12 +8,28 @@ CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
||||
CONFIG_PARTITION_TABLE_MD5=y
|
||||
# end of Partition Table
|
||||
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
|
||||
#
|
||||
# Serial flasher config
|
||||
#
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
# end of Serial flasher config
|
||||
|
||||
#
|
||||
# Zboss
|
||||
# Event
|
||||
#
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
|
||||
#end of Event
|
||||
|
||||
|
||||
#
|
||||
# Zigbee
|
||||
#
|
||||
CONFIG_ZB_ENABLED=y
|
||||
CONFIG_ZB_ZCZR=y
|
||||
# end of Zboss
|
||||
# end of Component config
|
||||
# end of Zigbee
|
||||
|
||||
#
|
||||
# ESP Zigbee gateway RCP update
|
||||
#
|
||||
CONFIG_AUTO_UPDATE_RCP=n
|
||||
# end of ESP Zigbee gateway RCP update
|
||||
|
||||
Reference in New Issue
Block a user