Synchronizácia času

prečo je čas dôležitý v IoT riešeniach, hodiny reálneho času, problém synchronizácie času, Unixový čas, počiatok epochy, NTP protokol, podpora NTP a hodiny reálneho času v mikrokontroléri ESP32

Time Synchronization

  • (slide) Koľkí z vás máte hodinky? Ideálne - koľkí z vás nemáte inteligentné hodinky, proste len klasické “digitálky” alebo ručičkové hodinky? Tak mi teraz povedzte, koľko je hodín.

  • No a máme tu problém - toľkí z vás majú hodinky a aj tak mi neviete povedať, koľko je hodín. Pretože každému ukazujú čas s nejakou odchýlkou, ktorá sa v niektorých prípadoch dá rátať na sekundy a v niektorých na minúty. A potom sú niektorí, ktorí majú schválne čas posunutý o pár minút dopredu, aby všetko stihli. To všetko prispieva k tomu, že nevieme presne určiť aktuálny čas.

  • Poznať správny čas je veľmi dôležité. Hlavne ak uchovávate, resp. logujete údaje spolu s ich časovou značkou (časozberné údaje). Preto je veľmi dôležité, aby komunikujúce zariadenia poznali nie len správny čas, ale mali všetky aj rovnaký čas nastavený. Nemôže nastať situácia, keď čas odoslania v prijatej správe je z pohľadu prijímajúceho klienta v budúcnosti.

  • Pozrieme sa teda na to, ako si aktuálny čas zapamätať a samozrejme - ako zabezpečiť synchronizáciu času medzi zariadeniami v sieti.

Real Time Clock

  • (slide) Real-Time Clock (RTC) alebo hodiny reálneho času sú počítačové hodiny, ktoré sledujú aktuálny čas. Najčastejšie sú realizované vo forme samostatného integrovaného obvodu.

  • (slide) Takýto obvod sa nachádza aj na základných doskách počítačov. Spoznáte ho napr. aj podľa toho, že v jeho blízkosti sa nachádza gombíková baterka, ktorá ho zásobuje energiou aj v prípade, ak je počítač vypnutý. RTC sleduje čas stále, ale iba ak má elektrickú energiu.

  • (slide) V prípade, že chcete funkcionalitu hodín reálneho času použiť aj s niektorým mikrokontrolérom, musíte si overiť, či ho ten mikrokontrolér má alebo nie. Ak nie, môžete k nemu taký modul pripojiť. Príkladom takéhoto modulu môže byť napr. modul DS1302 alebo DS3231. Tieto moduly sa líšia prevedením, vlastnosťami ako aj spôsobom komunikácie s mikrokontrolérom. Súčasťou týchto modulov je však samozrejme aj miesto pre batériu, aby modul nezabudol aktuálny čas.

    RTC Module DS3231 (zdroj)

RTC and ESP32

  • (slide) V prípade mikrokontroléra ESP32 nie je potrebné používať osobitný externý modul, pretože mikrokontrolér je takýmto modulom už vybavený. Aj napriek tomu však niektoré riešenia využívajúce tento mikrokontrolér majú osobitný RTC modul hlavne kvôli neustálemu externému napájaniu.

    Blokový diagram ESP32 (zdroj)
  • Podpora pre hodiny reálneho času sa nachádza priamo v jazyku MicroPython - v module machine sa priamo nachádza trieda RTC. Takže ak chceme začať s modulom pracovať, tak importneme uvedenú triedu a vytvoríme objekt z triedy RTC:

    >>> from machine import RTC
    >>> rtc = RTC()
  • Aktuálny dátum a čas získame volaním metódy .datetime():

    >>> rtc.datetime()
    (2000, 1, 1, 5, 0, 2, 32, 184)
  • Nastaviť aktuálny čas je možné manuálne zavolaním rovnakej metódy s parametrom n-tice obsahujúcej aktuálny dátum a čas v tvare (year, month, day, weekday, hours, minutes, seconds, subseconds), pričom weekday začína s pondelkom ako s hodnotou 0:

    >>> rtc.datetime((2020, 3, 13, 4, 22, 0, 0, 0))
    >>> rtc.datetime()
    (2020, 3, 13, 4, 22, 0, 3, 964)
  • Ak náhodou mikrokontrolér reštartnete, informácia o aktuálnom čase sa nestratí, pretože si ho modul hodín reálneho času bude pamätať:

    >>> machine.reset()
    ...
    >>> rtc = machine.RTC()
    >>> rtc.datetime()
    (2020, 3, 13, 4, 22, 2, 36, 700)
  • Ak však mikrokontrolér odpojíme od zdroja elektrickej energie (napr. vypojíme USB kábel), tak modul hodín reálneho času stratí informáciu o aktuálnom čase a resetne sa do pôvodných nastavení:

    >>> rtc = machine.RTC()
    >>> rtc.datetime()
    (2000, 1, 1, 5, 0, 0, 13, 980)

Network Time Protocol

  • Problém však je, že hodiny treba nastaviť manuálne zakaždým, keď dôjde k výmene batérie. To však nie je veľmi praktické, nakoľko je potrebné vykonať ručný zásah do kódu, kde nastavíme čas a dátum podľa aktuálnych hodnôt.

  • (slide) Pokiaľ je však zariadenie pripojené do internetu, je možné za týmto účelom použiť Network Time Protocol (NTP). Network Time Protocol je sieťový protokol pre synchronizáciu času v zariadeniach pripojených do siete. Protokol NTP bol vytvorený už pred rokom 1985, vďaka čomu je jedným z najstarších v súčasnosti stále používaných protokolov.

  • (slide) Aby protokol NTP pracoval, niekto musí poznať správny čas. Ak by však všetci klienti pristupovali len k jednému zdroju presného času, odozva by trvala veľmi dlho. Miesto toho NTP protokol používa hierarchickú sieť zariadení.

    NTP Servers and Clients [@wikipediaNTP]
  • Každá vrstva v tejto stieti sa nazýva stratum. Na najvyššej vrstve, tzv. stratum 0 sa nachádza zdroj reálneho času, čo môžu byť napr. atómové hodiny, GPS a iné. Tieto hodiny sú pripojené k zariadeniam na vrstve stratum 1 priamo, napr. cez rozhranie USB. Zariadenia na vrstve stratum 0 sa tiež označujú ako referenčné hodiny (z angl. reference clocks), resp. referenčný čas.

  • Čas sa dá následne získavať až z vrstvy stratum 1. Zariadenia na tejto vrstve sú tiež označované ako primary time servers. Z pohľadu získania času budú mať tieto zariadenia najnižšiu odchýlku oproti reálnemu času.

  • Zisťovať čas zo zariadení na vrstve stratum 1 však nie je odporúčaný spôsob. Opäť by hrozilo, že zariadenie bude zahltené požiadavkami a nebude ich stíhať všetky obsluhovať. Preto je odporúčané čas na klientskych zariadeniach získavať až z vrstiev stratum 2 a vyšších.

  • Tu je však jeden problém - čím je úroveň vrstvy stratum vyššia, tým väčšia bude aj časová odchýlka od zdroja reálneho času. Aby bola táto odchýlka čo najmenšia, dokážu sa jednotlivé zariadenia synchronizovať na základe údajov z viacerých zariadení. A to nie len vertikálne (smerom k nižším vrstvám stratum), ale aj horizontálne.

  • (slide) Podpora protokolu NTP sa nachádza aj v bežných operačných systémoch. V linuxových máte možnosť si dokonca vybrať aj z viacerých démonov, ktorí sa o synchronizáciu času pomocou starajú.

  • Aktuálne sa vo veľkých distribúciách používa chrony. Klient z príkazového riadku sa volá chronyc a vypísať aktuálne informácie o hodinách môžete pomocou príkazu tracking:

    $ chronyc tracking 
    Reference ID    : 2E1D02AB (ns0.govps.gr)
    Stratum         : 3
    Ref time (UTC)  : Tue Mar 24 19:05:29 2020
    System time     : 0.001544221 seconds fast of NTP time
    Last offset     : +0.000488482 seconds
    RMS offset      : 0.004124337 seconds
    Frequency       : 9.526 ppm fast
    Residual freq   : +0.001 ppm
    Skew            : 0.168 ppm
    Root delay      : 0.034044463 seconds
    Root dispersion : 0.021502025 seconds
    Update interval : 1041.6 seconds
    Leap status     : Normal
  • (slide) Problém však môže nastať v momente konfigurácie služby, pretože je potrebné zadať adresu zariadenia, voči ktorému sa chcete synchronizovať. Za tým účelom existuje stránka www.ntppool.org/, kde nájdete konfiguráciu v podobe zoznamu adries zariadení, voči ktorým sa bude to vaše synchronizovať. Obecne stačí zadať adresu pool.ntp.org, ale rovnako je možné si vybrať zoznam serverov pre konkrétnu krajinu.

NTP Support in Micropython

  • (slide) Micropython obsahuje modul ntptime, ktorý zabezpečuje podporu protokolu NTP. Pre jeho použitie je potrebné ho najprv importovať:

    >>> import ntptime
  • Tento modul obsahuje niekoľko metód a vlastností. Ak si napr. necháme zobraziť obsah premennej .host, uvidíme adresu zariadenia, voči ktorému sa bude náš mikrokontrolér synchronizovať:

    >>> ntptime.host
    'pool.ntp.org'
  • Samotnú synchronizáciu času zabezpečíme volaním metódy .settime():

    >>> ntptime.settime()
  • Čas následne overíme zavolaním metódy .datetime() nad inštanciou triedy RTC:

    >>> rtc = machine.RTC()
    >>> rtc.datetime()
    (2020, 3, 14, 5, 13, 4, 11, 807)

Time Synchronization

  • Podobne ako v prípade bežných hodiniek, aj tu dochádza k rozsynchronizovaniu času. Ak teda čas zosynchronizujete pri štarte zariadenia a jeho následnom pripojení do siete, nemusí to znamenať, že rovnakú odchýlku bude mať aj o týždeň po nepretržitej prevádzke. Je preto dobré plánovať ďalšiu synchronizáciu.

  • Linuxové systémy tento problém riešia tak, že k časovej synchronizácii dôjde zakaždým, keď dochádza k pripojeniu do internetu. To je dôležité napr. pri mobilných zariadeniach, ako sú napr. laptopy. Podobne teda môžu fungovať aj IoT zariadenia, keďže aj tie nepotrebujú sieťovú konektivitu neustále, ale len v (ne)pravidelných intervaloch. Samotná synchronizácia netrvá dlho, čo čas potrebný pre zotrvanie v sieti predĺži max. o niekoľko sekúnd.

Time Epoch

  • (slide)

  • Získať počet sekúnd od počiatku epochy je možné pomocou metódy .time():

    >>> import utime
    >>> utime.time()
    669375512
  • Spätne konvertovať čas z počtu sekúnd od počiatku epochy na 8 prvkovú nticu je možné pomocou metód .gmtime() a .localtime():

    >>> import utime
    >>> secs = utime.time()
    >>> utime.gmtime(secs)
    (2021, 3, 18, 9, 46, 33, 3, 77)