Skip to content

Commit 4be3af4

Browse files
authored
Merge branch 'master' into idf-release/v5.3
2 parents accafc6 + 250c1ab commit 4be3af4

File tree

11 files changed

+768
-6
lines changed

11 files changed

+768
-6
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ set(ARDUINO_LIBRARY_Zigbee_SRCS
292292
libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp
293293
libraries/Zigbee/src/ep/ZigbeeContactSwitch.cpp
294294
libraries/Zigbee/src/ep/ZigbeeDoorWindowHandle.cpp
295+
libraries/Zigbee/src/ep/ZigbeeWindowCovering.cpp
295296
)
296297

297298
set(ARDUINO_LIBRARY_BLE_SRCS

libraries/ESP_I2S/src/ESP_I2S.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
#include "mp3dec.h"
1212
#endif
1313

14+
#if SOC_I2S_HW_VERSION_2
15+
#undef I2S_STD_CLK_DEFAULT_CONFIG
16+
#define I2S_STD_CLK_DEFAULT_CONFIG(rate) \
17+
{ .sample_rate_hz = rate, .clk_src = I2S_CLK_SRC_DEFAULT, .ext_clk_freq_hz = 0, .mclk_multiple = I2S_MCLK_MULTIPLE_256, }
18+
#endif
19+
1420
#define I2S_READ_CHUNK_SIZE 1920
1521

1622
#define I2S_DEFAULT_CFG() \

libraries/Network/src/NetworkInterface.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) {
8181
);
8282
#endif
8383
memcpy(&arduino_event.event_info.got_ip, event_data, sizeof(ip_event_got_ip_t));
84-
#if SOC_WIFI_SUPPORTED
84+
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
8585
if (_interface_id == ESP_NETIF_ID_STA) {
8686
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP;
8787
} else
@@ -96,7 +96,7 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) {
9696
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
9797
log_v("%s Lost IP", desc());
9898
#endif
99-
#if SOC_WIFI_SUPPORTED
99+
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
100100
if (_interface_id == ESP_NETIF_ID_STA) {
101101
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_LOST_IP;
102102
} else
@@ -123,7 +123,7 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) {
123123
);
124124
#endif
125125
memcpy(&arduino_event.event_info.got_ip6, event_data, sizeof(ip_event_got_ip6_t));
126-
#if SOC_WIFI_SUPPORTED
126+
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
127127
if (_interface_id == ESP_NETIF_ID_STA) {
128128
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP6;
129129
} else if (_interface_id == ESP_NETIF_ID_AP) {
@@ -136,7 +136,7 @@ void NetworkInterface::_onIpEvent(int32_t event_id, void *event_data) {
136136
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6;
137137
}
138138
#endif /* CONFIG_LWIP_IPV6 */
139-
#if SOC_WIFI_SUPPORTED
139+
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
140140
} else if (event_id == IP_EVENT_AP_STAIPASSIGNED && _interface_id == ESP_NETIF_ID_AP) {
141141
setStatusBits(ESP_NETIF_HAS_IP_BIT);
142142
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Arduino-ESP32 Window Covering Example
2+
3+
This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) window covering device.
4+
5+
To see if the communication with your Zigbee network works, use the Serial monitor and watch for output there.
6+
7+
# Supported Targets
8+
9+
Currently, this example supports the following targets.
10+
11+
| Supported Targets | ESP32-C6 | ESP32-H2 |
12+
| ----------------- | -------- | -------- |
13+
14+
## Hardware Required
15+
16+
* A USB cable for power supply and programming
17+
* Board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the Zigbee_Window_Covering example
18+
* Zigbee network / coordinator (Other board with switch examples or Zigbee2mqtt or ZigbeeHomeAssistant like application)
19+
20+
### Configure the Project
21+
22+
#### Using Arduino IDE
23+
24+
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
25+
26+
* Before Compile/Verify, select the correct board: `Tools -> Board`.
27+
* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)`
28+
* Select Tools / USB CDC On Boot: "Enabled"
29+
* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs`
30+
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
31+
* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`.
32+
33+
## Troubleshooting
34+
35+
If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator.
36+
You can do the following:
37+
38+
* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`.
39+
* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack.
40+
41+
By default, the coordinator network is closed after rebooting or flashing new firmware.
42+
To open the network you have 2 options:
43+
44+
* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`.
45+
* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join.
46+
47+
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source***
48+
49+
* **LED not blinking:** Check the wiring connection and the IO selection.
50+
* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed.
51+
* **COM port not detected:** Check the USB cable and the USB to Serial driver installation.
52+
53+
If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
54+
55+
## Contribute
56+
57+
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
58+
59+
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!
60+
61+
Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else.
62+
63+
## Resources
64+
65+
* Official ESP32 Forum: [Link](https://esp32.com)
66+
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
67+
* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf)
68+
* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf)
69+
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
// Copyright 2025 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @brief This example demonstrates Zigbee Window Covering.
17+
*
18+
* The example demonstrates how to use Zigbee library to create a end device window covering device.
19+
* The window covering is a Zigbee end device, which is moving the blinds (lift+tilt) and reporting
20+
* its current position to the Zigbee network.
21+
*
22+
* Use setCoveringType() to set the type of covering (blind, shade, etc.).
23+
*
24+
* The example also demonstrates how to use the button to manually control the lift position.
25+
*
26+
* Proper Zigbee mode must be selected in Tools->Zigbee mode
27+
* and also the correct partition scheme must be selected in Tools->Partition Scheme.
28+
*
29+
* Please check the README.md for instructions and more detailed description.
30+
*
31+
* Created by hennikul and Jan Procházka (https://github.com/P-R-O-C-H-Y/)
32+
*/
33+
34+
#ifndef ZIGBEE_MODE_ED
35+
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
36+
#endif
37+
38+
#include "ZigbeeCore.h"
39+
#include "ep/ZigbeeWindowCovering.h"
40+
41+
#define ZIGBEE_COVERING_ENDPOINT 10
42+
#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button
43+
44+
#define MAX_LIFT 200 // centimeters from open position (0-900)
45+
#define MIN_LIFT 0
46+
47+
#define MAX_TILT 40 // centimeters from open position (0-900)
48+
#define MIN_TILT 0
49+
50+
uint16_t currentLift = MAX_LIFT;
51+
uint8_t currentLiftPercentage = 100;
52+
53+
uint16_t currentTilt = MAX_TILT;
54+
uint8_t currentTiltPercentage = 100;
55+
56+
ZigbeeWindowCovering zbCovering = ZigbeeWindowCovering(ZIGBEE_COVERING_ENDPOINT);
57+
58+
void setup() {
59+
Serial.begin(115200);
60+
61+
// Init button for factory reset
62+
pinMode(BUTTON_PIN, INPUT_PULLUP);
63+
64+
// Optional: set Zigbee device name and model
65+
zbCovering.setManufacturerAndModel("Espressif", "WindowBlinds");
66+
67+
// Set proper covering type, it defines which attributes are available
68+
zbCovering.setCoveringType(BLIND_LIFT_AND_TILT);
69+
70+
// Set configuration: operational, online, not commands_reversed, lift / tilt closed_loop, lift / tilt encoder_controlled
71+
zbCovering.setConfigStatus(true, true, false, true, true, true, true);
72+
73+
// Set mode: not motor_reversed, calibration_mode, not maintenance_mode, not leds_on
74+
zbCovering.setMode(false, true, false, false);
75+
76+
// Set limits of motion
77+
zbCovering.setLimits(MIN_LIFT, MAX_LIFT, MIN_TILT, MAX_TILT);
78+
79+
// Set callback function for open, close, filt and tilt change, stop
80+
zbCovering.onOpen(fullOpen);
81+
zbCovering.onClose(fullClose);
82+
zbCovering.onGoToLiftPercentage(goToLiftPercentage);
83+
zbCovering.onGoToTiltPercentage(goToTiltPercentage);
84+
zbCovering.onStop(stopMotor);
85+
86+
// Add endpoint to Zigbee Core
87+
Serial.println("Adding ZigbeeWindowCovering endpoint to Zigbee Core");
88+
Zigbee.addEndpoint(&zbCovering);
89+
90+
// When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE
91+
Serial.println("Calling Zigbee.begin()");
92+
if (!Zigbee.begin()) {
93+
Serial.println("Zigbee failed to start!");
94+
Serial.println("Rebooting...");
95+
ESP.restart();
96+
}
97+
Serial.println("Connecting to network");
98+
while (!Zigbee.connected()) {
99+
Serial.print(".");
100+
delay(100);
101+
}
102+
Serial.println();
103+
104+
// Set initial position
105+
zbCovering.setLiftPercentage(currentLiftPercentage);
106+
zbCovering.setTiltPercentage(currentTiltPercentage);
107+
}
108+
109+
void loop() {
110+
// Checking button for factory reset
111+
if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed
112+
// Key debounce handling
113+
delay(100);
114+
int startTime = millis();
115+
while (digitalRead(BUTTON_PIN) == LOW) {
116+
delay(50);
117+
if ((millis() - startTime) > 3000) {
118+
// If key pressed for more than 3secs, factory reset Zigbee and reboot
119+
Serial.printf("Resetting Zigbee to factory settings, reboot.\n");
120+
Zigbee.factoryReset();
121+
delay(30000);
122+
}
123+
}
124+
// Manual lift control simulation by pressing button
125+
manualControl();
126+
}
127+
delay(500);
128+
}
129+
130+
void fullOpen() {
131+
/* This is where you would trigger your motor to go to full open state, currentLift should
132+
be updated until full open has been reached in order to provide feedback to controller of actual position
133+
The stop can be always called, so the movement can be stopped at any time */
134+
135+
// Our cover updates instantly!
136+
currentLift = MAX_LIFT;
137+
currentLiftPercentage = 100;
138+
Serial.println("Opening cover");
139+
// Update the current position
140+
zbCovering.setLiftPercentage(currentLiftPercentage);
141+
}
142+
143+
void fullClose() {
144+
/* This is where you would trigger your motor to go to full close state, currentLift should
145+
be updated until full close has been reached in order to provide feedback to controller of actual position
146+
The stop can be always called, so the movement can be stopped at any time */
147+
148+
// Our cover updates instantly!
149+
currentLift = MIN_LIFT;
150+
currentLiftPercentage = 0;
151+
Serial.println("Closing cover");
152+
// Update the current position
153+
zbCovering.setLiftPercentage(currentLiftPercentage);
154+
}
155+
156+
void goToLiftPercentage(uint8_t liftPercentage) {
157+
/* This is where you would trigger your motor to go towards liftPercentage, currentLift should
158+
be updated until liftPercentage has been reached in order to provide feedback to controller */
159+
160+
// Our simulated cover updates instantly!
161+
currentLift = (liftPercentage * MAX_LIFT) / 100;
162+
currentLiftPercentage = liftPercentage;
163+
Serial.printf("New requested lift from Zigbee: %d (%d)\n", currentLift, liftPercentage);
164+
165+
// Update the current position
166+
zbCovering.setLiftPercentage(currentLiftPercentage); //or setLiftPosition()
167+
}
168+
169+
void goToTiltPercentage(uint8_t tiltPercentage) {
170+
/* This is where you would trigger your motor to go towards tiltPercentage, currentTilt should
171+
be updated until tiltPercentage has been reached in order to provide feedback to controller */
172+
173+
// Our simulated cover updates instantly!
174+
currentTilt = (tiltPercentage * MAX_TILT) / 100;
175+
currentTiltPercentage = tiltPercentage;
176+
Serial.printf("New requested tilt from Zigbee: %d (%d)\n", currentTilt, tiltPercentage);
177+
178+
// Update the current position
179+
zbCovering.setTiltPercentage(currentTiltPercentage); //or setTiltPosition()
180+
}
181+
182+
void stopMotor() {
183+
// Motor can be stopped while moving cover toward current target, when stopped the actual position should be updated
184+
Serial.println("Stopping motor");
185+
// Update the current position of both lift and tilt
186+
zbCovering.setLiftPercentage(currentLiftPercentage);
187+
zbCovering.setTiltPercentage(currentTiltPercentage);
188+
}
189+
190+
void manualControl() {
191+
// Simulate lift percentage move by increasing it by 20% each time
192+
currentLiftPercentage += 20;
193+
if (currentLiftPercentage > 100) {
194+
currentLiftPercentage = 0;
195+
}
196+
zbCovering.setLiftPercentage(currentLiftPercentage);
197+
// Also setLiftPosition() can be used to set the exact position instead of percentage
198+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed",
3+
"requires": [
4+
"CONFIG_SOC_IEEE802154_SUPPORTED=y"
5+
]
6+
}

libraries/Zigbee/src/Zigbee.h

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@
2020
#include "ep/ZigbeeCarbonDioxideSensor.h"
2121
#include "ep/ZigbeeContactSwitch.h"
2222
#include "ep/ZigbeeDoorWindowHandle.h"
23+
#include "ep/ZigbeeWindowCovering.h"

libraries/Zigbee/src/ZigbeeEP.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class ZigbeeEP {
9595
void reportBatteryPercentage();
9696

9797
// Set time
98-
void addTimeCluster(tm time = {0}, int32_t gmt_offset = 0); // gmt offset in seconds
98+
void addTimeCluster(tm time = {}, int32_t gmt_offset = 0); // gmt offset in seconds
9999
void setTime(tm time);
100100
void setTimezone(int32_t gmt_offset);
101101

@@ -115,8 +115,8 @@ class ZigbeeEP {
115115
virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {};
116116
virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented
117117
virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message);
118+
virtual void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) {};
118119
virtual void zbReadTimeCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented
119-
120120
virtual void zbIASZoneStatusChangeNotification(const esp_zb_zcl_ias_zone_status_change_notification_message_t *message) {};
121121
virtual void zbIASZoneEnrollResponse(const esp_zb_zcl_ias_zone_enroll_response_message_t *message) {};
122122

0 commit comments

Comments
 (0)