[zigbee] add support for SED on esp32 (#20487)

This commit is contained in:
luar123
2026-10-10 13:24:13 -10:00
committed by GitHub
parent 924d7364ba
commit 1763adf526
8 changed files with 63 additions and 23 deletions
+23 -5
View File
@@ -13,7 +13,14 @@ from esphome.components.esp32.const import (
VARIANT_ESP32S31,
)
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INTERNAL, CONF_MODEL, CONF_NAME, CONF_ON_START
from esphome.const import (
CONF_ID,
CONF_INTERNAL,
CONF_MODEL,
CONF_NAME,
CONF_ON_START,
CONF_POLLING_INTERVAL,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.types import ConfigType
@@ -25,6 +32,7 @@ from .const import (
CONF_POWER_SOURCE,
CONF_REPORT,
CONF_ROUTER,
CONF_SLEEPY,
CONF_USE_DEVICE_TYPE,
CONF_WIPE_ON_BOOT,
KEY_ZIGBEE,
@@ -35,7 +43,6 @@ from .const import (
from .const_zephyr import (
CONF_IEEE802154_VENDOR_OUI,
CONF_MAX_EP_NUMBER_ZEPHYR,
CONF_SLEEPY,
CONF_ZIGBEE_ID,
KEY_EP_NUMBER,
)
@@ -128,8 +135,11 @@ NUMBER_SCHEMA = (
def _validate_router_sleepy(config: ConfigType) -> ConfigType:
if config.get(CONF_ROUTER) and config.get(CONF_SLEEPY):
raise cv.Invalid("router and sleepy are mutually exclusive")
if config.get(CONF_ROUTER):
if config.get(CONF_SLEEPY):
raise cv.Invalid("router and sleepy are mutually exclusive")
if config.get(CONF_POLLING_INTERVAL):
raise cv.Invalid(f"{CONF_POLLING_INTERVAL} is only valid for end devices.")
return config
@@ -160,9 +170,17 @@ CONFIG_SCHEMA = cv.All(
),
cv.requires_component("nrf52"),
),
cv.OnlyWith(CONF_SLEEPY, "nrf52", default=False): cv.All(
cv.Optional(CONF_SLEEPY, default=False): cv.All(
cv.boolean,
),
cv.Optional(CONF_POLLING_INTERVAL): cv.All(
cv.requires_component(ESP32_DOMAIN),
cv.positive_time_period_milliseconds,
cv.Range(
min=cv.TimePeriodMilliseconds(milliseconds=200),
max=cv.TimePeriodMinutes(minutes=60), # 1 hour
),
),
}
).extend(cv.COMPONENT_SCHEMA),
_validate_router_sleepy,
+1
View File
@@ -72,6 +72,7 @@ CONF_WIPE_ON_BOOT = "wipe_on_boot"
CONF_REPORT = "report"
CONF_ROUTER = "router"
CONF_POWER_SOURCE = "power_source"
CONF_SLEEPY = "sleepy"
CONF_USE_DEVICE_TYPE = "use_device_type"
POWER_SOURCE = {
"UNKNOWN": 0x00, # ZB_ZCL_BASIC_POWER_SOURCE_UNKNOWN
@@ -4,7 +4,6 @@ CONF_ZIGBEE_BINARY_SENSOR = "zigbee_binary_sensor"
CONF_ZIGBEE_SENSOR = "zigbee_sensor"
CONF_ZIGBEE_SWITCH = "zigbee_switch"
CONF_ZIGBEE_NUMBER = "zigbee_number"
CONF_SLEEPY = "sleepy"
CONF_IEEE802154_VENDOR_OUI = "ieee802154_vendor_oui"
# Keys for CORE.data storage
+24 -13
View File
@@ -319,7 +319,7 @@ void ZigbeeComponent::setup() {
#else
esp_zigbee_zed_config_s zb_zed_cfg = {
.ed_timeout = EZB_NWK_ED_TIMEOUT_64MIN,
.keep_alive = ED_KEEP_ALIVE,
.keep_alive = this->keep_alive_,
};
device_config.zed_config = zb_zed_cfg;
#endif
@@ -339,6 +339,8 @@ void ZigbeeComponent::setup() {
#ifdef CONFIG_ZB_ZCZR
ezb_bdb_set_router_rejoin_required(true);
#else
ezb_nwk_set_rx_on_when_idle(!this->sleepy_); // if sleepy, disable RX when idle
#endif
ezb_aps_secur_enable_distributed_security(false);
@@ -419,18 +421,27 @@ void ZigbeeComponent::loop() {
void ZigbeeComponent::dump_config() {
if (esp_zigbee_lock_acquire(10 / portTICK_PERIOD_MS)) {
ESP_LOGCONFIG(TAG,
"Zigbee\n"
" Model: %.*s\n"
" Router: %s\n"
" Device is joined to the network: %s\n"
" Current channel: %d\n"
" Short addr: 0x%04X\n"
" Short pan id: 0x%04X",
this->basic_cluster_data_.model[0],
reinterpret_cast<const char *>(this->basic_cluster_data_.model + 1),
YESNO(this->device_role_ == EZB_NWK_DEVICE_TYPE_ROUTER), YESNO(ezb_bdb_dev_joined()),
ezb_nwk_get_current_channel(), ezb_nwk_get_short_address(), ezb_nwk_get_panid());
ESP_LOGCONFIG(
TAG,
"Zigbee\n"
" Model: %.*s\n"
#ifdef CONFIG_ZB_ZCZR
" Router: %s\n"
#else
" Sleepy end device: %s\n"
" Poll interval: %" PRIu32 " ms\n"
#endif
" Device is joined to the network: %s\n"
" Current channel: %d\n"
" Short addr: 0x%04X\n"
" Short pan id: 0x%04X",
this->basic_cluster_data_.model[0], reinterpret_cast<const char *>(this->basic_cluster_data_.model + 1),
#ifdef CONFIG_ZB_ZCZR
YESNO(this->device_role_ == EZB_NWK_DEVICE_TYPE_ROUTER),
#else
YESNO(this->sleepy_), this->keep_alive_,
#endif
YESNO(ezb_bdb_dev_joined()), ezb_nwk_get_current_channel(), ezb_nwk_get_short_address(), ezb_nwk_get_panid());
esp_zigbee_lock_release();
} else {
ESP_LOGCONFIG(TAG,
+4 -1
View File
@@ -20,7 +20,6 @@
namespace esphome::zigbee {
/* Zigbee configuration */
static const uint16_t ED_KEEP_ALIVE = 3000; /* 3000 millisecond */
static const uint8_t MAX_CHILDREN = 10;
static const uint32_t EZB_PRIMARY_CHANNEL_MASK = 0x07FFF800U; /* channels 11-26 */
static constexpr uint8_t MAX_ZB_QUEUE_SIZE = 32;
@@ -43,6 +42,8 @@ class ZigbeeComponent final : public Component {
void loop() override;
void dump_config() override;
void set_sleepy(bool sleepy) { this->sleepy_ = sleepy; }
void set_keep_alive(uint32_t keep_alive) { this->keep_alive_ = keep_alive; }
void set_basic_cluster(const char *model, const char *manufacturer, uint8_t power_source);
void add_cluster(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role);
void create_default_cluster(uint8_t endpoint_id, uint16_t device_id);
@@ -73,6 +74,8 @@ class ZigbeeComponent final : public Component {
bool is_joined() { return this->joined_; }
protected:
bool sleepy_{false};
uint32_t keep_alive_{3000};
struct {
uint8_t *model;
uint8_t *manufacturer;
@@ -24,6 +24,7 @@ from esphome.const import (
CONF_MAX_LENGTH,
CONF_MODEL,
CONF_NAME,
CONF_POLLING_INTERVAL,
CONF_TYPE,
CONF_UNIT_OF_MEASUREMENT,
CONF_VALUE,
@@ -45,6 +46,7 @@ from .const import (
CONF_POWER_SOURCE,
CONF_REPORT,
CONF_ROUTER,
CONF_SLEEPY,
CONF_USE_DEVICE_TYPE,
KEY_ZIGBEE,
POWER_SOURCE,
@@ -412,6 +414,11 @@ async def esp32_to_code(config: ConfigType) -> "MockObj":
# setup zigbee components
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
if config.get(CONF_SLEEPY):
cg.add(var.set_sleepy(True))
if (keep_alive := config.get(CONF_POLLING_INTERVAL, 3000)) != 3000:
cg.add(var.set_keep_alive(keep_alive))
cg.add(
var.set_basic_cluster(
config[CONF_MODEL],
+1 -1
View File
@@ -24,6 +24,7 @@ from .const import (
BACNET_UNITS,
CONF_POWER_SOURCE,
CONF_ROUTER,
CONF_SLEEPY,
CONF_WIPE_ON_BOOT,
KEY_ZIGBEE,
POWER_SOURCE,
@@ -35,7 +36,6 @@ from .const import (
)
from .const_zephyr import (
CONF_IEEE802154_VENDOR_OUI,
CONF_SLEEPY,
CONF_ZIGBEE_BINARY_SENSOR,
CONF_ZIGBEE_ID,
CONF_ZIGBEE_NUMBER,
+3 -2
View File
@@ -58,8 +58,9 @@ switch:
zigbee:
model: zigbee_test
router: false
power_source: MAINS_SINGLE_PHASE
sleepy: true
polling_interval: 2s
power_source: BATTERY
on_join:
then:
- logger.log: "Joined network"