OpenHarmony輕量系統(tǒng)-獲取當(dāng)?shù)貢r(shí)間
想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:
前言
在輕量設(shè)備里面,我們常常需要獲取本地時(shí)間,用于時(shí)間顯示,log記錄,幫助RTC芯片糾正時(shí)間等等。我們?cè)谥霸O(shè)計(jì)了一個(gè)智慧時(shí)鐘,需要使用到本地當(dāng)前時(shí)間,因此本篇文章想在OpenHarmony上實(shí)現(xiàn)SNTP獲取本地時(shí)間,并將此功能集成為一個(gè)模塊,便于我們的主程序調(diào)用。
環(huán)境
OpenHarmony3.1
潤(rùn)和hispark_pegasus Hi3861開發(fā)板
DevEco Device Tool
串口調(diào)試助手
SNTP介紹
SNTP(Simple Network Time Protocal簡(jiǎn)單網(wǎng)絡(luò)時(shí)間協(xié)議),用于跨廣域網(wǎng)或局域網(wǎng)同步時(shí)間的協(xié)議,主要用來(lái)同步因特網(wǎng)中的計(jì)算機(jī)時(shí)鐘,具有較高的精確度(幾十毫秒)。
SNTP協(xié)議相對(duì)于NTP,優(yōu)化了網(wǎng)絡(luò)傳播延時(shí)的影響,同時(shí)也能保證時(shí)間達(dá)到一定的精確度。
SNTP協(xié)議采用客戶端/服務(wù)器的工作方式,可以采用單播(點(diǎn)對(duì)點(diǎn))或者廣播(一點(diǎn)對(duì)多點(diǎn))模式操作。SNTP服務(wù)器通過(guò)接收 GPS信號(hào)或自帶的原子鐘作為系統(tǒng)的時(shí)間基準(zhǔn)。單播模式下,SNTP客戶端能夠通過(guò)定期訪問 SNTP服務(wù)器獲得準(zhǔn)確的時(shí)間信息,用于調(diào)整客戶端自身所在系統(tǒng)的時(shí)間,達(dá)到同步時(shí)間的目的。
時(shí)間戳
SNTP發(fā)送回來(lái)的時(shí)間戳是NTP時(shí)間戳。
NTP時(shí)間戳和UTC時(shí)間戳的主要區(qū)別在于它們的起始時(shí)間:
NTP時(shí)間戳的起始點(diǎn)是1900年1月1日00:00:00。
UTC時(shí)間戳(Unix時(shí)間戳)的起始點(diǎn)是1970年1月1日00:00:00。
軟件設(shè)計(jì)流程
流程圖
文件樹狀圖
.
├── include //sntp庫(kù)
│ └── lwip
│ └── apps
│ ├── sntp.h
│ └── sntp_opts.h
├── src //sntp源文件
│ ├── BUILD.gn
│ ├── sntp.c
│ ├── sntp_debug.c
│ ├── sntp_port.c
│ └── sntp_port.h
└── test //模塊主代碼
├── BUILD.gn
├── sntp_test.c //模塊源代碼
├── sntp_test.h //模塊接口、wifi配置
├── wifi_connecter.c //wifi連接庫(kù)
└── wifi_connecter.h
使用方法
- 下載源碼。
- 將SNTP文件夾放入applications/sample/wifi-iot/app路徑下。
- 在applications/sample/wifi-iot/app/BUILD.gn的features內(nèi)添加以下代碼。
"sntp/src:sntp",
"sntp/test:sntp_test",
在自己的主程序中引用sntp_test.h文件,調(diào)用set_sntp_init()函數(shù)初始化,隨后即可通過(guò)訪問sntp_time_sec變量獲取當(dāng)前時(shí)間(NTP時(shí)間戳0時(shí)區(qū))。
流程介紹
連接WIFI
連接的WIFI需要可以訪問互聯(lián)網(wǎng),否則設(shè)備無(wú)法聯(lián)網(wǎng)獲取時(shí)間。
WIFI當(dāng)前設(shè)置為:(配置在/sntp/test/sntp_test.h)。
- SSID:M20P
- PSK:12345678
設(shè)置SNTP服務(wù)器
常用SNTP服務(wù)器有以下四個(gè):
"cn.ntp.org.cn", // 中國(guó) NTP 快速授時(shí)服務(wù)
"ntp.ntsc.ac.cn", // 國(guó)家授時(shí)中心 NTP 服務(wù)器
"time.pool.aliyun.com", // 阿里云公共 NTP 服務(wù)器
"cn.pool.ntp.org", // 國(guó)際 NTP 快速授時(shí)服務(wù)
在本文章中,SNTP_SERVER_DNS默認(rèn)為0,因此我們使用IP進(jìn)行配置SNTP服務(wù)器。
#if SNTP_SERVER_DNS
static const char* g_ntpServerList[] = {
// refers from https://dns.icoa.cn/ntp/#china
"cn.ntp.org.cn", // 中國(guó) NTP 快速授時(shí)服務(wù)
"ntp.ntsc.ac.cn", // 國(guó)家授時(shí)中心 NTP 服務(wù)器
"time.pool.aliyun.com", // 阿里云公共 NTP 服務(wù)器
"cn.pool.ntp.org", // 國(guó)際 NTP 快速授時(shí)服務(wù)
};
#define SNTP_SERVERS ARRAY_SIZE(g_ntpServerList)
void SntpSetServernames(void)
{
for (size_t i = 0; i < SNTP_SERVERS; i++) {
sntp_setservername(i, g_ntpServerList[i]);
}
}
#else
ip4_addr_t g_ntpServerList[SNTP_MAX_SERVERS];
void SntpSetServers(void)
{
IP4_ADDR(&g_ntpServerList[0], 114, 67, 237, 130); // cn.ntp.org.cn
IP4_ADDR(&g_ntpServerList[1], 114, 118, 7, 163); // ntp.ntsc.ac.cn
IP4_ADDR(&g_ntpServerList[2], 182, 92, 12, 11); // time.pool.aliyun.com
IP4_ADDR(&g_ntpServerList[3], 193, 182, 111, 12); // cn.pool.ntp.org
#define SNTP_SERVERS 4
for (size_t i = 0; i < SNTP_SERVERS; i++) {
sntp_setserver(i, (ip_addr_t*)&g_ntpServerList[i]);
}
}
#endif
void set_sntp_init(void)
{
/****************************/
#if SNTP_SERVER_DNS
ip4_addr_t dnsServerAddr;
IP4_ADDR(&dnsServerAddr, 192, 168, 1, 1);
dns_setserver(0, (struct ip_addr *)&dnsServerAddr);
dns_init();
SntpSetServernames();
#else
SntpSetServers();
#endif
/****************************/
}
SNTP初始化以及獲取時(shí)間
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_init();
printf("sntp_enabled: %d\r\n", sntp_enabled());
for (size_t i = 0; i < SNTP_SERVERS; i++) {
printf("sntp_getreachability(%d): %d\r\n", i, sntp_getreachability(i));
}
osDelay(500);
for (size_t i = 0; i < SNTP_SERVERS; i++) {
printf("sntp_getreachability(%d): %d\r\n", i, sntp_getreachability(i));
}
時(shí)間顯示
本樣例源碼僅作為一個(gè)底層模塊,因此尚未有主程序。可以自行創(chuàng)建一個(gè)主程序進(jìn)行測(cè)試獲取時(shí)間,或者按照以下方式修改源碼:在sntp/test/sntp_test.c的SntpSetServers函數(shù)末尾添加以下代碼(顯示獲取到的時(shí)間):
time_t ut;
ut = (unsigned int)((unsigned int)sntp_time_sec + ((unsigned int)2085978496L)); //轉(zhuǎn)換成UTC時(shí)間(0時(shí)區(qū))
struct tm *now_time = gmtime(&ut);
printf("%d %d %d\n", now_time->tm_hour, now_time->tm_min, now_time->tm_sec);
在sntp/test/sntp_test.c末尾添加以下代碼(開機(jī)自啟動(dòng)):
SYS_RUN(set_sntp_init);
測(cè)試
文章相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往下載:
https://ost.51cto.com/resource/3095。