当前位置:   article > 正文

ESP32超详细学习记录:NTP同步时间_esp32 ntp

esp32 ntp

本来想从开源项目找找灵感的,但是!那些代码真烂!!!!!

开源项目免不了的就是抄抄抄代码,想知道 NTP 是怎么实现的还要读那一堆烂代码,烦!

就算开源项目能怎么样!不还是一样的  烂!代!码!

自己想办法看看 NTP 的相关库是怎么实现的吧。


可以使用 aliyun 的 NTP 服务器。

发现不少开源项目都是用的 aliyun 的 NTP 服务器。

阿里云NTP服务器 - 云服务器 ECS - 阿里云https://help.aliyun.com/document_detail/92704.html


什么是NTP

NTP:Network Time Protocol(网络时间协议)

▶️ NTP 是用于同步网络中计算机时间的协议。它的用途是把计算机的时钟同步到世界协调时UTC。

UTC:Universal Time Coordinated(协调世界时)以原子时秒长为基础。

GMT:Universal Time(世界时)以地球自转为基础。

北京时间采用东八区的区时作为标准时间。北京时间比世界时(UTC)早8小时,北京时间=UTC+8。


使用 NTPClient 库获取时间

▶️ 如果使用 NTPClient 库,其实很简单很简单很简单!!

官方例程里就几个函数就实现了!就四个!

  1. WiFiUDP ntpUDP; //创建UDP实例
  2. NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 60 * 60 * 8, 60000); //NTC
  3. //UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval
  4. //初始化函数
  5. timeClient.begin();
  6. //获取时间
  7. timeClient.update();
  8. timeClient.getFormattedTime();

这样,就能直接获取 小时:分钟:秒 的格式的时间了。

有感而发:学习ESP32还是要学一学网络协议啊!

需要说明的函数:

  1. NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 60 * 60 * 8, 60000); //NTC
  2. //UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval
  • ntpUDP:UDP实例

  • "europe.pool.ntp.org":NTP服务器地址

  • 60 * 60 * 8:是换算为东八区的时间需要的参数:秒*分钟*小时

  • 60000:更新时间

在库接口中,只看到了星期、时、分、秒的接口!没有年、月、日。

  1. #include <WiFi.h>
  2. #include <WiFiUdp.h>
  3. #include <NTPClient.h>
  4. const char *ssid = "<SSID>";
  5. const char *password = "<PASSWORD>";
  6. WiFiUDP ntpUDP;
  7. NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
  8. void setup()
  9. {
  10. Serial.begin(115200);
  11. WiFi.begin(ssid, password);
  12. while ( WiFi.status() != WL_CONNECTED )
  13. {
  14. delay ( 500 );
  15. Serial.print ( "." );
  16. }
  17. timeClient.begin();
  18. }
  19. void loop()
  20. {
  21. timeClient.update();
  22. Serial.println(timeClient.getFormattedTime());
  23. delay(1000);
  24. }

如果想隔一段时间调用一次这种类似时间中断的功能,可引用 Ticker 库实现定时器功能。


ESP32核心库函数

在 ESP32 的核心文件夹下有 time.c 文件。定义了 configTime 函数用来配置时间。不需要引用头文件可以直接调用函数。

void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)
  • gmtOffset_sec:世界时偏移量
  • daylightOffset_sec:时间偏移
  • server:服务器地址

在 time.c 文件中,还提供了其他的时间设置函数,包括设置时区、获取时区时间等等。

▶️ 获取本地时间,函数同样定义在 time.c 中,但是使用此函数需要 tm 类型的结构体存储时间!

tm 是定义在 C++ 库 time.h 中的结构体。

struct tm - C++ Referencehttps://cplusplus.com/reference/ctime/tm/

  1. struct tm
  2. {  
  3. //以下为常规日期
  4. int tm_year; /* 年份,其值从1900开始 */
  5. int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */  
  6. int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */  
  7. int tm_hour; /* 时 - 取值区间为[0,23] */
  8. int tm_min; /* 分 - 取值区间为[0,59] */   
  9. int tm_sec; /* 秒–取值区间为[0,59] */   
  10. int tm_wday; /* 星期–取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */  
  11. int tm_yday; /* 从每年的1月1日开始的天数–取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */  
  12. int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/  
  13. long int tm_gmtoff; /*指定了日期变更线东面时区中UTC东部时区正秒数或UTC西部时区的负秒数*/   
  14. const char *tm_zone; /*当前时区的名字(与环境变量TZ有关)*/  
  15. };

▶️ 如果是中国时间,需要注意的是年、月的时间问题!

函数示例:

此处函数参考了:Getting Date & Time From NTP Server With ESP32

  1. #include "Arduino.h"
  2. #include <WiFi.h>
  3. #include "time.h" // 为了使用tm结构体
  4. const char* ssid = "<SSID>";
  5. const char* password = "<PASSWORD>";
  6. struct tm timeinfo;
  7. void setup()
  8. {
  9. Serial.begin(115200);
  10. Serial.printf("Connecting to %s ", ssid);
  11. WiFi.begin(ssid, password);
  12. while (WiFi.status() != WL_CONNECTED)
  13. {
  14. delay(500);
  15. Serial.print(".");
  16. }
  17. Serial.println(" CONNECTED");
  18. configTime(60*60*8, 0, "ntp3.aliyun.com"); // 用的阿里云的服务器
  19. printLocalTime();
  20. WiFi.disconnect(true);
  21. WiFi.mode(WIFI_OFF);
  22. }
  23. void loop()
  24. {
  25. struct tm timeinfo;
  26. if(!getLocalTime(&timeinfo))
  27. {
  28. Serial.println("Failed to obtain time");
  29. return;
  30. }
  31. Serial.println(&timeinfo, "%A, %Y-%m-%d %H:%M:%S");
  32. delay(1000);
  33. }

不出意外的情况下,会在串口打印如下类似信息:


也可以通过读取结构体的情况,取得

  1. year = timeinfo.tm_year + 1900; // 年份从1900开始
  2. month = timeinfo.tm_mon + 1; // 0表示1月
  3. week = timeinfo.tm_wday; // 这里要注意这是返回的数字,并不是单词!
  4. ...

但是这种办法不能自动更新时间,就比较烦一点点!可以加 Ticker 来进行定时执行获取时间。


不使用NTP获取时间的方法:API

其实和前面获取心知天气的文章使用相同的方法

心知天气天气状况获取,ESP32获取天气信息(含源码)_喜暖知寒的博客-CSDN博客_esp32获取天气ESP32获取天气信息https://blog.csdn.net/qq_41650023/article/details/124697234在网上找到了几个 API 的接口:

例如心知天气API返回的JSON数据:

苏宁返回的数据:http://quan.suning.com/getSysTime.do


甚至还能查网站的 GET 请求获取某些网站API

例如网站:现在北京时间 在线标准北京时间校对

在此网站找到了 GET 请求接口

可发现请求时间的 API 就是这个了:https://www.beijing-time.org/t/time.asp

请求返回值:

有些网站的 API 比较好找,有些比较难找。在此只是提供一个想法!


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/472030
推荐阅读
相关标签