Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

settimeofday_cb: distinguish from user or sntp #7637

Merged
merged 5 commits into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cores/esp8266/coredecls.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ uint32_t crc32 (const void* data, size_t length, uint32_t crc = 0xffffffff);

#include <functional>

using BoolCB = std::function<void(bool)>;
using TrivialCB = std::function<void()>;

void settimeofday_cb (TrivialCB&& cb);
void settimeofday_cb (const BoolCB& cb);
void settimeofday_cb (const TrivialCB& cb);

#endif
Expand Down
24 changes: 19 additions & 5 deletions cores/esp8266/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,14 @@ void configTime(const char* tz, const char* server1, const char* server2, const
sntp_init();
}

static TrivialCB _settimeofday_cb;
static BoolCB _settimeofday_cb;

void settimeofday_cb (TrivialCB&& cb)
void settimeofday_cb (const TrivialCB& cb)
{
_settimeofday_cb = std::move(cb);
_settimeofday_cb = [cb](bool sntp) { (void)sntp; cb(); };
}

void settimeofday_cb (const TrivialCB& cb)
void settimeofday_cb (const BoolCB& cb)
{
_settimeofday_cb = cb;
}
Expand All @@ -222,6 +222,20 @@ extern "C" {

int settimeofday(const struct timeval* tv, const struct timezone* tz)
{
bool from_sntp;
if (tz == (struct timezone*)0xFeedC0de)
{
// This special constant is used by lwip2/SNTP calling
// settimeofday(sntp-time, 0xfeedc0de), secretly using the
// obsolete-but-yet-still-there `tz` field.
// It allows to avoid duplicating this function and inform user
// about the source time change.
tz = nullptr;
from_sntp = true;
}
else
from_sntp = false;

if (tz || !tv)
// tz is obsolete (cf. man settimeofday)
return EINVAL;
Expand All @@ -230,7 +244,7 @@ int settimeofday(const struct timeval* tv, const struct timezone* tz)
tune_timeshift64(tv->tv_sec * 1000000ULL + tv->tv_usec);

if (_settimeofday_cb)
schedule_recurrent_function_us([](){ _settimeofday_cb(); return false; }, 0);
schedule_recurrent_function_us([from_sntp](){ _settimeofday_cb(from_sntp); return false; }, 0);

return 0;
}
Expand Down
100 changes: 63 additions & 37 deletions libraries/esp8266/examples/NTP-TZ-DST/NTP-TZ-DST.ino
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ static time_t now;
static uint32_t now_ms, now_us;

static esp8266::polledTimeout::periodicMs showTimeNow(60000);
static int time_machine_days = 0; // 0 = now
static int time_machine_days = 0; // 0 = present
static bool time_machine_running = false;
static bool time_machine_run_once = false;

// OPTIONAL: change SNTP startup delay
// a weak function is already defined and returns 0 (RFC violation)
Expand Down Expand Up @@ -112,7 +113,7 @@ void showTime() {
// time from boot
Serial.print("clock: ");
Serial.print((uint32_t)tp.tv_sec);
Serial.print("s / ");
Serial.print("s + ");
Serial.print((uint32_t)tp.tv_nsec);
Serial.println("ns");

Expand All @@ -125,7 +126,7 @@ void showTime() {
// EPOCH+tz+dst
Serial.print("gtod: ");
Serial.print((uint32_t)tv.tv_sec);
Serial.print("s / ");
Serial.print("s + ");
Serial.print((uint32_t)tv.tv_usec);
Serial.println("us");

Expand All @@ -140,7 +141,7 @@ void showTime() {
Serial.print("ctime: ");
Serial.print(ctime(&now));

// LwIP v2 is able to list more details about the currently configured SNTP servers
// lwIP v2 is able to list more details about the currently configured SNTP servers
for (int i = 0; i < SNTP_MAX_SERVERS; i++) {
IPAddress sntp = *sntp_getserver(i);
const char* name = sntp_getservername(i);
Expand All @@ -151,48 +152,67 @@ void showTime() {
} else {
Serial.printf("%s ", sntp.toString().c_str());
}
Serial.printf("IPv6: %s Reachability: %o\n",
Serial.printf("- IPv6: %s - Reachability: %o\n",
sntp.isV6() ? "Yes" : "No",
sntp_getreachability(i));
}
}

Serial.println();

// subsecond synchronisation
gettimeofday(&tv, nullptr);
time_t sec = tv.tv_sec;
do {
// show subsecond synchronisation
timeval prevtv;
time_t prevtime = time(nullptr);
gettimeofday(&prevtv, nullptr);

while (true) {
gettimeofday(&tv, nullptr);
Serial.printf("time(): %u gettimeofday(): %u.%06u",
(uint32_t)time(nullptr),
(uint32_t)tv.tv_sec, (uint32_t)tv.tv_usec);
if (tv.tv_sec == sec) {
Serial.println(" second unchanged");
} else {
Serial.println(" <-- second changed");
if (tv.tv_sec != prevtv.tv_sec) {
Serial.printf("time(): %u gettimeofday(): %u.%06u seconds are unchanged\n",
(uint32_t)prevtime,
(uint32_t)prevtv.tv_sec, (uint32_t)prevtv.tv_usec);
Serial.printf("time(): %u gettimeofday(): %u.%06u <-- seconds have changed\n",
(uint32_t)(prevtime = time(nullptr)),
(uint32_t)tv.tv_sec, (uint32_t)tv.tv_usec);
break;
}
prevtv = tv;
delay(50);
} while (tv.tv_sec == sec);
}

Serial.println();
}

void time_is_set_scheduled() {
// everything is allowed in this function
void time_is_set(bool from_sntp /* <= this parameter is optional */) {
// in CONT stack, unlike ISRs,
// any function is allowed in this callback

if (time_machine_days == 0) {
time_machine_running = !time_machine_running;
if (time_machine_running) {
time_machine_run_once = true;
time_machine_running = false;
} else {
time_machine_running = from_sntp && !time_machine_run_once;
}
if (time_machine_running) {
Serial.printf("\n-- \n-- Starting time machine demo to show libc's "
"automatic DST handling\n-- \n");
}
}

Serial.print("settimeofday(");
if (from_sntp) {
Serial.print("SNTP");
} else {
Serial.print("USER");
}
Serial.print(")");

// time machine demo
if (time_machine_running) {
if (time_machine_days == 0)
Serial.printf("---- settimeofday() has been called - possibly from SNTP\n"
" (starting time machine demo to show libc's automatic DST handling)\n\n");
now = time(nullptr);
const tm* tm = localtime(&now);
Serial.printf("future=%3ddays: DST=%s - ",
Serial.printf(": future=%3ddays: DST=%s - ",
time_machine_days,
tm->tm_isdst ? "true " : "false");
Serial.print(ctime(&now));
Expand All @@ -207,49 +227,55 @@ void time_is_set_scheduled() {
}
settimeofday(&tv, nullptr);
} else {
showTime();
Serial.println();
}
}

void setup() {
WiFi.persistent(false);
WiFi.mode(WIFI_OFF);

Serial.begin(115200);
Serial.println("\nStarting...\n");
Serial.println("\nStarting in 2secs...\n");
delay(2000);

// install callback - called when settimeofday is called (by SNTP or user)
// once enabled (by DHCP), SNTP is updated every hour by default
// ** optional boolean in callback function is true when triggerred by SNTP **
settimeofday_cb(time_is_set);

// setup RTC time
// it will be used until NTP server will send us real current time
Serial.println("Manually setting some time from some RTC:");
time_t rtc = RTC_UTC_TEST;
timeval tv = { rtc, 0 };
settimeofday(&tv, nullptr);

// install callback - called when settimeofday is called (by SNTP or us)
// once enabled (by DHCP), SNTP is updated every hour
settimeofday_cb(time_is_set_scheduled);

// NTP servers may be overriden by your DHCP server for a more local one
// (see below)

// ----> Here is the ONLY ONE LINE needed in your sketch

configTime(MYTZ, "pool.ntp.org");
// <----
// Replace MYTZ by a value from TZ.h (search for this file in your filesystem).

// Here is the ONLY ONE LINE needed in your sketch <----
// pick a value from TZ.h (search for this file in your filesystem) for MYTZ

// former configTime is still valid, here is the call for 7 hours to the west
// Former configTime is still valid, here is the call for 7 hours to the west
// with an enabled 30mn DST
//configTime(7 * 3600, 3600 / 2, "pool.ntp.org");

// OPTIONAL: disable obtaining SNTP servers from DHCP
//sntp_servermode_dhcp(0); // 0: disable obtaining SNTP servers from DHCP (enabled by default)

// Give now a chance to the settimeofday callback,
// because it is *always* deferred to the next yield()/loop()-call.
yield();

// start network
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(STASSID, STAPSK);

// don't wait for network, observe time changing
// when NTP timestamp is received
Serial.printf("Time is currently set by a constant:\n");
showTime();
}

Expand Down
Binary file modified tools/sdk/lib/liblwip2-1460-feat.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip2-1460.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip2-536-feat.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip2-536.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip6-1460-feat.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip6-536-feat.a
Binary file not shown.
2 changes: 1 addition & 1 deletion tools/sdk/lwip2/builder
2 changes: 1 addition & 1 deletion tools/sdk/lwip2/include/lwip-git-hash.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// generated by makefiles/make-lwip2-hash
#ifndef LWIP_HASH_H
#define LWIP_HASH_H
#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.2-34-gf56e795"
#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.2-43-ge20f213"
#endif // LWIP_HASH_H
2 changes: 1 addition & 1 deletion tools/sdk/lwip2/include/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -3574,7 +3574,7 @@ extern "C" {

#define SNTP_SERVER_DNS 1 // enable SNTP support DNS names through sntp_setservername / sntp_getservername

#define SNTP_SET_SYSTEM_TIME_US(t,us) do { struct timeval tv = { t, us }; settimeofday(&tv, NULL); } while (0)
#define SNTP_SET_SYSTEM_TIME_US(t,us) do { struct timeval tv = { t, us }; settimeofday(&tv, (struct timezone*)0xFeedC0de); } while (0)

#define SNTP_SUPPRESS_DELAY_CHECK 1
#define SNTP_UPDATE_DELAY_DEFAULT 3600000 // update delay defined by a default weak function
Expand Down