• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Как задать локальное время без модуля и NTP-Сервера?

enjoynering

Well-known member
Немного оффтопа. Я щупаю Arduino ESP8266 Core с его первой версии, но вот только сейчас в нем стало более-менее комфортно работать, а Google хорошо проидексиоровал паутину и практический на любой вопрос можно найти ответ с примером.
 

Mоnk

Member

Mоnk

Member
три строчки находятся тут. за вас я их искать не буду.
Ну да, всего "три строчки"...
C++:
#include <ESP8266WiFi.h>
#include <time.h>

#define SSID            "Wolf-1"
#define SSIDPWD         "********"

void setup()
{
  Serial.begin(115200);
  Serial.println("");
 
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, SSIDPWD);
 
  configTime(3 * 3600, 0, "pool.ntp.org"); 
}

void loop()
{
  time_t now = time(nullptr);
  Serial.println(ctime(&now));
  delay(1000);
}
Вот только восьмилетний код я вижу регулярно в работающих проектах, а про Ваш только слышал на разнообразных ресурсах. И то только от ВАС.
Всех с наступающим!
 

enjoynering

Well-known member
молодец. но можно лучше. у вас сейчас time zone захаркодена - и автоматическая смена летнее-зимнее время работать не будет. поключите #include <TZ.h> и разберитесь как его подставлять.

проекты пока все еще сыроваты. я не програмист и потому все идет туго. сейчас вот разбираюсь с указателями. без них мне webradio не доделать. могу выложить бинарники часов. за них уже почти не стыдно. там пока нету будильников и не работает ночная-дневная подсветка (третий раз ее переписываю, но почему-то ticker не срабатывает) и небольшой глюк в вебморде со списком time zones. у вас есть 5 штук матричных дисплеев на MAX7219?
 

enjoynering

Well-known member
откройте стандарт на NTP. в этой 8-и летней копипасте не реализованно и половины стандарта. даже такой вещи как Kiss-o-Death нету, а она имхо ой какак нужна. чтоб любители опрашивать сервера с интервалом < 16 секунд понимали, что так делать нельзя.
 

Mоnk

Member
у вас сейчас time zone захаркодена
Ну как бЕ если коробочка стоит в Москве, есть ли смысл автоматизировать лето-зиму? Наоборот лишнее с моей точки зрения вырезал.
Бинарники - это как раз для тех, кто "не программист". Я себя к ним конечно с натяжкой причисляю. Скорее "скульптор". Беру, и отсекаю все лишнее. Взять хотя бы уроки тов. Третьякова. Очень много полезного было препарировано под себя.
Будильники - это для часов. Хотя все, что на ЕСП8266 - это всегда часы. Например так я включаю-выключаю свет в курятнике:
C++:
int lightON   = 330;  // ===== 05:30
int lightOFF  = 1110; // ===== 18:30

void light_ON_OFF()
{
  if (lighttoggle == AUTO)
  {
    if ((hourDS * 60 + minuteDS) > lightON && (hourDS * 60 + minuteDS) < lightOFF)
    {
      digitalWrite(light_pin, ON);
    }
    else
    {
      digitalWrite(light_pin, OFF);
    }
  }
  check_status_Light();
}
С подсветкой проще, поскольку у меня в большинстве ТМ1637 занимаются индикацией:
C++:
#ifdef TM1637
void showTime()
{
  #ifdef A0Readpresent    // ===== Фоторезистор
    int Readanalog = analogRead(A0);
    if (Readanalog < 150)
    {
      brightUp = 1;
    }
    else if (Readanalog > 150 && (Readanalog < 400))
    {
      brightUp = 2;
    }
    else if (Readanalog > 400 && (Readanalog < 750))
    {
      brightUp = 3;
    }
    else if (Readanalog > 750 && (Readanalog < 850))
    {
    brightUp = 4;
    }
    else if (Readanalog > 850)
    {
      brightUp = 8;
    }
  #endif
Я на МАХсы конечно заглядываюсь... Пока нет времени (простите за каламбур) заняться изучением.
 

Mоnk

Member
в этой 8-и летней копипасте не реализованно и половины стандарта.
Ну на тот момент, да и сейчас, она справляется с поставленной задачей. Практически во всех моих коробочках стоит 3231. И устройство приоритетно смотрит время оттуда. Но время из интернета все равно "тащит". Вот если ЕСП не видит РТС, то ориентируется уже на НТП. Просто интересно стало, как "соскочить" с этой библиотеки. И насколько без неё оперативки прибавится?
Вот у Вас как дата-время из полученной строчки парсится? Чтобы все в отдельные переменные, число-месяц-год, минуты-секунды-часы...
 

enjoynering

Well-known member
Код:
if ((hourDS * 60 + minuteDS) > lightON && (hourDS * 60 + minuteDS) < lightOFF)
не мой метод. я такие вещи делаю на ticker.h
 

enjoynering

Well-known member
Вот у Вас как дата-время из полученной строчки парсится?
ничего не надо парсить. в примере что я дал есть еще одна функция которая через structure tm возвращает ВСЕ.


Код:
      - struct tm
        {
          int tm_sec;   //seconds after the minute, 0-61 ???
          int tm_min;   //minutes after the hour, 0-59
          int tm_hour;  //hours since midnight, 0-23
          int tm_mday;  //day of the month, 1-31
          int tm_mon;   //months since January, 0-11
          int tm_year;  //years since 1900 ???
          int tm_wday;  //days since Sunday 0-6
          int tm_yday;  //days since January 1 0-365
          int tm_isdst; //daylight saving time flag
        }
 

pvvx

Активный участник сообщества
Сейчас у меня на базе этого примера часы сделаны. Получаю время по NTP 3-я!!! строчками кода.
С Новым Годом!
И как ваши часы показали 2020, потом 2021, а затем опять 2020 год, т.к. стекляшка уходит вперед, а обновление по ntp ставит время назад? :)
Два раза будильник не срабатывает?
Во всех нормальных ОС время корректируется плавно...
Или они всего раз в день показывают правильное время?
Немного оффтопа. Я щупаю Arduino ESP8266 Core с его первой версии, но вот только сейчас в нем стало более-менее комфортно работать, а Google хорошо проидексиоровал паутину и практический на любой вопрос можно найти ответ с примером.
NTP и TZ было встроено в SDK ESP8266 до появления предварительных версий Арудино на него. Это стандартная часть LwIP, а преобразования time - это стандартная либа входящая в GCC.
 

pvvx

Активный участник сообщества
ничего не надо парсить. в примере что я дал есть еще одна функция которая через structure tm возвращает ВСЕ.


Код:
      - struct tm
        {
          int tm_sec;   //seconds after the minute, 0-61 ???
          int tm_min;   //minutes after the hour, 0-59
          int tm_hour;  //hours since midnight, 0-23
          int tm_mday;  //day of the month, 1-31
          int tm_mon;   //months since January, 0-11
          int tm_year;  //years since 1900 ???
          int tm_wday;  //days since Sunday 0-6
          int tm_yday;  //days since January 1 0-365
          int tm_isdst; //daylight saving time flag
        }
И структура tm не такая, как вы описываете. Она описана в tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\time.h , а вы в очке Ардуино это не видите.
 

Mоnk

Member
есть еще одна функция которая через structure tm возвращает ВСЕ
Почти как в "Бриллиантовой руке" - а вот это попробуйте! Что "это", как пробовать?
В общем что-то слепил. Но не уверен, что правильно.
C++:
#include <ESP8266WiFi.h>
#include <time.h>

#define SSID            "Wolf-1"
#define SSIDPWD         "********"

const char* month_str[] = {"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь", "ZERO"};
const char* day_of_week[] = {"ZERO", "Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"};

void printLocalTime()
{
  //char timeBuffer[14];              //Строка для сохранения преобразованного времени
  time_t rawtime;                   //Переменная для системного времени
  struct tm * timeinfo;             //Указатель на структуру с локальным временем
  time (&rawtime);                  //Считываем системное время
  timeinfo = localtime (&rawtime);  //Преобразуем системное время в локальное

  //Преобразуем локальное время в текстовую строку
  //strftime (timeBuffer, 14, "%w%d%m%y%H%M%S", timeinfo);
 
  //Serial.println(timeBuffer);

int secondNTP     = timeinfo -> tm_sec;
int minuteNTP     = timeinfo -> tm_min;
int hourNTP       = timeinfo -> tm_hour;
int dayOfWeekNTP  = timeinfo -> tm_wday;
int dayOfMonthNTP = timeinfo -> tm_mday;
int monthNTP      = timeinfo -> tm_mon;
int yearNTP       = timeinfo -> tm_year;

String timeS = String(day_of_week[dayOfWeekNTP + 1]) + " " + dayOfMonthNTP + " " + month_str[monthNTP] + " " + (yearNTP + 1900) + " ";
  timeS += String(hourNTP) + ":" + minuteNTP + ":" + secondNTP;
    Serial.println(timeS);
}

void setup()
{
  Serial.begin(115200);
  Serial.println("");
 
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, SSIDPWD);
 
  configTime(3 * 3600, 0, "pool.ntp.org"); 
}

void loop()
{
  printLocalTime();
  delay(1000);
}
Терминал радостно сообщает:
Код:
Четверг 1 Январь 1970 8:0:13
Четверг 1 Январь 1970 8:0:14
Пятница 1 Январь 2021 22:36:28
Пятница 1 Январь 2021 22:36:29
Сразу вопросЫ. Как определить, что время по НТП получено? Надо ли вручную делать запрос НТП, и как?
 

enjoynering

Well-known member
по default запрос делается автоматический каждый час и esp корректирует свой внутренний software таймер. можно менять время между запросами с помощью weak функции. все есть в примере. определить очень просто без сихрозации часы стартуют с 20:00 песчитываем в секунды и сравниваем со внутренним software таймером если больше то значит сихронизация прошла успешна. есть еще функция по которй косьвенно можн оопределить - возвращает что ntp сервер живой.

выложил часы на github.
 

pvvx

Активный участник сообщества
Да, нам не повезло.
Может расскажете, как он выглядит, "северный олень"?
Включает смещение локального времени и текстовый описатель TM_ZONE. Если не учитывать опции, то при копировании описанной структуры от enjoynering произойдет переполнение буфера.
Но вам то наверно всё равно.
 

Mоnk

Member
Но вам то наверно всё равно.
Похоже что да.
Цифры я из структуры "вынул". Синхронизация раз в час, да и ладно. Как понять, что данные по НТП получены - придумаю.
Видел в документации ESP32 sntp_get_sync_status(). К 8266 не применимо.
 

enjoynering

Well-known member
Чтоб нормально работал переход на зимнее-летнее время для неризиновска, time zone надо задавать вот так:

PSTR("MSK-3")

Смотри TZ.h в исходниках Arduino ESP8266.

Чтоб применить TZ, нужно воспользоваться функцией configTime(), чтоб изменить с текущего TZ на другой применяем setTZ();

Вместо sntp_get_sync_status() в ардуино есть функция sntp_getreachability()

Все это я вынудил из исходников Arduino ESP8266 на Github. Вы их смотрели?? Все там, просто. Что вам не понятно при разборе исходников? Я помогу. А вот выуживать и разбирать исходники за вас я не буду.
 
Сверху Снизу