W tym poście chciałbym opisać sposób implementacji klienta NTP.
Na samym początku należy zdefiniować dane do połączenia po WIFI oraz nazwę serwera NTP:
- #include <WiFi.h>
- #include "time.h"
- //----------------------------------------------
- #define TIME_VALUE 3600
- #define GMT_OFFSET 0
- #define DAY_OFFSET 3600
- //----------------------------------------------
- const char* ssid = "SSID";
- const char* password = "PASSWORD";
- const char* ntpServer_0 = "0.pl.pool.ntp.org";
- const char* ntpServer_1 = "1.pl.pool.ntp.org";
- const char* ntpServer_2 = "2.pl.pool.ntp.org";
- uint16_t readTimeCounter = 0;
W funkcji setup następuje inicjalizacja UART'u, podłączenie do sieci wifi, ustawienie parametrów do pobrania danych z serwera NTP.
- void setup(){
- //-------------------------------------------
- Serial.begin(115200);
- //-------------------------------------------
- Serial.print("Connect to: ");
- Serial.println(ssid);
- Serial.println(password);
- WiFi.begin(ssid, password);
- //-------------------------------------------
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.print(".");
- }
- //-------------------------------------------
- Serial.println("WiFi connected!!");
- //-------------------------------------------
- configTime(GMT_OFFSET, DAY_OFFSET, ntpServer_0,
- ntpServer_1, ntpServer_2);
- displayTime();
- //-------------------------------------------
- //Disconnect wifi to save power
- WiFi.disconnect(true);
- WiFi.mode(WIFI_OFF);
- }
Funkcja odpowiedzialna za połączenie z serwerem NTP została zdefiniowana w pliku time.h.
- void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)
- {
- tcpip_adapter_init(); // Should not hurt anything if already inited
- if(sntp_enabled()){
- sntp_stop();
- }
- sntp_setoperatingmode(SNTP_OPMODE_POLL);
- sntp_setservername(0, (char*)server1);
- sntp_setservername(1, (char*)server2);
- sntp_setservername(2, (char*)server3);
- sntp_init();
- setTimeZone(-gmtOffset_sec, daylightOffset_sec);
- }
Do funkcji można podać maksymalnie trzy rodzaje serwerów. Wyłączanie wifi jest wykonywane w celu oszczędzenia energii.
W pętli głównej wyświetlam czas umieszczony na serwerach NTP. Dodatkowo raz na godzinę wykonuje ponowne połączenie z serwerem NTP.
- void loop(){
- delay(1000);
- displayTime();
- if(readTimeCounter >= TIME_VALUE) {
- readTimeCounter = 0;
- connectToWifiAndGetTime();
- }
- readTimeCounter++;
- }
Funkcja wykonywająca ponowne odczytanie danych:
- void connectToWifiAndGetTime()
- {
- uint8_t connectionCounter = 0;
- Serial.print("Reconnect to ");
- Serial.println(ssid);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.print(".");
- connectionCounter++;
- if(connectionCounter >= 6)
- {
- Serial.println("Connection error...");
- connectionCounter = 0xFF;
- break;
- }
- }
- if(connectionCounter == 0xFF)
- {
- /* Data calculated with previos time settings */
- return;
- }
- Serial.println("WiFi connected!!");
- configTime(GMT_OFFSET, DAY_OFFSET, ntpServer_0, ntpServer_1, ntpServer_2);
- displayTime();
- WiFi.disconnect(true);
- WiFi.mode(WIFI_OFF);
- }
Wyświetlenie czasu:
- void displayTime(){
- struct tm timeinfo;
- if(!getLocalTime(&timeinfo)){
- Serial.println("Get local time error!");
- return;
- }
- Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
- Serial.print(" DOW: ");
- Serial.print(&timeinfo, "%A");
- Serial.print(" Month: ");
- Serial.print(&timeinfo, "%B");
- Serial.print(" DOM: ");
- Serial.print(&timeinfo, "%d");
- Serial.print(" Year: ");
- Serial.println(&timeinfo, "%Y");
- Serial.print(" Hour: ");
- Serial.print(&timeinfo, "%H");
- Serial.print(" Hour (12 hour format): ");
- Serial.print(&timeinfo, "%I");
- Serial.print(" Minute: ");
- Serial.print(&timeinfo, "%M");
- Serial.print(" Second: ");
- Serial.println(&timeinfo, "%S");
- }
Funkcja odpowiedzialna za odczytanie danych z czasem została zdefiniowana w bibliotekach ESP:
- bool getLocalTime(struct tm * info, uint32_t ms)
- {
- uint32_t start = millis();
- time_t now;
- while((millis()-start) <= ms) {
- time(&now);
- localtime_r(&now, info);
- if(info->tm_year > (2016 - 1900)){
- return true;
- }
- delay(10);
- }
- return false;
- }
Cały projekt wygląda następująco:
- #include <WiFi.h>
- #include "time.h"
- //----------------------------------------------
- #define TIME_VALUE 3600
- #define GMT_OFFSET 0
- #define DAY_OFFSET 3600
- //----------------------------------------------
- const char* ssid = "SSID";
- const char* password = "PASSWORD";
- const char* ntpServer_0 = "0.pl.pool.ntp.org";
- const char* ntpServer_1 = "1.pl.pool.ntp.org";
- const char* ntpServer_2 = "2.pl.pool.ntp.org";
- uint16_t readTimeCounter = 0;
- void setup(){
- //-------------------------------------------
- Serial.begin(115200);
- //-------------------------------------------
- Serial.print("Connect to: ");
- Serial.println(ssid);
- Serial.println(password);
- WiFi.begin(ssid, password);
- //-------------------------------------------
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.print(".");
- }
- //-------------------------------------------
- Serial.println("WiFi connected!!");
- //-------------------------------------------
- configTime(GMT_OFFSET, DAY_OFFSET, ntpServer_0,
- ntpServer_1, ntpServer_2);
- displayTime();
- //-------------------------------------------
- //Disconnect wifi to save power
- WiFi.disconnect(true);
- WiFi.mode(WIFI_OFF);
- }
- void loop(){
- delay(1000);
- displayTime();
- if(readTimeCounter >= TIME_VALUE) {
- readTimeCounter = 0;
- connectToWifiAndGetTime();
- }
- readTimeCounter++;
- }
- void connectToWifiAndGetTime()
- {
- uint8_t connectionCounter = 0;
- Serial.print("Reconnect to ");
- Serial.println(ssid);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.print(".");
- connectionCounter++;
- if(connectionCounter >= 6)
- {
- Serial.println("Connection error...");
- connectionCounter = 0xFF;
- break;
- }
- }
- if(connectionCounter == 0xFF)
- {
- /* Data calculated with previos time settings */
- return;
- }
- Serial.println("WiFi connected!!");
- configTime(GMT_OFFSET, DAY_OFFSET, ntpServer_0, ntpServer_1, ntpServer_2);
- displayTime();
- WiFi.disconnect(true);
- WiFi.mode(WIFI_OFF);
- }
- void displayTime(){
- struct tm timeinfo;
- if(!getLocalTime(&timeinfo)){
- Serial.println("Get local time error!");
- return;
- }
- Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
- Serial.print(" DOW: ");
- Serial.print(&timeinfo, "%A");
- Serial.print(" Month: ");
- Serial.print(&timeinfo, "%B");
- Serial.print(" DOM: ");
- Serial.print(&timeinfo, "%d");
- Serial.print(" Year: ");
- Serial.println(&timeinfo, "%Y");
- Serial.print(" Hour: ");
- Serial.print(&timeinfo, "%H");
- Serial.print(" Hour (12 hour format): ");
- Serial.print(&timeinfo, "%I");
- Serial.print(" Minute: ");
- Serial.print(&timeinfo, "%M");
- Serial.print(" Second: ");
- Serial.println(&timeinfo, "%S");
- }