mirror of
https://github.com/esphome/esphome.git
synced 2026-10-12 06:14:17 +00:00
[nrf52] fix zigbee time component (#20527)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,8 @@ from esphome.const import (
|
||||
CONF_SECONDS,
|
||||
CONF_TIMEZONE,
|
||||
CONF_TRIGGER_ID,
|
||||
KEY_CORE,
|
||||
KEY_FRAMEWORK_VERSION,
|
||||
PLATFORM_BK72XX,
|
||||
PLATFORM_ESP32,
|
||||
PLATFORM_ESP8266,
|
||||
@@ -462,6 +464,12 @@ async def register_time(time_var, config):
|
||||
async def to_code(config):
|
||||
if CORE.using_zephyr:
|
||||
zephyr_add_prj_conf("POSIX_CLOCK", True)
|
||||
# From sdk-nrf 2.8.0 newlib time() gets the clock through gettimeofday(),
|
||||
# which Zephyr only provides with XSI_SINGLE_PROCESS. Without it time()
|
||||
# always returns -1.
|
||||
if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(2, 8, 0):
|
||||
zephyr_add_prj_conf("POSIX_SINGLE_PROCESS", True)
|
||||
zephyr_add_prj_conf("XSI_SINGLE_PROCESS", True)
|
||||
cg.add_define("USE_TIME")
|
||||
cg.add_global(time_ns.using)
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ from ..zigbee_zephyr import (
|
||||
ZigbeeClusterDesc,
|
||||
ZigbeeComponent,
|
||||
get_slot_index,
|
||||
zigbee_assign,
|
||||
zigbee_new_attr_list,
|
||||
zigbee_new_cluster_list,
|
||||
zigbee_new_variable,
|
||||
@@ -81,6 +82,7 @@ async def _add_time_zephyr(config: ConfigType) -> None:
|
||||
|
||||
# Create the binary attributes structure
|
||||
time_attrs = zigbee_new_variable(attrs_name, "zb_zcl_time_attrs_t")
|
||||
zigbee_assign(time_attrs.time, cg.RawExpression("ZB_ZCL_TIME_TIME_INVALID_VALUE"))
|
||||
attr_list = zigbee_new_attr_list(
|
||||
attr_list_name,
|
||||
"ZB_ZCL_DECLARE_TIME_ATTR_LIST",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_TIME)
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include <limits>
|
||||
|
||||
namespace esphome::zigbee {
|
||||
|
||||
@@ -10,12 +11,14 @@ static const char *const TAG = "zigbee.time";
|
||||
// This time standard is the number of
|
||||
// seconds since 0 hrs 0 mins 0 sec on 1st January 2000 UTC (Universal Coordinated Time).
|
||||
constexpr time_t EPOCH_2000 = 946684800;
|
||||
// Largest ZCL time that still fits the 32-bit epoch. Also rejects ZB_ZCL_TIME_TIME_INVALID_VALUE.
|
||||
constexpr uint32_t MAX_ZCL_TIME = std::numeric_limits<uint32_t>::max() - EPOCH_2000;
|
||||
|
||||
ZigbeeTime *global_time = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
void ZigbeeTime::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) {
|
||||
if (status == RET_OK && auth_level >= ZB_ZCL_TIME_HAS_SYNCHRONIZED_BIT) {
|
||||
if (status == RET_OK && auth_level >= ZB_ZCL_TIME_HAS_SYNCHRONIZED_BIT && nw_time <= MAX_ZCL_TIME) {
|
||||
global_time->set_epoch_time(nw_time + EPOCH_2000);
|
||||
} else if (status != RET_TIMEOUT || !global_time->has_time_) {
|
||||
ESP_LOGE(TAG, "Status: %d, auth_level: %u, short_addr: %d, endpoint: %d, nw_time: %u", status, auth_level,
|
||||
@@ -26,7 +29,6 @@ void ZigbeeTime::sync_time(zb_ret_t status, zb_uint32_t auth_level, zb_uint16_t
|
||||
void ZigbeeTime::setup() {
|
||||
global_time = this;
|
||||
this->parent_->add_callback(this->endpoint_, [this](zb_bufid_t bufid) { this->zcl_device_cb_(bufid); });
|
||||
synchronize_epoch_(EPOCH_2000);
|
||||
this->parent_->add_on_join_callback([this](bool x) { zb_zcl_time_server_synchronize(this->endpoint_, sync_time); });
|
||||
}
|
||||
|
||||
@@ -39,8 +41,12 @@ void ZigbeeTime::dump_config() {
|
||||
}
|
||||
|
||||
void ZigbeeTime::update() {
|
||||
time_t time = timestamp_now();
|
||||
this->cluster_attributes_->time = time - EPOCH_2000;
|
||||
const time_t now = this->timestamp_now();
|
||||
if (now < EPOCH_2000) {
|
||||
this->cluster_attributes_->time = ZB_ZCL_TIME_TIME_INVALID_VALUE;
|
||||
} else {
|
||||
this->cluster_attributes_->time = static_cast<uint32_t>(now - EPOCH_2000);
|
||||
}
|
||||
}
|
||||
|
||||
void ZigbeeTime::set_epoch_time(uint32_t epoch) {
|
||||
@@ -63,8 +69,12 @@ void ZigbeeTime::zcl_device_cb_(zb_bufid_t bufid) {
|
||||
if (cluster_id == ZB_ZCL_CLUSTER_ID_TIME) {
|
||||
if (attr_id == ZB_ZCL_ATTR_TIME_TIME_ID) {
|
||||
zb_uint32_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data32;
|
||||
ESP_LOGI(TAG, "Synchronize time to %u", value);
|
||||
this->defer([this, value]() { synchronize_epoch_(value + EPOCH_2000); });
|
||||
if (value <= MAX_ZCL_TIME) {
|
||||
ESP_LOGI(TAG, "Synchronize time to %u", value);
|
||||
this->defer([this, value]() { this->synchronize_epoch_(value + EPOCH_2000); });
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Ignoring invalid time %u", value);
|
||||
}
|
||||
} else if (attr_id == ZB_ZCL_ATTR_TIME_TIME_STATUS_ID) {
|
||||
zb_uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8;
|
||||
ESP_LOGI(TAG, "Time status %hd", value);
|
||||
|
||||
Reference in New Issue
Block a user