ESP8266 NodeMCU NTP клиент-сервер: получение даты и времени (Arduino IDE)

В этом руководстве вы узнаете, как получить дату и время с NTP-сервера с помощью ESP8266 NodeMCU в Arduino IDE. Получение даты и времени полезно в проектах регистрации данных для отметки времени показаний. Для получения времени от NTP-сервера ESP8266 должен иметь подключение к Интернету, и вам не нужно дополнительное оборудование (например, часы реального времени RTC).

ESP8266 NodeMCU NTP клиент-сервер получение даты и времени Arduino IDE

Перед тем как приступить, убедитесь, что плата ESP8266 установлена в Arduino IDE:

Рекомендуется: Получение даты и времени с ESP32 NTP клиент-сервер

NTP (Network Time Protocol)

NTP расшифровывается как Network Time Protocol (протокол сетевого времени) – это сетевой протокол для синхронизации часов между компьютерными системами. Другими словами, он используется для синхронизации времени компьютерных часов в сети.

Существуют NTP-серверы, такие как pool.ntp.org, которые любой может использовать для запроса времени в качестве клиента. В этом случае ESP8266 является NTP-клиентом, который запрашивает время у NTP-сервера (pool.ntp.org).

NTP протокол сетевого времени ESP8266 NodeMCU запрос времени и даты

Установка библиотеки NTPClient

Мы будем использовать библиотеку NTPClient для получения времени. В Arduino IDE перейдите в Sketch > Library > Manage Libraries. Должен открыться менеджер библиотек.

Найдите NTPClient и установите библиотеку от Fabrice Weinber, как показано на следующем изображении.

Установка библиотеки NTPClient ESP8266 NodeMCU

Функции времени библиотеки 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: флаг летнего времени;

  • документация по структуре tm.

Следующие строки получают день месяца:

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 бод. Дата и время должны отображаться в нескольких форматах, как показано ниже.

ESP8266 NodeMCU получение даты и времени NTP клиент-сервер Arduino IDE демонстрация Serial Monitor

Заключение

В этом руководстве вы узнали, как получить дату и время с NTP-сервера с помощью ESP8266. Это особенно полезно для проектов регистрации данных, имеющих доступ к Интернету.

Если у вас нет доступа к Интернету, вы можете использовать модуль RTC, например DS1307.

Если вы хотите узнать больше о ESP8266, ознакомьтесь с нашими ресурсами:

Спасибо за чтение.