Sfoglia il codice sorgente

Add NTP client README.md and some apis.

armink 8 anni fa
parent
commit
cf8debf80f
4 ha cambiato i file con 224 aggiunte e 39 eliminazioni
  1. 76 1
      ntp/README.md
  2. 91 36
      ntp/ntp.c
  3. 55 0
      ntp/ntp.h
  4. 2 2
      tftp/tftp_opts.h

+ 76 - 1
ntp/README.md

@@ -1 +1,76 @@
-Coming soon...
+# NTP:网络时间协议
+
+## 1、介绍
+
+[NTP](https://baike.baidu.com/item/NTP) 是网络时间协议(Network Time Protocol),它是用来同步网络中各个计算机时间的协议。
+
+在 RT-Thread 上实现了 NTP 客户端,连接上网络后,可以获取当前 UTC 时间,并更新至 RTC 中。
+
+## 2、使用
+
+### 2.1 获取 UTC 时间
+
+[UTC 时间](https://baike.baidu.com/item/%E5%8D%8F%E8%B0%83%E4%B8%96%E7%95%8C%E6%97%B6/787659?fromtitle=UTC&fromid=5899996) 又称世界统一时间、世界标准时间、国际协调时间。北京时间为 UTC+8 时间,比 UTC 时间多 8 小时,或者理解为早 8 小时。
+
+API: `time_t ntp_get_time(void)`
+
+|参数                                    |描述|
+|:-----                                  |:----|
+|return                                  |`>0`: 当前 UTC 时间,`=0`:获取时间失败|
+
+
+示例代码:
+
+```C
+#include <ntp.h>
+
+void main(void)
+{
+    time_t cur_time;
+
+    cur_time = ntp_get_time();
+    
+    if (cur_time)
+    {
+        rt_kprintf("NTP Server Time: %s", ctime((const time_t*) &cur_time));
+    }
+}
+```
+
+### 2.2 获取本地时间
+
+本地时间比 UTC 时间多了时区的概念,例如:北京时间为东八区,比 UTC 时间多 8 个小时。
+
+在 `menuconfig` 中可以设置当前时区,默认为 `8`
+
+API: `time_t ntp_get_local_time(void)`
+
+|参数                                    |描述|
+|:-----                                  |:----|
+|return                                  |`>0`: 当前本地时间,`=0`:获取时间失败|
+
+该 API 使用方法与 `ntp_get_time()` 类似
+
+### 2.3 同步本地时间至 RTC
+
+如果开启 RTC 设备,还可以使用下面的命令及 API 同步 NTP 的本地时间至 RTC 设备。
+
+Finsh/MSH 命令效果如下:
+
+```
+msh />ntp_sync
+Get local time from NTP server: Sat Feb 10 15:22:33 2018
+The system time is updated. Timezone is 8.
+msh />
+```
+
+API: `time_t ntp_sync_to_rtc(void)`
+
+|参数                                    |描述|
+|:-----                                  |:----|
+|return                                  |`>0`: 当前本地时间,`=0`:同步时间失败|
+
+## 3、注意事项
+
+- 1、NTP API 方法执行时会占用较多的线程堆栈,使用时保证堆栈空间充足(≥1.5K);
+- 2、NTP API 方法 **不支持可重入** ,并发使用时,请注意加锁。

+ 91 - 36
ntp/ntp.c

@@ -1,7 +1,7 @@
 /*
  *
  * (C) 2014 David Lettier.
- * (C) 2017 Armink (armink.ztl@gmail.com)
+ * (C) 2018 Armink (armink.ztl@gmail.com)
  *
  * http://www.lettier.com/
  *
@@ -22,18 +22,29 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
 #include <rtthread.h>
 
-#define NTP_TIMESTAMP_DELTA 2208988800ull
-#define NTP_GET_TIMEOUT     10
+#ifdef NETUTILS_NTP_TIMEZONE
+#define NTP_TIMEZONE                   NETUTILS_NTP_TIMEZONE
+#endif
+
+#ifdef NETUTILS_NTP_HOSTNAME
+#define NTP_HOSTNAME                   NETUTILS_NTP_HOSTNAME
+#endif
+
+#define NTP_TIMESTAMP_DELTA            2208988800ull
+#define NTP_GET_TIMEOUT                10
+
+#ifndef NTP_TIMEZONE
+#define NTP_TIMEZONE                   8
+#endif
 
-#ifndef NTP_TIMEZONE_DEAULT
-#define NTP_TIMEZONE_DEAULT 8
+#ifndef NTP_HOSTNAME
+#define NTP_HOSTNAME                   "cn.pool.ntp.org"
 #endif
 
 #define LI(packet)   (uint8_t) ((packet.li_vn_mode & 0xC0) >> 6) // (li   & 11 000 000) >> 6
@@ -72,20 +83,31 @@ typedef struct {
 
 static ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-static void error(char* msg)
+static void ntp_error(char* msg)
 {
-    printf("[NTP]: %s\n", msg); // Print the error message to stderr.
+    rt_kprintf("\033[31;22m[E/NTP]: ERROR %s\033[0m\n", msg); // Print the error message to stderr.
 }
 
-void ntp( int argc, char* argv[])
+/**
+ * Get the UTC time from NTP server
+ *
+ * @note this function is not reentrant
+ *
+ * @return >0: success, current UTC time
+ *         =0: get failed
+ */
+time_t ntp_get_time(void)
 {
     int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket.
 
     int portno = 123; // NTP UDP port number.
 
-    char* host_name = "cn.pool.ntp.org"; // NTP server host-name.
+    char* host_name = NTP_HOSTNAME; // NTP server host-name.
 
-    struct tm time_new;
+    time_t new_time = 0;
+
+    fd_set readset;
+    struct timeval timeout;
 
     // Create and zero out the packet. All 48 bytes worth.
 
@@ -104,14 +126,14 @@ void ntp( int argc, char* argv[])
     sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Create a UDP socket.
 
     if (sockfd < 0) {
-        error("ERROR opening socket");
+        ntp_error("opening socket");
         goto __exit;
     }
 
     server = gethostbyname(host_name); // Convert URL to IP.
 
     if (server == NULL) {
-        error("ERROR, no such host");
+        ntp_error("no such host");
         goto __exit;
     }
 
@@ -132,7 +154,7 @@ void ntp( int argc, char* argv[])
     // Call up the server using its IP address and port number.
 
     if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
-        error("ERROR connecting");
+        ntp_error("connecting");
         goto __exit;
     }
 
@@ -141,12 +163,10 @@ void ntp( int argc, char* argv[])
     n = write(sockfd, (char*) &packet, sizeof(ntp_packet));
 
     if (n < 0) {
-        error("ERROR writing to socket");
+        ntp_error("writing to socket");
         goto __exit;
     }
 
-    fd_set readset;
-    struct timeval timeout;
     timeout.tv_sec = NTP_GET_TIMEOUT;
     timeout.tv_usec = 0;
 
@@ -154,7 +174,7 @@ void ntp( int argc, char* argv[])
     FD_SET(sockfd, &readset);
 
     if (select(sockfd + 1, &readset, RT_NULL, RT_NULL, &timeout) <= 0) {
-        error("ERROR select the socket timeout(10s)");
+        ntp_error("select the socket timeout(10s)");
         goto __exit;
     }
 
@@ -163,7 +183,7 @@ void ntp( int argc, char* argv[])
     n = read(sockfd, (char*) &packet, sizeof(ntp_packet));
 
     if (n < 0) {
-        error("ERROR reading from socket");
+        ntp_error("reading from socket");
         goto __exit;
     }
 
@@ -179,33 +199,68 @@ void ntp( int argc, char* argv[])
     // This leaves the seconds since the UNIX epoch of 1970.
     // (1900)------------------(1970)**************************************(Time Packet Left the Server)
 
-    time_t txTm = (time_t) (packet.txTm_s - NTP_TIMESTAMP_DELTA);
+    new_time = (time_t) (packet.txTm_s - NTP_TIMESTAMP_DELTA);
 
-    // Print the time we got from the server, accounting for local timezone and conversion from UTC time.
+__exit:
 
-    printf("NTP Server Time: %s", ctime((const time_t*) &txTm));
+    close(sockfd);
 
-    /* add the timezone offset for set_time/set_date */
-    txTm += NTP_TIMEZONE_DEAULT * 3600;
+    return new_time;
+}
 
-    localtime_r(&txTm, &time_new);
+/**
+ * Get the local time from NTP server
+ *
+ * @return >0: success, current local time, offset timezone by NTP_TIMEZONE
+ *         =0: get failed
+ */
+time_t ntp_get_local_time(void)
+{
+    time_t cur_time = ntp_get_time();
+
+    if (cur_time)
+    {
+        /* add the timezone offset for set_time/set_date */
+        cur_time += NTP_TIMEZONE * 3600;
+    }
+
+    return cur_time;
+}
 
 #ifdef RT_USING_RTC
-    set_time(time_new.tm_hour, time_new.tm_min, time_new.tm_sec);
-    set_date(time_new.tm_year + 1900, time_new.tm_mon + 1, time_new.tm_mday);
-#endif
+/**
+ * Sync current local time to RTC by NTP
+ *
+ * @return >0: success, current local time, offset timezone by NTP_TIMEZONE
+ *         =0: sync failed
+ */
+time_t ntp_sync_to_rtc(void)
+{
+    struct tm cur_tm;
+    time_t cur_time = ntp_get_local_time();
 
-    printf("The system time is updated. Timezone is %d.\n", NTP_TIMEZONE_DEAULT);
+    if (cur_time)
+    {
+        set_time(cur_tm.tm_hour, cur_tm.tm_min, cur_tm.tm_sec);
+        set_date(cur_tm.tm_year + 1900, cur_tm.tm_mon + 1, cur_tm.tm_mday);
+    }
 
-__exit:
+    return cur_time;
+}
 
-    close(sockfd);
+void cmd_ntp_sync(void)
+{
+    time_t cur_time = ntp_sync_to_rtc();
+
+    if (cur_time)
+    {
+        rt_kprintf("Get local time from NTP server: %s", ctime((const time_t*) &cur_time));
+        rt_kprintf("The system time is updated. Timezone is %d.\n", NTP_TIMEZONE);
+    }
 }
+
 #ifdef RT_USING_FINSH
 #include <finsh.h>
-FINSH_FUNCTION_EXPORT(ntp, Update time by NTP(Network Time Protocol));
-#ifdef FINSH_USING_MSH
-MSH_CMD_EXPORT(ntp, Update time by NTP(Network Time Protocol));
-#endif /* FINSH_USING_MSH */
+FINSH_FUNCTION_EXPORT_ALIAS(cmd_ntp_sync, __cmd_ntp_sync, Update time by NTP(Network Time Protocol));
 #endif /* RT_USING_FINSH */
-
+#endif /* RT_USING_RTC */

+ 55 - 0
ntp/ntp.h

@@ -0,0 +1,55 @@
+/*
+ * File      : ntp.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-10     armink       the first version
+ */
+#ifndef _NTP_H_
+#define _NTP_H_
+
+#include <time.h>
+
+/**
+ * Get the UTC time from NTP server
+ *
+ * @note this function is not reentrant
+ *
+ * @return >0: success, current UTC time
+ *         =0: get failed
+ */
+time_t ntp_get_time(void);
+
+/**
+ * Get the local time from NTP server
+ *
+ * @return >0: success, current local time, offset timezone by NTP_TIMEZONE
+ *         =0: get failed
+ */
+time_t ntp_get_local_time(void);
+
+/**
+ * Sync current local time to RTC by NTP
+ *
+ * @return >0: success, current local time, offset timezone by NTP_TIMEZONE
+ *         =0: sync failed
+ */
+time_t ntp_sync_to_rtc(void);
+
+#endif /* _NTP_H_ */

+ 2 - 2
tftp/tftp_opts.h

@@ -59,8 +59,8 @@
 /**
  * TFTP server port
  */
-#if defined PKG_NETUTILS_TFTP_PORT
-#define TFTP_PORT             PKG_NETUTILS_TFTP_PORT
+#if defined NETUTILS_TFTP_PORT
+#define TFTP_PORT             NETUTILS_TFTP_PORT
 #elif !defined TFTP_PORT
 #define TFTP_PORT             69
 #endif