ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
zigbee_time_zephyr.cpp
Go to the documentation of this file.
2#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_TIME)
3#include "esphome/core/log.h"
4#include <limits>
5
6namespace esphome::zigbee {
7
8ESPHOME_LOG_TAG(TAG, "zigbee.time");
9
10// This time standard is the number of
11// seconds since 0 hrs 0 mins 0 sec on 1st January 2000 UTC (Universal Coordinated Time).
12constexpr time_t EPOCH_2000 = 946684800;
13// Largest ZCL time that still fits the 32-bit epoch. Also rejects ZB_ZCL_TIME_TIME_INVALID_VALUE.
14constexpr uint32_t MAX_ZCL_TIME = std::numeric_limits<uint32_t>::max() - EPOCH_2000;
15
16ZigbeeTime *global_time = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
17
18void ZigbeeTime::sync_time(zb_ret_t status, zb_uint32_t auth_level, zb_uint16_t short_addr, zb_uint8_t endpoint,
19 zb_uint32_t nw_time) {
20 if (status == RET_OK && auth_level >= ZB_ZCL_TIME_HAS_SYNCHRONIZED_BIT && nw_time <= MAX_ZCL_TIME) {
21 global_time->set_epoch_time(nw_time + EPOCH_2000);
22 } else if (status != RET_TIMEOUT || !global_time->has_time_) {
23 ESP_LOGE(TAG, "Status: %d, auth_level: %u, short_addr: %d, endpoint: %d, nw_time: %u", status, auth_level,
24 short_addr, endpoint, nw_time);
25 }
26}
27
28void ZigbeeTime::setup() {
29 global_time = this;
30 this->parent_->add_callback(this->endpoint_, [this](zb_bufid_t bufid) { this->zcl_device_cb_(bufid); });
31 this->parent_->add_on_join_callback([this](bool x) { zb_zcl_time_server_synchronize(this->endpoint_, sync_time); });
32}
33
35 ESP_LOGCONFIG(TAG,
36 "Zigbee Time\n"
37 " Endpoint: %d",
38 this->endpoint_);
39 RealTimeClock::dump_config();
40}
41
42void ZigbeeTime::update() {
43 const time_t now = this->timestamp_now();
44 if (now < EPOCH_2000) {
45 this->cluster_attributes_->time = ZB_ZCL_TIME_TIME_INVALID_VALUE;
46 } else {
47 this->cluster_attributes_->time = static_cast<uint32_t>(now - EPOCH_2000);
48 }
49}
50
52 this->defer([this, epoch]() {
53 this->synchronize_epoch_(epoch);
54 this->has_time_ = true;
55 });
56}
57
58void ZigbeeTime::zcl_device_cb_(zb_bufid_t bufid) {
59 zb_zcl_device_callback_param_t *p_device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t);
60 zb_zcl_device_callback_id_t device_cb_id = p_device_cb_param->device_cb_id;
61 zb_uint16_t cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id;
62 zb_uint16_t attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id;
63
64 switch (device_cb_id) {
65 /* ZCL set attribute value */
66 case ZB_ZCL_SET_ATTR_VALUE_CB_ID:
67 if (cluster_id == ZB_ZCL_CLUSTER_ID_TIME) {
68 if (attr_id == ZB_ZCL_ATTR_TIME_TIME_ID) {
69 zb_uint32_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data32;
70 if (value <= MAX_ZCL_TIME) {
71 ESP_LOGI(TAG, "Synchronize time to %u", value);
72 this->defer([this, value]() { this->synchronize_epoch_(value + EPOCH_2000); });
73 } else {
74 ESP_LOGW(TAG, "Ignoring invalid time %u", value);
75 }
76 } else if (attr_id == ZB_ZCL_ATTR_TIME_TIME_STATUS_ID) {
77 zb_uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8;
78 ESP_LOGI(TAG, "Time status %hd", value);
79 this->defer([this, value]() { this->has_time_ = ZB_ZCL_TIME_TIME_STATUS_SYNCHRONIZED_BIT_IS_SET(value); });
80 }
81 } else {
82 /* other clusters attribute handled here */
83 ESP_LOGI(TAG, "Unhandled cluster attribute id: %d", cluster_id);
84 p_device_cb_param->status = RET_NOT_IMPLEMENTED;
85 }
86 break;
87 default:
88 p_device_cb_param->status = RET_NOT_IMPLEMENTED;
89 break;
90 }
91
92 ESP_LOGD(TAG, "Zcl_device_cb_ status: %hd", p_device_cb_param->status);
93}
94
95} // namespace esphome::zigbee
96
97#endif
uint8_t status
Definition bl0942.h:8
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
ESPTime now()
Get the time in the currently defined timezone.
virtual time_t timestamp_now()
Get the current time as the UTC epoch since January 1st 1970.
void synchronize_epoch_(uint32_t epoch)
Report a unix epoch as current time.
void add_callback(zb_uint8_t endpoint, std::function< void(zb_bufid_t bufid)> &&cb)
static void sync_time(zb_ret_t status, zb_uint32_t auth_level, zb_uint16_t short_addr, zb_uint8_t endpoint, zb_uint32_t nw_time)
void zcl_device_cb_(zb_bufid_t bufid)
zb_zcl_time_attrs_t * cluster_attributes_
constexpr time_t EPOCH_2000
constexpr uint32_t MAX_ZCL_TIME
ESPHOME_LOG_TAG(TAG, "zigbee.time")
static void uint32_t
uint16_t x
Definition tt21100.cpp:5