Chat freely about anything...

User avatar
By Random Spaceship
#90231 Hello all!

I'm trying to get NTP time without using libraries, as I have a few specific features I want. However, the ESP appears to not receive the NTP packets. Sending to my PC (different port, however) works (tested using Packet Sender), and manually sending packets from my PC to the ESP (again using Packet Sender) works. Sending the exact same packet from my PC to the NTP server also works, but the ESP sends the packet to the server it doesn't appear to receive a reply.

Hardware: ESP-01, modded with 4M flash.
IDE: VSCode with PlatformIO

Code:
Send a character via serial port @ 115200 baud to test. Space sends to specified IP, any other character sends to the first NTP server to resolve to an IP address.
Code: Select all#include <Arduino.h>
#include <ESP8266WiFiMulti.h>
#include <WiFiUdp.h>

#define NTP_PACKET_SIZE 48
#define NTP_TIMEOUT 10000  // retry if no reply in 10 seconds
#define MAX_NTP_RETRYS 5   // only retry 5 times
// NTP
byte NTPBuffer[NTP_PACKET_SIZE];
IPAddress ntpServerAddress;
WiFiUDP UDP;
const String ntpServerHostnames[] = {"au.pool.ntp.org" /* AU NTP pool*/, "time.google.com", "time.windows.com", "time.nist.gov" /* US servers */};
byte ntpRequestCount = 0;
void setup() {
    delay(50);  // probably a good idea to have this. Let things "settle"
    Serial.begin(115200);
    while (!Serial)
        ;
    Serial.println("\n\nBeginning setup");
    delay(10);
    WiFi.begin("ssid", "pass");
    WiFi.mode(WIFI_STA);
    delay(5000);
    Serial.println(WiFi.status() == WL_CONNECTED ? "WiFi connected" : "WiFi not connected, rebooting");
    bool udp = UDP.begin(123);
    Serial.println(udp ? "UDP setup" : "UDP fail");
    if (WiFi.status() != WL_CONNECTED || !udp) ESP.restart();
}

void requestNtpTime();
uint32_t parseNtpTime();
void sendNTPpacket(IPAddress& address);

void loop() {
    while (!Serial.available()) ;
    delay(100);
    bool local = false;
    if (Serial.peek() == ' ') local = true;
    while (Serial.available()) Serial.read();
    IPAddress pc = IPAddress(10, 0, 0, 1); // PC address here
    if (!local)
        requestNtpTime();
    else
        sendNTPpacket(pc);
    delay(100);
    Serial.println(UDP.parsePacket());
    Serial.println(UDP.available());
    Serial.println(parseNtpTime(), HEX);
}

void requestNtpTime() {
    bool addrResolved = false;
    for (byte i = 0; i < 4 && !addrResolved; i++)
        if (WiFi.hostByName(ntpServerHostnames[i].c_str(), ntpServerAddress)) addrResolved = true;
    if (!addrResolved) WiFi.hostByName("pool.ntp.org", ntpServerAddress);
    Serial.println("Requesting time");
    sendNTPpacket(ntpServerAddress);
}
uint32_t parseNtpTime() {
    if (UDP.parsePacket() == 0) {  // If there's no response (yet)
        return 0;
    }
    Serial.printf("Got time from %s:%d\n", UDP.remoteIP().toString().c_str(), UDP.remotePort());
    UDP.read(NTPBuffer, NTP_PACKET_SIZE);  // read the packet into the buffer
    // Combine the 4 timestamp bytes into one 32-bit number
    uint32_t NTPTime = (NTPBuffer[40] << 24) | (NTPBuffer[41] << 16) | (NTPBuffer[42] << 8) | NTPBuffer[43];  //NTP Timestamp
    // Convert NTP time to a UNIX timestamp:
    // Unix time starts on Jan 1 1970. That's 2208988800 seconds in NTP time:
    Serial.println(NTPTime, HEX);
    const uint32_t seventyYears = 2208988800UL;
    // subtract seventy years:
    uint32_t UNIXTime = NTPTime - seventyYears;
    return UNIXTime;
}
void sendNTPpacket(IPAddress& address) {
    memset(NTPBuffer, 0, NTP_PACKET_SIZE);  // set all bytes in the buffer to 0
    // Initialize values needed to form NTP request
    NTPBuffer[0] = 0b11011011;  // LI (3 - unsynchronised, 2 bits), Version (3, 3 bits), Mode(3 - client, 3 bits)
    NTPBuffer[1] = 0;           //Clock stratum
    // send a packet requesting a timestamp:
    bool begun = UDP.beginPacket(address, 123);  // NTP requests are to port 123
    UDP.write(NTPBuffer, NTP_PACKET_SIZE);
    bool end = UDP.endPacket();
    Serial.printf("Sending packet: %s, %s, to %s\n", begun ? "true" : "false", end ? "true" : "false", address.toString().c_str());
}