forked from esp8266/Arduino
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathNTP-TZ-DST.ino
223 lines (176 loc) · 6.4 KB
/
NTP-TZ-DST.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
NTP-TZ-DST (v2)
NetWork Time Protocol - Time Zone - Daylight Saving Time
This example shows:
- how to read and set time
- how to set timezone per country/city
- how is local time automatically handled per official timezone definitions
This example code is in the public domain.
*/
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
// initial time (possibly given by an external RTC)
#define RTC_UTC_TEST 1510592825 // 1510592825 = Monday 13 November 2017 17:07:05 UTC
// This database is autogenerated from IANA timezone database
// https://www.iana.org/time-zones
// and can be updated on demand in this repository
#include <TZ.h>
// "TZ_" macros follow DST change across seasons without source code change
// check for your nearest city in TZ.h
// select espressif headquarter TZ
#define MYTZ TZ_Asia_Shanghai
// example for "Not Only Whole Hours" timezones:
// Kolkata/Calcutta is shifted by 30mn
//#define MYTZ TZ_Asia_Kolkata
// example to watch automatic local time time adjustment on Summer/Winter change
// (exactly 182 days (~6 month) are regularly added or substracted in the example)
//#define MYTZ TZ_Europe_Paris
////////////////////////////////////////////////////////
#include <ESP8266WiFi.h>
#include <coredecls.h> // settimeofday_cb()
#include <Schedule.h>
#include <PolledTimeout.h>
#include <time.h> // time() ctime()
#include <sys/time.h> // struct timeval
#if LWIP_VERSION_MAJOR == 1
#include <lwip/sntp.h> // sntp_servermode_dhcp()
#else
#include <lwip/apps/sntp.h> // sntp_servermode_dhcp()
#endif
// for testing purpose:
extern "C" int clock_gettime(clockid_t unused, struct timespec *tp);
////////////////////////////////////////////////////////
timeval tv;
timespec tp;
time_t now;
uint32_t now_ms, now_us;
bool time_is_set = false;
esp8266::polledTimeout::periodicMs showTime(3200);
bool next_change_is_future = true;
esp8266::polledTimeout::periodicMs add_6months_now(esp8266::polledTimeout::periodicMs::neverExpires);
unsigned long testcbms;
void time_is_set_scheduled() {
// everything is allowed in this function
Serial.printf("\n----------> scheduled CB: settimeofday() has been called %ldms ago <----------\n"
"sleeping 2s\n\n",
millis() - testcbms);
delay(2000);
}
void time_is_set_callback() {
// like in an ISR
// it is not allowed to call "heavy" core API
// like yield()/delay()/print()/network/...
time_is_set = true;
testcbms = millis();
// call time_is_set_scheduled() at next loop():
schedule_function(time_is_set_scheduled);
}
// OPTIONAL: change SNTP startup delay
// a weak function is already defined and returns 0 (RFC violation)
// it can be redefined:
//uint32_t sntp_startup_delay_MS_rfc_not_less_than_60000 ()
//{
// //::printf("(debug: sntp_startup_delay_MS_rfc_not_less_than_60000 is called)\n");a
// return 60000; // 60s (or lwIP's original default: (random() % 5000))
//}
// OPTIONAL: change SNTP update delay
// a weak function is already defined and returns 1 hour
// it can be redefined:
//uint32_t sntp_update_delay_MS_rfc_not_less_than_15000 ()
//{
// ::printf("(debug: sntp_update_delay_MS_rfc_not_less_than_15000 is called)\n");
// return 15000; // 15s
//}
void setup() {
Serial.begin(115200);
Serial.println("\nStarting...\n");
// setup RTC time
// it will be used until NTP server will send us real current time
time_t rtc = RTC_UTC_TEST;
timeval tv = { rtc, 0 };
timezone tz = { 0, 0 };
settimeofday(&tv, &tz);
// 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_callback);
// NTP servers may be overriden by your DHCP server for a more local one
// (see below)
configTime(MYTZ, "pool.ntp.org");
// OPTIONAL: disable obtaining SNTP servers from DHCP
//sntp_servermode_dhcp(0); // 0: disable obtaining SNTP servers from DHCP (enabled by default)
// 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
}
#define PTM(w) \
Serial.print(" " #w "="); \
Serial.print(tm->tm_##w);
void printTm(const char* what, const tm* tm) {
Serial.print(what);
PTM(isdst); PTM(yday); PTM(wday);
PTM(year); PTM(mon); PTM(mday);
PTM(hour); PTM(min); PTM(sec);
}
void loop() {
if (time_is_set) {
Serial.printf("\n----------> loop: settimeofday() has been called %ldms ago ! <----------\n\n", millis() - testcbms);
time_is_set = false;
add_6months_now.reset(20000);
}
if (showTime) {
gettimeofday(&tv, nullptr);
clock_gettime(0, &tp);
now = time(nullptr);
now_ms = millis();
now_us = micros();
// for demo purpose, switch 6 months back and forth
if (add_6months_now) {
tv.tv_sec += (next_change_is_future ? -1 : 1) * (60 * 60 * 24 * 364 / 2);
settimeofday(&tv, nullptr);
Serial.printf("\n"
"-- time machine: artificially moving 6 months %s\n"
"-- observe local time change according to selected TZ's DST rules\n"
"-- (and without assistance from sketch)\n"
"\n",
next_change_is_future ? "forward (future)" : "backward (to now)");
next_change_is_future = !next_change_is_future;
return;
}
printTm("localtime:", localtime(&now));
Serial.println();
printTm("gmtime: ", gmtime(&now));
Serial.println();
// time from boot
Serial.print("clock: ");
Serial.print((uint32_t)tp.tv_sec);
Serial.print("s / ");
Serial.print((uint32_t)tp.tv_nsec);
Serial.println("ns");
// time from boot
Serial.print("millis: ");
Serial.println(now_ms);
Serial.print("micros: ");
Serial.println(now_us);
// EPOCH+tz+dst
Serial.print("gtod: ");
Serial.print((uint32_t)tv.tv_sec);
Serial.print("s / ");
Serial.print((uint32_t)tv.tv_usec);
Serial.println("us");
// EPOCH+tz+dst
Serial.print("time: ");
Serial.println((uint32_t)now);
// timezone and demo in the future
Serial.printf("timezone: %s\n", MYTZ);
Serial.printf("in future: %s\n", next_change_is_future ? "no" : "6 months");
// human readable
Serial.print("ctime: ");
Serial.print(ctime(&now));
Serial.println();
}
}