#pragma once #include "esphome/core/defines.h" #if defined(USE_ZIGBEE) && defined(USE_NRF52) #include "esphome/core/component.h" #include "esphome/core/automation.h" extern "C" { #include #include } // copy of ZB_DECLARE_SIMPLE_DESC. Due to https://github.com/nrfconnect/sdk-nrfxlib/pull/666 #define ESPHOME_ZB_DECLARE_SIMPLE_DESC(ep_name, in_clusters_count, out_clusters_count) \ typedef ZB_PACKED_PRE struct zb_af_simple_desc_##ep_name##_##in_clusters_count##_##out_clusters_count##_s { \ zb_uint8_t endpoint; /* Endpoint */ \ zb_uint16_t app_profile_id; /* Application profile identifier */ \ zb_uint16_t app_device_id; /* Application device identifier */ \ zb_bitfield_t app_device_version : 4; /* Application device version */ \ zb_bitfield_t reserved : 4; /* Reserved */ \ zb_uint8_t app_input_cluster_count; /* Application input cluster count */ \ zb_uint8_t app_output_cluster_count; /* Application output cluster count */ \ /* Application input and output cluster list */ \ zb_uint16_t app_cluster_list[(in_clusters_count) + (out_clusters_count)]; \ } ZB_PACKED_STRUCT zb_af_simple_desc_##ep_name##_##in_clusters_count##_##out_clusters_count##_t #define ESPHOME_CAT7(a, b, c, d, e, f, g) a##b##c##d##e##f##g // needed to use ESPHOME_ZB_DECLARE_SIMPLE_DESC #define ESPHOME_ZB_AF_SIMPLE_DESC_TYPE(ep_name, in_num, out_num) \ ESPHOME_CAT7(zb_af_simple_desc_, ep_name, _, in_num, _, out_num, _t) // needed to use ESPHOME_ZB_DECLARE_SIMPLE_DESC #define ESPHOME_ZB_ZCL_DECLARE_SIMPLE_DESC(ep_name, ep_id, in_clust_num, out_clust_num, app_device_id, ...) \ ESPHOME_ZB_DECLARE_SIMPLE_DESC(ep_name, in_clust_num, out_clust_num); \ ESPHOME_ZB_AF_SIMPLE_DESC_TYPE(ep_name, in_clust_num, out_clust_num) \ simple_desc_##ep_name = {ep_id, ZB_AF_HA_PROFILE_ID, app_device_id, 0, 0, in_clust_num, out_clust_num, {__VA_ARGS__}} // needed to use ESPHOME_ZB_ZCL_DECLARE_SIMPLE_DESC #define ESPHOME_ZB_HA_DECLARE_EP(ep_name, ep_id, cluster_list, in_cluster_num, out_cluster_num, report_attr_count, \ app_device_id, ...) \ ESPHOME_ZB_ZCL_DECLARE_SIMPLE_DESC(ep_name, ep_id, in_cluster_num, out_cluster_num, app_device_id, __VA_ARGS__); \ ZBOSS_DEVICE_DECLARE_REPORTING_CTX(reporting_info##ep_name, report_attr_count); \ ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, ep_id, ZB_AF_HA_PROFILE_ID, 0, NULL, \ ZB_ZCL_ARRAY_SIZE(cluster_list, zb_zcl_cluster_desc_t), cluster_list, \ (zb_af_simple_desc_1_1_t *) &simple_desc_##ep_name, report_attr_count, \ reporting_info##ep_name, 0, NULL) namespace esphome::zigbee { struct BinaryAttrs { zb_bool_t out_of_service; zb_bool_t present_value; zb_uint8_t status_flags; zb_uchar_t description[ZB_ZCL_MAX_STRING_SIZE]; }; struct AnalogAttrs { zb_bool_t out_of_service; float present_value; zb_uint8_t status_flags; zb_uint16_t engineering_units; zb_uchar_t description[ZB_ZCL_MAX_STRING_SIZE]; }; struct AnalogAttrsOutput : AnalogAttrs { float max_present_value; float min_present_value; float resolution; }; class ZigbeeComponent : public Component { public: void setup() override; void dump_config() override; void add_callback(zb_uint8_t endpoint, std::function &&cb) { // endpoints are enumerated from 1 this->callbacks_[endpoint - 1] = std::move(cb); } template void add_join_callback(F &&cb) { this->join_cb_.add(std::forward(cb)); } void zboss_signal_handler_esphome(zb_bufid_t bufid); void after_reporting_info(zb_zcl_configure_reporting_req_t *config_rep_req, zb_zcl_attr_addr_info_t *attr_addr_info); void factory_reset(); Trigger<> *get_join_trigger() { return &this->join_trigger_; }; void force_report(); void loop() override; protected: static void zcl_device_cb(zb_bufid_t bufid); void on_join_(); #ifdef USE_ZIGBEE_WIPE_ON_BOOT void erase_flash_(int area); #endif void dump_reporting_(); std::array, ZIGBEE_ENDPOINTS_COUNT> callbacks_{}; CallbackManager join_cb_; Trigger<> join_trigger_; bool force_report_{false}; uint32_t sleep_time_{}; uint32_t sleep_remainder_{}; }; class ZigbeeEntity { public: void set_parent(ZigbeeComponent *parent) { this->parent_ = parent; } void set_endpoint(zb_uint8_t endpoint) { this->endpoint_ = endpoint; } protected: zb_uint8_t endpoint_{0}; ZigbeeComponent *parent_{nullptr}; }; } // namespace esphome::zigbee #endif