NTP s letním časem pro ESP32
Na webových stránkách Wernera Rothschopfa je k nalezení několik zajímavých postřehů k programování modulu Arduino a také modulů ESP32. Určitě doporučujeme se na některá zapojení alespoň podívat. Dnes jsme si z jeho stránek dovolili „vytáhnout“ zajímavé řešení NTP klienta, který zohledňuje platnost letního času. A jelikož toto řešení je nejen hezké, ale i jednoduché, pojďme se na něj podívat.
Příklad NTP s automatickým nastavením letního času:
Následující výpis programu je vytvořen v jazyce wire a lze je do modulu ESP32 přeložit a zapsat prostředím Arduino IDE.
/* Konfigurace NTP */
// zvolime nejvhodnejsi NTP server pro svoji zemi
#define MY_NTP_SERVER "at.pool.ntp.org"
// zvolime sve casove pasmo
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
#define MY_TZ "CET-1CEST,M3.5.0,M10.5.0/3"
#include <WiFi.h> // pro pristupu k internetu potrebujeme wifi
#include <time.h> // time() pro cteni casu
const char* ssid = "YOUR_SSID"; // nazev wifi site, ke ktere se chcete pripojit
const char* password = "YOUR_PASS"; // heslo pro pripojeni k wifi siti
/* Globals */
time_t now; // cas v UNIX podobe (epocha)
tm tm; // struktura tm uchovava cas lepsim zpusobem
void showTime() {
time(&now); // nacte aktualni cas
localtime_r(&now, &tm); // aktualizuje strukturu tm aktualnim casem
Serial.print("Rok: ");
Serial.println(tm.tm_year + 1900); // n tm je pocet roku od 1900
Serial.print("Mesic: ");
Serial.println(tm.tm_mon + 1); // leden = 0 (tak bacha!)
Serial.print("Den: ");
Serial.println(tm.tm_mday); // den v mesici (0-31)
Serial.print("Hodina: ");
Serial.println(tm.tm_hour); // hodina od pulnoci (0-23)
Serial.print("Minuty: ");
Serial.println(tm.tm_min); // minuty (0-59)
Serial.print("Sekundy: ");
Serial.println(tm.tm_sec); // sekundy (0-59)
Serial.print("Den tydne: ");
Serial.println (tm.tm_wday); // Den v tydnu od nedele (0-6)
if (tm.tm_isdst == 1) // priznak letniho casu
Serial.print("LETNI");
else
Serial.print("ZIMNI");
Serial.println("CAS");
Serial.println("---------");
}
void setup() {
Serial.begin(115200);
configTime(0, 0, MY_NTP_SERVER); // 0, 0 protoze dale pouzijeme TZ
setenv("TZ", MY_TZ, 1); // nastaveni promenne s casovym pasmem
tzset();
// start Wifi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { // nez se pripoji, tiskni tecky
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}
void loop() {
showTime();
delay(1000); // cekani a pak znova
}
Části kódu, které jsou důležité pro načtení času z NTP serveru i s ohledem na letní čas, jsou zeleně zvýrazněny. Jinak se jedná o standardní načtení času z NTP serveru, podobně jako bylo ukázáno v předchozím článku ESP32: Získání času a data ze NTP serveru.
Základním nastavením programu je dvojice řetězců, které definují NTP server (MY_NTP_SERVER), na který chcete odeslat požadavek na získání času, a definice časového pásma (MY_TZ). Časové pásmo je vybráno podle seznamu z CSV souboru uzmíněného v kódu (URL uvedeno v komentáři kódu). Pro náš účel je časové pásmo nastaveno pro střední Evropu (Prahu) "CET-1CEST,M3.5.0/02,M10.5.0/03".
Tento záznam obsahuje všechny informace pro modul ESP32 a jeho výpočet místního času včetně letního času. Zde konkrétně se letní čas mění ve třetím měsíci (M3)
, pátém týdnu (5)
, v neděli (0)
, ve dvě hodiny (02)
. Zimní čas se mění v 10. měsíci (M10)
, v pátém týdnu (5)
, v neděli (0)
, ve tři hodiny (03)
.
Aby vše fungovalo, potřebujeme do kódu zahrnout časovou knihovnu Time
, pro kterou využijeme dvě globální proměnné now
a tm
.
Proměnná now
se používá pro uložení časového razítka. Tato proměnná obsahuje sekundy od 1. ledna 1970. Protože jsou lidé zvyklí pracovat s datem/časem ve formátu dnů, měsíců, let … atd., použijeme strukturu tm
. Její vytěžování na jednotlivé dílčí části si ukážeme dále.
V proceduře setup()
jsou pro naše účely důležité následující 3 řádky kódu:
configTime(0, 0, MY_NTP_SERVER); // 0, 0 protoze dále pouzijeme TZ
setenv("TZ", MY_TZ, 1); // nastaveni promenne s casovym pasmem
tzset();
Pomocí těchto 3 řádků definujete své časové pásmo a server NTP. Tím máme hotovo!
Pochopitelně abychom si mohli ukázat funkci kódu, je třeba nějaký čas načíst a vypsat jej na sériový monitor. K tomu slouží procedura showTime()
, ve které se nejdříve načte aktuální čas a aktualizuje se proměnná now
. Pomocí funkce localtime_r
převedeme časové razítko z proměnné now
do struktury tm
. Struktura obsahuje následující důležité dílčí proměnné:
proměnná | význam | rozsah |
---|---|---|
tm_sec |
počet sekund akt. času | 0–59 |
tm_min |
počet minut akt. času | 0–59* |
tm_hour |
počet hodin akt. času | 0–23 |
tm_mday |
den v měsíci | 1–31 |
tm_mon |
pořadí měsíce (ledna = 0) | 0–11 |
tm_year |
počet roků od roku 1900 | 0–? |
tm_wday |
den v týdnu (neděle = 0) | 0–6 |
tm_yday |
den v roce (od 1. ledna) | 0–365 |
tm_isdst |
příznak letního/zimního času | 1 / 0 |
* skutečný rozsah tm_sec
je 0–61, tento extra rozsah je přizpůsoben pro určité systémy potřebující přestupné sekundy. My se však budeme pohybovat ve standardním rozsahu 0…59.
Test programu:
Před přeložením programu a jeho zápisu do modulu ESP32 je třeba nastavit přístupové údaje ke zvolené Wi-Fi pomocí proměnných ssid
a password
, tedy zadat jméno Wi-Fi sítě a platné přístupové heslo.
Pro spuštění programu se každou vteřinu vypisují časové údaje na sériový port, kde je můžeme načítat kupříkladu vestavěným sériovým monitorem prostředí Arduino IDE – viz následující obrázek.
Jak vidíme v okně sériového monitoru prostředí Arduino IDE, modul ESP32 vypisuje v pravidelných intervalech jednotlivé položky struktury tm
. Údaje zcela odpovídají okamžiku vzniku tohoto článku. 👍
Text inspirován článkem: https://