diff --git a/README.md b/README.md index 63d7ac8..779c531 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ -[![Foo](https://img.shields.io/badge/Library%20Manager-NTPtime%201.1.1-000282.svg?style=for-the-badge&logo=arduino)](https://www.ardu-badge.com/NTPtime) +[![Foo](https://img.shields.io/badge/Library%20Manager-NTPtime%201.1.2-000282.svg?style=for-the-badge&logo=arduino)](https://www.ardu-badge.com/NTPtime) [![Foo](https://img.shields.io/badge/README-English-fff700.svg?style=for-the-badge)](https://github-com.translate.goog/DenysChuhlib/NTPtime?_x_tr_sl=uk&_x_tr_tl=en) -[![Foo](https://img.shields.io/badge/README-Руский-fff700.svg?style=for-the-badge)](/README_RU.md) +[![Foo](https://img.shields.io/badge/README-Руский-fff700.svg?style=for-the-badge)](https://github-com.translate.goog/DenysChuhlib/NTPtime?_x_tr_sl=uk&_x_tr_tl=ru) # NTPtime Бібліотека часу з багатьма функціями: -- Отримання точного часу за допомогою NTP -- Альтернатива стандартній бібліотеці `Time.h` +- Отримання точного часу за допомогою NTP сервера і використання +- Використання UNIX часу і його декодування +- Альтернатива стандартній бібліотеці `Time.h` в оптимізації і простоті використання - Можливість робити таймер у рівний час, наприклад рівно о 12:00 і так щогодини, який займає лише один байт +- Безліч інших зручних функцій - Можна робити цілий календар ### Сумісність усієї бібліотеки @@ -30,7 +32,7 @@ esp8266, esp32, Ethernet ## Установка - Бібліотеку можна знайти за назвою `NTPtime` та встановити через менеджер бібліотек у: - Arduino IDE - - Arduino IDE v2 + - Arduino IDE v2.0 - [Завантажити бібліотеку](https://github.com/DenysChuhlib/NTPtime/archive/refs/heads/main.zip) .zip архівом для ручної установки: - Розпакувати та покласти в `Документи/Arduino/libraries/` - (Arduino IDE) автоматичне встановлення з .zip: `Скетч/Підключити бібліотеку/Додати .ZIP бібліотеку…` та вказати завантажений архів @@ -51,20 +53,22 @@ UNIXtime(uint16_t y, uint8_t m, uint8_t d, uint8_t h, uint8_t mn, uint8_t s, int ### NTPtime ```cpp -void setHost(const char* host); // установити хост (за умвч. pool.ntp.org) +void setHost(const String& host); // установити хост (за умовч. pool.ntp.org) +void setPort(uint16_t port); // установити порт NTP сервера (за умовч. 123) +void setTimeout(uint16_t timeout); // установити таймаут відповіді сервера (200 - 64000) (за умовч. 64000) -bool begin(uint16_t port = _NTPtime_NTP_PORT); // запустити +bool begin(uint16_t port); // запустити (вхідний порт за умовч. 123) void end(); // зупинити -void asyncMode(bool _on_off); // асинхронний режим (за умовч. включений, true) +void asyncMode(bool _on_off); // асинхронний режим (за умовч. ввімкнений, true) void updateNow(); // обновити зараз (ручний запуск оновлення) bool updateOnTime(uint8_t h, uint8_t m, uint8_t s); // функція `loop()` цикла яка оновлює час в Г, Х, С (працює в парі з tick()) -bool tick(uint16_t prd); // функція `loop()` цикла яка оновлює час по періоду (prd), після ручного запуска або в певний час, підчас оновлення повертає true +bool tick(uint16_t prd); // функція `loop()` цикла яка оновлює час по періоду (1 хв <= prd <= 1 доба), після ручного запуска або в певний час, підчас оновлення повертає true -int16_t ping(); // отримати пінг сервера +int16_t ping(); // отримати пінг сервера (при відсутньому з'єднанні повертає -1) // отримати статус оновлення /* @@ -79,6 +83,10 @@ int16_t ping(); // отримати пінг сервера */ uint8_t NTPstatus(); ``` +### Особливості +- `tick()`, `DST()`, `updateOnTime()` працюють головному в циклі `loop()` +- Чим більше потрібна точність часу тим меньше потрібен період в `tick(prd)`. Якщо простий годинник достатньо одного updateOnTime(0,0,10) і обновляти в ніч, коли найкращий Інтернет + ### UNIXtime і NTPtime @@ -178,7 +186,7 @@ bool timeOutS(uint32_t last_unix, uint16_t time_out); bool isLeap(); // якщо високосний рік то повертає true -uint8_t lastDayOfMonth(); // останній день місяця +uint8_t lastDayOfMonth(); // останній день місяця void delay(uint32_t t, void (*func)()); // з функцією яка виконуеться підчас затримки) @@ -201,14 +209,17 @@ String dayWeekStringRU(); String monthShortStringRU(); String dayWeekShortStringRU(); ``` +### Особливості +- Мілісекунди зберігаються при зупинці відліку часу і відновлюються при запуску. + ### TimeFunc Просто - + ```cpp TimeFunc.isLeap(uint16_t y); ``` -і все. + і все. ```cpp @@ -259,12 +270,8 @@ void decodeUNIX(uint32_t unix, uint8_t& d, uint8_t& m, uint16_t& y); // швид void decodeUNIX(uint32_t unix, uint8_t& d, uint8_t& m, uint16_t& y, uint16_t& h, uint16_t& min, uint16_t& s); void delay(uint32_t t, void (*func)()); // з функцією яка виконуеться підчас затримки (наприклад, TimeFunc.delay(1000, Loop);) - ``` -### Особливості -- `tick()`, `DST()`, `updateOnTime()` працюють головному в циклі `loop()` - ## Приклад testBlink.ino ```cpp @@ -281,7 +288,7 @@ void delay(uint32_t t, void (*func)()); // з функцією яка вико //#include // esp32 /*#include - #define NTPtimeEthernetUdp //Ethernet + #define NTPtimeEthernet //Ethernet byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; @@ -362,3 +369,11 @@ void loop() { - `hourFormat12();` - `decodeUNIX();` - швидке декодування - `delay()` з функцією яка виконуеться підчас затримки +- v1.1.2 + - Оптимізація + - Виправлення помилок + - Добавлені нові функції + - `setHost(const String& host);` + - `setPort(uint16_t port);` + - `setTimeout(uint16_t timeout);` + - Інші важливі виправлення \ No newline at end of file diff --git a/README_RU.md b/README_RU.md deleted file mode 100644 index 0176a6d..0000000 --- a/README_RU.md +++ /dev/null @@ -1,359 +0,0 @@ -# NTPtime -Библиотека времени со многими функциями: -- получение точного времени с помощью NTP -- Альтернатива стандартной библиотеке `Time.h` -- Возможность делать таймер в равное время, например ровно в 12:00 и так ежечасно, занимающий только один байт -- Можно делать целый календарь - -### Совместимость всей библиотеки -Любые ардуино совместимые платы - -### Совместимость синхронизации NTP -esp8266, esp32, Ethernet - -## Содержание -- [Установка](#install) -- [Инициализация](#init) -- [Использование](#usage) - - [NTPtime](#NTPtime) - - [UNIXtime і NTPtime](#UNIXtime&NTPtime) - - [TimeFunc](#TimeFunc) -- [Пример](#example) -- [Версии](#versions) - - -## Установка -- Библиотеку можно найти по названию `NTPtime` и установить через менеджер библиотек в: - - Arduino IDE - - Arduino IDE v2 -- [Загрузить библиотеку](https://github.com/DenysChuhlib/NTPtime/archive/refs/heads/main.zip) .zip архивом для ручной установки: - - Распаковать и положить в `Документы/Arduino/libraries/` - - (Arduino IDE) автоматическая установка с .zip: `Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…` и указать загруженный архив - - -## Инициализация -```cpp -NTPtime Time; // параметры по умолчанию (time zone 0, time zone minune) -NTPtime(time_zona, time_zonaM); // часовой пояс в часах и минутах - -UNIXtime Timer; // Таймер (запустить Timer.startTime();) -UNIXtime(uint32_t unix, int8_t tz, int8_t tzM, uint16_t ms) //unix время, часовой пояс, минуты часового пояса, миллискекунди -UNIXtime(uint16_t y, uint8_t m, uint8_t d, uint8_t h, uint8_t mn, uint8_t s, int16_t tzM, uint16_t ms) // год, месяц, день, часы, минуты, секунды, секунды, часовой пояс в минутах, -```` - -## Использование - -### NTPtime -```cpp - -void setHost(const char* host); // установить хост (по умвч. pool.ntp.org) - -bool begin(uint16_t port = _NTPtime_NTP_PORT); // запустить обновление -void end(); // остановить обновление - -void asyncMode(bool _on_off); // асинхронный режим (по умолч. включен, true) - -void updateNow(); // обновить сейчас (ручной запуск обновления) - -bool updateOnTime(uint8_t h, uint8_t m, uint8_t s); // функция `loop()` цикла обновляющая время в Г, Х, С (работает в паре с tick()) - -bool tick(uint16_t prd); // функция `loop()` цикла обновляющая время по периоду (prd), после ручного запуска или в определенное время, во время обновления возвращает true - -int16_t ping(); // получить пинг сервера - -// получить статус обновления -/* - NTP_OK 0 – все ок - NTP_NOT_STARTED 1 - не запущен UDP - NTP_NOT_CONNECTED_WIFI 2 – не подключен WiFi - NTP_NOT_CONNECTED_TO_SERVER 3 – ошибка подключения к серверу - NTP_NOT_SENT_PACKET 4 – ошибка отправки пакета - NTP_WAITING_REPLY 5 – идет ожидание ответа - NTP_TIMEOUT 6 – таймаут ответы сервера - NTP_REPLY_ERROR 7 – полученный некорректный ответ сервера -*/ -uint8_t NTPstatus(); -``` - -### UNIXtime и NTPtime - -```cpp -void setUnixGMT(uint32_t unix, uint16_t ms); // установить unix время относительно гринвича - -void setUnixFromDate(uint16_t y, uint8_t m, uint8_t d, uint8_t h, uint8_t mn, uint8_t s, int16_t tzM = 0, uint16_t ms = 0); // название функции говорит само за себя - -void setTimeZone(int8_t tz, int8_t tzM); // установить часовой пояс -int16_t getTimeZoneM(); // узнать часовой пояс в минутах - -void setDST(int8_t dst_wt); // установить летнее время 1 (по умолчанию) и зимнее время -1 или стандартное время 0 -void setSummerTime(); // установить летнее время - -void setWinterTime(); // установить зимнее время - -void setStandardTime(); // установить стандартное время - -int8_t getDST(); // вернет, если летнее время 1 и зимнее время -1 или стандартное время 0 - -void DST(uint8_t month_start, uint8_t week_start, uint8_t dayWeek_start, uint8_t h_start, -uint8_t month_end, uint8_t week_end, uint8_t dayWeek_end, uint8_t h_end, bool dst_or_wt); -//month_start – месяц начала летнего/зимнего времени -//week_start - неделя начала летнего/зимнего времени (если 0 то последняя неделя) -//dayWeek_start – день недели начала летнего/зимнего времени -//h_start – час начала летнего/зимнего времени - -//month_end – месяц конца летнего/зимнего времени -//week_end - неделя конца летнего/зимнего времени (если 0 то последняя неделя) -//dayWeek_end - день недели конца летнего/зимнего времени -//h_end – час конца летнего/зимнего времени - -//dst_or_wt по умолчанию 1 – летнее время, если 0 то зимнее -//DST(2, 0, 7, 3, 10, 0, 7, 4); //https://en.wikipedia.org/wiki/Eastern_European_Summer_Time - -// получить статус системы -/* - UNIX_OK 0 – все ок - UNIX_NOT_SYNCHRONIZED 1 – не синхронизировано - UNIX_NOT_STARTED 2 - остановлено -*/ -bool status(); - -void startTime(); // начать отсчет времени - -void stopTime(); // сбросить отсчет времени - -uint32_t msFromUpdate(); // миллисекунд последнего обновления - -uint32_t unixGMT(); // unix время в отношении гринвича - -uint32_t unix(); // unix время в отношении данного часового пояса - -uint16_t ms(); // миллисекунды - -uint8_t second(); // получить секунды - -uint8_t minute(); // получить минуты - -uint8_t hour(); // получить часы - -uint8_t day(); // получить день месяца - -uint8_t month(); // получить месяц - -uint16_t year(); // получить год - -uint8_t dayWeek(); // получить день недели - -bool isAM(); -bool isPM(); -uint8_t hourFormat12(); - -bool onTime (uint8_t h, uint8_t m, uint8_t s); // название функции говорит само за себя - -bool onDate (uint8_t d, uint8_t m, uint8_t y); // название функции говорит само за себя - -bool timeAfter (uint8_t h, uint8_t m, uint8_t s); // название функции говорит само за себя - -bool dateAfter (uint8_t d, uint8_t m, uint8_t y); // название функции говорит само за себя - -bool everyH(uint8_t time_last, uint8_t time_out); // простые и маленькие таймеры (time_last - последний сохраненный hour()) (time_out от 0 до 24) -bool everyM(uint8_t time_last, uint8_t time_out); // (time_last - последний сохранен minute()) (time_out от 0 до 60) -bool everyS(uint8_t time_last, uint8_t time_out); // (time_last - последний сохраненный second()) (time_out от 0 до 60) -bool everyMs(uint16_t time_last, uint16_t time_out); // (time_last - последний сохраненный ms()) (time_out от 0 до 1000) - -uint32_t periodInSec(uint32_t last_unix); // период в секундах (last_unix – последний сохраненный unix()) -uint16_t periodInDays(uint32_t last_unix); -uint16_t periodInFullDays(uint32_t last_unix); -uint16_t periodInMonths(uint32_t last_unix); - -bool timeOutMonth(uint32_t unix_now, uint32_t last_unix, uint16_t time_out); // если период больше или равен таймауту, то возвращает true -bool timeOutD(uint32_t last_unix, uint16_t time_out); -bool timeOutH(uint32_t last_unix, uint16_t time_out); -bool timeOutM(uint32_t last_unix, uint16_t time_out); -bool timeOutS(uint32_t last_unix, uint16_t time_out); - -bool isLeap(); // если високосный год возвращает true - -uint8_t lastDayOfMonth(); // последний день месяца - -void delay(uint32_t t, void (*func)()); // с функцией выполняемой при задержке - -String timeString(); // получить строчку времени формата ГГ:ХХ:СС - -String dateString(); // получить строку даты формата ДД.ММ.ГГГГ - -String monthString(); -String dayWeekString(); -String monthShortString(); -String dayWeekShortString(); - -String monthStringUA(); -String dayWeekStringUA(); -String monthShortStringUA(); -String dayWeekShortStringUA(); - -String monthStringRU(); -String dayWeekStringRU(); -String monthShortStringRU(); -String dayWeekShortStringRU(); -``` - -### TimeFunc -Просто - -```cpp - TimeFunc.isLeap(uint16_t y); -``` -и все. - -```cpp - -bool isAM(uint8_t h); -bool isPM(uint8_t h); -uint8_t hourFormat12(uint8_t h); - -bool everyH(uint8_t time_now, uint8_t time_last, uint8_t time_out); // простые и маленькие таймеры (time_last - последний сохраненный hour()) (time_out от 0 до 24) -bool everyM(uint8_t time_now, uint8_t time_last, uint8_t time_out); // (time_last – последний сохраненная минута) (time_out от 0 до 60) -bool everyS(uint8_t time_now, uint8_t time_last, uint8_t time_out); // (time_last – последний сохраненная секунда) (time_out от 0 до 60) -bool everyMs(uint16_t time_now, uint16_t time_last, uint16_t time_out); // (time_last – последний сохраненная миллисекунда) (time_out от 0 до 1000) - -uint32_t periodInSec(uint32_t unix_now, uint32_t last_unix); // период в секундах (last_unix – последний сохраненный unix()) -uint16_t periodInDays(uint32_t unix_now, uint32_t last_unix); -uint16_t periodInFullDays(uint32_t unix_now, uint32_t last_unix); -uint16_t periodInMonths(uint32_t unix_now, uint32_t last_unix); - -bool timeOutMonth(uint32_t unix_now, uint32_t last_unix, uint16_t time_out); // если период больше или равен таймауту, то возвращает true -bool timeOutD(uint32_t unix_now, uint32_t last_unix, uint16_t time_out); -bool timeOutH(uint32_t unix_now, uint32_t last_unix, uint16_t time_out); -bool timeOutM(uint32_t unix_now, uint32_t last_unix, uint16_t time_out); -bool timeOutS(uint32_t unix_now, uint32_t last_unix, uint16_t time_out); - -bool isLeap(uint16_t y); // если високосный год возвращает true - -uint8_t lastDayOfMonth(uint8_t m, uint16_t y); // последний день месяца - -String timeString(uint8_t h, uint8_t m, uint8_t s); // получить строчку времени формата ЧЧ:ММ:СС - -String dateString(uint8_t d, uint8_t m, uint8_t y); // получить строку даты формата ДД.ММ.ГГГГ - -String monthString(uint8_t m); -String dayWeekString(uint8_t wd); -String monthShortString(uint8_t m); -String dayWeekShortString(uint8_t wd); - -String monthStringUA(uint8_t m); -String dayWeekStringUA(uint8_t wd); -String monthShortStringUA(uint8_t m); -String dayWeekShortStringUA(uint8_t wd); - -String monthStringRU(uint8_t m); -String dayWeekStringRU(uint8_t wd); -String monthShortStringRU(uint8_t m); -String dayWeekShortStringRU(uint8_t wd); - -void decodeUNIX(uint32_t unix, uint8_t& d, uint8_t& m, uint16_t& y); // быстрое декодирование -void decodeUNIX(uint32_t unix, uint8_t& d, uint8_t& m, uint16_t& y, uint16_t& h, uint16_t& min, uint16_t& s); - -void delay(uint32_t t, void (*func)()); // с функцией выполняемой при задержке (например, TimeFunc.delay(1000, Loop);) - -``` - -### Особенности -- `tick()`, `DST()`, `updateOnTime()` работают главном в цикле `loop()` - - -## Пример testBlink.ino -```cpp -//EN -// example outputting time every second -// and the LED flashes twice a second -// you can flash several boards - they will flash synchronously -//UA -// приклад виводу часу кожну секунду -// а також два раза в секунду блимає світлодіодом -// можно прошити декілька плат - вони будуть мигати синхронно - -#include // esp8266 -//#include // esp32 - -/*#include - #define NTPtimeEthernetUdp //Ethernet - byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED - }; -*/ - -#include -NTPtime Time(3); - -void setup() { - Serial.begin(115200); - - WiFi.begin("WIFI_SSID", "WIFI_PASS"); - while (WiFi.status() != WL_CONNECTED) delay(100); - Serial.println("Connected"); - - /*Ethernet - // You can use Ethernet.init(pin) to configure the CS pin - //Ethernet.init(10); // Most Arduino shields - //Ethernet.init(5); // MKR ETH shield - //Ethernet.init(0); // Teensy 2.0 - //Ethernet.init(20); // Teensy++ 2.0 - //Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet - //Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet - - // start the Ethernet connection: - Serial.println("Initialize Ethernet with DHCP:"); - if (Ethernet.begin(mac) == 0) { - Serial.println("Failed to configure Ethernet using DHCP"); - // Check for Ethernet hardware present - if (Ethernet.hardwareStatus() == EthernetNoHardware) { - Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); - while (true) { - delay(1); // do nothing, no point running without Ethernet hardware - } - } - if (Ethernet.linkStatus() == LinkOFF) { - Serial.println("Ethernet cable is not connected."); - } - // try to congifure using IP address instead of DHCP: - Ethernet.begin(mac, IPAddress(192, 168, 0, 1)); - } else { - Serial.print(" DHCP assigned IP "); - Serial.println(Ethernet.localIP()); - } - */ - -Time.begin(); -pinMode(LED_BUILTIN, OUTPUT); -} - -void loop() { - Time.tick(); - - if (Time.ms() == 0) {// секунда почалась / second started - delay(1); - digitalWrite(LED_BUILTIN, 0); //включити інвертований світлодіод esp8266 / turn on the esp8266(inverted) LED - Serial.println(Time.timeString()); //виводимо / outputting - Serial.println(Time.dateString()); - Serial.println(); - } - if (Time.ms() == 500) { - delay(1); - digitalWrite(LED_BUILTIN, 1); - } -} -```` - - -## Версии -- v1.0 -- v1.1.0 -– v1.1.1 - - оптимизация - - добавлены новые функции - - `periodInFullDays();` - - `isAM();` - - `isPM();` - - `hourFormat12();` - - `decodeUNIX();` - быстрое декодирование - - `delay()` с функцией выполняемой при задержке diff --git a/examples/Clock_strata/Clock_strata.ino b/examples/Clock_strata/Clock_strata.ino index c13eaa9..ab20ac8 100644 --- a/examples/Clock_strata/Clock_strata.ino +++ b/examples/Clock_strata/Clock_strata.ino @@ -3,7 +3,7 @@ //#include // esp32 //#include -//#define NTPtimeEthernetUdp //Ethernet +//#define NTPtimeEthernet //Ethernet uint8_t Clock_strata; //https://en.wikipedia.org/wiki/Network_Time_Protocol#Clock_strata #define NTPtimeClockStrata_val Clock_strata diff --git a/examples/Watch/Watch.ino b/examples/Watch/Watch.ino new file mode 100644 index 0000000..a7d99d8 --- /dev/null +++ b/examples/Watch/Watch.ino @@ -0,0 +1,22 @@ +#include // esp8266 +//#include // esp32 + +#include +NTPtime Time(2); //UA in +2 time zone + +void setup() { + Serial.begin(115200); + + WiFi.begin("WIFI_SSID", "WIFI_PASS"); + while (WiFi.status() != WL_CONNECTED) delay(10); + Serial.println("Connected"); + + Time.begin(); +} + +void loop() { + Time.DST(2, 0, 7, 3, 10, 0, 7, 4); //https://en.wikipedia.org/wiki/Eastern_European_Summer_Time + Time.updateOnTime(0,0,10); + Time.tick(); + if(Time.everyMs(0,1000)) Serial.println(Time.timeString()); +} \ No newline at end of file diff --git a/examples/testBlink/testBlink.ino b/examples/testBlink/testBlink.ino index 0b581e4..e3fae90 100644 --- a/examples/testBlink/testBlink.ino +++ b/examples/testBlink/testBlink.ino @@ -11,7 +11,7 @@ //#include // esp32 /*#include - #define NTPtimeEthernetUdp //Ethernet + #define NTPtimeEthernet //Ethernet byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; diff --git a/keywords.txt b/keywords.txt index 0aa590e..90e57d3 100644 --- a/keywords.txt +++ b/keywords.txt @@ -16,12 +16,17 @@ Timer KEYWORD1 TimeFunc KEYWORD1 +NTPtimeClockStrata_val KEYWORD1 +NTPtimeEthernet KEYWORD1 + ####################################### # Methods and Functions (KEYWORD2) ####################################### setPeriod KEYWORD2 setHost KEYWORD2 +setPort KEYWORD2 +setTimeout KEYWORD2 begin KEYWORD2 end KEYWORD2 asyncMode KEYWORD2 @@ -120,9 +125,6 @@ decodeUNIX KEYWORD2 # Constants (LITERAL1) ####################################### -NTPtimeClockStrata_val LITERAL1 -NTPtimeEthernetUdp LITERAL1 - NTP_OK LITERAL1 NTP_NOT_STARTED LITERAL1 NTP_NOT_CONNECTED_WIFI LITERAL1 diff --git a/library.properties b/library.properties index 7b836aa..bf9805d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=NTPtime -version=1.1.1 +version=1.1.2 author=Denys Chuhlib maintainer=Denys Chuhlib sentence=NTPtime, UNIXtime and TimeFunc give you full control and more manipulation with time. diff --git a/src/NTPtime.h b/src/NTPtime.h index e5c36c8..b505d0e 100644 --- a/src/NTPtime.h +++ b/src/NTPtime.h @@ -10,9 +10,6 @@ MIT License #include "UNIXtime.h" -#define _NTPtime_NTP_TIMEOUT 64000 -#define _NTPtime_NTP_PORT 123 - #define NTP_OK 0 #define NTP_NOT_STARTED 1 #define NTP_NOT_CONNECTED_WIFI 2 @@ -24,12 +21,20 @@ MIT License const PROGMEM char* _NTPtime_DEFAULT_HOST = "pool.ntp.org"; -#ifndef NTPtimeEthernetUdp -#include +#ifndef NTPtimeEthernet +// +#ifdef ESP8266 +#include #else +#include +#endif +// +#include +#else// +#include #include #define NTP_NOT_CONNECTED_Ethernet 2 -#endif +#endif// /*example uint8_t Clock_strata; @@ -51,12 +56,20 @@ class NTPtime : public UNIXtime { } // установити хост (за умвч. pool.ntp.org) - void setHost(const char* host) { + void setHost(const String& host) { _host = host; } + + void setPort(uint16_t port) { + _port = port; + } + + void setTimeout(uint16_t timeout) { + _timeout = constrain(timeout, 200, 64000); + } // запустити - bool begin(uint16_t port = _NTPtime_NTP_PORT) { + bool begin(uint16_t port = 123) { _ntp_stat = !udp.begin(port); return !_ntp_stat; } @@ -92,7 +105,7 @@ class NTPtime : public UNIXtime { if (prd) { prd = constrain(prd, 60, 86400UL); if (msFromUpdate() >= prd * 1000UL) setTimeStat(UNIX_NOT_SYNCHRONIZED); - } + } else msFromUpdate();// перевірка переповнення if (_ntp_stat != NTP_NOT_STARTED && _time_stat == UNIX_NOT_SYNCHRONIZED) { do { @@ -103,7 +116,7 @@ class NTPtime : public UNIXtime { return 1; } else if (_time_stat == UNIX_NOT_STARTED || _ntp_stat == NTP_NOT_STARTED) { - if (_send_pack) _send_pack = false; + _send_pack = false; } return 0; } @@ -142,7 +155,7 @@ class NTPtime : public UNIXtime { // запитати і обновити час з сервера uint8_t requestTime() { uint8_t buf[48]; - #ifndef NTPtimeEthernetUdp + #ifndef NTPtimeEthernet if (!WiFi.isConnected()) return 2; #else if (Ethernet.linkStatus() == LinkOFF || Ethernet.hardwareStatus() == EthernetNoHardware) return 2; @@ -152,38 +165,41 @@ class NTPtime : public UNIXtime { //https://en.wikipedia.org/wiki/Network_Time_Protocol, https://ru.wikipedia.org/wiki/NTP buf[0] = 0b11100011; // LI 0x3, v4, client buf[2] = 6; //таймаут 2^6 = 64 секунд - buf[3] = 0xEC; //точність -20 - двійковий логарифм секунд - if (!udp.beginPacket(_host, _NTPtime_NTP_PORT)) return 3; + if (!udp.beginPacket(_host.c_str(), _port)) return 3; udp.write(buf, 48); if (!udp.endPacket()) return 4; _way = millis(); _send_pack = true; } if (_send_pack) {//перевіряємо чи був ли відправлений запит - if (udp.parsePacket() != 48 || udp.remotePort() != _NTPtime_NTP_PORT) { - if (millis() - _way > _NTPtime_NTP_TIMEOUT) { + if (udp.parsePacket() != 48 || udp.remotePort() != _port) { + if (millis() - _way > (uint32_t)_timeout) { _send_pack = false; - _way = millis() - _way; - _ping = _way; + _ping = -1; return 6; } } else { - udp.read(buf, 48); // читаємо - if (buf[40] < 98) { // некоректний час (if (unix < 1644167168) error) + udp.read(buf, 48); // читаємо + uint32_t got_time = millis(); // запам'ятали час оновлення + uint16_t serv_ms = ((buf[44] << 8) | buf[45]) * 1000L >> 16; // мс сервера + int16_t ser_del = (int16_t)serv_ms - (((buf[36] << 8) | buf[37]) * 1000L >> 16); // мс затримки сервера + if (ser_del < 0) ser_del += 1000; // перехід через секунду + _way = millis() - _way; // весь шлях пакета і затримка сервера (фактично це пінг, але пакет NTP більший ніж пакет ping і тому затримка сервера більша) + int16_t ping = _way - ser_del; // нинішній пінг (шлях пакета, або RTT) + _way = ping / 2; // середній шлях в одну сторону + got_time -= (serv_ms + _way); // затримка часу + uint32_t unix = (uint32_t)(buf[40] << 8 | buf[41]) << 16 | (buf[42] << 8 | buf[43]); // 1900 + unix -= 2208988800UL; // переводимо в UNIX (1970) + + if (unix < 1662757200ul) { // некоректний час _send_pack = false; _ping = -1; return 7; } - _last_upd = millis(); // запам'ятали час оновлення - uint16_t a_ms = ((buf[44] << 8) | buf[45]) * 1000L >> 16; // мс сервера - int16_t ser_del = (int16_t)a_ms - (((buf[36] << 8) | buf[37]) * 1000L >> 16); // мс затримки сервера - if (ser_del < 0) ser_del += 1000; // перехід через секунду - _way = millis() - _way; // весь шлях пакета і затримка сервера (фактично це пінг, але пакет NTP більший ніж пакет ping і тому затримка сервера більша) - _ping = _way - ser_del; // нинішній пінг (шлях пакета, або RTT) - _way = _ping / 2; // середній шлях в одну сторону - _last_upd -= (a_ms + _way); // затримка часу - _unix = (uint32_t)(buf[40] << 8 | buf[41]) << 16 | (buf[42] << 8 | buf[43]); // 1900 - _unix -= 2208988800UL; // переводимо в UNIX (1970) + + _ping = ping; + _last_upd = got_time; + _unix = unix; _send_pack = false; setTimeStat(UNIX_OK); #ifdef NTPtimeClockStrata_val @@ -195,12 +211,14 @@ class NTPtime : public UNIXtime { return 5; } - #ifndef NTPtimeEthernetUdp + #ifndef NTPtimeEthernet WiFiUDP udp; #else EthernetUDP udp; #endif - const char* _host = _NTPtime_DEFAULT_HOST; + String _host = FPSTR(_NTPtime_DEFAULT_HOST); + uint16_t _port = 123; + uint16_t _timeout = 64000; bool _async : 1 = 1; bool _send_pack : 1 = 0; diff --git a/src/UNIXtime.h b/src/UNIXtime.h index b2d72c5..a05fc30 100644 --- a/src/UNIXtime.h +++ b/src/UNIXtime.h @@ -224,6 +224,7 @@ class UNIXtime { if (diff > 129600000UL) { //1,5 доби _unix += diff / 1000UL; _last_upd = millis() - diff % 1000UL; + setTimeStat(UNIX_NOT_SYNCHRONIZED); } return diff; } else {