/* * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD * * SPDX-License-Identifier: MIT */ #include "hal.h" #include "board/hal_bridge.h" #include "drivers/PCF8563_Class/PCF8563_Class.hpp" #include #include #include #include #include static const std::string_view _tag = "HAL-RTC"; static std::unique_ptr _pcf8563; void Hal::rtc_init() { mclog::tagInfo(_tag, "init"); auto i2c_bus = hal_bridge::board_get_i2c_bus(); _pcf8563 = std::make_unique(i2c_bus); if (!_pcf8563->begin()) { _pcf8563.reset(); mclog::tagError(_tag, "PCF8563 init failed"); return; } mclog::tagInfo(_tag, "PCF8563 init ok"); // Load timezone from settings std::string tz = getTimezone(); setenv("TZ", tz.c_str(), 1); tzset(); mclog::tagInfo(_tag, "load timezone from nvs: {}", tz); syncRtcTimeToSystem(); } void Hal::syncRtcTimeToSystem() { if (!_pcf8563) { return; } m5::rtc_date_t date; m5::rtc_time_t time; if (_pcf8563->getDateTime(&date, &time)) { struct tm tm_curr = {0}; tm_curr.tm_year = date.year - 1900; tm_curr.tm_mon = date.month - 1; tm_curr.tm_mday = date.date; tm_curr.tm_hour = time.hours; tm_curr.tm_min = time.minutes; tm_curr.tm_sec = time.seconds; tm_curr.tm_isdst = 0; // Temporarily set TZ to UTC to interpret RTC time as UTC std::string current_tz = getenv("TZ") ? getenv("TZ") : ""; setenv("TZ", "UTC0", 1); tzset(); time_t t = mktime(&tm_curr); // Restore original TZ if (!current_tz.empty()) { setenv("TZ", current_tz.c_str(), 1); } else { unsetenv("TZ"); } tzset(); struct timeval tv = {.tv_sec = t, .tv_usec = 0}; settimeofday(&tv, NULL); mclog::tagInfo(_tag, "rtc synced to system (UTC): {:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}", date.year, date.month, date.date, time.hours, time.minutes, time.seconds); } else { mclog::tagError(_tag, "failed to read rtc"); } } void Hal::syncSystemTimeToRtc() { if (!_pcf8563) { return; } struct timeval tv; gettimeofday(&tv, NULL); struct tm tm_curr; gmtime_r(&tv.tv_sec, &tm_curr); m5::rtc_date_t date; m5::rtc_time_t time; date.year = tm_curr.tm_year + 1900; date.month = tm_curr.tm_mon + 1; date.date = tm_curr.tm_mday; date.weekDay = tm_curr.tm_wday; time.hours = tm_curr.tm_hour; time.minutes = tm_curr.tm_min; time.seconds = tm_curr.tm_sec; if (_pcf8563->setDateTime(&date, &time)) { mclog::tagInfo(_tag, "system synced to rtc (UTC): {:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}", date.year, date.month, date.date, time.hours, time.minutes, time.seconds); } else { mclog::tagError(_tag, "failed to write rtc"); } } void Hal::setTimezone(std::string_view tz) { setenv("TZ", tz.data(), 1); tzset(); Settings settings("system", true); settings.SetString("tz", std::string(tz)); mclog::tagInfo(_tag, "timezone updated to: {}", tz); } std::string Hal::getTimezone() { Settings settings("system", false); return settings.GetString("tz", "GMT0"); }