我试图在不使用库的情况下获得 NTP 时间,因为我有一些我想要的特定功能。但是,ESP 似乎没有收到 NTP 数据包。发送到我的 PC(但是不同的端口)有效(使用 Packet Sender 测试),并且手动将数据包从我的 PC 发送到 ESP(再次使用 Packet Sender)有效。将完全相同的数据包从我的 PC 发送到 NTP 服务器也可以,但 ESP 将数据包发送到服务器似乎没有收到回复。
硬件:ESP-01,改装4M闪存。
IDE:带有 PlatformIO
代码的 VSCode:
通过串行端口发送字符 @ 115200 波特进行测试。空格发送到指定的 IP,任何其他字符发送到第一个 NTP 服务器以解析到 IP 地址。
代码:
全选#include
#include
#include
#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
.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());
}