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. ה-API של Python: 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 מבוססת. המתן ש-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)

שעון קיץ, שניות מעוברות ושינויי אזור היסטוריים אינם מטופלים בגישה זו. עבור רוב פריסות המצלמה היסט קבוע מספיק; אם סקריפט באמת זקוק לזמן אזרחי עם שעון קיץ, בצע את ההמרה בצד השרת.

9.16.6. מה יכול להשתבש

  • אין עדיין רשת. ntptime.settime() מעלה OSError אם אינה מצליחה להגיע לשרת. או שהחיבור אינו פעיל, או שחיפוש השם נכשל, או שהשרת אינו נגיש, או שלא הגיעה תשובה בתוך ntptime.timeout. נסה שוב לאחר שהחיבור יציב.

  • פורטלים כבולים. רשת Wi-Fi שמיירטת DNS עשויה להשיב לשם שרת ה-NTP בכתובת ה-IP של הפורטל עצמו, ובקשות NTP לאותה כתובת מחזירות שטויות. המצלמה תחשוב שהרשת פעילה אך כיוון הזמן ייכשל או יהיה שגוי לחלוטין. עבור לרשת נקייה או קודד כתובת IP קבועה.

  • הצפת מאגרים ציבוריים. מאגרי NTP ציבוריים מגבילים את קצב הלקוחות המתעללים. פעם בשעה הוא שפע; פעם בדקה יגרום לחסימת המצלמה.

להפניה המלאה אל ntptime, ראה ntptime — לקוח NTP פשוט.