การเรียกใช้เวลามาตรฐาน NTP

การดึงค่าเวลามาตรฐานสากลจากอินเตอร์เน็ต จะดึงจาก Server ที่ให้บริการโพรโทคอล NTP โดย NTP Server มีอยู่ด้วยกันหลายที่

คำว่า "NTP” จาก https://www.thaicert.or.th/papers/technical/2014/pa2014te002.html ได้อธิบายความหมายของ ว่า NTP หรือที่ย่อมาจากคำว่า Network Time Protocol เป็นโพรโทคอลสำหรับการเทียบเวลามาตรฐานและตั้งค่าเวลาบนเครื่องคอมพิวเตอร์นั้นๆผ่านระบบเครือข่าย ส่วนใหญ่ถูกนำมาใช้ในองค์กรเพื่อช่วยทำให้เวลาในเครื่องคอมพิวเตอร์หรือเครื่องแม่ข่ายนั้นมีค่าตรงกัน โดยรูปแบบการทำงานนั้นแบ่งเป็น 2 ส่วนหลักๆคืออุปกรณ์ที่ให้บริการเทียบเวลา (NTP Server) กับเครื่องคอมพิวเตอร์หรืออุปกรณ์ที่ต้องการเทียบเวลา (NTP Client) โดยโพรโทคอล NTP นั้นเชื่อมต่อผ่านทางระบบเครือข่ายด้วยโพรโทคอล UDP ผ่านพอร์ต 123 (โพรโทคอล UDP มีความรวดเร็วในการรับส่งข้อมูลแต่ก็มีข้อเสียตรงที่โพรโทคอล UDP ไม่มีการตรวจสอบความถูกต้องของข้อมูลที่รับส่งกันอยู่เหมือน TCP)”

วัตถุประสงค์

ใช้ ESP8266 NodeMCU สร้าง Station เพื่อดึงค่าเวลามาตรฐานจาก NTP Server แล้วแสดงผลทาง Serial monitor

อุปกรณ์

    1. ESP8266 NodeMCU

    2. บอร์ดทดลอง (Breadboard)

ตัวอย่างโปรแกรม ใช้ไลบรารี Time.h และใช้ ฟังก์ชั่นมาตรฐาน localtime() or gmtime() and the struct tm. เพื่อดึงค่าเป็น วัน-เดือน-ปี ชม- นาที และ วินาที ค่าที่ดึงได้นี้จะเป็นตัวเลข ใช้การแปลงจากตัวเลขวัน ตัวเลขเดือน ให้เป็นชื่อเดือน ชื่อวัน ส่วนปี ค.ศ. เปลี่ยนเป็นปี พ.ศ.

โปรแกรม time_ntp3.ino

#include <ESP8266WiFi.h>

#include <Time.h>

const char* ssid = "TOT"; // your network SSID (name)

const char* password = "0815610067"; // your network password

const String month_name[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

const String day_name[7] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};

int timezone = 7 * 3600; //ตั้งค่า TimeZone ตามเวลาประเทศไทย

int dst = 0; //กำหนดค่า Date Swing Time

void setup()

{

Serial.begin(115200);

Serial.setDebugOutput(true);

WiFi.mode(WIFI_STA); //เชื่อมต่อ Wifi

WiFi.begin(ssid, password);

Serial.println("\nConnecting to WiFi");

while (WiFi.status() != WL_CONNECTED)

{

Serial.print("*");

delay(1000);

}

configTime(timezone, dst, "pool.ntp.org", "time.nist.gov"); //ดึงเวลาจาก Server

Serial.println("\nLoading time");

while (!time(nullptr)) {

Serial.print("*");

delay(1000);

}

Serial.println("");

}

void loop()

{

//แสดงเวลาปัจจุบัน

time_t now = time(nullptr);

struct tm* p_tm = localtime(&now);

Serial.print(p_tm->tm_hour);

Serial.print(":");

Serial.print(p_tm->tm_min);

Serial.print(":");

Serial.print(p_tm->tm_sec);

Serial.print(" / ");

Serial.print(day_name[(p_tm->tm_wday)]);

Serial.print("/");

Serial.print(p_tm->tm_mday);

Serial.print(" / ");

Serial.print(month_name[(p_tm->tm_mon)]);

Serial.print(" / ");

Serial.print(p_tm->tm_year + 2443);

Serial.println("");

delay(1000);

}

ความหมาย

1. configTime จาก https://github.com/esp8266/Arduino/blob/9913e5210779d2f3c4197760d6813270dbba6232/cores/esp8266/time.c#L58 มีรายละเอียดดังนี้

void configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)

{

sntp_stop();

setServer(0, server1);

setServer(1, server2);

setServer(2, server3);

sntp_set_timezone(timezone/3600);

sntp_set_daylight(daylightOffset_sec);

sntp_init();

}

int timezone = 7 * 3600;

ถ้าเป็น San Francisco TimeZone เป็น GMT-7

int timezone = -7 * 3600;

(1) timezone ของกรุงเทพเป็น GMT+7 จึงเท่ากับ 7 * 3600

(2) daylightOffset_sec ค่า Date Swing Time เป็นวินาที

(3) server สามารถกำหนด Server ได้ตั้งแต่ 1 ถึง 3 ที่ เช่นถ้าต้องการใช้ NTP Server ของไทยที่มีอยู่หลายแห่งเช่น

ตัวอย่าง configTime(timezone, dst, "time.navy.mi.th");

2. โครงสร้างของตัวแปร tm มีดังนี้

struct tm {

int tm_sec; // วินาที, มีค่าตั้งแต่ 0 ถึง 59

int tm_min; // นาที, มีค่าตั้งแต่ 0 ถึง 59

int tm_hour; // ชั่วโมง, มีค่าตั้งแต่ 0 ถึง 23

int tm_mday; // วันที่, มีค่าตั้งแต่ 1 ถึง 31

int tm_mon; // เดือน, มีค่าตั้งแต่ 0 ถึง 11

int tm_year; // ปีคริสศักราช ตั้งแต่ 1900

int tm_wday; // วัน, มีค่าตั้งแต่ 0 ถึง 6

int tm_yday; // วันใน 1 ปี, มีค่าตั้งแต่ 0 ถึง 365

int tm_isdst; // daylight saving time

};

วิธีการเรียกใช้ดูจากตัวอย่างในโปรแกรม

การทดสอบ

1. เมื่อแปลและ Upload ลงไปบน ESP8266 NodeMCU ให้เปิด Serial Monitor (อย่าลืมใช้ Baud Rate 115200) ผลลัพธ์ควรได้ทำนองนี้