9.16. เวลาและ NTP¶
กล้องที่เพิ่งเปิดใช้งานใหม่ไม่ทราบว่าเวลาปัจจุบันคืออะไร นาฬิกาภายในเครื่องเริ่มต้นจากจุดที่กำหนดโดยพลการ (1970-01-01 บนบอร์ดส่วนใหญ่) และนับเพิ่มขึ้นจากนั้นจนกว่าจะมีสิ่งใดมาบอกให้เปลี่ยนแปลง NTP -- Network Time Protocol -- คือวิธีที่กล้องขอเวลานาฬิกาจริงจากเครือข่ายและตั้งนาฬิกาของตัวเองตามคำตอบที่ได้รับ
9.16.1. เหตุใดกล้องจึงต้องรู้เวลา¶
สำหรับสคริปต์หลายอย่าง นาฬิกาของกล้องไม่สำคัญ -- ลูปจับภาพเฟรมไม่สนใจว่าวันนี้เป็นวันอะไร แต่สำหรับบางสิ่งที่พบบ่อย เวลาสำคัญมาก:
การประทับเวลาในล็อกหรือข้อมูลที่อัปโหลด รายการที่ระบุว่า
1970-01-01ทั้งหมดนั้นเข้าใจยากในภายหลังงานตามตารางเวลา "รันเวลา 03:00" ต้องให้กล้องรู้ว่าเวลา 03:00 คือเมื่อไหร่
9.16.2. NTP ทำงานอย่างไร¶
NTP เป็นบริการสาธารณะขนาดเล็ก ประกอบด้วยเครือข่ายเซิร์ฟเวอร์ที่ตอบคำถาม "เวลาเท่าไหร่แล้ว?" ผ่านการแลกเปลี่ยน UDP ครั้งเดียว กล้องส่งคำขอสั้น ๆ ไปยังเซิร์ฟเวอร์ NTP ที่รู้จัก เซิร์ฟเวอร์ตอบกลับพร้อมการประทับเวลาที่แม่นยำ (แม่นยำถึงไม่กี่มิลลิวินาทีสำหรับเซิร์ฟเวอร์สาธารณะทั่วไป) จากนั้นกล้องใช้ข้อมูลนั้นตั้งนาฬิกาของตัวเอง เซิร์ฟเวอร์เริ่มต้นที่กล้องใช้คือ pool.ntp.org ซึ่งเป็นกลุ่มเซิร์ฟเวอร์ที่กระจายโหลดทั่วโลก ออกแบบมาเพื่อไคลเอนต์ประเภทนี้โดยเฉพาะ
9.16.3. Python API: ntptime¶
MicroPython รวมโปรโตคอลไว้ในการเรียกใช้ครั้งเดียว รูปแบบที่ใช้ทั่วไปคือเชื่อมต่อลิงก์ก่อน จากนั้นจึงขอเวลาจาก NTP:
import network
import ntptime
import time
wlan = network.WLAN(network.WLAN.IF_STA)
wlan.active(True)
wlan.connect("my-network", "my-password")
while not wlan.isconnected():
time.sleep_ms(100)
ntptime.settime() # cam's clock is now UTC
print(time.localtime())
หลังจาก ntptime.settime() คืนค่าแล้ว นาฬิกาเรียลไทม์ภายในเครื่องและ time.localtime() จะสะท้อนเวลา UTC ปัจจุบัน มีตัวปรับสองตัวสำหรับค่าเริ่มต้น:
ntptime.hostคือชื่อเซิร์ฟเวอร์ที่จะสอบถาม กำหนดค่าใหม่ (ntptime.host = "time.google.com") ก่อนเรียกsettime()เพื่อชี้ไปยังเซิร์ฟเวอร์อื่นntptime.timeoutคือจำนวนวินาทีที่รอการตอบกลับก่อนยกเลิก ค่าเริ่มต้นสั้นมาก
9.16.4. ควรเรียกใช้เมื่อใด¶
หลังจากลิงก์เครือข่ายทำงานแล้ว NTP ทำงานบน UDP ซึ่งทำงานบน IP setup ที่ตั้งค่าไว้แล้ว รอให้
isconnected()คืนค่าTrueก่อนเป็นระยะสำหรับกล้องที่ทำงานนาน นาฬิกาภายในเครื่องจะเดินช้าลงตามชั่วโมงและวัน การเรียก
settime()รายวันหรือรายสัปดาห์จะรักษาความแม่นยำ
9.16.5. เขตเวลา¶
NTP คืนเวลา UTC MicroPython ไม่มีฐานข้อมูลเขตเวลา ดังนั้นการแปลง UTC เป็นเวลาท้องถิ่นจึงเป็นหน้าที่ของสคริปต์ วิธีที่ใช้บ่อยคือใช้ค่าชดเชยคงที่สำหรับเขตเวลาของการใช้งาน:
import time
offset = -5 * 3600 # hours -> seconds, US Eastern
local = time.localtime(time.time() + offset)
print(local)
วิธีนี้ไม่รองรับการปรับเวลาตามฤดูกาล (Daylight Saving Time) วินาทีอธิกสุรทิน และการเปลี่ยนแปลงเขตเวลาในประวัติศาสตร์ สำหรับการใช้งานกล้องส่วนใหญ่ ค่าชดเชยคงที่ก็เพียงพอแล้ว หากสคริปต์ต้องการเวลาพลเรือนพร้อมการปรับเวลาตามฤดูกาลจริง ๆ ให้ทำการแปลงฝั่งเซิร์ฟเวอร์แทน
9.16.6. สิ่งที่อาจผิดพลาด¶
ยังไม่มีเครือข่าย
ntptime.settime()จะส่งOSErrorหากไม่สามารถเข้าถึงเซิร์ฟเวอร์ได้ ไม่ว่าจะเป็นเพราะลิงก์ยังไม่ทำงาน การค้นหาชื่อล้มเหลว เซิร์ฟเวอร์ไม่สามารถเข้าถึงได้ หรือไม่มีการตอบกลับภายในntptime.timeoutลองใหม่เมื่อลิงก์เสถียรCaptive portals เครือข่าย Wi-Fi ที่ดักจับ DNS อาจตอบชื่อเซิร์ฟเวอร์ NTP ด้วย IP ของพอร์ทัลเอง และคำขอ NTP ที่ส่งไปจะได้รับข้อมูลที่ผิดพลาด กล้องจะคิดว่าเครือข่ายทำงานปกติแต่การตั้งเวลาจะล้มเหลวหรือผิดพลาดอย่างมาก ให้เปลี่ยนไปใช้เครือข่ายที่ไม่มีการดักจับหรือระบุ IP แบบตายตัว
การส่งคำขอถี่เกินไปไปยัง public pools NTP pools สาธารณะมีการจำกัดอัตราสำหรับไคลเอนต์ที่ใช้งานมากเกินไป การส่งคำขอหนึ่งครั้งต่อชั่วโมงเพียงพอแล้ว หากส่งทุกนาทีกล้องอาจถูกแบน
สำหรับข้อมูลอ้างอิง ntptime ฉบับสมบูรณ์ โปรดดู ntptime --- ไคลเอนต์ NTP แบบง่าย