ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
zigbee_event_esp32.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_ESP32
5#ifdef USE_ZIGBEE
6
7#include <cstddef> // for offsetof
8#include <cstring> // for memcpy
9#include "esp_zigbee.h"
10#include "ezbee/zha.h"
11
12namespace esphome::zigbee {
13
14class ZBEvent {
15 public:
16 // IMPORTANT: We MUST copy all values because the pointer from ESP-IDF
17 // is only valid during the callback execution. Since ZB events are processed
18 // asynchronously in the main loop, we store our own copy inline to ensure
19 // the data remains valid until the event is processed.
20 ZBEvent(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute)
21 : event_{}, callback_id_(EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID) {
22 this->init_set_attr_value_data_(info, attribute);
23 }
24
25 // Destructor to clean up heap allocations
26 ~ZBEvent() { this->release(); }
27
28 // Default constructor for pre-allocation in pool
29 ZBEvent() : event_{}, callback_id_(EZB_ZCL_CORE_CB_ID_END) {}
30
31 // Invoked on return to EventPool - clean up any heap-allocated data
32 void release() {
33 // Free any allocated memory within the event
34 switch (this->callback_id_) {
35 case EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID:
36 if (!this->event_.set_attr.is_inline && this->event_.set_attr.data.heap_data != nullptr) {
37 delete[] this->event_.set_attr.data.heap_data;
38 this->event_.set_attr.data.heap_data = nullptr;
39 }
40 break;
41 default:
42 break;
43 }
44 }
45
46 // Load new event data for reuse (replaces previous event data)
47 // Note: release() is NOT called here because EventPool::release() already
48 // calls event->release() before returning to the free list. Every event
49 // from allocate() is already in a clean state.
50 void load_set_attr_value_event(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute) {
51 this->callback_id_ = EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID;
52 this->init_set_attr_value_data_(info, attribute);
53 }
54
55 // Disable copy to prevent double-delete
56 ZBEvent(const ZBEvent &) = delete;
57 ZBEvent &operator=(const ZBEvent &) = delete;
58
59 union {
60 // NOLINTNEXTLINE(readability-identifier-naming)
61 struct set_attr_event {
62 ezb_zcl_message_info_t info;
63 ezb_zcl_attribute_t attribute;
64 union {
65 uint8_t *heap_data;
66 uint8_t inline_data[4]; // For small data types (<= 32 bit)
67 } data;
71
72 ezb_zcl_core_action_callback_id_t callback_id_;
73
74 private:
75 void init_set_attr_value_data_(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute) {
76 this->event_.set_attr.info = info;
77 this->event_.set_attr.attribute = attribute;
78 // get attribute.data.value with correct type
79 if (attribute.data.value != nullptr) {
80 // Copy the attribute value to avoid dangling pointer issues
81 size_t value_size = ezb_zcl_get_attr_value_size(attribute.data.type, attribute.data.value);
82 if (value_size > 4) {
83 this->event_.set_attr.data.heap_data = new uint8_t[value_size];
84 memcpy(this->event_.set_attr.data.heap_data, attribute.data.value, value_size);
85 this->event_.set_attr.attribute.data.value = this->event_.set_attr.data.heap_data;
86 this->event_.set_attr.is_inline = false;
87 } else {
88 memcpy(this->event_.set_attr.data.inline_data, attribute.data.value, value_size);
89 this->event_.set_attr.attribute.data.value = this->event_.set_attr.data.inline_data;
90 this->event_.set_attr.is_inline = true;
91 }
92 }
93 }
94};
95} // namespace esphome::zigbee
96#endif // USE_ZIGBEE
97#endif // USE_ESP32
ezb_zcl_core_action_callback_id_t callback_id_
struct esphome::zigbee::ZBEvent::@207::set_attr_event set_attr
ezb_zcl_message_info_t info
ZBEvent(const ZBEvent &)=delete
ZBEvent(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute)
union esphome::zigbee::ZBEvent::@207 event_
void load_set_attr_value_event(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute)
ezb_zcl_attribute_t attribute
ZBEvent & operator=(const ZBEvent &)=delete