15#include "esp_system.h"
17#include "esp_clk_tree.h"
21static const char*
TAG =
"RTC";
41 const char*
getName()
const override {
return "rtc"; }
44 void getTime(
struct tm* timeinfo)
const override;
45 void getTimeStr(
char* buf,
size_t bufLen)
const override;
46 void getDateStr(
char* buf,
size_t bufLen)
const override;
47 void setTime(
int hour,
int minute,
int second)
override;
48 void setDate(
int year,
int month,
int day)
override;
51 bool isTimeSet()
const override {
return timeIsSet_; }
57 void loadTimezoneFromNvs();
61 bool timeIsSet_ =
false;
75 LOG_I(
TAG,
"Initializing ESP32-S3 internal RTC");
77 esp_reset_reason_t reset_reason = esp_reset_reason();
78 int64_t rtc_us = esp_timer_get_time();
79 uint32_t rtc_clk_hz = 0;
80 esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_RTC_SLOW,
81 ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED,
83 LOG_W(
TAG,
"boot diag: reset=%d esp_timer=%lld us RTC_SLOW=%lu Hz",
84 static_cast<int>(reset_reason), (
long long)rtc_us,
85 (
unsigned long)rtc_clk_hz);
87 loadTimezoneFromNvs();
93 localtime_r(&now, &timeinfo);
95 LOG_W(
TAG,
"boot RTC: %04d-%02d-%02d %02d:%02d (ts=%ld)",
96 timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
97 timeinfo.tm_hour, timeinfo.tm_min, (
long)now);
99 if (timeinfo.tm_year >= (2024 - 1900)) {
106 LOG_I(
TAG,
"RTC time not set - use NTP or SET_TIME command");
119 if (!timeinfo)
return;
122 localtime_r(&now, timeinfo);
132 if (!buf || bufLen < 6)
return;
135 strftime(buf, bufLen,
"%H:%M", &timeinfo);
145 if (!buf || bufLen < 11)
return;
148 strftime(buf, bufLen,
"%Y-%m-%d", &timeinfo);
163 if (timeinfo.tm_year < (2024 - 1900)) {
164 LOG_W(
TAG,
"Year invalid (%d), setting default date 2025-01-01",
165 timeinfo.tm_year + 1900);
166 timeinfo.tm_year = 2025 - 1900;
168 timeinfo.tm_mday = 1;
171 timeinfo.tm_hour = hour;
172 timeinfo.tm_min = minute;
173 timeinfo.tm_sec = second;
175 time_t t = mktime(&timeinfo);
176 struct timeval tv = { .tv_sec = t, .tv_usec = 0 };
177 settimeofday(&tv,
nullptr);
181 LOG_I(
TAG,
"Time set to %02d:%02d:%02d (date: %04d-%02d-%02d)",
182 hour, minute, second,
183 timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
197 timeinfo.tm_year = year - 1900;
198 timeinfo.tm_mon = month - 1;
199 timeinfo.tm_mday = day;
201 time_t t = mktime(&timeinfo);
202 struct timeval tv = { .tv_sec = t, .tv_usec = 0 };
203 settimeofday(&tv,
nullptr);
207 LOG_I(
TAG,
"Date set to %04d-%02d-%02d", year, month, day);
216 struct timeval tv = { .tv_sec = timestamp, .tv_usec = 0 };
217 settimeofday(&tv,
nullptr);
222 localtime_r(×tamp, &timeinfo);
223 LOG_I(
TAG,
"Timestamp set: %04d-%02d-%02d %02d:%02d:%02d",
224 timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
225 timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
244 if (hours < -12 || hours > 14) {
245 LOG_W(
TAG,
"Invalid timezone offset: %d", hours);
254 if (nvs_open(
NVS_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) {
260 LOG_I(
TAG,
"Timezone set to UTC%+d", hours);
267void Esp32Rtc::loadTimezoneFromNvs() {
271 if (nvs_get_i8(nvs,
NVS_KEY_TZ, &tz) == ESP_OK) {
282void Esp32Rtc::applyTimezone() {
286 if (tzOffset_ == 0) {
287 snprintf(tz,
sizeof(tz),
"UTC0");
289 snprintf(tz,
sizeof(tz),
"UTC%+d", -tzOffset_);
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
#define LOG_I(tag, fmt,...)
time_t getTimestamp() const override
Returns current UNIX timestamp.
bool isTimeSet() const override
const char * getName() const override
void getDateStr(char *buf, size_t bufLen) const override
Formats current date as YYYY-MM-DD.
int8_t getTimezoneOffset() const override
void setTime(int hour, int minute, int second) override
Sets RTC time while preserving current date.
bool init() override
Initializes RTC service and timezone context.
void setTimezoneOffset(int8_t hours) override
Sets timezone offset and persists it.
void setTimestamp(time_t timestamp) override
Sets RTC from UNIX timestamp.
void getTimeStr(char *buf, size_t bufLen) const override
Formats current time as HH:MM.
void getTime(struct tm *timeinfo) const override
Reads current local time into tm.
void setDate(int year, int month, int day) override
Sets RTC date while preserving current time.
void markTimeSet() override
core::ServiceState getState() const override
static constexpr const char * NVS_KEY_TS
static Esp32Rtc g_rtc
Singleton RTC implementation instance.
static constexpr const char * NVS_NAMESPACE
NVS namespace and keys for display settings.
IRtc * getRtcInstance()
Returns the singleton RTC service instance.
static constexpr const char * NVS_KEY_TZ