Mokoversity 在 2015 年 3 月 19 日舉辦一個免費課程:Ethernet IoT Kit 與 Virtual DOM 技術。這是台灣第一場 ARM mbed 課程。課堂上,筆者談到「IoT 裝置的時間問題」。這是一個未來可能會浮上臺面,但目前還未被提出討論的技術議題。要讓 IoT 裝置進行時間同步,若涉及整體的 IoT Cloud 架構,事情可能沒這麼簡單。
不過,目前可以使用 NTP 來暫時解決這個問題。NTP(Network Time Protocol)是一個非常古老的通訊協定,也是少數目前仍在運作中的元老級網路技術。ARM mbed 社群實作了 NTPClient 程式庫,可以很容易讓 IoT 裝置經由 NTP 進行時間同步。
利用 Import Wizard 將底下的 NTPClient 匯入專案:
http://developer.mbed.org/users/donatien/code/NTPClient/
並引入所需的標頭檔:
#include "NTPClient.h"
接著,取得 NTPClient 的實例化:
NTPClient ntp;
使用 NTP Pool Project 的主機服務,任意選取一台主機名稱:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
- 3.pool.ntp.org
讓 mbed 裝置連上 NTP Pool 主機:
ntp.setTime("0.pool.ntp.org");
NTPClient 自動同步 mbed 裝置的時間。如果想取得目前的時間,可以使用 mbed 的標準函數-time(),用法與 libc 的 time() 相同:
if (ntp.setTime("0.pool.ntp.org") == 0)
// Set time successfully.
{
time_t ctTime;
// Get the current time.
ctTime = time(NULL);
// Print out the current time.
printf("Time is now (UTC): %s\r\n", ctime(&ctTime));
// Convert it to local time representation.
struct tm *locTime;
locTime = localtime(&ctTime);
// Print out the date and time in the standard format.
printf("%s\r\n", asctime(locTime));
}
如此一來,就能為推送出去的數據裡加上時間截記(timestamp)了。修改上述範例如下:
#include "mbed.h"
#include "EthernetInterface.h"
#include "Websocket.h"
#include "NTPClient.h"
// Ethernet Status
DigitalOut led1(LED1);
DigitalOut led2(LED2);
int main()
{
char data[256];
time_t ctTime;
// Ethernet Interface
EthernetInterface eth;
// Network Time Protocol
NTPClient ntp;
// init status
led1 = 1;
led2 = 1;
// 使用 DHCP
eth.init();
eth.connect();
led1 = 0;
// 同步時間
if (ntp.setTime("0.pool.ntp.org") == 0)
{
ctTime = time(NULL);
printf("Time is now (UTC): %s\r\n", ctime(&ctTime));
}
// 與 WoT.City 建立 Websocket 連線
Websocket ws("ws://wot.city/object/jollentemp1/send");
// 不斷 Retry,直到連線成功
while( !ws.connect() );
led2 = 0;
// 每隔 1 秒,推送一筆數據至 WoT.City
while(1) {
wait(1.0);
ctTime = time(NULL);
sprintf(data , "{ \"temperature\": %f, \"time\": \"%s\" }", 25.0, ctime(&ctTime));
ws.send(data);
}
}