本来想从开源项目找找灵感的,但是!那些代码真烂!!!!!
开源项目免不了的就是抄抄抄代码,想知道 NTP 是怎么实现的还要读那一堆烂代码,烦!
就算开源项目能怎么样!不还是一样的 烂!代!码!
自己想办法看看 NTP 的相关库是怎么实现的吧。
可以使用 aliyun 的 NTP 服务器。
发现不少开源项目都是用的 aliyun 的 NTP 服务器。
阿里云NTP服务器 - 云服务器 ECS - 阿里云https://help.aliyun.com/document_detail/92704.html
NTP:Network Time Protocol(网络时间协议)
▶️ NTP 是用于同步网络中计算机时间的协议。它的用途是把计算机的时钟同步到世界协调时UTC。
UTC:Universal Time Coordinated(协调世界时)以原子时秒长为基础。
GMT:Universal Time(世界时)以地球自转为基础。
北京时间采用东八区的区时作为标准时间。北京时间比世界时(UTC)早8小时,北京时间=UTC+8。
▶️ 如果使用 NTPClient 库,其实很简单很简单很简单!!
官方例程里就几个函数就实现了!就四个!
WiFiUDP ntpUDP; //创建UDP实例
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 60 * 60 * 8, 60000); //NTC
//UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval
//初始化函数
timeClient.begin();
//获取时间
timeClient.update();
timeClient.getFormattedTime();
这样,就能直接获取 小时:分钟:秒 的格式的时间了。
有感而发:学习ESP32还是要学一学网络协议啊!
需要说明的函数:
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 60 * 60 * 8, 60000); //NTC
//UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval
ntpUDP:UDP实例
"europe.pool.ntp.org":NTP服务器地址
60 * 60 * 8:是换算为东八区的时间需要的参数:秒*分钟*小时
60000:更新时间
在库接口中,只看到了星期、时、分、秒的接口!没有年、月、日。
#include
#include
#include
const char *ssid = "";
const char *password = "";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
void setup()
{
Serial.begin(115200);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED )
{
delay ( 500 );
Serial.print ( "." );
}
timeClient.begin();
}
void loop()
{
timeClient.update();
Serial.println(timeClient.getFormattedTime());
delay(1000);
}
如果想隔一段时间调用一次这种类似时间中断的功能,可引用 Ticker 库实现定时器功能。
在 ESP32 的核心文件夹下有 time.c 文件。定义了 configTime 函数用来配置时间。不需要引用头文件可以直接调用函数。
void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)
在 time.c 文件中,还提供了其他的时间设置函数,包括设置时区、获取时区时间等等。
▶️ 获取本地时间,函数同样定义在 time.c 中,但是使用此函数需要 tm 类型的结构体存储时间!
tm 是定义在 C++ 库 time.h 中的结构体。
struct tm - C++ Referencehttps://cplusplus.com/reference/ctime/tm/
struct tm
{
//以下为常规日期
int tm_year; /* 年份,其值从1900开始 */
int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */
int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
int tm_hour; /* 时 - 取值区间为[0,23] */
int tm_min; /* 分 - 取值区间为[0,59] */
int tm_sec; /* 秒–取值区间为[0,59] */
int tm_wday; /* 星期–取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */
int tm_yday; /* 从每年的1月1日开始的天数–取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */
int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/
long int tm_gmtoff; /*指定了日期变更线东面时区中UTC东部时区正秒数或UTC西部时区的负秒数*/
const char *tm_zone; /*当前时区的名字(与环境变量TZ有关)*/
};
▶️ 如果是中国时间,需要注意的是年、月的时间问题!
函数示例:
此处函数参考了:Getting Date & Time From NTP Server With ESP32
#include "Arduino.h"
#include
#include "time.h" // 为了使用tm结构体
const char* ssid = "";
const char* password = "";
struct tm timeinfo;
void setup()
{
Serial.begin(115200);
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
configTime(60*60*8, 0, "ntp3.aliyun.com"); // 用的阿里云的服务器
printLocalTime();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
void loop()
{
struct tm timeinfo;
if(!getLocalTime(&timeinfo))
{
Serial.println("Failed to obtain time");
return;
}
Serial.println(&timeinfo, "%A, %Y-%m-%d %H:%M:%S");
delay(1000);
}
不出意外的情况下,会在串口打印如下类似信息:
也可以通过读取结构体的情况,取得
year = timeinfo.tm_year + 1900; // 年份从1900开始
month = timeinfo.tm_mon + 1; // 0表示1月
week = timeinfo.tm_wday; // 这里要注意这是返回的数字,并不是单词!
...
但是这种办法不能自动更新时间,就比较烦一点点!可以加 Ticker 来进行定时执行获取时间。
其实和前面获取心知天气的文章使用相同的方法:
心知天气天气状况获取,ESP32获取天气信息(含源码)_喜暖知寒的博客-CSDN博客_esp32获取天气ESP32获取天气信息https://blog.csdn.net/qq_41650023/article/details/124697234在网上找到了几个 API 的接口:
例如心知天气API返回的JSON数据:
苏宁返回的数据:http://quan.suning.com/getSysTime.do
例如网站:现在北京时间 在线标准北京时间校对
在此网站找到了 GET 请求接口
可发现请求时间的 API 就是这个了:https://www.beijing-time.org/t/time.asp
请求返回值:
有些网站的 API 比较好找,有些比较难找。在此只是提供一个想法!
最后就结束了啊 ~
其实没什么难的吧 ~ !
了解一下后才发现 NTP 这种东西在 ESP32 for Arduino 上这么好实现,以前以为不好实现还恐惧了好久呢 !
本篇文章也就是提供一个思路,附上了两个实现方式的完整代码,测试是可用的!应该要是应用的话会有BUG,不过那都不重要了。
OK,本篇文章如果有幸被小伙伴看到的话,希望对你有所帮助。
今日份开心哦 ~ 学到了心的知识 ~
会持续更新关于 ESP32 for Arduino 的一些小知识点哦 ~ 因为最近也在抽时间学一学!
如果本篇文章给您带来一些帮助,不妨 点 个 赞 ~ 或者是 点 点 关 注 !~
要是同样初学的小伙伴,也不方便关注一下本专栏有关 ESP32 for Arduino 的其他文章哦 ~ 都是最为自己的笔记写的,相信会对你有所帮助!