|
发表于 2023-5-9 12:37:21
|
显示全部楼层
本帖最后由 jpdd521 于 2023-5-9 13:02 编辑
直接GPS转成网络的NTP服务器,好像是很简单的。
然后,只要是你上班,你就让服务器工作,你不上班就让服务器不工作,这样,你就成了不可或缺的了
直接用8266就可以完成这个工作,然后加一个GPS模块就可以了,放到室外加一小块太阳能,完美了。
以下是偷懒代码
“
要使用ESP8266通过串口获取GPS时间并提供NTP服务,您可以使用以下步骤: - 首先,您需要将GPS模块连接到ESP8266的串口上。根据您的GPS模块和ESP8266板的引脚分配进行连接,确保将GPS模块的TX引脚连接到ESP8266的RX引脚上,将GPS模块的RX引脚连接到ESP8266的TX引脚上。
- 接下来,您需要编写ESP8266的Arduino代码来解析GPS数据并提供NTP服务。以下是一个示例代码,它使用TinyGPS++库解析GPS数据,并使用WiFiUDP库提供NTP服务:
在这个例子中,我们使用了 SoftwareSerial 库来创建一个串口对象,以便将GPS模块连接到ESP8266的D1和D2引脚。在 setup() 函数中,我们启动了GPS串口通信和UDP。在 loop() 函数中,我们检查GPS数据是否有更新,并且如果有新的有效GPS数据,我们会使用 makeEpochTime() 函数将日期和时间转换为自1970年以来的秒数。然后,我们发送一个NTP请求到 ntpServerName,等待响应,并将系统时间设置为GPS时间和NTP时间的平均值。
请注意,此代码仅提供了一个基本的实现,并且可能需要根据您的具体需求进行修改和调整。此外,为了确保准确性,您需要使用可靠的GPS模块和可靠的NTP服务器。”
- #include <ESP8266WiFi.h>
- #include <WiFiUdp.h>
- #include <SoftwareSerial.h>
- #include <TinyGPS++.h>
- // 替换为您的网络凭据
- const char* ssid = "您的SSID";
- const char* password = "您的密码";
- // 替换为您的NTP服务器URL
- const char* ntpServerName = "pool.ntp.org";
- // NTP时间戳在消息的前48个字节中
- const int NTP_PACKET_SIZE = 48;
- byte packetBuffer[NTP_PACKET_SIZE]; // 用于保存传入和传出数据包的缓冲区
- WiFiUDP udp; // UDP实例
- // GPS模块
- SoftwareSerial gpsSerial(D1, D2); // RX, TX引脚
- TinyGPSPlus gps;
- void setup() {
- // 连接到Wi-Fi网络
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.println("正在连接到WiFi...");
- }
- Serial.println("已连接到WiFi");
- // 开始GPS串口通信
- gpsSerial.begin(9600);
- Serial.println("GPS串口通信已启动");
- // 开始UDP
- udp.begin(123);
- Serial.println("正在等待GPS信号...");
- }
- void loop() {
- // 检查是否有新的GPS数据
- while (gpsSerial.available() > 0) {
- gps.encode(gpsSerial.read());
- }
- // 如果有新的有效GPS数据,更新时间
- if (gps.time.isValid() && gps.date.isValid()) {
- Serial.println("收到有效的GPS数据");
- // 从GPS模块获取时间
- int year = gps.date.year();
- byte month = gps.date.month();
- byte day = gps.date.day();
- byte hour = gps.time.hour();
- byte minute = gps.time.minute();
- byte second = gps.time.second();
- // 将日期和时间转换为自1970年以来的秒数
- unsigned long epoch = makeEpochTime(year, month, day, hour, minute, second);
- // 发送NTP请求
- sendNTPpacket(ntpServerName);
- // 等待响应
- delay(1000);
- // 如果有可用数据,则读取数据
- if (udp.parsePacket()) {
- Serial.println("收到NTP响应");
- // 将NTP数据读入缓冲区
- udp.read(packetBuffer, NTP_PACKET_SIZE);
- // 将4个时间戳字节组合成一个32位整数
- unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
- unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
- unsigned long ntpTime = highWord << 16 | lowWord;
- // 将NTP时间转换为Unix时间(自1970年以来的秒数)
- unsigned long unixTime = ntpTime - 2208988800UL;
- // 使用GPS时间和NTP时间的平均值设置系统时间
- setTime(epoch + (unixTime - epoch) / 2);
- }
- }
- }
- // 将日期和时间转换为自1970年以来的秒数
- unsigned long makeEpochTime(int year, byte month, byte day, byte hour, byte minute, byte second) {
- // 1月和2月被计算为前一年的第13和14个月
- if (month < 3) {
- month += 12;
- year--;
- }
- // 将年份转换为天数
- unsigned long days = (year - 1970) * 365;
- // 添加闰年天数
- for (int i = 1972; i <= year; i += 4) {
- if (i % 100 != 0 || i % 400 == 0) {
- days++;
- }
- }
- // 添加当前年份的天数
- for (int i = 1; i < month; i++) {
- switch (i) {
- case 2:
- if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
- days += 29;
- } else {
- days += 28;
- }
- break;
- case 4:
- case 6:
- case 9:
- case 11:
- days += 30;
- break;
- default:
- days += 31;
- break;
- }
- }
- days += day - 1; // 减1是因为1月1日是第0天
- // 将天数转换为秒数
- unsigned long seconds = days * 86400;
- // 添加小时、分钟和秒
- seconds += hour * 3600;
- seconds += minute * 60;
- seconds += second;
- return seconds;
- }
- // 向指定的服务器发送NTP请求
- void sendNTPpacket(const char* address) {
- // 将缓冲区中的所有字节设置为0
- memset(packetBuffer, 0, NTP_PACKET_SIZE);
- // 初始化NTP请求所需的值
- packetBuffer[0] = 0b11100011; // LI、版本、模式
- packetBuffer[1] = 0; // Stratum或时钟类型
- packetBuffer[2] = 6; // 轮询间隔
- packetBuffer[3] = 0xEC; // 精度
- // 8个0字节用于Root Delay和Root Dispersion
- packetBuffer[12] = 49;
- packetBuffer[13] = 0x4E;
- packetBuffer[14] = 49;
- packetBuffer[15] = 52;
- // 发送请求
- udp.beginPacket(address, 123); // NTP请求发送到端口123
- udp.write(packetBuffer, NTP_PACKET_SIZE);
- udp.endPacket();
- }
复制代码
中国人要用北斗,那么,再来个北斗的代码
- #include <ESP8266WiFi.h>
- #include <WiFiUdp.h>
- #include <SoftwareSerial.h>
- #include <TimeLib.h>
- // 替换为您的网络凭据
- const char* ssid = "您的SSID";
- const char* password = "您的密码";
- // 替换为您的NTP服务器URL
- const char* ntpServerName = "pool.ntp.org";
- // NTP时间戳在消息的前48个字节中
- const int NTP_PACKET_SIZE = 48;
- byte packetBuffer[NTP_PACKET_SIZE]; // 用于保存传入和传出数据包的缓冲区
- WiFiUDP udp; // UDP实例
- // 北斗模块
- SoftwareSerial bdSerial(D1, D2); // RX, TX引脚
- void setup() {
- // 连接到Wi-Fi网络
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.println("正在连接到WiFi...");
- }
- Serial.println("已连接到WiFi");
- // 开始北斗串口通信
- bdSerial.begin(9600);
- Serial.println("北斗串口通信已启动");
- // 开始UDP
- udp.begin(123);
- Serial.println("正在等待北斗信号...");
- }
- void loop() {
- // 检查是否有新的北斗数据
- while (bdSerial.available() > 0) {
- char c = bdSerial.read();
- // 如果接收到的是'$',则表示开始接收北斗数据
- if (c == '$') {
- // 读取北斗数据
- char buf[64] = {0};
- int i = 0;
- while (true) {
- if (bdSerial.available() > 0) {
- c = bdSerial.read();
- if (c == '\r') {
- break;
- }
- if (i < 63) {
- buf[i++] = c;
- }
- }
- }
- // 分离数据
- char* p = strtok(buf, ",");
- int time[6];
- for (int i = 0; i < 6; i++) {
- time[i] = atoi(p);
- p = strtok(NULL, ",");
- }
- // 将日期和时间转换为自1970年以来的秒数
- unsigned long epoch = makeEpochTime(time[0], time[1], time[2], time[3], time[4], time[5]);
- // 发送NTP请求
- sendNTPpacket(ntpServerName);
- // 等待响应
- delay(1000);
- // 如果有可用数据,则读取数据
- if (udp.parsePacket()) {
- Serial.println("收到NTP响应");
- // 将NTP数据读入缓冲区
- udp.read(packetBuffer, NTP_PACKET_SIZE);
- // 将4个时间戳字节组合成一个32位整数
- unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
- unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
- unsigned long ntpTime = highWord << 16 | lowWord;
- // 将NTP时间转换为Unix时间(自1970年以来的秒数)
- unsigned long unixTime = ntpTime - 2208988800UL;
- // 使用北斗时间和NTP时间的平均值设置系统时间
- setTime(epoch + (unixTime - epoch) / 2);
- }
- }
- }
- }
- // 将日期和时间转换为自1970年以来的秒数
- unsigned long makeEpochTime(int year, int month, int day, int hour, int minute, int second) {
- // 1月和2月被计算为前一年的第13和14个月
- if (month < 3) {
- month += 12;
- year--;
- }
- // 将年份转换为天数
- unsigned long days = (year - 1970) * 365;
- // 添加闰年天数
- for (int i = 1972; i <= year; i += 4) {
- if (i % 100 != 0 || i % 400 == 0) {
- days++;
- }
- }
- // 添加当前年份的天数
- for (int i = 1; i < month; i++) {
- switch (i) {
- case 2:
- if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
- days += 29;
- } else {
- days += 28;
- }
- break;
- case 4:
- case 6:
- case 9:
- case 11:
- days += 30;
- break;
- default:
- days += 31;
- break;
- }
- }
- days += day - 1; // 减1是因为1月1日是第0天
- // 将天数转换为秒数
- unsigned long seconds = days * 86400;
- // 添加小时、分钟和秒
- seconds += hour * 3600;
- seconds += minute * 60;
- seconds += second;
- return seconds;
- }
- // 向指定的服务器发送NTP请求
- void sendNTPpacket(const char* address) {
- // 将缓冲区中的所有字节设置为0
- memset(packetBuffer, 0, NTP_PACKET_SIZE);
- // 初始化NTP请求所需的值
- packetBuffer[0] = 0b11100011; // LI、版本、模式
- packetBuffer[1] = 0; // Stratum或时钟类型
- packetBuffer[2] = 6; // 轮询间隔
- packetBuffer[3] = 0xEC; // 精度
- // 8个0字节用于Root Delay和Root Dispersion
- packetBuffer[12] = 49;
- packetBuffer[13] = 0x4E;
- packetBuffer[14] = 49;
- packetBuffer[15] = 52;
- // 发送请求
- udp.beginPacket(address, 123); // NTP请求发送到端口123
- udp.write(packetBuffer, NTP_PACKET_SIZE);
- udp.endPacket();
- }
复制代码
|
打赏
-
查看全部打赏
|