Files
Crosspoint/lib/hal/HalClock.cpp
T

113 lines
3.3 KiB
C++

#include "HalClock.h"
#include <Logging.h>
#include <WiFi.h>
#include <esp_sntp.h>
#include <time.h>
HalClock halClock; // Singleton instance
void HalClock::begin() {
_available = _sdkRtc.begin();
LOG_INF("CLK", _available ? "SDK RTC found" : "RTC not found");
}
bool HalClock::getTime(uint8_t& hour, uint8_t& minute) const {
if (!_available) return false;
const unsigned long now = millis();
if (_lastPollMs != 0 && (now - _lastPollMs) < CLOCK_POLL_MS) {
hour = _cachedHour;
minute = _cachedMinute;
return true;
}
Rtc::DateTime dt;
if (!_sdkRtc.now(dt)) {
if (!_hasCachedTime) return false;
_lastPollMs = now;
hour = _cachedHour;
minute = _cachedMinute;
return true;
}
_cachedHour = dt.hour;
_cachedMinute = dt.minute;
_lastPollMs = now;
_hasCachedTime = true;
hour = _cachedHour;
minute = _cachedMinute;
return true;
}
bool HalClock::formatTime(char* buf, size_t bufSize, uint8_t utcOffsetQuarterHoursBiased, bool use12Hour) const {
if (bufSize < (use12Hour ? 9u : 6u)) return false;
uint8_t h, m;
if (!getTime(h, m)) return false;
// Apply UTC offset: convert biased value to signed quarter-hours.
// Clamp against corrupted persisted values so display time can't drift outside [-12:00, +14:00].
if (utcOffsetQuarterHoursBiased > 104) utcOffsetQuarterHoursBiased = 104;
int offsetQuarterHours = static_cast<int>(utcOffsetQuarterHoursBiased) - 48;
int totalMinutes = static_cast<int>(h) * 60 + static_cast<int>(m) + offsetQuarterHours * 15;
// Wrap around 24 hours
totalMinutes = ((totalMinutes % 1440) + 1440) % 1440;
const int hour24 = totalMinutes / 60;
const int min = totalMinutes % 60;
if (use12Hour) {
const bool pm = hour24 >= 12;
int hour12 = hour24 % 12;
if (hour12 == 0) hour12 = 12;
snprintf(buf, bufSize, "%d:%02d %s", hour12, min, pm ? "PM" : "AM");
} else {
snprintf(buf, bufSize, "%02d:%02d", hour24, min);
}
return true;
}
bool HalClock::syncFromNTP() {
if (!_available) return false;
if (WiFi.status() != WL_CONNECTED) {
LOG_ERR("CLK", "WiFi not connected, cannot sync NTP");
return false;
}
LOG_INF("CLK", "Starting NTP sync...");
configTzTime("UTC0", "pool.ntp.org", "time.nist.gov");
// Wait for SNTP sync to complete (up to 5 seconds)
constexpr int maxAttempts = 50;
for (int i = 0; i < maxAttempts; i++) {
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) {
time_t now = time(nullptr);
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Rtc::DateTime dt;
dt.year = static_cast<uint16_t>(timeinfo.tm_year + 1900);
dt.month = static_cast<uint8_t>(timeinfo.tm_mon + 1);
dt.day = static_cast<uint8_t>(timeinfo.tm_mday);
dt.hour = static_cast<uint8_t>(timeinfo.tm_hour);
dt.minute = static_cast<uint8_t>(timeinfo.tm_min);
dt.second = static_cast<uint8_t>(timeinfo.tm_sec);
dt.weekday = static_cast<uint8_t>(timeinfo.tm_wday);
if (_sdkRtc.set(dt)) {
_lastPollMs = 0;
_cachedHour = dt.hour;
_cachedMinute = dt.minute;
_hasCachedTime = true;
LOG_INF("CLK", "RTC set to %04u-%02u-%02u %02u:%02u:%02u UTC", dt.year, dt.month, dt.day, dt.hour, dt.minute,
dt.second);
return true;
}
return false;
}
delay(100);
}
LOG_ERR("CLK", "NTP sync timed out");
return false;
}