Network Time Protocol
There are many applications where you want to know the time. In a normal Arduino project, you would have to get a RTC module, set
the right time, sacrifice some Arduino pins for communication ... And when the RTC battery runs out, you have to replace it.
On the ESP8266, all you need is an Internet connection: you can just ask a time server what time it is. To do this, the Network Time
Protocol (NTP) is used.
In the previous examples (HTTP, WebSockets) we've only used TCP connections, but NTP is based on UDP. There are a couple of
differences, but it's really easy to use, thanks to the great libraries that come with the ESP8266 Arduino Core.
The main difference between TCP and UDP is that TCP needs a connection to send messages: First a handshake is sent by the client,
the server responds, and a connection is established, and the client can send its messages. After the client has received the response
of the server, the connection is closed (except when using WebSockets). To send a new message, the client has to open a new
connection to the server first. This introduces latency and overhead.
UDP doesn't use a connection, a client can just send a message to the server directly, and the server can just send a response
message back to the client when it has finished processing. There is, however, no guarantee that the messages will arrive at their
destination, and there's no way to know whether they arrived or not (without sending an acknowledgement, of course). This means
that we can't halt the program to wait for a response, because the request or response packet could have been lost on the Internet,
and the ESP8266 will enter an infinite loop.
Instead of waiting for a response, we just send multiple requests, with a fixed interval between two requests, and just regularly check
if a response has been received.
Getting the time
Let's take a look at an example that uses UDP to request the time from a NTP server.
Libraries, constants and globals
#include
<
ESP8266WiFi
.
h
>
#include
<
ESP8266WiFiMulti
.
h
>
#include
<
WiFiUdp
.
h
>
ESP8266WiFiMulti wifiMulti;
// Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
WiFiUDP
UDP;
// Create an instance of the WiFiUDP class to send and receive
IPAddress
timeServerIP;
// time.nist.gov NTP server address
const
char
*
NTPServerName
=
"time.nist.gov"
;
const
int
NTP_PACKET_SIZE
=
48;
// NTP time stamp is in the first 48 bytes of the message
byte
NTPBuffer[NTP_PACKET_SIZE];
// buffer to hold incoming and outgoing packets
To use UDP, we have to include the WiFiUdp library, and create a UDP object. We'll also need to allocate memory for a buffer to store
the UDP packets. For NTP, we need a buffer of 48 bytes long.
To know where to send the UDP packets to, we need the hostname of the NTP server, this is time.nist.gov.
Setup
void
setup
() {
Serial
.
begin
(115200);
// Start the Serial communication to send messages to the computer
delay
(10);
Serial
.
println
(
"\r\n"
);
startWiFi();
// Try to connect to some given access points. Then wait for a connection
startUDP();
if
(
!
WiFi
.
hostByName
(NTPServerName
,
timeServerIP)) {
// Get the IP address of the NTP server
Serial
.
println
(
"DNS lookup failed. Rebooting."
);
Serial
.
flush
();
ESP
.
reset
();
}
Serial
.
(
"Time server IP:\t"
);
Serial
.
println
(timeServerIP);
Serial
.
println
(
"\r\nSending NTP request ..."
);
sendNTPpacket(timeServerIP);
}
In the setup, we just start our Serial and Wi-Fi, as usual, and we start UDP as well. We'll look at the implementation of this function
later.
We need the IP address of the NTP server, so we perform a DNS lookup with the server's hostname. There's not much we can do
without the IP address of the time server, so if the lookup fails, reboot the ESP.
If we do get an IP, send the first NTP request, and enter the loop.
Loop
unsigned
long
intervalNTP
=
60000;
// Request NTP time every minute
unsigned
long
prevNTP
=
0;
unsigned
long
lastNTPResponse
=
millis
();
uint32_t
timeUNIX
=
0;
unsigned
long
prevActualTime
=
0;
void
loop
() {
unsigned
long
currentMillis
=
millis
();
if
(currentMillis
-
prevNTP
>
intervalNTP) {
// If a minute has passed since last NTP request
Содержание ESP8266 SDK
Страница 4: ......
Страница 22: ......
Страница 32: ...It automatically detected that it had to send the compressed versions of index html and favicon ico ...
Страница 50: ......