[zigbee] add report action on esp32 (#20488)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
luar123
2026-10-11 11:31:49 -10:00
committed by GitHub
co-authored by J. Nick Koston
parent 2ef95bbc28
commit 7d7db6bf90
8 changed files with 52 additions and 24 deletions
+2 -2
View File
@@ -78,9 +78,9 @@ CONFLICTS_WITH = ["openthread"]
def _check_report_deprecation(value: str) -> str:
if str(value).lower() in ("coordinator", "enable"):
if str(value).lower() == "coordinator":
_LOGGER.warning(
"Report options 'coordinator' and 'enable' are deprecated and will be removed in a future release. Use 'default' instead."
"Report option 'coordinator' is deprecated and will be removed in a future release. Use 'default' instead."
)
return value
@@ -62,6 +62,9 @@ void ZigbeeAttribute::report_(bool has_lock) {
}
void ZigbeeAttribute::set_report(ZigbeeReportT report) {
if (report == ZigbeeReportT::ZIGBEE_REPORT_DEFAULT || report == ZigbeeReportT::ZIGBEE_REPORT_COORDINATOR) {
return;
}
this->report_enabled = true;
if (report == ZigbeeReportT::ZIGBEE_REPORT_FORCE) {
this->force_report_ = true;
@@ -73,6 +76,14 @@ void ZigbeeAttribute::set_report(ZigbeeReportT report) {
});
}
void ZigbeeAttribute::report() {
if (!this->report_enabled) {
return;
}
this->report_requested_ = true;
this->enable_loop();
}
void ZigbeeAttribute::loop() {
if (this->set_attr_requested_) {
this->set_attr_();
@@ -53,6 +53,7 @@ class ZigbeeAttribute final : public Component {
template<typename T> void set_attr(const T &value);
uint8_t attr_type() { return attr_type_; }
void set_report(ZigbeeReportT report);
void report();
template<typename F> void add_on_value_callback(F &&callback) { on_value_callback_.add(std::forward<F>(callback)); }
void on_value(ezb_zcl_attribute_t attribute) {
+1 -20
View File
@@ -27,13 +27,7 @@ from esphome.const import (
)
from esphome.core import CORE, Lambda
from .const import (
CONF_MAX_EP_NUMBER,
CONF_REPORT,
CONF_USE_DEVICE_TYPE,
KEY_ZIGBEE,
REPORT,
)
from .const import CONF_MAX_EP_NUMBER, CONF_USE_DEVICE_TYPE, KEY_ZIGBEE
from .const_esp32 import (
ALLOWED_UNITS,
CONF_ATTRIBUTE_ID,
@@ -58,7 +52,6 @@ ANALOG_INPUT_EP = {
{
CONF_ATTRIBUTE_ID: 0x55,
CONF_TYPE: "SINGLE",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
},
{
@@ -87,7 +80,6 @@ ANALOG_OUTPUT_EP = {
{
CONF_ATTRIBUTE_ID: 0x55,
CONF_TYPE: "SINGLE",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
},
{
@@ -117,7 +109,6 @@ BINARY_INPUT_EP = {
{
CONF_ATTRIBUTE_ID: 0x55,
CONF_TYPE: "BOOL",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
},
{
@@ -146,7 +137,6 @@ BINARY_OUTPUT_EP = {
{
CONF_ATTRIBUTE_ID: 0x55,
CONF_TYPE: "BOOL",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
},
{
@@ -178,7 +168,6 @@ def _pressure_ep(device_type: bool = False) -> dict[str, Any]:
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "INT16",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
SCALE: {
UNIT_HECTOPASCAL: 1,
@@ -208,7 +197,6 @@ SENSOR_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "INT16",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
SCALE: 100,
CONNECT: True,
},
@@ -226,7 +214,6 @@ SENSOR_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "UINT16",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
SCALE: 100,
CONNECT: True,
},
@@ -247,7 +234,6 @@ SENSOR_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "UINT16",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
SCALE: {
UNIT_LITRE_PER_HOUR: 0.01,
@@ -269,7 +255,6 @@ SENSOR_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "UINT16",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONF_LAMBDA: cv.lambda_(
Lambda(
"if (x < 0.0f || std::isnan(x)) return 0xFFFF;" # NaN
@@ -294,7 +279,6 @@ SENSOR_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "SINGLE",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
},
{
@@ -316,7 +300,6 @@ SENSOR_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0000,
CONF_TYPE: "SINGLE",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
SCALE: 0.000001,
},
@@ -339,7 +322,6 @@ BINARY_SENSOR_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "MAP8",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
},
{
@@ -369,7 +351,6 @@ SWITCH_EP_CONFIGS: dict[str, dict[str, Any]] = {
{
CONF_ATTRIBUTE_ID: 0x0,
CONF_TYPE: "BOOL",
CONF_REPORT: cv.enum(REPORT, lower=True)("default"),
CONNECT: True,
},
],
@@ -49,6 +49,12 @@ void ZigbeeComponent::factory_reset() {
esp_zigbee_lock_release();
}
void ZigbeeComponent::report() {
for (const auto &[_, attribute] : this->attributes_) {
attribute->report();
}
}
void ZigbeeComponent::esp_zigbee_alarm_bdb_commissioning(ezb_bdb_comm_mode_mask_t mode) {
if (!esp_zigbee_lock_acquire(10 / portTICK_PERIOD_MS)) {
global_zigbee->set_timeout(COMMISSIONING_RETRY_TIMEOUT_ID, 100,
+1
View File
@@ -61,6 +61,7 @@ class ZigbeeComponent final : public Component {
static void esp_zigbee_alarm_bdb_commissioning(ezb_bdb_comm_mode_mask_t mode);
void factory_reset();
void report();
template<typename F> void add_on_join_callback(F &&cb) { this->join_cb_.add(std::forward<F>(cb)); }
template<typename F> void add_on_start_callback(F &&cb) { this->start_cb_.add(std::forward<F>(cb)); }
+26 -2
View File
@@ -3,10 +3,12 @@ import logging
import re
from typing import Any
from esphome import automation
import esphome.codegen as cg
from esphome.components.const import CONF_MANUFACTURER
from esphome.components.esp32 import (
CONF_PARTITIONS,
DOMAIN as ESP32_DOMAIN,
add_idf_component,
add_idf_sdkconfig_option,
add_partition,
@@ -55,6 +57,7 @@ from .const import (
KEY_ZIGBEE_VERSION_STR,
POWER_SOURCE,
ZigbeeAttribute,
ZigbeeComponent,
)
from .const_esp32 import (
ALLOWED_UNITS,
@@ -204,8 +207,11 @@ def setup_attributes(config: ConfigType, clusters: list[dict[str, Any]]) -> None
attr[CONF_VALUE] = str(name)
attr[CONF_MAX_LENGTH] = len(str(name))
if attr.get(CONNECT): # connect device
if CONF_REPORT in config:
attr[CONF_REPORT] = config[CONF_REPORT]
if (report := config.get(CONF_REPORT, "default")) not in (
"default",
"coordinator",
):
attr[CONF_REPORT] = report
attr[CONF_ID] = cv.declare_id(ZigbeeAttribute)(None)
attr_list = config.setdefault(KEY_ZIGBEE_ATTRIBUTES, [])
attr_list.append(attr)
@@ -460,3 +466,21 @@ async def add_component(entity: cg.MockObj, config: ConfigType) -> None:
cg.add(zb_attr.connect(template_arg, entity, lambda_))
else:
cg.add(zb_attr.connect(template_arg, entity))
ZIGBEE_ACTION_SCHEMA_ESP32 = automation.maybe_simple_id(
cv.All(
cv.Schema(
{
cv.GenerateID(): cv.use_id(ZigbeeComponent),
},
),
cv.requires_component(ESP32_DOMAIN),
)
)
automation.register_apply_action(
"zigbee.report",
ZIGBEE_ACTION_SCHEMA_ESP32,
automation.ApplyCall("report()"),
)
@@ -16,6 +16,9 @@ binary_sensor:
name: "Garage Door Open 13"
endpoint: 2
use_device_type: false
on_press:
then:
- zigbee.report
sensor:
- platform: template
@@ -26,6 +29,7 @@ sensor:
endpoint: 1
use_device_type: true
cluster: device_class
report: enable
- platform: template
name: "Light Sensor"
lambda: return 100.0;