9.16. Thời gian và NTP

Một camera vừa được bật nguồn không biết bây giờ là mấy giờ. Đồng hồ tích hợp bắt đầu từ một thời điểm tùy ý (1970-01-01 trên hầu hết các bo mạch) và đếm tiến từ đó cho đến khi có thứ gì đó báo cho nó biết khác đi. NTP -- Giao thức Thời gian Mạng -- là cách camera hỏi mạng để lấy thời gian thực tế và tự đặt đồng hồ theo câu trả lời.

9.16.1. Tại sao camera cần biết thời gian

Với nhiều tập lệnh, đồng hồ của camera không quan trọng -- một vòng lặp chụp ảnh không cần biết hôm nay là ngày gì. Nhưng với một số tác vụ phổ biến, điều này lại rất quan trọng:

  • Dấu thời gian trong nhật ký hoặc dữ liệu tải lên. Các mục đều ghi 1970-01-01 rất khó có ý nghĩa khi xem lại.

  • Các tác vụ theo lịch trình. "Chạy lúc 03:00" yêu cầu camera biết 03:00 là lúc nào.

9.16.2. NTP làm gì

NTP là một dịch vụ công cộng nhỏ: một mạng lưới máy chủ trả lời câu hỏi "bây giờ là mấy giờ?" qua một lần trao đổi UDP duy nhất. Camera gửi một yêu cầu ngắn đến một máy chủ NTP đã biết; máy chủ phản hồi với một dấu thời gian chính xác (chính xác đến vài mili giây với bất kỳ máy chủ công cộng thông thường nào); camera dùng thông tin đó để đặt đồng hồ của mình. Máy chủ mặc định mà camera sử dụng là pool.ntp.org, một nhóm cân bằng tải toàn cầu được thiết kế chính xác cho loại client này.

9.16.3. API Python: ntptime

MicroPython bọc giao thức này vào một lệnh duy nhất. Cách thức phổ biến là bật kết nối trước, sau đó yêu cầu NTP cung cấp thời gian:

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())

Sau khi ntptime.settime() trả về, đồng hồ thời gian thực tích hợp và time.localtime() phản ánh thời gian UTC hiện tại. Hai tùy chọn để điều chỉnh mặc định:

  • ntptime.host là tên máy chủ để truy vấn. Ghi đè nó (ntptime.host = "time.google.com") trước khi gọi settime() để trỏ đến một máy chủ khác.

  • ntptime.timeout là số giây chờ phản hồi trước khi từ bỏ; mặc định khá ngắn.

9.16.4. Khi nào nên gọi

  • Sau khi kết nối mạng đã hoạt động. NTP chạy trên UDP, vốn chạy trên một cấu hình IP đã được thiết lập. Hãy chờ isconnected() trả về True trước.

  • Định kỳ với các camera chạy dài. Đồng hồ tích hợp sẽ bị lệch theo giờ và ngày. Việc gọi settime() hàng ngày hoặc hàng tuần giúp giữ cho nó chính xác.

9.16.5. Múi giờ

NTP trả về UTC. MicroPython không đi kèm cơ sở dữ liệu múi giờ, vì vậy việc chuyển đổi UTC sang giờ địa phương là công việc của tập lệnh. Một độ lệch cố định cho múi giờ triển khai thường là cách tiếp cận phổ biến:

import time

offset = -5 * 3600                  # hours -> seconds, US Eastern
local = time.localtime(time.time() + offset)
print(local)

Giờ mùa hè (Daylight Saving Time), giây nhuận và các thay đổi lịch sử của múi giờ không được xử lý bởi cách tiếp cận này. Với hầu hết các triển khai camera, một độ lệch cố định là đủ; nếu một tập lệnh thực sự cần giờ dân sự với Daylight Saving Time, hãy thực hiện chuyển đổi phía máy chủ.

9.16.6. Những gì có thể xảy ra sai

  • Chưa có mạng. ntptime.settime() ném ra OSError nếu không thể kết nối đến máy chủ. Nguyên nhân có thể là kết nối chưa hoạt động, tra cứu tên thất bại, máy chủ không thể truy cập, hoặc không nhận được phản hồi trong ntptime.timeout. Hãy thử lại khi kết nối đã ổn định.

  • Cổng kết nối ẩn (Captive portals). Một mạng Wi-Fi chặn DNS có thể trả lời tên máy chủ NTP bằng địa chỉ IP của cổng kết nối, và các yêu cầu NTP đến đó trả về kết quả vô nghĩa. Camera sẽ nghĩ mạng đã hoạt động nhưng việc đặt thời gian sẽ thất bại hoặc sai hoàn toàn. Hãy chuyển sang mạng sạch hoặc mã hóa cứng địa chỉ IP.

  • Gửi quá nhiều yêu cầu đến các nhóm công cộng. Các nhóm NTP công cộng giới hạn tốc độ với các client lạm dụng. Mỗi giờ một lần là đủ; mỗi phút một lần sẽ khiến camera bị cấm.

Để xem tài liệu tham khảo đầy đủ về ntptime, hãy xem ntptime --- máy khách NTP đơn giản.