mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
settimeofday_cb: distinguish from user or sntp (#7637)
* settimeofday_cb: distinguish from user or sntp
This commit is contained in:
parent
ace5e98bf6
commit
95fb104562
@ -28,9 +28,10 @@ uint32_t crc32 (const void* data, size_t length, uint32_t crc = 0xffffffff);
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
using BoolCB = std::function<void(bool)>;
|
||||||
using TrivialCB = std::function<void()>;
|
using TrivialCB = std::function<void()>;
|
||||||
|
|
||||||
void settimeofday_cb (TrivialCB&& cb);
|
void settimeofday_cb (const BoolCB& cb);
|
||||||
void settimeofday_cb (const TrivialCB& cb);
|
void settimeofday_cb (const TrivialCB& cb);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -204,14 +204,14 @@ void configTime(const char* tz, const char* server1, const char* server2, const
|
|||||||
sntp_init();
|
sntp_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
static TrivialCB _settimeofday_cb;
|
static BoolCB _settimeofday_cb;
|
||||||
|
|
||||||
void settimeofday_cb (TrivialCB&& cb)
|
|
||||||
{
|
|
||||||
_settimeofday_cb = std::move(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
void settimeofday_cb (const TrivialCB& cb)
|
void settimeofday_cb (const TrivialCB& cb)
|
||||||
|
{
|
||||||
|
_settimeofday_cb = [cb](bool sntp) { (void)sntp; cb(); };
|
||||||
|
}
|
||||||
|
|
||||||
|
void settimeofday_cb (const BoolCB& cb)
|
||||||
{
|
{
|
||||||
_settimeofday_cb = cb;
|
_settimeofday_cb = cb;
|
||||||
}
|
}
|
||||||
@ -222,6 +222,20 @@ extern "C" {
|
|||||||
|
|
||||||
int settimeofday(const struct timeval* tv, const struct timezone* tz)
|
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)
|
if (tz || !tv)
|
||||||
// tz is obsolete (cf. man settimeofday)
|
// tz is obsolete (cf. man settimeofday)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -230,7 +244,7 @@ int settimeofday(const struct timeval* tv, const struct timezone* tz)
|
|||||||
tune_timeshift64(tv->tv_sec * 1000000ULL + tv->tv_usec);
|
tune_timeshift64(tv->tv_sec * 1000000ULL + tv->tv_usec);
|
||||||
|
|
||||||
if (_settimeofday_cb)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,9 @@ static time_t now;
|
|||||||
static uint32_t now_ms, now_us;
|
static uint32_t now_ms, now_us;
|
||||||
|
|
||||||
static esp8266::polledTimeout::periodicMs showTimeNow(60000);
|
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_running = false;
|
||||||
|
static bool time_machine_run_once = false;
|
||||||
|
|
||||||
// OPTIONAL: change SNTP startup delay
|
// OPTIONAL: change SNTP startup delay
|
||||||
// a weak function is already defined and returns 0 (RFC violation)
|
// a weak function is already defined and returns 0 (RFC violation)
|
||||||
@ -112,7 +113,7 @@ void showTime() {
|
|||||||
// time from boot
|
// time from boot
|
||||||
Serial.print("clock: ");
|
Serial.print("clock: ");
|
||||||
Serial.print((uint32_t)tp.tv_sec);
|
Serial.print((uint32_t)tp.tv_sec);
|
||||||
Serial.print("s / ");
|
Serial.print("s + ");
|
||||||
Serial.print((uint32_t)tp.tv_nsec);
|
Serial.print((uint32_t)tp.tv_nsec);
|
||||||
Serial.println("ns");
|
Serial.println("ns");
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ void showTime() {
|
|||||||
// EPOCH+tz+dst
|
// EPOCH+tz+dst
|
||||||
Serial.print("gtod: ");
|
Serial.print("gtod: ");
|
||||||
Serial.print((uint32_t)tv.tv_sec);
|
Serial.print((uint32_t)tv.tv_sec);
|
||||||
Serial.print("s / ");
|
Serial.print("s + ");
|
||||||
Serial.print((uint32_t)tv.tv_usec);
|
Serial.print((uint32_t)tv.tv_usec);
|
||||||
Serial.println("us");
|
Serial.println("us");
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ void showTime() {
|
|||||||
Serial.print("ctime: ");
|
Serial.print("ctime: ");
|
||||||
Serial.print(ctime(&now));
|
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++) {
|
for (int i = 0; i < SNTP_MAX_SERVERS; i++) {
|
||||||
IPAddress sntp = *sntp_getserver(i);
|
IPAddress sntp = *sntp_getserver(i);
|
||||||
const char* name = sntp_getservername(i);
|
const char* name = sntp_getservername(i);
|
||||||
@ -151,7 +152,7 @@ void showTime() {
|
|||||||
} else {
|
} else {
|
||||||
Serial.printf("%s ", sntp.toString().c_str());
|
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.isV6() ? "Yes" : "No",
|
||||||
sntp_getreachability(i));
|
sntp_getreachability(i));
|
||||||
}
|
}
|
||||||
@ -159,40 +160,59 @@ void showTime() {
|
|||||||
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
// subsecond synchronisation
|
// show subsecond synchronisation
|
||||||
|
timeval prevtv;
|
||||||
|
time_t prevtime = time(nullptr);
|
||||||
|
gettimeofday(&prevtv, nullptr);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
time_t sec = tv.tv_sec;
|
if (tv.tv_sec != prevtv.tv_sec) {
|
||||||
do {
|
Serial.printf("time(): %u gettimeofday(): %u.%06u seconds are unchanged\n",
|
||||||
gettimeofday(&tv, nullptr);
|
(uint32_t)prevtime,
|
||||||
Serial.printf("time(): %u gettimeofday(): %u.%06u",
|
(uint32_t)prevtv.tv_sec, (uint32_t)prevtv.tv_usec);
|
||||||
(uint32_t)time(nullptr),
|
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);
|
(uint32_t)tv.tv_sec, (uint32_t)tv.tv_usec);
|
||||||
if (tv.tv_sec == sec) {
|
break;
|
||||||
Serial.println(" second unchanged");
|
|
||||||
} else {
|
|
||||||
Serial.println(" <-- second changed");
|
|
||||||
}
|
}
|
||||||
|
prevtv = tv;
|
||||||
delay(50);
|
delay(50);
|
||||||
} while (tv.tv_sec == sec);
|
}
|
||||||
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void time_is_set_scheduled() {
|
void time_is_set(bool from_sntp /* <= this parameter is optional */) {
|
||||||
// everything is allowed in this function
|
// in CONT stack, unlike ISRs,
|
||||||
|
// any function is allowed in this callback
|
||||||
|
|
||||||
if (time_machine_days == 0) {
|
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
|
// time machine demo
|
||||||
if (time_machine_running) {
|
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);
|
now = time(nullptr);
|
||||||
const tm* tm = localtime(&now);
|
const tm* tm = localtime(&now);
|
||||||
Serial.printf("future=%3ddays: DST=%s - ",
|
Serial.printf(": future=%3ddays: DST=%s - ",
|
||||||
time_machine_days,
|
time_machine_days,
|
||||||
tm->tm_isdst ? "true " : "false");
|
tm->tm_isdst ? "true " : "false");
|
||||||
Serial.print(ctime(&now));
|
Serial.print(ctime(&now));
|
||||||
@ -207,49 +227,55 @@ void time_is_set_scheduled() {
|
|||||||
}
|
}
|
||||||
settimeofday(&tv, nullptr);
|
settimeofday(&tv, nullptr);
|
||||||
} else {
|
} else {
|
||||||
showTime();
|
Serial.println();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
WiFi.persistent(false);
|
||||||
|
WiFi.mode(WIFI_OFF);
|
||||||
|
|
||||||
Serial.begin(115200);
|
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
|
// setup RTC time
|
||||||
// it will be used until NTP server will send us real current 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;
|
time_t rtc = RTC_UTC_TEST;
|
||||||
timeval tv = { rtc, 0 };
|
timeval tv = { rtc, 0 };
|
||||||
settimeofday(&tv, nullptr);
|
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
|
// NTP servers may be overriden by your DHCP server for a more local one
|
||||||
// (see below)
|
// (see below)
|
||||||
|
|
||||||
// ----> Here is the ONLY ONE LINE needed in your sketch
|
// ----> Here is the ONLY ONE LINE needed in your sketch
|
||||||
|
|
||||||
configTime(MYTZ, "pool.ntp.org");
|
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 <----
|
// Former configTime is still valid, here is the call for 7 hours to the west
|
||||||
// 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
|
|
||||||
// with an enabled 30mn DST
|
// with an enabled 30mn DST
|
||||||
//configTime(7 * 3600, 3600 / 2, "pool.ntp.org");
|
//configTime(7 * 3600, 3600 / 2, "pool.ntp.org");
|
||||||
|
|
||||||
// OPTIONAL: disable obtaining SNTP servers from DHCP
|
// OPTIONAL: disable obtaining SNTP servers from DHCP
|
||||||
//sntp_servermode_dhcp(0); // 0: disable obtaining SNTP servers from DHCP (enabled by default)
|
//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
|
// start network
|
||||||
WiFi.persistent(false);
|
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
WiFi.begin(STASSID, STAPSK);
|
WiFi.begin(STASSID, STAPSK);
|
||||||
|
|
||||||
// don't wait for network, observe time changing
|
// don't wait for network, observe time changing
|
||||||
// when NTP timestamp is received
|
// when NTP timestamp is received
|
||||||
Serial.printf("Time is currently set by a constant:\n");
|
|
||||||
showTime();
|
showTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit f56e795ee8a770a8b9ccfb868f8e806c10505e70
|
Subproject commit 8dfe4663f290caea702aab97483b0d2b034930fe
|
@ -1,5 +1,5 @@
|
|||||||
// generated by makefiles/make-lwip2-hash
|
// generated by makefiles/make-lwip2-hash
|
||||||
#ifndef LWIP_HASH_H
|
#ifndef LWIP_HASH_H
|
||||||
#define 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
|
#endif // LWIP_HASH_H
|
||||||
|
@ -3574,7 +3574,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define SNTP_SERVER_DNS 1 // enable SNTP support DNS names through sntp_setservername / sntp_getservername
|
#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_SUPPRESS_DELAY_CHECK 1
|
||||||
#define SNTP_UPDATE_DELAY_DEFAULT 3600000 // update delay defined by a default weak function
|
#define SNTP_UPDATE_DELAY_DEFAULT 3600000 // update delay defined by a default weak function
|
||||||
|
Loading…
x
Reference in New Issue
Block a user