Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ set(ARDUINO_LIBRARY_Zigbee_SRCS
libraries/Zigbee/src/ep/ZigbeeVibrationSensor.cpp
libraries/Zigbee/src/ep/ZigbeeAnalog.cpp
libraries/Zigbee/src/ep/ZigbeeRangeExtender.cpp
libraries/Zigbee/src/ep/ZigbeeGateway.cpp
)

set(ARDUINO_LIBRARY_BLE_SRCS
Expand Down
12 changes: 12 additions & 0 deletions boards.txt
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,9 @@ esp32s3.menu.PartitionScheme.esp_sr_16.build.partitions=esp_sr_16
esp32s3.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs
esp32s3.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr
esp32s3.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720
esp32s3.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs
esp32s3.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB
esp32s3.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872
esp32s3.menu.PartitionScheme.custom=Custom
esp32s3.menu.PartitionScheme.custom.build.partitions=
esp32s3.menu.PartitionScheme.custom.upload.maximum_size=16777216
Expand Down Expand Up @@ -1108,6 +1111,9 @@ esp32c3.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480
esp32c3.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs
esp32c3.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr
esp32c3.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720
esp32c3.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs
esp32c3.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB
esp32c3.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872
esp32c3.menu.PartitionScheme.custom=Custom
esp32c3.menu.PartitionScheme.custom.build.partitions=
esp32c3.menu.PartitionScheme.custom.upload.maximum_size=16777216
Expand Down Expand Up @@ -1313,6 +1319,9 @@ esp32s2.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480
esp32s2.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs
esp32s2.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr
esp32s2.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720
esp32s2.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs
esp32s2.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB
esp32s2.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872
esp32s2.menu.PartitionScheme.custom=Custom
esp32s2.menu.PartitionScheme.custom.build.partitions=
esp32s2.menu.PartitionScheme.custom.upload.maximum_size=16777216
Expand Down Expand Up @@ -1493,6 +1502,9 @@ esp32.menu.PartitionScheme.rainmaker_8MB.upload.maximum_size=4116480
esp32.menu.PartitionScheme.zigbee_zczr=Zigbee ZCZR 4MB with spiffs
esp32.menu.PartitionScheme.zigbee_zczr.build.partitions=zigbee_zczr
esp32.menu.PartitionScheme.zigbee_zczr.upload.maximum_size=1310720
esp32.menu.PartitionScheme.zigbee_zczr_8MB=Zigbee ZCZR 8MB with spiffs
esp32.menu.PartitionScheme.zigbee_zczr_8MB.build.partitions=zigbee_zczr_8MB
esp32.menu.PartitionScheme.zigbee_zczr_8MB.upload.maximum_size=3407872
esp32.menu.PartitionScheme.custom=Custom
esp32.menu.PartitionScheme.custom.build.partitions=
esp32.menu.PartitionScheme.custom.upload.maximum_size=16777216
Expand Down
64 changes: 64 additions & 0 deletions libraries/Zigbee/examples/Zigbee_Gateway/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Arduino-ESP32 Zigbee Gateway Example

This example shows how to configure Zigbee Gateway device, running on SoCs without native IEEE 802.15.4.

# Supported Targets

Currently, this example supports the following targets.

| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 |
| ----------------- | ----- | -------- | -------- | -------- |

## Hardware Required

* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee Radio Co-processor loaded with [ot_rcp example](https://github.com/espressif/esp-idf/tree/master/examples/openthread/ot_rcp).
* A USB cable for power supply and programming.
* Choose another board from supported targets as Zigbee coordinator/router and upload the Zigbee_Gateway example.

### Configure the Project

Set the RCP connection (UART) by changing the `GATEWAY_RCP_UART_PORT`, `GATEWAY_RCP_RX_PIN` and `GATEWAY_RCP_TX_PIN` definition.

#### Using Arduino IDE

To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).

* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`.
* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs`.
* Select the COM port: `Tools -> Port: xxx where the `xxx` is the detected COM port.
* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`.

## Troubleshooting

* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`.

By default, the coordinator network is closed after rebooting or flashing new firmware.
To open the network you have 2 options:

* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`.
* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join.

***Important: Make sure you are using a good quality USB cable and that you have a reliable power source***

* **LED not blinking:** Check the wiring connection and the IO selection.
* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed.
* **COM port not detected:** Check the USB cable and the USB to Serial driver installation.

If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).

## Contribute

To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)

If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome!

Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else.

## Resources

* Official ESP32 Forum: [Link](https://esp32.com)
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf)
* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
130 changes: 130 additions & 0 deletions libraries/Zigbee/examples/Zigbee_Gateway/Zigbee_Gateway.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright 2025 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @brief This example demonstrates simple Zigbee Gateway functionality.
*
* The example demonstrates how to use Zigbee library on ESP32s to create a Zigbee Gateway, updating the time from NTP server.
* The Gateway is able to communicate with Zigbee end devices and send/receive data to/from them.
* The Gateway is also able to communicate with the cloud or other devices over Wi-Fi / BLE.
*
* Proper Zigbee mode must be selected in Tools->Zigbee mode->Zigbee ZCZR (coordinator/router)
* and also the correct partition scheme must be selected in Tools->Partition Scheme->Zigbee ZCZR
*
* Please check the README.md for instructions and more detailed description.
*
* Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/)
*/

#ifndef ZIGBEE_MODE_ZCZR
#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"
#include <WiFi.h>
#include "time.h"
#include "esp_sntp.h"

/* Zigbee gateway configuration */
#define GATEWAY_ENDPOINT_NUMBER 1
#define GATEWAY_RCP_UART_PORT UART_NUM_1 // UART 0 is used for Serial communication
#define GATEWAY_RCP_RX_PIN 4
#define GATEWAY_RCP_TX_PIN 5

ZigbeeGateway zbGateway = ZigbeeGateway(GATEWAY_ENDPOINT_NUMBER);

/* Wi-Fi credentials */
const char *ssid = "your-ssid";
const char *password = "your-password";

/* NTP server configuration */
const char *ntpServer1 = "pool.ntp.org";
const char *ntpServer2 = "time.nist.gov";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
const char *time_zone = "CET-1CEST,M3.5.0,M10.5.0/3"; // TimeZone rule for Europe/Rome including daylight adjustment rules (optional)

/* Time structure */
struct tm timeinfo;

/********************* Arduino functions **************************/
void setup() {
Serial.begin(115200);

// Initialize Wi-Fi and connect to AP
WiFi.begin(ssid, password);
esp_sntp_servermode_dhcp(1); // (optional)

Serial.print("Connecting to WiFi");

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");

// Initialize Zigbee and Begin Zigbee stack
// Optional: set Zigbee device name and model
zbGateway.setManufacturerAndModel("Espressif", "ZigbeeGateway");
zbGateway.addTimeCluster(timeinfo, gmtOffset_sec);

// Add endpoint to Zigbee Core
Serial.println("Adding Zigbee Gateway endpoint");
Zigbee.addEndpoint(&zbGateway);

// Optional: Open network for 180 seconds after boot
Zigbee.setRebootOpenNetwork(180);

// Set custom radio configuration for RCP communication
esp_zb_radio_config_t radio_config = ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG();
radio_config.radio_uart_config.port = GATEWAY_RCP_UART_PORT;
radio_config.radio_uart_config.rx_pin = (gpio_num_t)GATEWAY_RCP_RX_PIN;
radio_config.radio_uart_config.tx_pin = (gpio_num_t)GATEWAY_RCP_TX_PIN;

Zigbee.setRadioConfig(radio_config);

// When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR or ZIGBEE_ROUTER mode
if (!Zigbee.begin(ZIGBEE_COORDINATOR)) {
Serial.println("Zigbee failed to start!");
Serial.println("Rebooting...");
ESP.restart();
}

// set notification call-back function
sntp_set_time_sync_notification_cb(timeavailable);
sntp_set_sync_interval(30000); // sync every 30 seconds

// config time zone and NTP servers
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
}

void loop() {
// Nothing to do here in this example
}

void printLocalTime() {
if (!getLocalTime(&timeinfo)) {
Serial.println("No time available (yet)");
return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
zbGateway.setTime(timeinfo);
Serial.println("Time updated in Zigbee Gateway");
}

// Callback function (gets called when time adjusts via NTP)
void timeavailable(struct timeval *t) {
Serial.println("Got time adjustment from NTP!");
printLocalTime();
}
10 changes: 10 additions & 0 deletions libraries/Zigbee/examples/Zigbee_Gateway/ci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"fqbn_append": "PartitionScheme=zigbee_zczr_8MB,ZigbeeMode=zczr",
"requires": [
"CONFIG_ZB_ENABLED=y"
],
"targets": {
"esp32c6": false,
"esp32h2": false
}
}
50 changes: 48 additions & 2 deletions libraries/Zigbee/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,22 @@ ZigbeeThermostat KEYWORD1
ZigbeeFlowSensor KEYWORD1
ZigbeePressureSensor KEYWORD1
ZigbeeOccupancySensor KEYWORD1
ZigbeeAnalog KEYWORD1
ZigbeeCarbonDioxideSensor KEYWORD1
ZigbeeContactSwitch KEYWORD1
ZigbeeDoorWindowHandle KEYWORD1
ZigbeeGateway KEYWORD1
ZigbeeRangeExtender KEYWORD1
ZigbeeVibrationSensor KEYWORD1
ZigbeeWindowCovering KEYWORD1

# Other
zigbee_role_t KEYWORD1
zbstring_t KEYWORD1
zb_device_params_t KEYWORD1
zigbee_scan_result_t KEYWORD1
zb_power_source_t KEYWORD1
ZigbeeWindowCoveringType KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
Expand Down Expand Up @@ -126,6 +136,43 @@ setSensorType KEYWORD2
# ZigbeeCarbonDioxideSensor
setCarbonDioxide KEYWORD2

# ZigbeeAnalog
addAnalogValue KEYWORD2
addAnalogInput KEYWORD2
addAnalogOutput KEYWORD2
onAnalogOutputChange KEYWORD2
setAnalogValue KEYWORD2
setAnalogInput KEYWORD2
reportAnalogInput KEYWORD2
setAnalogInputReporting KEYWORD2

# ZigbeeCarbonDioxideSensor
setCarbonDioxide KEYWORD2

# ZigbeeContactSwitch + ZigbeeDoorWindowHandle
setIASClientEndpoint KEYWORD2
setClosed KEYWORD2
setOpen KEYWORD2
setTilted KEYWORD2

# ZigbeeVibrationSensor
setVibration KEYWORD2

ZigbeeWindowCovering
onOpen KEYWORD2
onClose KEYWORD2
onGoToLiftPercentage KEYWORD2
onGoToTiltPercentage KEYWORD2
onStop KEYWORD2
setLiftPosition KEYWORD2
setLiftPercentage KEYWORD2
setTiltPosition KEYWORD2
setTiltPercentage KEYWORD2
setCoveringType KEYWORD2
setConfigStatus KEYWORD2
setMode KEYWORD2
setLimits KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################
Expand All @@ -137,7 +184,6 @@ ZIGBEE_DEFAULT_ED_CONFIG LITERAL1
ZIGBEE_DEFAULT_ROUTER_CONFIG LITERAL1
ZIGBEE_DEFAULT_COORDINATOR_CONFIG LITERAL1
ZIGBEE_DEFAULT_RADIO_CONFIG LITERAL1
ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG LITERAL1
ZIGBEE_DEFAULT_HOST_CONFIG LITERAL1
ZB_ARRAY_LENTH LITERAL1
XYZ_TO_RGB LITERAL1
RGB_TO_XYZ LITERAL1
1 change: 1 addition & 0 deletions libraries/Zigbee/src/Zigbee.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
#include "ep/ZigbeeWindowCovering.h"
#include "ep/ZigbeeVibrationSensor.h"
#include "ep/ZigbeeRangeExtender.h"
#include "ep/ZigbeeGateway.h"
8 changes: 6 additions & 2 deletions libraries/Zigbee/src/ZigbeeCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ void ZigbeeCore::addEndpoint(ZigbeeEP *ep) {
return;
}

esp_zb_ep_list_add_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config);
if(ep->_device_id == ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID) {
esp_zb_ep_list_add_gateway_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config);
} else {
esp_zb_ep_list_add_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config);
}
}

static void esp_zb_task(void *pvParameters) {
Expand Down Expand Up @@ -156,7 +160,7 @@ bool ZigbeeCore::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) {
}

// Create Zigbee task and start Zigbee stack
xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL);
xTaskCreate(esp_zb_task, "Zigbee_main", 8192, NULL, 5, NULL);

return true;
}
Expand Down
19 changes: 19 additions & 0 deletions libraries/Zigbee/src/ZigbeeCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ typedef enum {
} \
}

#define ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG() \
{ \
.radio_mode = ZB_RADIO_MODE_UART_RCP, \
.radio_uart_config = { \
.port = UART_NUM_1, \
.rx_pin = GPIO_NUM_NC, \
.tx_pin = GPIO_NUM_NC, \
.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, \
}, \
}, \
}

class ZigbeeCore {
private:
esp_zb_radio_config_t _radio_config;
Expand Down
Loading
Loading