acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
NTP_Time.h (12549B)
1 //==================================================================================== 2 // Libraries 3 //==================================================================================== 4 5 // Time library: 6 // https://github.com/PaulStoffregen/Time 7 #include <Time.h> 8 9 // Time zone correction library: 10 // https://github.com/JChristensen/Timezone 11 #include <Timezone.h> 12 13 // Choose library to load 14 #ifdef ARDUINO_ARCH_ESP8266 15 // ESP8266 16 #include <ESP8266WiFi.h> 17 #elif (defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_RP2040)) && !defined(ARDUINO_RASPBERRY_PI_PICO_W) 18 // RP2040 Nano Connect 19 #include <WiFiNINA.h> 20 #else 21 // ESP32 22 #include <WiFi.h> 23 #endif 24 25 #include <WiFiUdp.h> 26 27 // A UDP instance to let us send and receive packets over UDP 28 WiFiUDP udp; 29 30 //==================================================================================== 31 // Settings 32 //==================================================================================== 33 34 #define TIMEZONE UK // See below for other "Zone references", UK, usMT etc 35 36 #ifdef ESP32 // Temporary fix, ESP8266 fails to communicate with some servers... 37 // Try to use pool url instead so the server IP address is looked up from those available 38 // (use a pool server in your own country to improve response time and reliability) 39 //const char* ntpServerName = "time.nist.gov"; 40 //const char* ntpServerName = "pool.ntp.org"; 41 const char* ntpServerName = "time.google.com"; 42 #else 43 // Try to use pool url instead so the server IP address is looked up from those available 44 // (use a pool server in your own country to improve response time and reliability) 45 // const char* ntpServerName = "time.nist.gov"; 46 const char* ntpServerName = "pool.ntp.org"; 47 //const char* ntpServerName = "time.google.com"; 48 #endif 49 50 // Try not to use hard-coded IP addresses which might change, you can if you want though... 51 //IPAddress timeServerIP(129, 6, 15, 30); // time-c.nist.gov NTP server 52 //IPAddress timeServerIP(24, 56, 178, 140); // wwv.nist.gov NTP server 53 IPAddress timeServerIP; // Use server pool 54 55 // Example time zone and DST rules, see Timezone library documents to see how 56 // to add more time zones https://github.com/JChristensen/Timezone 57 58 // Zone reference "UK" United Kingdom (London, Belfast) 59 TimeChangeRule BST = {"BST", Last, Sun, Mar, 1, 60}; //British Summer (Daylight saving) Time 60 TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 2, 0}; //Standard Time 61 Timezone UK(BST, GMT); 62 63 // Zone reference "euCET" Central European Time (Frankfurt, Paris) 64 TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; //Central European Summer Time 65 TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; //Central European Standard Time 66 Timezone euCET(CEST, CET); 67 68 // Zone reference "ausET" Australia Eastern Time Zone (Sydney, Melbourne) 69 TimeChangeRule aEDT = {"AEDT", First, Sun, Oct, 2, 660}; //UTC + 11 hours 70 TimeChangeRule aEST = {"AEST", First, Sun, Apr, 3, 600}; //UTC + 10 hours 71 Timezone ausET(aEDT, aEST); 72 73 // Zone reference "usET US Eastern Time Zone (New York, Detroit) 74 TimeChangeRule usEDT = {"EDT", Second, Sun, Mar, 2, -240}; //Eastern Daylight Time = UTC - 4 hours 75 TimeChangeRule usEST = {"EST", First, Sun, Nov, 2, -300}; //Eastern Standard Time = UTC - 5 hours 76 Timezone usET(usEDT, usEST); 77 78 // Zone reference "usCT" US Central Time Zone (Chicago, Houston) 79 TimeChangeRule usCDT = {"CDT", Second, dowSunday, Mar, 2, -300}; 80 TimeChangeRule usCST = {"CST", First, dowSunday, Nov, 2, -360}; 81 Timezone usCT(usCDT, usCST); 82 83 // Zone reference "usMT" US Mountain Time Zone (Denver, Salt Lake City) 84 TimeChangeRule usMDT = {"MDT", Second, dowSunday, Mar, 2, -360}; 85 TimeChangeRule usMST = {"MST", First, dowSunday, Nov, 2, -420}; 86 Timezone usMT(usMDT, usMST); 87 88 // Zone reference "usAZ" Arizona is US Mountain Time Zone but does not use DST 89 Timezone usAZ(usMST, usMST); 90 91 // Zone reference "usPT" US Pacific Time Zone (Las Vegas, Los Angeles) 92 TimeChangeRule usPDT = {"PDT", Second, dowSunday, Mar, 2, -420}; 93 TimeChangeRule usPST = {"PST", First, dowSunday, Nov, 2, -480}; 94 Timezone usPT(usPDT, usPST); 95 96 97 //==================================================================================== 98 // Variables 99 //==================================================================================== 100 TimeChangeRule *tz1_Code; // Pointer to the time change rule, use to get the TZ abbrev, e.g. "GMT" 101 102 time_t utc = 0; 103 104 bool timeValid = false; 105 106 unsigned int localPort = 2390; // local port to listen for UDP packets 107 108 const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message 109 110 byte packetBuffer[ NTP_PACKET_SIZE ]; //buffer to hold incoming and outgoing packets 111 112 uint8_t lastMinute = 0; 113 114 uint32_t nextSendTime = 0; 115 uint32_t newRecvTime = 0; 116 uint32_t lastRecvTime = 0; 117 118 uint32_t newTickTime = 0; 119 uint32_t lastTickTime = 0; 120 121 bool ntp_start = 1; 122 123 uint32_t no_packet_count = 0; 124 125 126 //==================================================================================== 127 // Function prototype 128 //==================================================================================== 129 130 void syncTime(void); 131 void displayTime(void); 132 void printTime(time_t zone, char *tzCode); 133 String timeString(); 134 void decodeNTP(void); 135 void sendNTPpacket(IPAddress& address); 136 137 //==================================================================================== 138 // Update Time 139 //==================================================================================== 140 void syncTime(void) 141 { 142 if (ntp_start) { // Run once 143 144 // Call once for ESP32 and ESP8266 145 #if !defined(ARDUINO_ARCH_MBED) 146 WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 147 #endif 148 149 while (WiFi.status() != WL_CONNECTED) { 150 Serial.print("."); 151 #if defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_RP2040) 152 if (WiFi.status() != WL_CONNECTED) WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 153 #endif 154 delay(500); 155 } 156 Serial.println(); 157 158 udp.begin(localPort); ntp_start = 0; 159 } 160 161 // Don't send too often so we don't trigger Denial of Service 162 if (nextSendTime < millis()) { 163 164 // Wait 1 hour for next sync 165 nextSendTime = millis() + 60 * 60 * 1000; 166 167 // Get a random server from the pool 168 WiFi.hostByName(ntpServerName, timeServerIP); 169 170 sendNTPpacket(timeServerIP); // send an NTP packet to a time server 171 decodeNTP(); 172 173 if ( no_packet_count > 0 ) { 174 // Wait 1 minute for next sync 175 nextSendTime = millis() + 60 * 1000; 176 } 177 else { 178 // Wait 1 hour for next sync 179 nextSendTime = millis() + 60 * 60 * 1000; 180 } 181 } 182 } 183 184 //==================================================================================== 185 // Send an NTP request to the time server at the given address 186 //==================================================================================== 187 void sendNTPpacket(IPAddress& address) 188 { 189 // Serial.println("sending NTP packet..."); 190 // set all bytes in the buffer to 0 191 memset(packetBuffer, 0, NTP_PACKET_SIZE); 192 // Initialize values needed to form NTP request 193 // (see URL above for details on the packets) 194 packetBuffer[0] = 0b11100011; // LI, Version, Mode 195 packetBuffer[1] = 0; // Stratum, or type of clock 196 packetBuffer[2] = 6; // Polling Interval 197 packetBuffer[3] = 0xEC; // Peer Clock Precision 198 199 // 8 bytes of zero for Root Delay & Root Dispersion 200 201 packetBuffer[12] = 49; 202 packetBuffer[13] = 0x4E; 203 packetBuffer[14] = 49; 204 packetBuffer[15] = 52; 205 206 // all NTP fields have been given values, now 207 // you can send a packet requesting a timestamp: 208 udp.beginPacket(address, 123); //NTP requests are to port 123 209 udp.write(packetBuffer, NTP_PACKET_SIZE); 210 udp.endPacket(); 211 } 212 213 //==================================================================================== 214 // Decode the NTP message and print status to serial port 215 //==================================================================================== 216 void decodeNTP(void) 217 { 218 timeValid = false; 219 uint32_t waitTime = millis() + 500; 220 while (millis() < waitTime && !timeValid) 221 { 222 yield(); 223 if (udp.parsePacket()) 224 { 225 newRecvTime = millis(); 226 227 // We've received a packet, read the data from it 228 udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer 229 230 Serial.print("\nNTP response time was : "); 231 Serial.print(500 - (waitTime - newRecvTime)); 232 Serial.println(" ms"); 233 234 Serial.print("Time since last sync is: "); 235 Serial.print((newRecvTime - lastRecvTime) / 1000.0); 236 Serial.println(" s"); 237 lastRecvTime = newRecvTime; 238 239 // The timestamp starts at byte 40 of the received packet and is four bytes, 240 // or two words, long. First, extract the two words: 241 unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 242 unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 243 244 // Combine the four bytes (two words) into a long integer 245 // this is NTP time (seconds since Jan 1 1900): 246 unsigned long secsSince1900 = highWord << 16 | lowWord; 247 248 // Now convert NTP Unix time (Seconds since Jan 1 1900) into everyday time: 249 // UTC time starts on Jan 1 1970. In seconds the difference is 2208988800: 250 utc = secsSince1900 - 2208988800UL; 251 252 setTime(utc); // Set system clock to utc time (not time zone compensated) 253 254 timeValid = true; 255 256 // Print the hour, minute and second: 257 Serial.print("Received NTP UTC time : "); 258 259 uint8_t hh = hour(utc); 260 Serial.print(hh); // print the hour (86400 equals secs per day) 261 262 Serial.print(':'); 263 uint8_t mm = minute(utc); 264 if (mm < 10 ) Serial.print('0'); 265 Serial.print(mm); // print the minute (3600 equals secs per minute) 266 267 Serial.print(':'); 268 uint8_t ss = second(utc); 269 if ( ss < 10 ) Serial.print('0'); 270 Serial.println(ss); // print the second 271 272 time_secs = hh * 3600 + mm * 60 + ss; // Update the clock time 273 } 274 } 275 276 // Keep a count of missing or bad NTP replies 277 278 if ( timeValid ) { 279 no_packet_count = 0; 280 } 281 else 282 { 283 Serial.println("\nNo NTP reply, trying again in 1 minute..."); 284 no_packet_count++; 285 } 286 287 if (no_packet_count >= 10) { 288 no_packet_count = 0; // Reset to one hour to try later 289 // TODO: Flag the lack of sync on the display 290 Serial.println("\nNo NTP packet in last 10 minutes"); 291 } 292 } 293 //==================================================================================== 294 // Time string: 00:00:00 295 //==================================================================================== 296 String timeString(uint32_t t_secs) 297 { 298 String timeNow = ""; 299 300 uint8_t h = t_secs / 3600; 301 if ( h < 10) timeNow += "0"; 302 timeNow += h; 303 304 timeNow += ":"; 305 uint8_t m = (t_secs - ( h * 3600 )) / 60; 306 if (m < 10) timeNow += "0"; 307 timeNow += m; 308 309 timeNow += ":"; 310 uint8_t s = t_secs - ( h * 3600 ) - ( m * 60 ); 311 if (s < 10) timeNow += "0"; 312 timeNow += s; 313 314 return timeNow; 315 } 316 //==================================================================================== 317 // Debug use only 318 //==================================================================================== 319 void printTime(time_t t, char *tzCode) 320 { 321 String dateString = dayStr(weekday(t)); 322 dateString += " "; 323 dateString += day(t); 324 if (day(t) == 1 || day(t) == 21 || day(t) == 31) dateString += "st"; 325 else if (day(t) == 2 || day(t) == 22) dateString += "nd"; 326 else if (day(t) == 3 || day(t) == 23) dateString += "rd"; 327 else dateString += "th"; 328 329 dateString += " "; 330 dateString += monthStr(month(t)); 331 dateString += " "; 332 dateString += year(t); 333 334 // Print time to serial port 335 Serial.print(hour(t)); 336 Serial.print(":"); 337 Serial.print(minute(t)); 338 Serial.print(":"); 339 Serial.print(second(t)); 340 Serial.print(" "); 341 // Print time t 342 Serial.print(tzCode); 343 Serial.print(" "); 344 345 // Print date 346 Serial.print(day(t)); 347 Serial.print("/"); 348 Serial.print(month(t)); 349 Serial.print("/"); 350 Serial.print(year(t)); 351 Serial.print(" "); 352 353 // Now test some other functions that might be useful one day! 354 Serial.print(dayStr(weekday(t))); 355 Serial.print(" "); 356 Serial.print(monthStr(month(t))); 357 Serial.print(" "); 358 Serial.print(dayShortStr(weekday(t))); 359 Serial.print(" "); 360 Serial.print(monthShortStr(month(t))); 361 Serial.println(); 362 } 363 364 //====================================================================================