feat(esp32): Zigbee power outlet example (#11296)
* feat(esp32): Zigbee power outlet example Zigbee power outlet example * feat(esp32): Zigbee power outlet example Change username * feat(esp32): Zigbee power outlet example Remove old comment * fix(zigbee): fix power outlet compile errors and update example * fix(example): Update readme * fix(example): Update ci json file * ci(pre-commit): Apply automatic fixes * fix(): precommit codespell --------- Co-authored-by: Jan Procházka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
parent
d85b75c219
commit
9090b46da5
8 changed files with 272 additions and 0 deletions
|
|
@ -301,6 +301,7 @@ set(ARDUINO_LIBRARY_Zigbee_SRCS
|
|||
libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp
|
||||
libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp
|
||||
libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp
|
||||
libraries/Zigbee/src/ep/ZigbeePowerOutlet.cpp
|
||||
)
|
||||
|
||||
set(ARDUINO_LIBRARY_BLE_SRCS
|
||||
|
|
|
|||
61
libraries/Zigbee/examples/Zigbee_Power_Outlet/README.md
Normal file
61
libraries/Zigbee/examples/Zigbee_Power_Outlet/README.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
@ -0,0 +1,68 @@
|
||||
# Arduino-ESP32 Zigbee On/Off Power Outlet Example
|
||||
|
||||
This example shows how to configure Zigbee Router device and use it as a Home Automation (HA) on/off power outlet.
|
||||
|
||||
# Supported Targets
|
||||
|
||||
Currently, this example supports the following targets.
|
||||
|
||||
| Supported Targets | ESP32-C6 | ESP32-H2 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
||||
## Hardware Required
|
||||
|
||||
* A USB cable for power supply and programming.
|
||||
|
||||
### Configure the Project
|
||||
|
||||
Set the Button GPIO by changing the `button` definition. By default, it's the pin `9` (BOOT button on ESP32-C6 and ESP32-H2).
|
||||
|
||||
#### 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 ZCZR 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
|
||||
|
||||
If the device flashed with the example `Zigbee_Power_Outlet` is not connecting to the coordinator, erase the flash of the device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator or do some big changes in the application code.
|
||||
You can do the following:
|
||||
|
||||
* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`.
|
||||
* In the `Zigbee_Power_Outlet` example sketch call `Zigbee.factoryReset();`.
|
||||
|
||||
***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)
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// 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 power outlet.
|
||||
*
|
||||
* The example demonstrates how to use Zigbee library to create a end device power outlet.
|
||||
* The power outlet is a Zigbee end device, which is controlled by a Zigbee coordinator.
|
||||
*
|
||||
* Proper Zigbee mode must be selected in Tools->Zigbee mode
|
||||
* and also the correct partition scheme must be selected in Tools->Partition Scheme.
|
||||
*
|
||||
* Please check the README.md for instructions and more detailed description.
|
||||
*
|
||||
* Created by Ludovic Boué (https://github.com/lboue)
|
||||
*/
|
||||
|
||||
#ifndef ZIGBEE_MODE_ZCZR
|
||||
#error "Zigbee router mode is not selected in Tools->Zigbee mode"
|
||||
#endif
|
||||
|
||||
#include "Zigbee.h"
|
||||
|
||||
/* Zigbee power outlet configuration */
|
||||
#define ZIGBEE_OUTLET_ENDPOINT 1
|
||||
uint8_t led = RGB_BUILTIN;
|
||||
uint8_t button = BOOT_PIN;
|
||||
|
||||
ZigbeePowerOutlet zbOutlet = ZigbeePowerOutlet(ZIGBEE_OUTLET_ENDPOINT);
|
||||
|
||||
/********************* RGB LED functions **************************/
|
||||
void setLED(bool value) {
|
||||
digitalWrite(led, value);
|
||||
}
|
||||
|
||||
/********************* Arduino functions **************************/
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Init LED and turn it OFF (if LED_PIN == RGB_BUILTIN, the rgbLedWrite() will be used under the hood)
|
||||
pinMode(led, OUTPUT);
|
||||
digitalWrite(led, LOW);
|
||||
|
||||
// Init button for factory reset
|
||||
pinMode(button, INPUT_PULLUP);
|
||||
|
||||
//Optional: set Zigbee device name and model
|
||||
zbOutlet.setManufacturerAndModel("Espressif", "ZBPowerOutlet");
|
||||
|
||||
// Set callback function for power outlet change
|
||||
zbOutlet.onPowerOutletChange(setLED);
|
||||
|
||||
//Add endpoint to Zigbee Core
|
||||
Serial.println("Adding ZigbeePowerOutlet endpoint to Zigbee Core");
|
||||
Zigbee.addEndpoint(&zbOutlet);
|
||||
|
||||
// When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE
|
||||
if (!Zigbee.begin(ZIGBEE_ROUTER)) {
|
||||
Serial.println("Zigbee failed to start!");
|
||||
Serial.println("Rebooting...");
|
||||
ESP.restart();
|
||||
}
|
||||
Serial.println("Connecting to network");
|
||||
while (!Zigbee.connected()) {
|
||||
Serial.print(".");
|
||||
delay(100);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Checking button for factory reset
|
||||
if (digitalRead(button) == LOW) { // Push button pressed
|
||||
// Key debounce handling
|
||||
delay(100);
|
||||
int startTime = millis();
|
||||
while (digitalRead(button) == LOW) {
|
||||
delay(50);
|
||||
if ((millis() - startTime) > 3000) {
|
||||
// If key pressed for more than 3secs, factory reset Zigbee and reboot
|
||||
Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
|
||||
delay(1000);
|
||||
Zigbee.factoryReset();
|
||||
}
|
||||
}
|
||||
// Toggle state by pressing the button
|
||||
zbOutlet.setState(!zbOutlet.getPowerOutletState());
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
7
libraries/Zigbee/examples/Zigbee_Power_Outlet/ci.json
Normal file
7
libraries/Zigbee/examples/Zigbee_Power_Outlet/ci.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"fqbn_append": "PartitionScheme=zigbee_zczr,ZigbeeMode=zczr",
|
||||
"requires": [
|
||||
"CONFIG_SOC_IEEE802154_SUPPORTED=y",
|
||||
"CONFIG_ZB_ENABLED=y"
|
||||
]
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ ZigbeeRangeExtender KEYWORD1
|
|||
ZigbeeVibrationSensor KEYWORD1
|
||||
ZigbeeWindowCovering KEYWORD1
|
||||
ZigbeeIlluminanceSensor KEYWORD1
|
||||
ZigbeePowerOutlet KEYWORD1
|
||||
|
||||
# Other
|
||||
zigbee_role_t KEYWORD1
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "ep/ZigbeeLight.h"
|
||||
//// Controllers
|
||||
#include "ep/ZigbeeThermostat.h"
|
||||
////Outlets
|
||||
#include "ep/ZigbeePowerOutlet.h"
|
||||
//// Sensors
|
||||
#include "ep/ZigbeeAnalog.h"
|
||||
#include "ep/ZigbeeCarbonDioxideSensor.h"
|
||||
|
|
|
|||
58
libraries/Zigbee/src/ep/ZigbeePowerOutlet.cpp
Normal file
58
libraries/Zigbee/src/ep/ZigbeePowerOutlet.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include "ZigbeePowerOutlet.h"
|
||||
#if CONFIG_ZB_ENABLED
|
||||
|
||||
ZigbeePowerOutlet::ZigbeePowerOutlet(uint8_t endpoint) : ZigbeeEP(endpoint) {
|
||||
_device_id = ESP_ZB_HA_MAINS_POWER_OUTLET_DEVICE_ID;
|
||||
|
||||
esp_zb_mains_power_outlet_cfg_t outlet_cfg = ESP_ZB_DEFAULT_MAINS_POWER_OUTLET_CONFIG();
|
||||
_cluster_list = esp_zb_mains_power_outlet_clusters_create(&outlet_cfg);
|
||||
_ep_config = {
|
||||
.endpoint = endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_MAINS_POWER_OUTLET_DEVICE_ID, .app_device_version = 0
|
||||
};
|
||||
log_v("Outlet endpoint created %d", _endpoint);
|
||||
}
|
||||
|
||||
//set attribute method -> method overridden in child class
|
||||
void ZigbeePowerOutlet::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {
|
||||
//check the data and call right method
|
||||
if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) {
|
||||
if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) {
|
||||
_current_state = *(bool *)message->attribute.data.value;
|
||||
stateChanged();
|
||||
} else {
|
||||
log_w("Received message ignored. Attribute ID: %d not supported for On/Off Outlet", message->attribute.id);
|
||||
}
|
||||
} else {
|
||||
log_w("Received message ignored. Cluster ID: %d not supported for On/Off Outlet", message->info.cluster);
|
||||
}
|
||||
}
|
||||
|
||||
void ZigbeePowerOutlet::stateChanged() {
|
||||
if (_on_state_change) {
|
||||
_on_state_change(_current_state);
|
||||
} else {
|
||||
log_w("No callback function set for outlet change");
|
||||
}
|
||||
}
|
||||
|
||||
bool ZigbeePowerOutlet::setState(bool state) {
|
||||
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
|
||||
_current_state = state;
|
||||
stateChanged();
|
||||
|
||||
log_v("Updating on/off outlet state to %d", state);
|
||||
/* Update on/off outlet state */
|
||||
esp_zb_lock_acquire(portMAX_DELAY);
|
||||
ret = esp_zb_zcl_set_attribute_val(
|
||||
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false
|
||||
);
|
||||
esp_zb_lock_release();
|
||||
|
||||
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
|
||||
log_e("Failed to set outlet state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // CONFIG_ZB_ENABLED
|
||||
41
libraries/Zigbee/src/ep/ZigbeePowerOutlet.h
Normal file
41
libraries/Zigbee/src/ep/ZigbeePowerOutlet.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* Class of Zigbee On/Off Power outlet endpoint inherited from common EP class */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_ZB_ENABLED
|
||||
|
||||
#include "ZigbeeEP.h"
|
||||
#include "ha/esp_zigbee_ha_standard.h"
|
||||
|
||||
class ZigbeePowerOutlet : public ZigbeeEP {
|
||||
public:
|
||||
ZigbeePowerOutlet(uint8_t endpoint);
|
||||
~ZigbeePowerOutlet() {}
|
||||
|
||||
// Use to set a cb function to be called on outlet change
|
||||
void onPowerOutletChange(void (*callback)(bool)) {
|
||||
_on_state_change = callback;
|
||||
}
|
||||
// Use to restore outlet state
|
||||
void restoreState() {
|
||||
stateChanged();
|
||||
}
|
||||
// Use to control outlet state
|
||||
bool setState(bool state);
|
||||
// Use to get outlet state
|
||||
bool getPowerOutletState() {
|
||||
return _current_state;
|
||||
}
|
||||
|
||||
private:
|
||||
void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override;
|
||||
//callback function to be called on outlet change
|
||||
void (*_on_state_change)(bool);
|
||||
void stateChanged();
|
||||
|
||||
bool _current_state;
|
||||
};
|
||||
|
||||
#endif // CONFIG_ZB_ENABLED
|
||||
Loading…
Reference in a new issue