Skip to content

Commit b31b66f

Browse files
committed
centralized repeated code, improvements on asyncUpdate
1 parent e370ab6 commit b31b66f

File tree

2 files changed

+84
-58
lines changed

2 files changed

+84
-58
lines changed

NTPClient.cpp

+72-54
Original file line numberDiff line numberDiff line change
@@ -81,95 +81,67 @@ void NTPClient::begin(unsigned int port) {
8181
this->_udpSetup = true;
8282
}
8383

84-
bool NTPClient::forceUpdate() {
84+
bool NTPClient::forceUpdate(unsigned long timeout) {
85+
this->sendNTPPacket();
86+
8587
#ifdef DEBUG_NTPClient
86-
Serial.println("Update from NTP Server");
88+
Serial.println("[NTPClient] Waiting for NTP Server response...");
8789
#endif
8890

89-
// flush any existing packets
90-
while(this->_udp->parsePacket() != 0)
91-
this->_udp->flush();
92-
93-
this->sendNTPPacket();
94-
9591
// Wait till data is there or timeout...
96-
byte timeout = 0;
97-
int cb = 0;
98-
do {
99-
delay ( 10 );
100-
cb = this->_udp->parsePacket();
101-
if (timeout > 100) return false; // timeout after 1000 ms
102-
timeout++;
103-
} while (cb == 0);
92+
if (this->receiveNTPPacket(timeout)) return true;
10493

105-
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
106-
107-
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
108-
109-
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
110-
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
111-
// combine the four bytes (two words) into a long integer
112-
// this is NTP time (seconds since Jan 1 1900):
113-
unsigned long secsSince1900 = highWord << 16 | lowWord;
94+
#ifdef DEBUG_NTPClient
95+
Serial.println("[NTPClient] Timeout");
96+
#endif
97+
return false; // timeout
98+
}
11499

115-
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
100+
bool NTPClient::needUpdate() {
101+
if (this->_sendTime == 0) return true; // Was never updated before.
102+
if (millis() - this->_sendTime >= this->_updateInterval) return true; // Previous update was more than configured interval ago.
116103

117-
return true; // return true after successful update
104+
return false;
118105
}
119106

120-
bool NTPClient::update() {
121-
if ((millis() - this->_lastUpdate >= this->_updateInterval) // Update after _updateInterval
122-
|| this->_lastUpdate == 0) { // Update if there was no update yet.
123-
if (!this->_udpSetup || this->_port != NTP_DEFAULT_LOCAL_PORT) this->begin(this->_port); // setup the UDP client if needed
124-
return this->forceUpdate();
107+
bool NTPClient::update(unsigned long timeout) {
108+
if (this->needUpdate()) {
109+
return this->forceUpdate(timeout);
125110
}
126111
return false; // return false if update does not occur
127112
}
128113

129114
int NTPClient::asyncUpdate() {
130-
if ((millis() - this->_sendTime >= this->_updateInterval) // Update after _updateInterval
131-
|| this->_sendTime == 0) { // Update if there was no update yet.
132-
_sendTime = millis();
133-
if (!this->_udpSetup || this->_port != NTP_DEFAULT_LOCAL_PORT) this->begin(this->_port); // setup the UDP client if needed
115+
if (this->needUpdate()) {
134116
this->sendNTPPacket();
135117

136-
int code = 2;
137-
if (_needUpdate) code = -1; // timeout
118+
if (_needUpdate) return -1; // return -1 if timeout
138119
_needUpdate = true;
139-
return code;
120+
return 2; // return 2 if update is in progress
140121
}
141122

142123
if (_needUpdate) {
143-
int cb = this->_udp->parsePacket();
144-
if (cb == 0) return 2;
145-
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
146-
147-
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
148-
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
149-
// combine the four bytes (two words) into a long integer
150-
// this is NTP time (seconds since Jan 1 1900):
151-
unsigned long secsSince1900 = highWord << 16 | lowWord;
152-
153-
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
154-
this->_lastUpdate = millis();
124+
if (!this->receiveNTPPacket()) return 2;
155125
_needUpdate = false;
156126
return 0;
157127
}
158128

159-
return 1; // return false if update does not occur
129+
return 1; // return 1 if update does not occur
160130
}
161131

162132
bool NTPClient::isTimeSet() const {
163133
return (this->_lastUpdate != 0); // returns true if the time has been set, else false
164134
}
165135

166136
long long NTPClient::getEpochTimeMillis() const {
167-
return this->_currentEpoc * 1000LL + millis() - this->_lastUpdate;
137+
return (this->_timeOffset + // User offset
138+
this->_currentEpoch) * 1000LL + // Epoch returned by the NTP server
139+
(millis() - this->_lastUpdate); // Time since last update
168140
}
169141

170142
unsigned long NTPClient::getEpochTime() const {
171143
return this->_timeOffset + // User offset
172-
this->_currentEpoc + // Epoch returned by the NTP server
144+
this->_currentEpoch + // Epoch returned by the NTP server
173145
((millis() - this->_lastUpdate) / 1000); // Time since last update
174146
}
175147

@@ -219,6 +191,13 @@ void NTPClient::setPoolServerName(const char* poolServerName) {
219191
}
220192

221193
void NTPClient::sendNTPPacket() {
194+
if (this->_udpSetup) {
195+
// flush any existing packets
196+
while(this->_udp->parsePacket() != 0)
197+
this->_udp->flush();
198+
}
199+
200+
if (!this->_udpSetup) this->begin(this->_port); // setup the UDP client if needed
222201
// set all bytes in the buffer to 0
223202
memset(this->_packetBuffer, 0, NTP_PACKET_SIZE);
224203
// Initialize values needed to form NTP request
@@ -241,6 +220,45 @@ void NTPClient::sendNTPPacket() {
241220
}
242221
this->_udp->write(this->_packetBuffer, NTP_PACKET_SIZE);
243222
this->_udp->endPacket();
223+
this->_sendTime = millis();
224+
225+
#ifdef DEBUG_NTPClient
226+
Serial.println("[NTPClient] Sent UDP packet");
227+
#endif
228+
}
229+
230+
bool NTPClient::receiveNTPPacket(unsigned long timeout) {
231+
int packetSize = this->_udp->parsePacket();
232+
233+
if (packetSize < NTP_PACKET_SIZE) {
234+
if (timeout == 0) return false;
235+
236+
unsigned long start = millis();
237+
while (millis() - start < timeout) {
238+
delay(1);
239+
packetSize = this->_udp->parsePacket();
240+
if (packetSize >= NTP_PACKET_SIZE) break;
241+
}
242+
}
243+
244+
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
245+
246+
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
247+
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
248+
// combine the four bytes (two words) into a long integer
249+
// this is NTP time (seconds since Jan 1 1900):
250+
unsigned long secsSince1900 = highWord << 16 | lowWord;
251+
252+
this->_currentEpoch = secsSince1900 - SEVENTY_YEARS;
253+
int latency = (millis() - this->_sendTime);
254+
this->_lastUpdate = millis() - (latency / 2); // Account for latency in reading the time
255+
256+
#ifdef DEBUG_NTPClient
257+
Serial.print("[NTPClient] Received UDP packet latency: ");
258+
Serial.println(latency);
259+
#endif
260+
261+
return true;
244262
}
245263

246264
void NTPClient::setRandomPort(unsigned int minValue, unsigned int maxValue) {

NTPClient.h

+12-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#include <Udp.h>
66

7-
#define SEVENZYYEARS 2208988800UL
7+
#define SEVENTY_YEARS 2208988800UL
88
#define NTP_PACKET_SIZE 48
99
#define NTP_DEFAULT_LOCAL_PORT 1337
1010

@@ -22,12 +22,13 @@ class NTPClient {
2222

2323
bool _needUpdate = true;
2424
unsigned long _sendTime = 0;
25-
unsigned long _currentEpoc = 0; // In s
25+
unsigned long _currentEpoch = 0; // In s
2626
unsigned long _lastUpdate = 0; // In ms
2727

2828
byte _packetBuffer[NTP_PACKET_SIZE];
2929

3030
void sendNTPPacket();
31+
bool receiveNTPPacket(unsigned long timeout = 0);
3132

3233
public:
3334
NTPClient(UDP& udp);
@@ -61,20 +62,27 @@ class NTPClient {
6162
*/
6263
void begin(unsigned int port);
6364

65+
/**
66+
* Returns true if an first time or if the last update was more than configured interval ago.
67+
*
68+
* @return true on need, false on "not now"
69+
*/
70+
bool needUpdate();
71+
6472
/**
6573
* This should be called in the main loop of your application. By default an update from the NTP Server is only
6674
* made every 60 seconds. This can be configured in the NTPClient constructor.
6775
*
6876
* @return true on success, false on failure
6977
*/
70-
bool update();
78+
bool update(unsigned long timeout = 1000);
7179

7280
/**
7381
* This will force the update from the NTP Server.
7482
*
7583
* @return true on success, false on failure
7684
*/
77-
bool forceUpdate();
85+
bool forceUpdate(unsigned long timeout = 1000);
7886

7987
/**
8088
* Alternatevly this can be called instead of update() in the main loop of your application.

0 commit comments

Comments
 (0)