NTP stands for Network Time Protocol and it is a networking protocol for clock synchronization between computer systems. In other words, it is used to synchronize computer clock times in a network.
There are NTP servers like pool.ntp.org that anyone can use to request time as a client. In this case, the ESP8266 is an NTP Client that requests time from an NTP Server (pool.ntp.org).
台灣國家時間與頻率標準實驗室 – NTP Server
time.stdtime.gov.tw
tock.stdtime.gov.tw
watch.stdtime.gov.tw
clock.stdtime.gov.tw
tick.stdtime.gov.tw
Apple – NTP Server
time.asia.apple.com (亞洲)
time.apple.com (美洲)
time.euro.apple.com (歐洲)
微軟Microsoft – NTP Server
time.windows.com
Facebook – NTP Server
time1.facebook.com
time2.facebook.com
time3.facebook.com
time4.facebook.com
time5.facebook.com
參考:https://engineering.fb.com/production-engineering/ntp-service/
TAIWAN: UTC+8
使用 NTP 協定由 NTP 時間伺服器抓取時間
利用由 NTP 時間伺服器抓取到的時間進行物聯網控制
程式庫 Arduino Time Library
本實作使用作者 Github 提供之最新版本函式庫
草稿碼 > 匯入程式庫 > 加入 .ZIP 程式庫
成功加入 .ZIP 程式庫後,可檢查看
或 離線版 TUNIOT(執行資料夾中 demo/code/index.html)
IOT > Web Services > Time
#include <TimeLib.h>
#include <WiFiUdp.h>
char ntpServerName[] = "us.pool.ntp.org";
int timeZone = 0;
WiFiUDP Udp;
unsigned int localPort = 8888;
time_t getNtpTime();
int digitalClockDisplay(char d);
void printDigits(int digits);
void sendNTPpacket(IPAddress &address);
int digitalClockDisplay(char m){
int interm;
if (m=='h'){
interm=hour();
return interm;
}
if (m=='m'){
interm=minute();
return interm;
}
if (m=='s'){
interm=second();
return interm;
}
if (m=='w'){
interm=weekday();
return interm;
}
if (m=='j'){
interm=day();
return interm;
}
if (m=='n'){
interm=month();
return interm;
}
if (m=='y'){
interm=year();
return interm;
}
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP server's ip address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request");
// get a random server from the pool
WiFi.hostByName(ntpServerName, ntpServerIP);
Serial.print(ntpServerName);
Serial.print(":");
Serial.println(ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
void sendNTPpacket(IPAddress &address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
==============================================
setup(){
......
Udp.begin(localPort);
setSyncProvider(getNtpTime);
setSyncInterval(300);
}
==============================================
loop(){
......
digitalClockDisplay('s');
}
完成之積木程式
儲存積木檔(.xml),儲存 Arduino 程式碼(.ino)
Arduino IDE 開啟載入程式碼(.ino),選擇正確控制板,選擇正確連接埠,上傳燒錄。開啟序列埠視窗,baudrate 9600
利用 NTP 校時抓取到的時間,於指定時間開關 LED 燈(電器)。
同 1.1
或 離線版 TUNIOT(執行資料夾中 demo/code/index.html)
完成之積木程式
led1State = digitalRead(D0);
儲存積木檔(.xml),儲存 Arduino 程式碼(.ino)
Arduino IDE 開啟載入程式碼(.ino),選擇正確控制板,選擇正確連接埠,上傳燒錄。開啟序列埠視窗,baudrate 9600
同 1.1
使用之 ThingSpeak Channel:
擬定:
field1: 0(不啟用),1(啟用)
field2: 時
field3: 分
field4: 腳位 GPIO(D4: GPIO2,D5: GPIO14,D6: GPIO12)
field5: 1(HIGH,開),0(LOW,關)
或 離線版 TUNIOT(執行資料夾中 demo/code/index.html)
完成之積木程式
gpioState = digitalRead(gpio);
digitalWrite(gpio, setValue);
儲存積木檔(.xml),儲存 Arduino 程式碼(.ino)
Arduino IDE 開啟載入程式碼(.ino),選擇正確控制板,選擇正確連接埠,上傳燒錄。開啟序列埠視窗,baudrate 9600
使用之 ThingSpeak Channel:
設定:
field1: 0(不啟用),1(啟用)
field2: 時
field3: 分
field4: 腳位 GPIO(D4: GPIO2,D5: GPIO14,D6: GPIO12)
field5: 1(HIGH,開),0(LOW,關)
設定 21:55, GPIO 14 ON
以瀏覽器下 ThingSpeak API 控制
https://api.thingspeak.com/update?api_key=TXTHGUCP576ZLMDM&field1=1&field2=21&field3=55&field4=14&field5=1
21:57, GPIO 14 OFF
https://api.thingspeak.com/update?api_key=TXTHGUCP576ZLMDM&field1=1&field2=21&field3=57&field4=14&field5=0
不啟用
https://api.thingspeak.com/update?api_key=TXTHGUCP576ZLMDM&field1=0&field2=21&field3=57&field4=14&field5=0
同 1.1
使用之 ThingSpeak Channel:
擬定:
field1: 0(不啟用),1(啟用)
field2: 時
field3: 分
控制腳位:(D4, D5, D6)
field4: 0(0,0,0);1(1,0,0);2(0,1,0);3(1,1,0);4(0,0,1);5(1,0,1);6(0,1,1);7(1,1,1)
或 離線版 TUNIOT(執行資料夾中 demo/code/index.html)