[zigbee] move init back into setup (#19427)

This commit is contained in:
luar123
2026-09-25 09:29:16 +01:00
committed by GitHub
parent 91210c5ef5
commit cc5ed93247
2 changed files with 62 additions and 8 deletions
+29 -5
View File
@@ -272,7 +272,9 @@ static void ezb_task(void *pv_parameters) {
vTaskDelete(NULL);
}
ZigbeeComponent::ZigbeeComponent() {
void ZigbeeComponent::setup() {
global_zigbee = this;
esp_zigbee_platform_config_t platform_config = {
.storage_partition_name = "nvs",
.radio_config = EZB_DEFAULT_RADIO_CONFIG(),
@@ -299,11 +301,7 @@ ZigbeeComponent::ZigbeeComponent() {
this->mark_failed();
return;
}
this->dev_desc_ = ezb_af_create_device_desc();
}
void ZigbeeComponent::setup() {
global_zigbee = this;
#ifdef USE_WIFI
if (esp_coex_wifi_i154_enable() != ESP_OK) {
this->mark_failed();
@@ -341,6 +339,15 @@ void ZigbeeComponent::setup() {
};
ezb_af_set_node_power_desc(&desc);
// Finish zigbee data model
for (auto &attr_value : this->attr_values_) {
ezb_zcl_attr_desc_t attr_desc = attr_value.attr_desc;
void *value_p = &attr_value.value;
ezb_zcl_attr_desc_set_value(attr_desc, value_p);
}
// free memory
std::vector<AttrValue>().swap(this->attr_values_);
// Start the Zigbee task with priority 1 to ensure main loop can still run even if Zigbee is busy
xTaskCreate(ezb_task, "Zigbee_main", 4096, NULL, 1, NULL);
this->disable_loop(); // loop is only needed for processing events, so disable until we join a network
@@ -383,6 +390,23 @@ void ZigbeeComponent::dump_config() {
YESNO(this->device_role_ == EZB_NWK_DEVICE_TYPE_ROUTER));
}
}
bool ZigbeeComponent::string_attr_exists_(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id) {
ezb_af_ep_desc_t ep_desc = ezb_af_device_get_endpoint_desc(this->dev_desc_, endpoint_id);
if (ep_desc == NULL) {
return false;
}
ezb_zcl_cluster_desc_t cluster_desc = ezb_af_endpoint_get_cluster_desc(ep_desc, cluster_id, role);
if (cluster_desc == NULL) {
return false;
}
if (ezb_zcl_cluster_get_attr_desc(cluster_desc, attr_id, EZB_ZCL_STD_MANUF_CODE) == NULL) {
return false;
}
ESP_LOGW(TAG, "Attribute 0x%04X already exists in endpoint %u cluster 0x%04X. Can't add new value", attr_id,
endpoint_id, cluster_id);
return true;
}
} // namespace esphome::zigbee
#endif
+33 -3
View File
@@ -30,11 +30,15 @@ static const uint32_t EZB_PRIMARY_CHANNEL_MASK = 0x07FFF800U; /* channels 11-26
uint8_t *get_zcl_string(const char *str, uint8_t max_size, bool use_max_size = false);
struct AttrValue {
ezb_zcl_attr_desc_t attr_desc;
uint8_t value[4];
};
class ZigbeeAttribute;
class ZigbeeComponent final : public Component {
public:
ZigbeeComponent();
void setup() override;
void loop() override;
void dump_config() override;
@@ -88,7 +92,8 @@ class ZigbeeComponent final : public Component {
// automations
// key tuple could be replaced by single 64 (48) bit int with bit fields for endpoint, cluster, role and attr_id
std::map<std::tuple<uint8_t, uint16_t, uint8_t, uint16_t>, ZigbeeAttribute *> attributes_;
ezb_af_device_desc_t dev_desc_;
std::vector<AttrValue> attr_values_;
ezb_af_device_desc_t dev_desc_ = ezb_af_create_device_desc();
CallbackManager<void(bool)> join_cb_{};
LazyCallbackManager<void()> start_cb_{};
bool start_reported_{false};
@@ -96,6 +101,8 @@ class ZigbeeComponent final : public Component {
std::atomic<bool> joined_ = false;
std::atomic<bool> join_pending_ = false;
std::atomic<bool> factory_new_ = false;
// TODO: remove when esp-zigbee-lib fixes set_value before init
bool string_attr_exists_(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id);
};
template<typename T>
@@ -110,10 +117,22 @@ void ZigbeeComponent::add_attr(ZigbeeAttribute *attr, uint8_t endpoint_id, uint1
// The size byte of the zcl_str must be set to the maximum value,
// even though the initial string may be shorter.
if constexpr (std::is_same<T, std::string>::value) {
if (this->string_attr_exists_(endpoint_id, cluster_id, role, attr_id)) {
if (attr != nullptr) {
this->attributes_[{endpoint_id, cluster_id, role, attr_id}] = attr;
}
return;
}
auto zcl_str = get_zcl_string(value.c_str(), max_size, true);
add_attr_(attr, endpoint_id, cluster_id, role, attr_id, zcl_str);
delete[] zcl_str;
} else if constexpr (std::is_convertible<T, const char *>::value) {
if (this->string_attr_exists_(endpoint_id, cluster_id, role, attr_id)) {
if (attr != nullptr) {
this->attributes_[{endpoint_id, cluster_id, role, attr_id}] = attr;
}
return;
}
auto zcl_str = get_zcl_string(value, max_size, true);
add_attr_(attr, endpoint_id, cluster_id, role, attr_id, zcl_str);
delete[] zcl_str;
@@ -133,7 +152,18 @@ void ZigbeeComponent::add_attr_(ZigbeeAttribute *attr, uint8_t endpoint_id, uint
if (cluster_desc == NULL) {
return;
}
esphome_zb_cluster_add_or_update_attr(cluster_id, cluster_desc, attr_id, value_p);
// TODO: revert when esp-zigbee-lib fixes set_value before init
ezb_zcl_attr_desc_t attr_desc = ezb_zcl_cluster_get_attr_desc(cluster_desc, attr_id, EZB_ZCL_STD_MANUF_CODE);
if (attr_desc != NULL) {
static_assert(sizeof(*value_p) <= 4);
AttrValue attr_value;
attr_value.attr_desc = attr_desc;
memcpy(&attr_value.value, value_p, sizeof(*value_p));
attr_values_.push_back(attr_value);
} else {
esphome_zb_cluster_add_attr(cluster_id, cluster_desc, attr_id, value_p);
}
if (attr != nullptr) {
this->attributes_[{endpoint_id, cluster_id, role, attr_id}] = attr;