9.16. Aika ja NTP

Juuri käynnistetyllä kameralla ei ole aavistustakaan kellonajasta. Sisäinen kello käynnistyy jostakin mielivaltaisesta hetkestä (useimmilla korteilla 1970-01-01) ja laskee siitä eteenpäin, kunnes jokin kertoo sille toisin. NTP – Network Time Protocol – on tapa, jolla kamera kysyy verkolta todellista seinäkelloaikaa ja asettaa oman kellonsa vastauksen perusteella.

9.16.1. Miksi kameran täytyy tietää kellonaika

Monille skripteille kameran kellolla ei ole merkitystä – kehyksen kaappaussilmukka ei välitä siitä, mikä päivä on. Muutamissa yleisissä tilanteissa sillä on paljonkin merkitystä:

  • Aikaleimat lokeissa tai ladatussa datassa. Merkintöjä, joissa kaikissa lukee 1970-01-01, on jälkikäteen vaikea tulkita.

  • Ajastetut tehtävät. ”Suorita kello 03:00” edellyttää, että kamera tietää, mitä 03:00 tarkoittaa.

9.16.2. Mitä NTP tekee

NTP on pieni julkinen palvelu: verkosto palvelimia, jotka vastaavat kysymykseen ”paljonko kello on?” yhdellä UDP-vaihdolla. Kamera lähettää lyhyen pyynnön tunnetulle NTP-palvelimelle; palvelin vastaa tarkalla aikaleimalla (minkä tahansa yleisen julkisen palvelimen tapauksessa muutaman millisekunnin tarkkuudella); kamera käyttää sitä oman kellonsa asettamiseen. Oletuspalvelin, jota kamera käyttää, on pool.ntp.org, maailmanlaajuisesti kuormaa tasaava pooli, joka on suunniteltu juuri tällaisille asiakkaille.

9.16.3. Python-rajapinta: ntptime

MicroPython kääräisee protokollan yhteen kutsuun. Yleinen toimintamalli on tuoda yhteys ensin pystyyn ja kysyä sitten aika NTP:ltä:

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

Kun ntptime.settime() palaa, sisäinen reaaliaikakello ja time.localtime() heijastavat nykyistä UTC-aikaa. Kaksi säädintä muuttaa oletuksia:

  • ntptime.host on kyseltävän palvelimen nimi. Ohita se (ntptime.host = "time.google.com") ennen settime() -kutsua osoittaaksesi eri palvelimeen.

  • ntptime.timeout on sekuntien määrä, jonka vastausta odotetaan ennen luovuttamista; oletus on lyhyt.

9.16.4. Milloin sitä kutsutaan

  • Kun verkkoyhteys on pystyssä. NTP kulkee UDP:n päällä, joka puolestaan kulkee valmiiksi pystytetyn IP-asetuksen päällä. Odota ensin, että isconnected() palauttaa True.

  • Säännöllisesti pitkään käynnissä olevilla kameroilla. Sisäinen kello ajautuu tuntien ja päivien mittaan. Päivittäinen tai viikoittainen settime() pitää sen rehellisenä.

9.16.5. Aikavyöhykkeet

NTP palauttaa UTC-ajan. MicroPython ei sisällä aikavyöhyketietokantaa, joten UTC:n muuntaminen paikalliseksi ajaksi on skriptin tehtävä. Tavallinen lähestymistapa on käyttää käyttöönottoympäristön vyöhykkeelle kiinteää poikkeamaa:

import time

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

Tämä lähestymistapa ei käsittele kesäaikaa, karkaussekunteja eikä historiallisia vyöhykemuutoksia. Useimmissa kameran käyttöönotoissa kiinteä poikkeama riittää; jos skripti todella tarvitsee siviiliaikaa kesäaikoineen, tee muunnos palvelimen puolella.

9.16.6. Mikä voi mennä pieleen

  • Verkkoa ei vielä ole. ntptime.settime() nostaa virheen OSError, jos se ei tavoita palvelinta. Joko yhteys ei ole pystyssä, nimihaku epäonnistui, palvelin ei ole tavoitettavissa tai vastausta ei saapunut ajassa ntptime.timeout. Yritä uudelleen, kun yhteys on vakaa.

  • Vankilaportaalit. Wi-Fi-verkko, joka sieppaa DNS:n, saattaa vastata NTP-palvelimen nimeen portaalin omalla IP-osoitteella, ja sinne lähetetyt NTP-pyynnöt palauttavat roskaa. Kamera luulee verkon olevan pystyssä, mutta ajan asetus epäonnistuu tai menee täysin pieleen. Siirry puhtaaseen verkkoon tai koodaa IP-osoite kovakoodattuna.

  • Julkisten poolien rasittaminen. Julkiset NTP-poolit rajoittavat väärinkäyttävien asiakkaiden nopeutta. Kerran tunnissa on aivan riittävästi; kerran minuutissa johtaa kameran porttikieltoon.

Täydellinen ntptime -viite löytyy kohdasta ntptime — yksinkertainen NTP-asiakas.