ESP8266 NodeMCU NTP клиент-сервер: получение даты и времени (Arduino IDE)
В этом руководстве вы узнаете, как получить дату и время с NTP-сервера с помощью ESP8266 NodeMCU в Arduino IDE. Получение даты и времени полезно в проектах регистрации данных для отметки времени показаний. Для получения времени от NTP-сервера ESP8266 должен иметь подключение к Интернету, и вам не нужно дополнительное оборудование (например, часы реального времени RTC).
Перед тем как приступить, убедитесь, что плата ESP8266 установлена в Arduino IDE:
Рекомендуется: Получение даты и времени с ESP32 NTP клиент-сервер
NTP (Network Time Protocol)
NTP расшифровывается как Network Time Protocol (протокол сетевого времени) – это сетевой протокол для синхронизации часов между компьютерными системами. Другими словами, он используется для синхронизации времени компьютерных часов в сети.
Существуют NTP-серверы, такие как pool.ntp.org, которые любой может использовать для запроса времени в качестве клиента. В этом случае ESP8266 является NTP-клиентом, который запрашивает время у NTP-сервера (pool.ntp.org).
Установка библиотеки NTPClient
Мы будем использовать библиотеку NTPClient для получения времени. В Arduino IDE перейдите в Sketch > Library > Manage Libraries. Должен открыться менеджер библиотек.
Найдите NTPClient и установите библиотеку от Fabrice Weinber, как показано на следующем изображении.
Функции времени библиотеки NTPClient
Библиотека NTPClient поставляется со следующими функциями для получения времени:
getDay() – возвращает число типа int, соответствующее дню недели (от 0 до 6), начиная с воскресенья;
getHours() – возвращает число типа int с текущим часом (от 0 до 23) в 24-часовом формате;
getMinutes() – возвращает число типа int с текущими минутами (от 0 до 59);
getSeconds() – возвращает число типа int с текущей секундой;
getEpochTime() – возвращает значение unsigned long с временем эпохи (количество секунд, прошедших с 1 января 1970 года (полночь GMT));
getFormattedTime() – возвращает строку String с временем в формате ЧЧ:ММ:СС;
Эта библиотека не имеет функций для получения даты, но мы покажем вам в коде, как получить дату (день, месяц и год).
Код ESP8266 NodeMCU
Следующий код подключает ESP8266 к NTP-серверу (pool.ntp.org) для запроса даты и времени. Он отображает текущую дату и время в нескольких форматах в Serial Monitor.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp8266-nodemcu-date-time-ntp-client-server-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// Replace with your network credentials
const char *ssid = "REPLACE_WITH_YOUR_SSID";
const char *password = "REPLACE_WITH_YOUR_PASSWORD";
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
//Week Days
String weekDays[7]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Month names
String months[12]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Initialize a NTPClient to get time
timeClient.begin();
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(0);
}
void loop() {
timeClient.update();
time_t epochTime = timeClient.getEpochTime();
Serial.print("Epoch Time: ");
Serial.println(epochTime);
String formattedTime = timeClient.getFormattedTime();
Serial.print("Formatted Time: ");
Serial.println(formattedTime);
int currentHour = timeClient.getHours();
Serial.print("Hour: ");
Serial.println(currentHour);
int currentMinute = timeClient.getMinutes();
Serial.print("Minutes: ");
Serial.println(currentMinute);
int currentSecond = timeClient.getSeconds();
Serial.print("Seconds: ");
Serial.println(currentSecond);
String weekDay = weekDays[timeClient.getDay()];
Serial.print("Week Day: ");
Serial.println(weekDay);
//Get a time structure
struct tm *ptm = gmtime ((time_t *)&epochTime);
int monthDay = ptm->tm_mday;
Serial.print("Month day: ");
Serial.println(monthDay);
int currentMonth = ptm->tm_mon+1;
Serial.print("Month: ");
Serial.println(currentMonth);
String currentMonthName = months[currentMonth-1];
Serial.print("Month name: ");
Serial.println(currentMonthName);
int currentYear = ptm->tm_year+1900;
Serial.print("Year: ");
Serial.println(currentYear);
//Print complete date:
String currentDate = String(currentYear) + "-" + String(currentMonth) + "-" + String(monthDay);
Serial.print("Current date: ");
Serial.println(currentDate);
Serial.println("");
delay(2000);
}
Как работает код
Сначала подключите необходимые библиотеки.
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
Вставьте свои сетевые учётные данные в следующие переменные, чтобы ESP8266 мог подключиться к вашему маршрутизатору для доступа к Интернету и запроса даты и времени от NTP-сервера.
const char *ssid = "REPLACE_WITH_YOUR_SSID";
const char *password = "REPLACE_WITH_YOUR_PASSWORD";
Определите NTP-клиент для получения даты и времени.
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
Мы будем запрашивать время у pool.ntp.org, который представляет собой кластер серверов времени, доступных для использования любым желающим.
Далее мы создаём два массива для хранения дней недели и названий месяцев.
//Week Days
String weekDays[7]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Month names
String months[12]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
setup()
В setup() инициализируем Serial Monitor для отображения информации.
Serial.begin(115200);
Далее подключаем ESP8266 к Интернету.
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Инициализируем NTPClient.
timeClient.begin();
Установка часового пояса
Вы можете использовать метод setTimeOffset() для настройки времени для вашего часового пояса в секундах.
timeClient.setTimeOffset(3600);
Вот несколько примеров для разных часовых поясов:
GMT +1 = 3600
GMT +8 = 28800
GMT -1 = -3600
GMT 0 = 0
Мы живём в Португалии, поэтому нам не нужно корректировать время.
timeClient.setTimeOffset(0);
loop()
В loop() вызываем функцию update() для получения текущей даты и времени от NTP-сервера.
timeClient.update();
Получение времени
Затем мы можем использовать функции, предоставляемые библиотекой, для получения времени. Например, для получения времени эпохи:
unsigned long epochTime = timeClient.getEpochTime();
Serial.print("Epoch Time: ");
Serial.println(epochTime);
Функция getFormattedTime() возвращает время в формате ЧЧ:ММ:СС.
String formattedTime = timeClient.getFormattedTime();
Serial.print("Formatted Time: ");
Serial.println(formattedTime);
Вы можете получить часы, минуты или секунды отдельно, используя функции getHours(), getMinutes() и getSeconds() следующим образом:
int currentHour = timeClient.getHours();
Serial.print("Hour: ");
Serial.println(currentHour);
int currentMinute = timeClient.getMinutes();
Serial.print("Minutes: ");
Serial.println(currentMinute);
int currentSecond = timeClient.getSeconds();
Serial.print("Seconds: ");
Serial.println(currentSecond);
Получение даты
Функция getDay() возвращает число от 0 до 6, где 0 соответствует воскресенью, а 6 – субботе. Таким образом, мы можем получить название дня недели из массива, созданного ранее, следующим образом:
String weekDay = weekDays[timeClient.getDay()];
Serial.print("Week Day: ");
Serial.println(weekDay);
NTP-клиент не имеет функций для получения даты. Поэтому нам нужно создать структуру времени (struct tm) и затем обращаться к её элементам для получения информации о дате.
struct tm *ptm = gmtime ((time_t *)&epochTime);
Структура времени содержит следующие элементы:
tm_sec: секунды после минуты;
tm_min: минуты после часа;
tm_hour: часы с полуночи;
tm_mday: день месяца;
tm_year: годы с 1900;
tm_wday: дни с воскресенья;
tm_yday: дни с 1 января;
tm_isdst: флаг летнего времени;
Следующие строки получают день месяца:
int monthDay = ptm->tm_mday;
Serial.print("Month day: ");
Serial.println(monthDay);
Для получения других элементов используется аналогичный подход. Например, для месяца:
int currentMonth = ptm->tm_mon+1;
Serial.print("Month: ");
Serial.println(currentMonth);
Поскольку tm_mon начинается с 0, мы добавляем 1 к месяцу, чтобы январь соответствовал 1, февраль – 2 и так далее.
Затем мы можем получить название месяца, используя массив months, созданный ранее. Нумерация массивов начинается с 0, поэтому мы вычитаем 1.
String currentMonthName = months[currentMonth-1];
Serial.print("Month name: ");
Serial.println(currentMonthName);
Для получения года нам нужно добавить 1900, потому что tm_year хранит количество лет после 1900.
int currentYear = ptm->tm_year+1900;
Serial.print("Year: ");
Serial.println(currentYear);
Наконец, мы создаём строку currentDate, которая содержит текущую дату в формате ГГГГ-ММ-ДД.
String currentDate = String(currentYear) + "-" + String(currentMonth) + "-" + String(monthDay);
Serial.print("Current date: ");
Serial.println(currentDate);
Демонстрация
После ввода сетевых учётных данных и изменения переменных для настройки времени вашего часового пояса, протестируйте пример.
Загрузите код на плату ESP8266. Убедитесь, что выбраны правильная плата и COM-порт.
Откройте Serial Monitor на скорости 115200 бод. Дата и время должны отображаться в нескольких форматах, как показано ниже.
Заключение
В этом руководстве вы узнали, как получить дату и время с NTP-сервера с помощью ESP8266. Это особенно полезно для проектов регистрации данных, имеющих доступ к Интернету.
Если у вас нет доступа к Интернету, вы можете использовать модуль RTC, например DS1307.
Если вы хотите узнать больше о ESP8266, ознакомьтесь с нашими ресурсами:
Спасибо за чтение.