Skip to content

Commit 25797f1

Browse files
committed
Initial commit
0 parents  commit 25797f1

File tree

7 files changed

+341
-0
lines changed

7 files changed

+341
-0
lines changed

NTPClient.cpp

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* The MIT License (MIT)
3+
* Copyright (c) 2015 by Fabrice Weinberg
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
* SOFTWARE.
20+
*/
21+
22+
#include "NTPClient.h"
23+
24+
NTPClient::NTPClient(int timeOffset) {
25+
this->_timeOffset = timeOffset;
26+
}
27+
28+
NTPClient::NTPClient(const char* poolServerName) {
29+
this->_poolServerName = poolServerName;
30+
}
31+
32+
NTPClient::NTPClient(const char* poolServerName, int timeOffset) {
33+
this->_timeOffset = timeOffset;
34+
this->_poolServerName = poolServerName;
35+
}
36+
37+
NTPClient::NTPClient(const char* poolServerName, int timeOffset, int updateInterval) {
38+
this->_timeOffset = timeOffset;
39+
this->_poolServerName = poolServerName;
40+
this->_updateInterval = updateInterval;
41+
}
42+
43+
void NTPClient::begin() {
44+
#ifdef DEBUG_NTPClient
45+
Serial.println("Begin NTPClient");
46+
Serial.print("Start udp connection on port: ");
47+
Serial.println(this->_port);
48+
#endif
49+
this->_udp.begin(this->_port);
50+
this->forceUpdate();
51+
}
52+
53+
void NTPClient::forceUpdate() {
54+
#ifdef DEBUG_NTPClient
55+
Serial.println("Update from NTP Server");
56+
#endif
57+
58+
IPAddress address;
59+
WiFi.hostByName(this->_poolServerName, address);
60+
61+
this->sendNTPPacket(address);
62+
63+
// Wait till data is there or timeout...
64+
byte timeout = 0;
65+
int cb = 0;
66+
do {
67+
delay ( 10 );
68+
cb = this->_udp.parsePacket();
69+
if (timeout > 100) return; // timeout after 1000 ms
70+
timeout++;
71+
} while (cb == 0);
72+
73+
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
74+
75+
this->_udp.read(this->_packetBuffer, NTP_PACKET_SIZE);
76+
77+
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
78+
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
79+
// combine the four bytes (two words) into a long integer
80+
// this is NTP time (seconds since Jan 1 1900):
81+
unsigned long secsSince1900 = highWord << 16 | lowWord;
82+
83+
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
84+
}
85+
86+
void NTPClient::update() {
87+
unsigned long runtime = millis();
88+
if (runtime - this->_lastUpdate >= this->_updateInterval && this->_updateInterval != 0) {
89+
this->forceUpdate();
90+
}
91+
}
92+
93+
unsigned long NTPClient::getRawTime() {
94+
return this->_timeOffset + // User offset
95+
this->_currentEpoc + // Epoc returned by the NTP server
96+
((millis() - this->_lastUpdate) / 1000); // Time since last update
97+
}
98+
99+
String NTPClient::getHours() {
100+
return String((this->getRawTime() % 86400L) / 3600);
101+
}
102+
String NTPClient::getMinutes() {
103+
return String((this->getRawTime() % 3600) / 60);
104+
}
105+
106+
String NTPClient::getSeconds() {
107+
return String(this->getRawTime() % 60);
108+
}
109+
110+
String NTPClient::getFormattedTime() {
111+
unsigned long rawTime = this->getRawTime();
112+
unsigned long hours = (rawTime % 86400L) / 3600;
113+
String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);
114+
115+
unsigned long minutes = (rawTime % 3600) / 60;
116+
String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);
117+
118+
unsigned long seconds = rawTime % 60;
119+
String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);
120+
121+
return hoursStr + ":" + minuteStr + ":" + secondStr;
122+
}
123+
124+
void NTPClient::sendNTPPacket(IPAddress ip) {
125+
// set all bytes in the buffer to 0
126+
memset(this->_packetBuffer, 0, NTP_PACKET_SIZE);
127+
// Initialize values needed to form NTP request
128+
// (see URL above for details on the packets)
129+
this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode
130+
this->_packetBuffer[1] = 0; // Stratum, or type of clock
131+
this->_packetBuffer[2] = 6; // Polling Interval
132+
this->_packetBuffer[3] = 0xEC; // Peer Clock Precision
133+
// 8 bytes of zero for Root Delay & Root Dispersion
134+
this->_packetBuffer[12] = 49;
135+
this->_packetBuffer[13] = 0x4E;
136+
this->_packetBuffer[14] = 49;
137+
this->_packetBuffer[15] = 52;
138+
139+
// all NTP fields have been given values, now
140+
// you can send a packet requesting a timestamp:
141+
this->_udp.beginPacket(ip, 123); //NTP requests are to port 123
142+
this->_udp.write(this->_packetBuffer, NTP_PACKET_SIZE);
143+
this->_udp.endPacket();
144+
}
145+

NTPClient.h

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#pragma once
2+
3+
#include "Arduino.h"
4+
5+
#include <ESP8266WiFi.h>
6+
#include <WiFiUdp.h>
7+
8+
#define SEVENZYYEARS 2208988800UL
9+
#define NTP_PACKET_SIZE 48
10+
11+
class NTPClient {
12+
private:
13+
WiFiUDP _udp;
14+
15+
const char* _poolServerName = "time.nist.gov"; // Default time server
16+
int _port = 1337;
17+
int _timeOffset;
18+
19+
unsigned int _updateInterval = 60000; // In ms
20+
21+
unsigned long _currentEpoc; // In s
22+
unsigned long _lastUpdate = 0; // In ms
23+
24+
byte _packetBuffer[NTP_PACKET_SIZE];
25+
26+
void sendNTPPacket(IPAddress _timeServerIP);
27+
28+
public:
29+
NTPClient(int timeOffset);
30+
NTPClient(const char* poolServerName);
31+
NTPClient(const char* poolServerName, int timeOffset);
32+
NTPClient(const char* poolServerName, int timeOffset, int updateInterval);
33+
34+
/**
35+
* Starts the NTPClient
36+
* This will create the UDP Socket and get the first update from the NTP server. This must be called after
37+
* a WiFi connection is established.
38+
*/
39+
void begin();
40+
41+
/**
42+
* This should be called in the main loop of your application. By default an update from the NTP Server is only
43+
* made every 60 seconds. This can be configured in the NTPClient constructor.
44+
*/
45+
void update();
46+
47+
/**
48+
* This will force the update from the NTP Server.
49+
*/
50+
void forceUpdate();
51+
52+
String getHours();
53+
String getMinutes();
54+
String getSeconds();
55+
56+
/**
57+
* @return time formatted like `hh:mm:ss`
58+
*/
59+
String getFormattedTime();
60+
61+
/**
62+
* @return time as raw seconds
63+
*/
64+
unsigned long getRawTime();
65+
};

README.md

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# NTPClient
2+
3+
Connect to a NTP server, here is how:
4+
5+
```cpp
6+
#include <NTPClient.h>
7+
#include <ESP8266WiFi.h>
8+
9+
const char *ssid = "<SSID>";
10+
const char *password = "<PASSWORD>";
11+
12+
// By default 'time.nist.gov' is used.
13+
NTPClient timeClient();
14+
15+
// You can specify the time server pool and the offset, (in seconds)
16+
// additionaly you can specify the update interval (in milliseconds).
17+
// NTPClient timeClient("europe.pool.ntp.org", 3600, 60000);
18+
19+
void setup(){
20+
Serial.begin(11520);
21+
WiFi.begin(ssid, password);
22+
23+
while ( WiFi.status() != WL_CONNECTED ) {
24+
delay ( 500 );
25+
Serial.print ( "." );
26+
}
27+
28+
// Start the NTPClient after an WiFi connection is established
29+
timeClient.begin();
30+
31+
}
32+
33+
void loop() {
34+
timeClient.update();
35+
36+
Serial.println(timeClient.getFormattedTime());
37+
38+
delay(1000);
39+
}
40+
```

examples/Advanced/Advanced.ino

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <NTPClient.h>
2+
#include <ESP8266WiFi.h>
3+
4+
const char *ssid = "<SSID>";
5+
const char *password = "<PASSWORD>";
6+
7+
// You can specify the time server pool and the offset, (in seconds)
8+
// additionaly you can specify the update interval (in milliseconds).
9+
NTPClient timeClient("europe.pool.ntp.org", 3600, 60000);
10+
11+
void setup(){
12+
Serial.begin(115200);
13+
14+
WiFi.begin(ssid, password);
15+
16+
while ( WiFi.status() != WL_CONNECTED ) {
17+
delay ( 500 );
18+
Serial.print ( "." );
19+
}
20+
21+
// Start the NTPClient after an WiFi connection is established
22+
timeClient.begin();
23+
24+
}
25+
26+
void loop() {
27+
timeClient.update();
28+
29+
Serial.println(timeClient.getFormattedTime());
30+
31+
delay(1000);
32+
}

examples/Basic/Basic.ino

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <NTPClient.h>
2+
#include <ESP8266WiFi.h>
3+
4+
const char *ssid = "<SSID>";
5+
const char *password = "<PASSWORD>";
6+
7+
8+
9+
NTPClient timeClient();
10+
11+
void setup(){
12+
Serial.begin(115200);
13+
14+
WiFi.begin(ssid, password);
15+
16+
while ( WiFi.status() != WL_CONNECTED ) {
17+
delay ( 500 );
18+
Serial.print ( "." );
19+
}
20+
21+
// Start the NTPClient after an WiFi connection is established
22+
timeClient.begin();
23+
24+
}
25+
26+
void loop() {
27+
timeClient.update();
28+
29+
Serial.println(timeClient.getFormattedTime());
30+
31+
delay(1000);
32+
}

keywords.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#######################################
2+
# Datatypes (KEYWORD1)
3+
#######################################
4+
5+
NTPClient KEYWORD1
6+
7+
#######################################
8+
# Methods and Functions (KEYWORD2)
9+
#######################################
10+
11+
begin KEYWORD2
12+
update KEYWORD2
13+
forceUpdate KEYWORD2
14+
getHours KEYWORD2
15+
getMinutes KEYWORD2
16+
getSeconds KEYWORD2
17+
getFormattedTime KEYWORD2
18+
getRawTime KEYWORD2

library.properties

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=NTPClient
2+
version=1.0.0
3+
author=Fabrice Weinberg
4+
maintainer=Fabrice Weinberg <[email protected]>
5+
sentence=An NTPClient to connect to a time server
6+
paragraph=Get time from a NTP server and keep it in sync.
7+
category=Timing
8+
url=https://github.com/FWeinb/NTPClient
9+
architectures=esp8266

0 commit comments

Comments
 (0)