Čas a synchronizácia času

modul hodín reálneho času, synchronizácia pomocou protokolu NTP, štandard UTC, štandard ISO 8601

Práca s časom v jazyku MicroPython

Na prácu s časom a dátumom v jazyku MicroPython máme k dispozícii modul time. Tento modul je mikro implementáciou modulu time zo štandardnej knižnice jazyka Python, ktorý má rovnakú funkcionalitu. Ak teda poznáte modul time zo štandardnej knižnice jazyka, práca s modulom time bude pre vás úplne prirodzená.

Modul time poskytuje funkcie pre získanie aktuálneho času a dútumu, pre meranie časových intervalov a taktiež funkcie pre pozastavenie kódu.

Zistenie aktuálneho času

Aktuálny čas je možné zistiť zavolaním funkcie localtime() z modulu time. Táto funkcia vráti n-ticu pozostávajúcu z 8 prvkov, ktorých význam je nasledovný (v poradí prvkov n-tice):

Príklad použitia sa nachádza v nasledujúcom výpise:

>>> import time
>>> time.localtime()
(2024, 10, 31, 11, 3, 25, 3, 305)

Zistenie počiatku epochy

Moduly RTC reprezentujú čas ako počet sekúnd od počiatku epochy. Tento modul teda obsahuje len počítadlo, ktoré každú sekundu zvýši o 1. Keď potom chceme zistiť, aký je aktuálny čas, dôjde k prevedeniu tohto počtu sekúnd na zodpovedajúci dátum a čas, ktorý dostaneme po zavolaní napr. funkcie localtime().

Za počiatok epochy považujeme dátum 1.1.1970, ktorý tiež poznáme pod názvom Unixový čas. Pokiaľ RTC modul počíta čas od tohto dátumu, hodnota 0 sekúnd zodpovedá presne dátumu 1.1.1970 o 00:00:00.

Ak chceme zisiť, aký počiatok epochy používa RTC modul vášho zariadenia, môžeme tak urobiť zavolaním funkcie gmtime() alebo localtime() z modulu time s parametrom 0:

>>> import time
>>> time.gmtime(0)
(1970, 1, 1, 0, 0, 0, 3, 1)
>>> time.localtime(0)
(1970, 1, 1, 0, 0, 0, 3, 1)

Podľa výpisu je možné povedať, že 1. január 1970 pripadá na štvrtok (deň v týždni má hodnotu 3) a je to prvý deň v roku. To si môžeme overiť napríklad príkazom cal v príkazovom riadku OS Linux:

$ cal 1 1 1970
     január 1970
Po Ut St Št Pi So Ne
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Zistenie počtu sekúnd od počiatku epochy

Konverzia na štruktúru reprezentujúcu čas

Modul hodín reálneho času (RTC)

Aby mohol mikrokontrolér pracovať s aktuálnym časom, potrebuje modul hodín reálneho času (z angl. real time clock, skrátene RTC).

Niektoré mikrokontroléry, ako napr. ESP32 alebo RP2040, sú už RTC modulom vybavené. Nakoľko však nemajú k RTC modulom vyvedené aj osobitné napájanie, je pre mnohé riešenia aj tak potrebný externý RTC modul so samostatným napájaním.

Podpora pre hodiny reálneho času sa nachádza priamo v jazyku MicroPython - v module machine sa nachádza trieda RTC. Takže ak chceme začať s modulom pracovať, stačí vytvoriť inštanciu tejto triedy:

>>> from machine import RTC
>>> rtc = RTC()

Zistenie aktuálneho dátumu a času

Pre získanie aktuálneho času stačí nad inštanciou RTC zavolať metódu .datetime():

>>> rtc.datetime()
(2021, 1, 1, 5, 0, 2, 32, 184)

Výsledkom volania bude n-tica, ktorá obsahuje 8 prvkov. Ich význam je nasledovný (zľava doprava):

Manuálne nastavenie dátumu a času

Ak potrebujeme nastaviť aktuálny čas ručne, môžeme na to použiť opäť metódu .datetime() nad inštanciou triedy RTC. Jej parametrom bude n-tica, ktorá obsahuje aktuálny dátum a čas v tvare (year, month, day, weekday, hours, minutes, seconds, subseconds):

>>> # aktuálny dátum a čas pred nastavením
>>> rtc.datetime()
(2021, 1, 1, 5, 0, 2, 32, 184)
>>> # nastavenie aktuálneho dátumu a času
>>> rtc.datetime((2024, 3, 13, 4, 22, 0, 0, 0))
>>> rtc.datetime()
(2024, 3, 13, 4, 22, 0, 3, 964)

Udržanie času po reštartovaní

Ak mikrokontrolér reštartnete tzv. mäkkým reštartom (z angl. soft reset), informácia o aktuálnom čase sa nestratí, pretože si ho bude modul hodín reálneho času pamätať:

>>> machine.reset()
...
>>> rtc = machine.RTC()
>>> rtc.datetime()
(2020, 3, 13, 4, 22, 2, 36, 700)

Pokiaľ nemá mikrokontrolér externý modul hodín reálneho času a odpojíme ho od zdroja elektrického napätia (napr. odpojením USB kábla), dôjde k vynulovaniu hodín reálneho času:

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

Synchronizácia času pomocou protokolu NTP

Pomocou protokolu NTP je možné synchronizovať čas zariadenia prostredníctvom internetu. Pre zabezpečenie synchronizácie stačí, ak je zariadenie pripojené do internetu a má modul ntptime.

Pri práci s modulom ntptime nás budú zaujímať dve veci:

Príklad použitia modulu sa nachádza v nasledujúcom výpise:

>>> # pred synchronizáciou...
>>> import time
>>> time.localtime()
(2021, 1, 1, 1, 26, 0, 4, 1)
>>> # synchronizácia
>>> import ntptime
>>> ntptime.settime()
>>> time.localtime()
(2024, 10, 31, 17, 23, 19, 3, 305)

Práca s externým modulom RTC

V prípade, že používate externý RTC modul, na prácu s ním potrebujete potrebnú knižnicu. Ak hľadáte príslušný modul pre váš RTC modul, dobrý odrazový mostík môže zoznam Awesome MicroPython a v ňom časť venovaná RTC modulom.

Formátovanie času a dátumu

Na formátovanie času sa používa v rozličných jazykoch funkcia strftime(). Pomocou tejto funkcie je možné naformátovať dátum a čas ľubovoľne. Táto funkcia sa však v štandardnom firmvéri MicroPython-u nenachádza. Je ju však možné doinštalovať osobitne z projektu micropython-lib.

Pre vlastné projekty si je teda potrebné vytvoriť vlastný formátovač času. Príkladom môže byť funkcia v nasledujúcom výpise, ktorá vráti čas v štandarde ISO 8601.

def to_iso8601(ts: int = None) -> str:
    dt = gmtime(ts)
    return f'{dt[0]:04}-{dt[1]:02}-{dt[2]:02}T{dt[3]:02}:{dt[4]:02}:{dt[5]:02}Z'

Ďalšie zdroje