Hi
I set up a project based on NODEMCU. Basically it's an automated school bell system based on the TimeLib and TimeAlarms libraries. NODEMCU connects to an NTP server via WiFi, updates the time and runs the schedule.
I have two identical systems running the same code but each system is connected to the internet in a different way: one of then is going through the school network infrastructure of my country. That is the one i have problem with. It seems that something blocks the request to the NTP server. As a result the system time is set to 00:00:00 1/1/1970 and the whole thing fails. I got it working a few days ago but a power shortage for a few seconds restarted the MCU and everything has been lost. The other system works flawlessly.
I know that the school network has a restriction on the DNS server that can be used. We cannot use is Google's DNS. We can either set it to auto or use specific IP addresses. I tried both methods but no result.
Here is a part of my code (i removed irrelevant parts):
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <TimeAlarms.h>
ESP8266WebServer server;
static const char ntpServerName[] = "ntp.sch.gr";
const int timeZone = 3;
WiFiUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
// =================== Static IP setup ===================
// Set your Static IP address
IPAddress local_IP(192, 168, 1, 249);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 0, 0);
IPAddress primaryDNS(194, 63, 237, 4); //optional - School Network DNS
IPAddress secondaryDNS(194, 63, 238, 4); //optional
// =================== Static IP setup ===================
// =================== Alarm ID's ========================
AlarmId id1h;
///.... irrelevant code - removed!
AlarmId idRestart_2;
// =================== END Alarm ID's ========================
char wPagePM[] PROGMEM = R"foo(
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<html>
<body id="myBody">
<div id="resHolder">
// irrelevant code - web user interface - REMOVED
</html>
)foo";
void setup()
{
char* ssid = "blahblah";
char* pass = "123123";
Serial.begin(115200);
Serial.println();
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
// Configures static IP address
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
WiFi.begin(ssid, pass);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Σύνδεση επιτυχής, IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Εκκίνηση UDP");
Udp.begin(localPort);
Serial.print("Τοπική θύρα: ");
Serial.println(Udp.localPort());
Serial.println("αναμονή συγχρονισμού");
setSyncProvider(getNtpTime);
setSyncInterval(8 * 3600);
server.on("/", handleRoot);
server.on("/dlrm", handleDisableLrm);
server.on("/elrm", handleEnableLrm);
server.on("/ring", handleRing);
server.begin();
pinMode(D2, OUTPUT);
//pinMode(D5, OUTPUT);
digitalWrite(D2, LOW);
//digitalWrite(D4, LOW);
// ============ Alarm declarations ================
id1h = Alarm.alarmRepeat(8, 15, 0, BellRing);
// ... removed
//idRestart_2 = Alarm.alarmRepeat(dowMonday, 8, 14, 0, RestartAlarms);
Serial.print("Count: ");
Serial.println(Alarm.count());
// ============ END Alarm declarations ================
}
/*-------- Alarm functions ----------*/
void loop() {
server.handleClient();
Alarm.delay(50);
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP server's ip address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request");
// get a random server from the pool
WiFi.hostByName(ntpServerName, ntpServerIP); // THAT"S WHERE IT'S FAILS
Serial.print(ntpServerName);
Serial.print(": ");
Serial.println(ntpServerIP); // NO SERVER SET
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
// 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:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
This method WiFi.hostByName(ntpServerName, ntpServerIP); is supposed to return the IP address of the NTP server, but it fails. A tech of the school network support team did some tests today via Anydesk and he successfully reached various NTP servers from the CMD. My router can get the time and date from the NPT stored in it's settings. Everything works OK except this little thing!
Any ideas please?
Thanks in advance
Minas