diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 286b395e183..69e3fe9c5ae 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -87,9 +87,8 @@ CONFIG_SCHEMA = cv.All( ), cv.requires_component("nrf52"), ), - cv.OnlyWith(CONF_POWER_SOURCE, "nrf52", default="DC_SOURCE"): cv.All( - cv.enum(POWER_SOURCE, upper=True), - cv.requires_component("nrf52"), + cv.Optional(CONF_POWER_SOURCE, default="DC_SOURCE"): cv.enum( + POWER_SOURCE, upper=True ), cv.Optional(CONF_IEEE802154_VENDOR_OUI): cv.All( cv.Any( diff --git a/esphome/components/zigbee/zigbee_esp32.cpp b/esphome/components/zigbee/zigbee_esp32.cpp index 733f45cc2ae..c534a384320 100644 --- a/esphome/components/zigbee/zigbee_esp32.cpp +++ b/esphome/components/zigbee/zigbee_esp32.cpp @@ -153,7 +153,7 @@ void ZigbeeComponent::add_cluster(uint8_t endpoint_id, uint16_t cluster_id, uint this->attribute_list_[{endpoint_id, cluster_id, role}] = attr_list; } -void ZigbeeComponent::set_basic_cluster(const char *model, const char *manufacturer) { +void ZigbeeComponent::set_basic_cluster(const char *model, const char *manufacturer, uint8_t power_source) { char date_buf[16]; time_t time_val = App.get_build_time(); struct tm *timeinfo = localtime(&time_val); @@ -162,13 +162,14 @@ void ZigbeeComponent::set_basic_cluster(const char *model, const char *manufactu .model = get_zcl_string(model, 31), .manufacturer = get_zcl_string(manufacturer, 31), .date = get_zcl_string(date_buf, 15), + .power_source = power_source, }; } esp_zb_attribute_list_t *ZigbeeComponent::create_basic_cluster_() { esp_zb_basic_cluster_cfg_t basic_cluster_cfg = { .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, - .power_source = 0, + .power_source = this->basic_cluster_data_.power_source, }; esp_zb_attribute_list_t *attr_list = esp_zb_basic_cluster_create(&basic_cluster_cfg); esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, @@ -192,7 +193,12 @@ static void esp_zb_task_(void *pvParameters) { ESP_LOGE(TAG, "Could not setup Zigbee"); vTaskDelete(NULL); } - esp_zb_set_node_descriptor_power_source(1); + if (global_zigbee->is_battery_powered()) { + ESP_LOGD(TAG, "Battery powered!"); + esp_zb_set_node_descriptor_power_source(0); + } else { + esp_zb_set_node_descriptor_power_source(1); + } esp_zb_stack_main_loop(); } diff --git a/esphome/components/zigbee/zigbee_esp32.h b/esphome/components/zigbee/zigbee_esp32.h index a9072f6c8d4..03d3286ab82 100644 --- a/esphome/components/zigbee/zigbee_esp32.h +++ b/esphome/components/zigbee/zigbee_esp32.h @@ -43,7 +43,7 @@ class ZigbeeComponent : public Component { void dump_config() override; esp_err_t create_endpoint(uint8_t endpoint_id, zb_ha_standard_devs_e device_id, esp_zb_cluster_list_t *esp_zb_cluster_list); - void set_basic_cluster(const char *model, const char *manufacturer); + 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, zb_ha_standard_devs_e device_id); @@ -62,6 +62,7 @@ class ZigbeeComponent : public Component { template void add_on_join_callback(F &&cb) { this->join_cb_.add(std::forward(cb)); } + bool is_battery_powered() { return this->basic_cluster_data_.power_source == ESP_ZB_ZCL_BASIC_POWER_SOURCE_BATTERY; } bool is_started() { return this->started; } bool is_connected() { return this->connected_; } std::atomic started = false; @@ -73,6 +74,7 @@ class ZigbeeComponent : public Component { uint8_t *model; uint8_t *manufacturer; uint8_t *date; + uint8_t power_source; } basic_cluster_data_; bool connected_ = false; #ifdef ZB_ED_ROLE diff --git a/esphome/components/zigbee/zigbee_esp32.py b/esphome/components/zigbee/zigbee_esp32.py index 5b1808ea60d..e446377a06b 100644 --- a/esphome/components/zigbee/zigbee_esp32.py +++ b/esphome/components/zigbee/zigbee_esp32.py @@ -36,9 +36,11 @@ from .const import ( ANALOG_INPUT_APPTYPE, BACNET_UNIT_NO_UNITS, BACNET_UNITS, + CONF_POWER_SOURCE, CONF_REPORT, CONF_ROUTER, KEY_ZIGBEE, + POWER_SOURCE, REPORT, ZigbeeAttribute, ) @@ -320,6 +322,7 @@ async def esp32_to_code(config: ConfigType) -> "MockObj": var.set_basic_cluster( config[CONF_MODEL], "esphome", + cg.RawExpression(POWER_SOURCE[config[CONF_POWER_SOURCE]]), ) ) for ep in ep_list: diff --git a/tests/components/zigbee/common_esp32.yaml b/tests/components/zigbee/common_esp32.yaml index 77e202b5235..82a523fc7c4 100644 --- a/tests/components/zigbee/common_esp32.yaml +++ b/tests/components/zigbee/common_esp32.yaml @@ -12,6 +12,7 @@ binary_sensor: zigbee: model: zigbee_test router: true + power_source: MAINS_SINGLE_PHASE on_join: then: - logger.log: "Joined network"