diff --git a/Time.cpp b/Time.cpp index 8e53e56..d3e7bcf 100644 --- a/Time.cpp +++ b/Time.cpp @@ -1,101 +1,101 @@ /* - time.c - low level time and date functions - Copyright (c) Michael Margolis 2009-2014 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - 1.0 6 Jan 2010 - initial release - 1.1 12 Feb 2010 - fixed leap year calculation error - 1.2 1 Nov 2010 - fixed setTime bug (thanks to Korman for this) - 1.3 24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update - status, updated examples for Arduino 1.0, fixed ARM - compatibility issues, added TimeArduinoDue and TimeTeensy3 - examples, add error checking and messages to RTC examples, - add examples to DS1307RTC library. - 1.4 5 Sep 2014 - compatibility with Arduino 1.5.7 -*/ + time.c - low level time and date functions + Copyright (c) Michael Margolis 2009-2014 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + 1.0 6 Jan 2010 - initial release + 1.1 12 Feb 2010 - fixed leap year calculation error + 1.2 1 Nov 2010 - fixed setTime bug (thanks to Korman for this) + 1.3 24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update + status, updated examples for Arduino 1.0, fixed ARM + compatibility issues, added TimeArduinoDue and TimeTeensy3 + examples, add error checking and messages to RTC examples, + add examples to DS1307RTC library. + 1.4 5 Sep 2014 - compatibility with Arduino 1.5.7 + */ #if ARDUINO >= 100 -#include +#include #else -#include +#include #endif #include "TimeLib.h" static tmElements_t tm; // a cache of time elements static time_t cacheTime; // the time the cache was updated -static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds +static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds void refreshCache(time_t t) { if (t != cacheTime) { - breakTime(t, tm); - cacheTime = t; + breakTime(t, tm); + cacheTime = t; } } -int hour() { // the hour now - return hour(now()); +int hour() { // the hour now + return hour(now()); } int hour(time_t t) { // the hour for the given time refreshCache(t); - return tm.Hour; + return tm.Hour; } int hourFormat12() { // the hour now in 12 hour format - return hourFormat12(now()); + return hourFormat12(now()); } int hourFormat12(time_t t) { // the hour for the given time in 12 hour format refreshCache(t); - if( tm.Hour == 0 ) + if (tm.Hour == 0) return 12; // 12 midnight - else if( tm.Hour > 12) - return tm.Hour - 12 ; + else if (tm.Hour > 12) + return tm.Hour - 12; else - return tm.Hour ; + return tm.Hour; } uint8_t isAM() { // returns true if time now is AM - return !isPM(now()); + return !isPM(now()); } uint8_t isAM(time_t t) { // returns true if given time is AM - return !isPM(t); + return !isPM(t); } uint8_t isPM() { // returns true if PM - return isPM(now()); + return isPM(now()); } uint8_t isPM(time_t t) { // returns true if PM - return (hour(t) >= 12); + return (hour(t) >= 12); } int minute() { - return minute(now()); + return minute(now()); } int minute(time_t t) { // the minute for the given time refreshCache(t); - return tm.Minute; + return tm.Minute; } int second() { - return second(now()); + return second(now()); } int second(time_t t) { // the second for the given time @@ -103,8 +103,8 @@ int second(time_t t) { // the second for the given time return tm.Second; } -int day(){ - return(day(now())); +int day() { + return (day(now())); } int day(time_t t) { // the day for the given time (0-6) @@ -113,16 +113,16 @@ int day(time_t t) { // the day for the given time (0-6) } int weekday() { // Sunday is day 1 - return weekday(now()); + return weekday(now()); } int weekday(time_t t) { refreshCache(t); return tm.Wday; } - -int month(){ - return month(now()); + +int month() { + return month(now()); } int month(time_t t) { // the month for the given time @@ -130,8 +130,8 @@ int month(time_t t) { // the month for the given time return tm.Month; } -int year() { // as in Processing, the full four digit year: (2009, 2010 etc) - return year(now()); +int year() { // as in Processing, the full four digit year: (2009, 2010 etc) + return year(now()); } int year(time_t t) { // the year for the given time @@ -139,16 +139,17 @@ int year(time_t t) { // the year for the given time return tmYearToCalendar(tm.Year); } -/*============================================================================*/ +/*============================================================================*/ /* functions to convert to and from system time */ /* These are for interfacing with time serivces and are not normally needed in a sketch */ // leap year calulator expects year argument as years offset from 1970 #define LEAP_YEAR(Y) ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) ) -static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0 - -void breakTime(time_t timeInput, tmElements_t &tm){ +static const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, + 31 }; // API starts months from 1, this array starts from 0 + +void breakTime(time_t timeInput, tmElements_t &tm) { // break the given time_t into time components // this is a more compact version of the C library localtime function // note that year is offset from 1970 !!! @@ -158,103 +159,103 @@ void breakTime(time_t timeInput, tmElements_t &tm){ uint32_t time; unsigned long days; - time = (uint32_t)timeInput; + time = (uint32_t) timeInput; tm.Second = time % 60; time /= 60; // now it is minutes tm.Minute = time % 60; time /= 60; // now it is hours tm.Hour = time % 24; time /= 24; // now it is days - tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1 - - year = 0; + tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1 + + year = 0; days = 0; - while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { + while ((unsigned) (days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { year++; } - tm.Year = year; // year is offset from 1970 - + tm.Year = year; // year is offset from 1970 + days -= LEAP_YEAR(year) ? 366 : 365; - time -= days; // now it is days in this year, starting at 0 - - days=0; - month=0; - monthLength=0; - for (month=0; month<12; month++) { - if (month==1) { // february + time -= days; // now it is days in this year, starting at 0 + + days = 0; + month = 0; + monthLength = 0; + for (month = 0; month < 12; month++) { + if (month == 1) { // february if (LEAP_YEAR(year)) { - monthLength=29; + monthLength = 29; } else { - monthLength=28; + monthLength = 28; } } else { monthLength = monthDays[month]; } - + if (time >= monthLength) { time -= monthLength; } else { - break; + break; } } - tm.Month = month + 1; // jan is month 1 + tm.Month = month + 1; // jan is month 1 tm.Day = time + 1; // day of month } -time_t makeTime(const tmElements_t &tm){ -// assemble time elements into time_t +time_t makeTime(const tmElements_t &tm) { +// assemble time elements into time_t // note year argument is offset from 1970 (see macros in time.h to convert to other formats) // previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9 - + int i; uint32_t seconds; // seconds from 1970 till 1 jan 00:00:00 of the given year - seconds= tm.Year*(SECS_PER_DAY * 365); + seconds = tm.Year * (SECS_PER_DAY * 365); for (i = 0; i < tm.Year; i++) { if (LEAP_YEAR(i)) { - seconds += SECS_PER_DAY; // add extra days for leap years + seconds += SECS_PER_DAY; // add extra days for leap years } } - + // add days for this year, months start from 1 for (i = 1; i < tm.Month; i++) { - if ( (i == 2) && LEAP_YEAR(tm.Year)) { + if ((i == 2) && LEAP_YEAR(tm.Year)) { seconds += SECS_PER_DAY * 29; } else { - seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0 + seconds += SECS_PER_DAY * monthDays[i - 1]; //monthDay array starts from 0 } } - seconds+= (tm.Day-1) * SECS_PER_DAY; - seconds+= tm.Hour * SECS_PER_HOUR; - seconds+= tm.Minute * SECS_PER_MIN; - seconds+= tm.Second; - return (time_t)seconds; + seconds += (tm.Day - 1) * SECS_PER_DAY; + seconds += tm.Hour * SECS_PER_HOUR; + seconds += tm.Minute * SECS_PER_MIN; + seconds += tm.Second; + return (time_t) seconds; } -/*=====================================================*/ +/*=====================================================*/ /* Low level system time functions */ static uint32_t sysTime = 0; static uint32_t prevMillis = 0; static uint32_t nextSyncTime = 0; static timeStatus_t Status = timeNotSet; +static bool immediateRetry = false; getExternalTime getTimePtr; // pointer to external sync function //setExternalTime setTimePtr; // not used in this version #ifdef TIME_DRIFT_INFO // define this to get drift data -time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync +time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync #endif - time_t now() { - // calculate number of seconds passed since last call to now() + // calculate number of seconds passed since last call to now() while (millis() - prevMillis >= 1000) { - // millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference + // millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference sysTime++; - prevMillis += 1000; + prevMillis += 1000; #ifdef TIME_DRIFT_INFO - sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift + sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift #endif } if (nextSyncTime <= sysTime) { @@ -263,33 +264,35 @@ time_t now() { if (t != 0) { setTime(t); } else { - nextSyncTime = sysTime + syncInterval; - Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync; + if (!immediateRetry) { + nextSyncTime = sysTime + syncInterval; + } + Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync; } } - } - return (time_t)sysTime; + } + return (time_t) sysTime; } -void setTime(time_t t) { +void setTime(time_t t) { #ifdef TIME_DRIFT_INFO - if(sysUnsyncedTime == 0) - sysUnsyncedTime = t; // store the time of the first call to set a valid Time + if(sysUnsyncedTime == 0) + sysUnsyncedTime = t; // store the time of the first call to set a valid Time #endif - sysTime = (uint32_t)t; - nextSyncTime = (uint32_t)t + syncInterval; + sysTime = (uint32_t) t; + nextSyncTime = (uint32_t) t + syncInterval; Status = timeSet; - prevMillis = millis(); // restart counting from now (thanks to Korman for this fix) -} - -void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ - // year can be given as full four digit year or two digts (2010 or 10 for 2010); - //it is converted to years since 1970 - if( yr > 99) - yr = yr - 1970; + prevMillis = millis(); // restart counting from now (thanks to Korman for this fix) +} + +void setTime(int hr, int min, int sec, int dy, int mnth, int yr) { + // year can be given as full four digit year or two digts (2010 or 10 for 2010); + //it is converted to years since 1970 + if (yr > 99) + yr = yr - 1970; else - yr += 30; + yr += 30; tm.Year = yr; tm.Month = mnth; tm.Day = dy; @@ -309,13 +312,21 @@ timeStatus_t timeStatus() { return Status; } -void setSyncProvider( getExternalTime getTimeFunction){ - getTimePtr = getTimeFunction; +void setSyncProvider(getExternalTime getTimeFunction, bool immedRetry, +bool wait) { + getTimePtr = getTimeFunction; nextSyncTime = sysTime; - now(); // this will sync the clock + immediateRetry = immedRetry; + while (Status != timeSet) { + now(); // this will sync the clock + if (!wait) { + break; + } + delay(1); + } } -void setSyncInterval(time_t interval){ // set the number of seconds between re-sync - syncInterval = (uint32_t)interval; +void setSyncInterval(time_t interval) { // set the number of seconds between re-sync + syncInterval = (uint32_t) interval; nextSyncTime = sysTime + syncInterval; } diff --git a/TimeLib.h b/TimeLib.h index 20e2445..d5915d9 100644 --- a/TimeLib.h +++ b/TimeLib.h @@ -5,7 +5,7 @@ /* July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this) - fixed daysToTime_t macro (thanks maniacbug) -*/ +*/ #ifndef _Time_h #ifdef __cplusplus @@ -40,23 +40,23 @@ typedef enum { typedef enum { tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields -} tmByteFields; +} tmByteFields; -typedef struct { - uint8_t Second; - uint8_t Minute; - uint8_t Hour; +typedef struct { + uint8_t Second; + uint8_t Minute; + uint8_t Hour; uint8_t Wday; // day of week, sunday is day 1 uint8_t Day; - uint8_t Month; - uint8_t Year; // offset from 1970; + uint8_t Month; + uint8_t Year; // offset from 1970; } tmElements_t, TimeElements, *tmElementsPtr_t; -//convenience macros to convert to and from tm years -#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year +//convenience macros to convert to and from tm years +#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year #define CalendarYrToTm(Y) ((Y) - 1970) #define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000 -#define y2kYearToTm(Y) ((Y) + 30) +#define y2kYearToTm(Y) ((Y) + 30) typedef time_t(*getExternalTime)(); //typedef void (*setExternalTime)(const time_t); // not used in this version @@ -71,32 +71,32 @@ typedef time_t(*getExternalTime)(); #define SECS_PER_WEEK ((time_t)(SECS_PER_DAY * DAYS_PER_WEEK)) #define SECS_PER_YEAR ((time_t)(SECS_PER_DAY * 365UL)) // TODO: ought to handle leap years #define SECS_YR_2000 ((time_t)(946684800UL)) // the time at the start of y2k - + /* Useful Macros for getting elapsed time */ -#define numberOfSeconds(_time_) ((_time_) % SECS_PER_MIN) -#define numberOfMinutes(_time_) (((_time_) / SECS_PER_MIN) % SECS_PER_MIN) +#define numberOfSeconds(_time_) ((_time_) % SECS_PER_MIN) +#define numberOfMinutes(_time_) (((_time_) / SECS_PER_MIN) % SECS_PER_MIN) #define numberOfHours(_time_) (((_time_) % SECS_PER_DAY) / SECS_PER_HOUR) #define dayOfWeek(_time_) ((((_time_) / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday #define elapsedDays(_time_) ((_time_) / SECS_PER_DAY) // this is number of days since Jan 1 1970 -#define elapsedSecsToday(_time_) ((_time_) % SECS_PER_DAY) // the number of seconds since last midnight +#define elapsedSecsToday(_time_) ((_time_) % SECS_PER_DAY) // the number of seconds since last midnight // The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971 // Always set the correct time before settting alarms #define previousMidnight(_time_) (((_time_) / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day -#define nextMidnight(_time_) (previousMidnight(_time_) + SECS_PER_DAY) // time at the end of the given day +#define nextMidnight(_time_) (previousMidnight(_time_) + SECS_PER_DAY) // time at the end of the given day #define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY)) // note that week starts on day 1 #define previousSunday(_time_) ((_time_) - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time #define nextSunday(_time_) (previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time /* Useful Macros for converting elapsed time to a time_t */ -#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN) -#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR) +#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN) +#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR) #define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011 -#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK) +#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK) /*============================================================================*/ /* time and date functions */ -int hour(); // the hour now +int hour(); // the hour now int hour(time_t t); // the hour for the given time int hourFormat12(); // the hour now in 12 hour format int hourFormat12(time_t t); // the hour for the given time in 12 hour format @@ -104,34 +104,35 @@ uint8_t isAM(); // returns true if time now is AM uint8_t isAM(time_t t); // returns true the given time is AM uint8_t isPM(); // returns true if time now is PM uint8_t isPM(time_t t); // returns true the given time is PM -int minute(); // the minute now +int minute(); // the minute now int minute(time_t t); // the minute for the given time -int second(); // the second now +int second(); // the second now int second(time_t t); // the second for the given time -int day(); // the day now +int day(); // the day now int day(time_t t); // the day for the given time -int weekday(); // the weekday now (Sunday is day 1) -int weekday(time_t t); // the weekday for the given time +int weekday(); // the weekday now (Sunday is day 1) +int weekday(time_t t); // the weekday for the given time int month(); // the month now (Jan is month 1) int month(time_t t); // the month for the given time -int year(); // the full four digit year: (2009, 2010 etc) +int year(); // the full four digit year: (2009, 2010 etc) int year(time_t t); // the year for the given time -time_t now(); // return the current time as seconds since Jan 1 1970 +time_t now(); // return the current time as seconds since Jan 1 1970 void setTime(time_t t); void setTime(int hr,int min,int sec,int day, int month, int yr); void adjustTime(long adjustment); -/* date strings */ +/* date strings */ #define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null) char* monthStr(uint8_t month); char* dayStr(uint8_t day); char* monthShortStr(uint8_t month); char* dayShortStr(uint8_t day); - + /* time sync functions */ timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized -void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider +void setSyncProvider(getExternalTime getTimeFunction, bool immedRetry = false, + bool wait = false); // identify the external time provider void setSyncInterval(time_t interval); // set the number of seconds between re-sync /* low level functions to convert to and from system time */ diff --git a/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino b/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino index 1aeb2d7..ed837fd 100644 --- a/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino +++ b/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino @@ -1,16 +1,17 @@ -/* - * TimeNTP_ESP8266WiFi.ino - * Example showing time sync to NTP time source - * - * This sketch uses the ESP8266WiFi library - */ - -#include +#include "Arduino.h" +#include "TimeLib.h" #include #include -const char ssid[] = "*************"; // your network SSID (name) -const char pass[] = "********"; // your network password +/* + TimeNTP_ESP8266WiFi.ino + Example showing time sync to NTP time source + + This sketch uses the ESP8266WiFi library + */ + +//const char ssid[] = "*************"; // your network SSID (name) +//const char pass[] = "********"; // your network password // NTP Servers: static const char ntpServerName[] = "us.pool.ntp.org"; @@ -25,7 +26,6 @@ const int timeZone = 1; // Central European Time //const int timeZone = -8; // Pacific Standard Time (USA) //const int timeZone = -7; // Pacific Daylight Time (USA) - WiFiUDP Udp; unsigned int localPort = 8888; // local port to listen for UDP packets @@ -34,66 +34,63 @@ void digitalClockDisplay(); void printDigits(int digits); void sendNTPpacket(IPAddress &address); -void setup() -{ - Serial.begin(9600); - while (!Serial) ; // Needed for Leonardo only - delay(250); - Serial.println("TimeNTP Example"); - Serial.print("Connecting to "); - Serial.println(ssid); - WiFi.begin(ssid, pass); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - - Serial.print("IP number assigned by DHCP is "); - Serial.println(WiFi.localIP()); - Serial.println("Starting UDP"); - Udp.begin(localPort); - Serial.print("Local port: "); - Serial.println(Udp.localPort()); - Serial.println("waiting for sync"); - setSyncProvider(getNtpTime); - setSyncInterval(300); +void setup() { + Serial.begin(115200); + while (!Serial) + ; // Needed for Leonardo only + delay(250); + Serial.println("TimeNTP Example"); + Serial.print("Connecting to "); + Serial.println(ssid); + WiFi.begin(ssid, pass); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.print("IP number assigned by DHCP is "); + Serial.println(WiFi.localIP()); + Serial.println("Starting UDP"); + Udp.begin(localPort); + Serial.print("Local port: "); + Serial.println(Udp.localPort()); + Serial.println("waiting for sync"); + setSyncProvider(getNtpTime, true, true); + setSyncInterval(300); } time_t prevDisplay = 0; // when the digital clock was displayed -void loop() -{ - if (timeStatus() != timeNotSet) { - if (now() != prevDisplay) { //update the display only if time has changed - prevDisplay = now(); - digitalClockDisplay(); - } - } +void loop() { + if (timeStatus() != timeNotSet) { + if (now() != prevDisplay) { //update the display only if time has changed + prevDisplay = now(); + digitalClockDisplay(); + } + } } -void digitalClockDisplay() -{ - // digital clock display of the time - Serial.print(hour()); - printDigits(minute()); - printDigits(second()); - Serial.print(" "); - Serial.print(day()); - Serial.print("."); - Serial.print(month()); - Serial.print("."); - Serial.print(year()); - Serial.println(); +void digitalClockDisplay() { + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print("."); + Serial.print(month()); + Serial.print("."); + Serial.print(year()); + Serial.println(); } -void printDigits(int digits) -{ - // utility for digital clock display: prints preceding colon and leading 0 - Serial.print(":"); - if (digits < 10) - Serial.print('0'); - Serial.print(digits); +void printDigits(int digits) { + // utility for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if (digits < 10) + Serial.print('0'); + Serial.print(digits); } /*-------- NTP code ----------*/ @@ -101,56 +98,68 @@ void printDigits(int digits) const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets -time_t getNtpTime() -{ - IPAddress ntpServerIP; // NTP server's ip address - - while (Udp.parsePacket() > 0) ; // discard any previously received packets - Serial.println("Transmit NTP Request"); - // get a random server from the pool - WiFi.hostByName(ntpServerName, ntpServerIP); - Serial.print(ntpServerName); - Serial.print(": "); - Serial.println(ntpServerIP); - sendNTPpacket(ntpServerIP); - uint32_t beginWait = millis(); - while (millis() - beginWait < 1500) { - int size = Udp.parsePacket(); - if (size >= NTP_PACKET_SIZE) { - Serial.println("Receive NTP Response"); - Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer - unsigned long secsSince1900; - // convert four bytes starting at location 40 to a long integer - secsSince1900 = (unsigned long)packetBuffer[40] << 24; - secsSince1900 |= (unsigned long)packetBuffer[41] << 16; - secsSince1900 |= (unsigned long)packetBuffer[42] << 8; - secsSince1900 |= (unsigned long)packetBuffer[43]; - return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; - } - } - Serial.println("No NTP Response :-("); - return 0; // return 0 if unable to get the time +time_t getNtpTime() { + IPAddress ntpServerIP; // NTP server's ip address + static bool waitingResponse = false; + static uint32_t packetSendTime; + const uint32_t maxWaitTime = 1500; + + if (!waitingResponse) { + while (Udp.parsePacket() > 0) + ; // discard any previously received packets + Serial.println("Transmit NTP Request"); + // get a random server from the pool + WiFi.hostByName(ntpServerName, ntpServerIP); + Serial.print(ntpServerName); + Serial.print(": "); + Serial.println(ntpServerIP); + sendNTPpacket(ntpServerIP); + waitingResponse = true; + packetSendTime = millis(); + return 0; + } + + int size = Udp.parsePacket(); + if (size >= NTP_PACKET_SIZE) { + Serial.print("Receive NTP Response, Delay = "); + Serial.print(millis() - packetSendTime); + Serial.println(" ms"); + Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer + unsigned long secsSince1900; + // convert four bytes starting at location 40 to a long integer + secsSince1900 = (unsigned long) packetBuffer[40] << 24; + secsSince1900 |= (unsigned long) packetBuffer[41] << 16; + secsSince1900 |= (unsigned long) packetBuffer[42] << 8; + secsSince1900 |= (unsigned long) packetBuffer[43]; + waitingResponse = false; + return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; + } + + if (millis() - packetSendTime >= maxWaitTime) { + waitingResponse = false; + Serial.println("NTP Request Timed Out"); + } + return 0; } // send an NTP request to the time server at the given address -void sendNTPpacket(IPAddress &address) -{ - // set all bytes in the buffer to 0 - memset(packetBuffer, 0, NTP_PACKET_SIZE); - // Initialize values needed to form NTP request - // (see URL above for details on the packets) - packetBuffer[0] = 0b11100011; // LI, Version, Mode - packetBuffer[1] = 0; // Stratum, or type of clock - packetBuffer[2] = 6; // Polling Interval - packetBuffer[3] = 0xEC; // Peer Clock Precision - // 8 bytes of zero for Root Delay & Root Dispersion - packetBuffer[12] = 49; - packetBuffer[13] = 0x4E; - packetBuffer[14] = 49; - packetBuffer[15] = 52; - // all NTP fields have been given values, now - // you can send a packet requesting a timestamp: - Udp.beginPacket(address, 123); //NTP requests are to port 123 - Udp.write(packetBuffer, NTP_PACKET_SIZE); - Udp.endPacket(); -} +void sendNTPpacket(IPAddress &address) { + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + Udp.beginPacket(address, 123); //NTP requests are to port 123 + Udp.write(packetBuffer, NTP_PACKET_SIZE); + Udp.endPacket(); +}