First of all thanks for your very good work on this library !
Having problems with my own skecth, I agregated 3 sketches from examples: NTP client, UDPSendReceive and Web Server, all are running simultaneously, this example exhibits the problem.
The mechanism is as follow: the HTTP part receive and send messages while the UDP part is also receiving messages (no send) and every 13 seconds the Arduino sends an NTP request to pool.ntp.org.
Most of the time the NTP request abort because the DNS request stays stuck in getHostByName() with a timeout but while this happens, HTTP and UDP processes continue to work correctly only the DNS requests don't work.
Other information:
Resetting the HTTP stack ( http_server.begin() ) resolve the DNS problem (i added a command in the sketch) for one or maybe some requests.
The Retry mechanism in getHostByName cause an arduino reboot (if suppressed no reboot)
Using an IP address directly instead of a hostname never shows the problem.
Example is joined to this request.
Thank you
Pierre
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Udp NTP Client
Get the time from a Network Time Protocol (NTP) time server
Demonstrates use of UDP sendPacket and ReceivePacket
UDPSendReceiveString
This sketch receives UDP message strings, prints them to the serial port
and sends an "acknowledge" string back to the sender
// HTTP part
EthernetServer server(80);
EthernetClient client;
// UDP part
unsigned int localPort = 8888; // local port to listen on
// buffers for receiving and sending data
char packetBuffer2[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet,
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
// NTP part
const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
uint32_t intervalle = 0;
const uint16_t INTERVALLE = 11325;
char packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming packet,
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("\nEthernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin( MAC, IP, FREEBOX, FREEBOX, SUBNET);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start HTTP server
server.begin();
Serial.print("server is at "); Serial.println(Ethernet.localIP());
// start UDP
Udp.begin(localPort);
// NTP
intervalle = millis() + INTERVALLE ;
// Proof the NTP part is Ok
ntp_loop();
}
void loop() {
// listen for incoming clients
client = server.available();
if (client) {
http_loop();
}
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize) {
udp_loop(packetSize);
}
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remote = Udp.remoteIP();
for (int i = 0; i < 4; i++) {
Serial.print(remote[i], DEC);
if (i < 3) {
Serial.print(".");
}
}
Serial.print(", port ");
Serial.println(Udp.remotePort());
// read the packet into packetBufffer
Udp.read(packetBuffer2, UDP_TX_PACKET_MAX_SIZE);
Serial.println("Contents:");
Serial.println(packetBuffer2);
/
// send a reply to the IP address and port that sent us the packet we received
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(ReplyBuffer);
Udp.endPacket();
/
//delay(10);
}
void http_loop() {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 20"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println(" ");
}
client.println("");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
void ntp_loop() {
Serial.println("NTP time !");
intervalle = millis() + INTERVALLE ;
sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait to see if a reply is available
delay(2000);
if (Udp.parsePacket()) {
// We've received a packet, read the data from it
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, extract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = ");
Serial.println(secsSince1900);
// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
Serial.println(epoch);
// print the hour, minute and second:
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
Serial.print(':');
if (((epoch % 3600) / 60) < 10) {
// In the first 10 minutes of each hour, we'll want a leading '0'
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
Serial.print(':');
if ((epoch % 60) < 10) {
// In the first 10 seconds of each minute, we'll want a leading '0'
Serial.print('0');
}
Serial.println(epoch % 60); // print the second
}
// wait ten seconds before asking for the time again
//Ethernet.maintain();
}
void sendNTPpacket(const char * address) {
// send an NTP request to the time server at the given address
Serial.println("Send NTP packet");
// 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:
int ret = Udp.beginPacket(address, 123); // NTP requests are to port 123
//int ret = Udp.beginPacket(FREEBOX, 123); // NTP requests for my internet box
if ( ret != 1 ) {
Serial.print("beginPacket: "); Serial.println(ret);
} else {
Serial.println("beginPacket sent");
}
Udp.write(packetBuffer, NTP_PACKET_SIZE);
ret = Udp.endPacket();
if ( ret != 1 ) {
Serial.print("endPacket: "); Serial.println(ret);
} else {
Serial.println("endPacket sent");
}
}
First of all thanks for your very good work on this library !
Having problems with my own skecth, I agregated 3 sketches from examples: NTP client, UDPSendReceive and Web Server, all are running simultaneously, this example exhibits the problem.
The mechanism is as follow: the HTTP part receive and send messages while the UDP part is also receiving messages (no send) and every 13 seconds the Arduino sends an NTP request to pool.ntp.org.
Most of the time the NTP request abort because the DNS request stays stuck in getHostByName() with a timeout but while this happens, HTTP and UDP processes continue to work correctly only the DNS requests don't work. Other information: Resetting the HTTP stack ( http_server.begin() ) resolve the DNS problem (i added a command in the sketch) for one or maybe some requests. The Retry mechanism in getHostByName cause an arduino reboot (if suppressed no reboot) Using an IP address directly instead of a hostname never shows the problem.
Example is joined to this request. Thank you Pierre
/* Web Server
A simple web server that shows the value of the analog input pins. using an Arduino Wiznet Ethernet shield.
Udp NTP Client
Get the time from a Network Time Protocol (NTP) time server Demonstrates use of UDP sendPacket and ReceivePacket
UDPSendReceiveString
This sketch receives UDP message strings, prints them to the serial port and sends an "acknowledge" string back to the sender
*/
include
include
include
// Ethernet part byte MAC[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xAB, 0xAF}; IPAddress IP( 192, 168, 0, 56 ); IPAddress FREEBOX( 192, 168, 0, 254 ); IPAddress SUBNET( 255, 255, 255, 0 );
// HTTP part EthernetServer server(80); EthernetClient client;
// UDP part unsigned int localPort = 8888; // local port to listen on // buffers for receiving and sending data char packetBuffer2[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet, // An EthernetUDP instance to let us send and receive packets over UDP EthernetUDP Udp;
// NTP part const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message uint32_t intervalle = 0; const uint16_t INTERVALLE = 11325; char packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming packet,
void setup() { // You can use Ethernet.init(pin) to configure the CS pin //Ethernet.init(10); // Most Arduino shields //Ethernet.init(5); // MKR ETH shield //Ethernet.init(0); // Teensy 2.0 //Ethernet.init(20); // Teensy++ 2.0 //Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet //Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open: Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } Serial.println("\nEthernet WebServer Example");
// start the Ethernet connection and the server: Ethernet.begin( MAC, IP, FREEBOX, FREEBOX, SUBNET);
// Check for Ethernet hardware present if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); while (true) { delay(1); // do nothing, no point running without Ethernet hardware } } if (Ethernet.linkStatus() == LinkOFF) { Serial.println("Ethernet cable is not connected."); }
// start HTTP server server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP());
// start UDP Udp.begin(localPort);
// NTP intervalle = millis() + INTERVALLE ; // Proof the NTP part is Ok ntp_loop(); }
void loop() {
// listen for incoming clients client = server.available(); if (client) { http_loop(); } // if there's data available, read a packet int packetSize = Udp.parsePacket(); if (packetSize) { udp_loop(packetSize); }
// NTP if ( millis() > intervalle ) { ntp_loop(); } }
void udp_loop(int packetSize) {
Serial.print("Received packet of size "); Serial.println(packetSize); Serial.print("From "); IPAddress remote = Udp.remoteIP(); for (int i = 0; i < 4; i++) { Serial.print(remote[i], DEC); if (i < 3) { Serial.print("."); } } Serial.print(", port "); Serial.println(Udp.remotePort());
// read the packet into packetBufffer Udp.read(packetBuffer2, UDP_TX_PACKET_MAX_SIZE); Serial.println("Contents:"); Serial.println(packetBuffer2); / // send a reply to the IP address and port that sent us the packet we received Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(ReplyBuffer); Udp.endPacket(); / //delay(10); }
void http_loop() {
Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println("Refresh: 20"); // refresh the page automatically every 5 sec client.println(); client.println("<!DOCTYPE HTML>"); client.println(""); // output the value of each analog input pin for (int analogChannel = 0; analogChannel < 6; analogChannel++) { int sensorReading = analogRead(analogChannel); client.print("analog input "); client.print(analogChannel); client.print(" is "); client.print(sensorReading); client.println("
"); } client.println(""); break; } if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); Serial.println("client disconnected"); }
void ntp_loop() {
Serial.println("NTP time !"); intervalle = millis() + INTERVALLE ; sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait to see if a reply is available delay(2000); if (Udp.parsePacket()) { // We've received a packet, read the data from it Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
} // wait ten seconds before asking for the time again
//Ethernet.maintain(); }
void sendNTPpacket(const char * address) {
// send an NTP request to the time server at the given address Serial.println("Send NTP packet"); // 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: int ret = Udp.beginPacket(address, 123); // NTP requests are to port 123 //int ret = Udp.beginPacket(FREEBOX, 123); // NTP requests for my internet box if ( ret != 1 ) { Serial.print("beginPacket: "); Serial.println(ret); } else { Serial.println("beginPacket sent"); } Udp.write(packetBuffer, NTP_PACKET_SIZE); ret = Udp.endPacket(); if ( ret != 1 ) { Serial.print("endPacket: "); Serial.println(ret); } else { Serial.println("endPacket sent"); } }