diff --git a/NTP.cpp b/NTP.cpp index eb9dbfc..e0d873e 100755 --- a/NTP.cpp +++ b/NTP.cpp @@ -32,18 +32,25 @@ NTP::~NTP() { void NTP::begin(const char* server) { this->server = server; - udp->begin(NTP_PORT); - ntpUpdate(); - if (dstZone) { - timezoneOffset = dstEnd.tzOffset * SECS_PER_MINUTES; - dstOffset = (dstStart.tzOffset - dstEnd.tzOffset) * SECS_PER_MINUTES; - currentTime(); - beginDST(); - } + init(); } void NTP::begin(IPAddress serverIP) { this->serverIP = serverIP; + init(); + } + +void NTP::init() { + memset(ntpRequest, 0, NTP_PACKET_SIZE); + ntpRequest[0] = 0b11100011; // LI, Version, Mode + ntpRequest[1] = 0; // Stratum, or type of clock + ntpRequest[2] = 6; // Polling Interval + ntpRequest[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + ntpRequest[12] = 49; + ntpRequest[13] = 0x4E; + ntpRequest[14] = 49; + ntpRequest[15] = 52; udp->begin(NTP_PORT); ntpUpdate(); if (dstZone) { @@ -66,7 +73,6 @@ bool NTP::update() { } bool NTP::ntpUpdate() { - udp->flush(); if (server == nullptr) udp->beginPacket(serverIP, NTP_PORT); else udp->beginPacket(server, NTP_PORT); udp->write(ntpRequest, NTP_PACKET_SIZE); @@ -81,8 +87,23 @@ bool NTP::ntpUpdate() { } while (size != 48); lastUpdate = millis() - (10 * (timeout + 1)); udp->read(ntpQuery, NTP_PACKET_SIZE); - uint32_t ntpTime = ntpQuery[40] << 24 | ntpQuery[41] << 16 | ntpQuery[42] << 8 | ntpQuery[43]; - utcTime = ntpTime - SEVENTYYEARS; + #ifdef __AVR__ + unsigned long highWord = word(ntpQuery[40], ntpQuery[41]); + unsigned long lowWord = word(ntpQuery[42], ntpQuery[43]); + timestamp = highWord << 16 | lowWord; + if (timestamp != 0) { + ntpTime = timestamp; + utcTime = ntpTime - NTP_OFFSET; + } + else return false; + #else + timestamp = ntpQuery[40] << 24 | ntpQuery[41] << 16 | ntpQuery[42] << 8 | ntpQuery[43]; + if (timestamp != 0) { + ntpTime = timestamp; + utcTime = ntpTime - SEVENTYYEARS; + } + else return false; + #endif return true; } @@ -156,7 +177,7 @@ time_t NTP::epoch() { } void NTP::currentTime() { - utcCurrent = diffTime + utcTime + ((millis() - lastUpdate) / 1000); + utcCurrent = utcTime + ((millis() - lastUpdate) / 1000); if (dstZone) { if (summerTime()) { local = utcCurrent + dstOffset + timezoneOffset; @@ -256,4 +277,12 @@ bool NTP::summerTime() { else { return false; } - } \ No newline at end of file + } + +uint32_t NTP::ntp() { + return ntpTime; + } + +uint32_t NTP::utc() { + return utcTime; + } diff --git a/NTP.h b/NTP.h index 902c71d..e889e87 100755 --- a/NTP.h +++ b/NTP.h @@ -28,6 +28,15 @@ #include #define SEVENTYYEARS 2208988800UL +#define UNIXOFFSET 946684800UL + +#ifdef __AVR__ + //#define POSIX_OFFSET NTP_OFFSET - SEVENTYYEARS// - UNIX_OFFSET// + 30 years + #define POSIX_OFFSET UNIXOFFSET +#else + #define POSIX_OFFSET -SEVENTYYEARS +#endif + #define NTP_PACKET_SIZE 48 #define NTP_PORT 123 #define SECS_PER_MINUTES 60 @@ -222,11 +231,25 @@ class NTP { */ const char* formattedTime(const char *format); + /** + * @brief returns NTP timestamp + * + * @return uint32_t + */ + uint32_t ntp(); + + /** + * @brief returns UNIX timestamp + * + * @return uint32_t + */ + uint32_t utc(); + private: UDP *udp; const char* server = nullptr; IPAddress serverIP; - const uint8_t ntpRequest[NTP_PACKET_SIZE] = {0xE3, 0x00, 0x06, 0xEC}; + uint8_t ntpRequest[NTP_PACKET_SIZE]; // = {0xE3, 0x00, 0x06, 0xEC}; uint8_t ntpQuery[NTP_PACKET_SIZE]; time_t utcCurrent = 0; time_t local = 0; @@ -238,8 +261,9 @@ class NTP { int32_t timezoneOffset; int16_t dstOffset = 0; bool dstZone = true; - uint32_t utcTime = 0; - int32_t diffTime; + uint32_t timestamp; + uint32_t ntpTime = 0; + uint32_t utcTime = 0; time_t utcSTD, utcDST; time_t dstTime, stdTime; uint16_t yearDST; @@ -252,13 +276,13 @@ class NTP { int8_t hour; // 0 - 23 int tzOffset; // offset from UTC in minutes } dstStart, dstEnd; + void init(); bool ntpUpdate(); - uint32_t localTime(); + time_t localTime(); void currentTime(); void beginDST(); time_t calcDateDST(struct ruleDST rule, int year); bool summerTime(); - }; #endif diff --git a/README.md b/README.md index 19edb3a..39b056a 100755 --- a/README.md +++ b/README.md @@ -3,7 +3,10 @@ The **NTP** library allows you to receive time information from the Internet. It different timezones and daylight saving time (DST). This NTP library uses the functions of the time.h standard library.
-The library doesn't work with AVR boards like UNO WiFi Rev2 because it seems there is a bug in "time.h" of the AVR C library. +## Changes for 1.7 + +- support for AVR +- optimizations ## Changes for 1.6 @@ -92,7 +95,7 @@ void stop(); ``` Stop the underlaying UDP client -Example +Example, this must done in ```setup()``` ```cpp ntp.stop(); ``` @@ -307,6 +310,21 @@ Format symbols: | p | writes localized a.m. or p.m. (locale dependent) ``` +## Return utc() + + ```cpp + uint32_t utc(); + ``` + + Return the timestamp received from the ntp server in Unix timestamp format + + ## Return ntp() + + ```cpp + uint32_t ntp(); + ``` + + Return the timestamp received from the ntp server in the NTP timestamp format diff --git a/keywords.txt b/keywords.txt index cd50cdb..8350645 100755 --- a/keywords.txt +++ b/keywords.txt @@ -26,3 +26,5 @@ hours KEYWORD2 minutes KEYWORD2 seconds KEYWORD2 formattedTime KEYWORD2 +utc KEYWORD2 +ntp KEYWORD2 diff --git a/library.json b/library.json index 882c81a..2dbe9dc 100755 --- a/library.json +++ b/library.json @@ -1,13 +1,13 @@ { "name": "NTP", "keywords": "ntp, client, time, timezone", - "description": "a NTP client with timezone support", + "description": "A NTP client with timezone support", "repository": { "type": "git", "url": "https://github.com/sstaub/NTP.git" }, - "version": "1.6", + "version": "1.7", "frameworks": "arduino", "platforms": "*" } diff --git a/library.properties b/library.properties index 2c44dfe..4f3cda3 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=NTP -version=1.6 +version=1.7 author=Stefan Staub maintainer=Stefan Staub sentence=NTP library