-
Notifications
You must be signed in to change notification settings - Fork 335
Timezones, NTP, and time
The RTC in Watchy doesn't know anything about timezones. You can set it to your local time, like the default Watchy.cpp
does, but that doesn't handle daylight savings time well. To adjust for daylight savings time, that means something has to set the RTC to the new time when the time changes. Until you do, your Watchy will have the wrong time. This may not be a big issue for you, but if it is, read on.
The localtime
function knows how to convert UTC to your local time, using timezone rules to know when DST starts and ends. It uses the TZ
environment variable and the tzset()
function. This is explained in the Espressif documentation for timezones. To use this, you set the RTC to UTC, and convert UTC to your local time using localtime
or localtime_r
whenever you need it.
You will probably want to synchronize your Watchy with an accurate time source. The most common method is to use the Network Time Protocol - NTP. The ESP documentation for SNTP is oriented towards ESP-IDF users, and is not so Arduino friendly.
A simple synchronous method for setting your Watchy's time from NTP is:
#include <Wifi.h>
#include "time.h"
void timeSyncCallback(struct timeval *tv) {
RTC.set(tv->tv_sec); // set RTC
setTime(tv->tv_sec); // set system time (optional)
settimeofday(tv, nullptr); // set posix time (optional)
sntp_set_sync_status(SNTP_SYNC_STATUS_COMPLETED);
}
bool syncTime() {
if (!connectWiFi()) {
return false;
}
if (sntp_get_sync_status() != SNTP_SYNC_STATUS_RESET) {
// SNTP busy
return false;
}
sntp_set_time_sync_notification_cb(timeSyncCallback);
configTzTime("UTC0", ntpServer); // sets TZ to UTC0, don't use this in production
uint32_t timeout = millis() + 5000; // 5 sec timeout
bool retVal = false;
while (millis() < timeout) {
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) {
retVal = true;
break;
}
delay(10); // or yield
}
WiFi.mode(WIFI_OFF);
btStop();
return retVal;
}
When Watchy wakes up from deep sleep, the system clock is not set. If you never use now()
or time()
this is not a problem but if you want now()
and time()
to return correct results, you will need to set the system time. The easiest way is probably something like:
tmElements_t currentTime;
if (RTC.read(currentTime) == 0) {
time_t t = makeTime(currentTime);
setTime(t);
timeval tv = {t, 0};
settimeofday(&tv, nullptr);
}
in your Watchy init()
function.