ESPHome 2026.5.0b1
Loading...
Searching...
No Matches
zigbee_esp32.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_ESP32
5#ifdef USE_ZIGBEE
6
7#include <map>
8#include <tuple>
9#include <atomic>
10
11#include "esp_zigbee_core.h"
12#include "zboss_api.h"
13#include "ha/esp_zigbee_ha_standard.h"
18
19#ifdef USE_BINARY_SENSOR
21#endif
22
23namespace esphome::zigbee {
24
25/* Zigbee configuration */
26static const uint16_t ED_KEEP_ALIVE = 3000; /* 3000 millisecond */
27static const uint8_t MAX_CHILDREN = 10;
28
29#define ESP_ZB_DEFAULT_RADIO_CONFIG() \
30 { .radio_mode = ZB_RADIO_MODE_NATIVE, }
31
32#define ESP_ZB_DEFAULT_HOST_CONFIG() \
33 { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, }
34
35uint8_t *get_zcl_string(const char *str, uint8_t max_size, bool use_max_size = false);
36
37class ZigbeeAttribute;
38
39class ZigbeeComponent : public Component {
40 public:
41 void setup() override;
42 void loop() override;
43 void dump_config() override;
44 esp_err_t create_endpoint(uint8_t endpoint_id, zb_ha_standard_devs_e device_id,
45 esp_zb_cluster_list_t *esp_zb_cluster_list);
46 void set_basic_cluster(const char *model, const char *manufacturer, uint8_t power_source);
47 void add_cluster(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role);
48 void create_default_cluster(uint8_t endpoint_id, zb_ha_standard_devs_e device_id);
49
50 template<typename T>
51 void add_attr(ZigbeeAttribute *attr, uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id,
52 uint8_t max_size, T value);
53
54 template<typename T>
55 void add_attr(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id, uint8_t max_size, T value);
56
58 esp_zb_lock_acquire(portMAX_DELAY);
59 esp_zb_factory_reset(); // triggers a reboot
60 esp_zb_lock_release();
61 }
62
63 template<typename F> void add_on_join_callback(F &&cb) { this->join_cb_.add(std::forward<F>(cb)); }
64
65 bool is_battery_powered() { return this->basic_cluster_data_.power_source == ESP_ZB_ZCL_BASIC_POWER_SOURCE_BATTERY; }
66 bool is_started() { return this->started; }
67 bool is_connected() { return this->connected_; }
68 std::atomic<bool> started = false;
69 std::atomic<bool> joined = false;
70 std::atomic<bool> factory_new = false;
71
72 protected:
73 struct {
74 uint8_t *model;
75 uint8_t *manufacturer;
76 uint8_t *date;
77 uint8_t power_source;
79 bool connected_ = false;
80#ifdef ZB_ED_ROLE
81 esp_zb_nwk_device_type_t device_role_ = ESP_ZB_DEVICE_TYPE_ED;
82#else
83 esp_zb_nwk_device_type_t device_role_ = ESP_ZB_DEVICE_TYPE_ROUTER;
84#endif
85 esp_zb_attribute_list_t *create_basic_cluster_();
86 template<typename T>
87 void add_attr_(ZigbeeAttribute *attr, uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id,
88 T *value_p);
89 // endpoint_list_ and attribute_list_ are only used during setup and are cleared afterwards
90 // value tuple could be replaced by struct
91 std::map<uint8_t, std::tuple<zb_ha_standard_devs_e, esp_zb_cluster_list_t *>> endpoint_list_;
92 // key tuple could be replaced by single 32 bit int with bit fields for endpoint, cluster and role
93 std::map<std::tuple<uint8_t, uint16_t, uint8_t>, esp_zb_attribute_list_t *> attribute_list_;
94 // attributes_ will be used during operation in zigbee callbacks to update the attribute values and trigger
95 // automations
96 // key tuple could be replaced by single 64 (48) bit int with bit fields for endpoint, cluster, role and attr_id
97 std::map<std::tuple<uint8_t, uint16_t, uint8_t, uint16_t>, ZigbeeAttribute *> attributes_;
98 esp_zb_ep_list_t *esp_zb_ep_list_ = esp_zb_ep_list_create();
100};
101
102extern "C" void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct);
103
104template<typename T>
105void ZigbeeComponent::add_attr(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id,
106 uint8_t max_size, T value) {
107 this->add_attr<T>(nullptr, endpoint_id, cluster_id, role, attr_id, max_size, value);
108}
109
110template<typename T>
111void ZigbeeComponent::add_attr(ZigbeeAttribute *attr, uint8_t endpoint_id, uint16_t cluster_id, uint8_t role,
112 uint16_t attr_id, uint8_t max_size, T value) {
113 // The size byte of the zcl_str must be set to the maximum value,
114 // even though the initial string may be shorter.
115 if constexpr (std::is_same<T, std::string>::value) {
116 auto zcl_str = get_zcl_string(value.c_str(), max_size, true);
117 add_attr_(attr, endpoint_id, cluster_id, role, attr_id, zcl_str);
118 delete[] zcl_str;
119 } else if constexpr (std::is_convertible<T, const char *>::value) {
120 auto zcl_str = get_zcl_string(value, max_size, true);
121 add_attr_(attr, endpoint_id, cluster_id, role, attr_id, zcl_str);
122 delete[] zcl_str;
123 } else {
124 add_attr_(attr, endpoint_id, cluster_id, role, attr_id, &value);
125 }
126}
127
128template<typename T>
129void ZigbeeComponent::add_attr_(ZigbeeAttribute *attr, uint8_t endpoint_id, uint16_t cluster_id, uint8_t role,
130 uint16_t attr_id, T *value_p) {
131 esp_zb_attribute_list_t *attr_list = this->attribute_list_[{endpoint_id, cluster_id, role}];
132 esp_err_t ret = esphome_zb_cluster_add_or_update_attr(cluster_id, attr_list, attr_id, value_p);
133
134 if (attr != nullptr) {
135 this->attributes_[{endpoint_id, cluster_id, role, attr_id}] = attr;
136 }
137}
138
139} // namespace esphome::zigbee
140
141#endif
142#endif
CallbackManager< void(bool)> join_cb_
esp_zb_ep_list_t * esp_zb_ep_list_
std::map< std::tuple< uint8_t, uint16_t, uint8_t, uint16_t >, ZigbeeAttribute * > attributes_
esp_zb_nwk_device_type_t device_role_
void create_default_cluster(uint8_t endpoint_id, zb_ha_standard_devs_e device_id)
void add_cluster(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role)
std::atomic< bool > factory_new
std::map< uint8_t, std::tuple< zb_ha_standard_devs_e, esp_zb_cluster_list_t * > > endpoint_list_
std::map< std::tuple< uint8_t, uint16_t, uint8_t >, esp_zb_attribute_list_t * > attribute_list_
void set_basic_cluster(const char *model, const char *manufacturer, uint8_t power_source)
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)
struct esphome::zigbee::ZigbeeComponent::@199 basic_cluster_data_
void add_attr(ZigbeeAttribute *attr, uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id, uint8_t max_size, T value)
esp_zb_attribute_list_t * create_basic_cluster_()
void add_attr_(ZigbeeAttribute *attr, uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id, T *value_p)
uint8_t * get_zcl_string(const char *str, uint8_t max_size, bool use_max_size)
void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct)
esp_err_t esphome_zb_cluster_add_or_update_attr(uint16_t cluster_id, esp_zb_attribute_list_t *attr_list, uint16_t attr_id, void *value_p)