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

Проблема с получением точного времени timeClient.update()

Как правило, система получения времени с одного из специальных серверов (например: "ntp.msk-ix.ru") работает. Однако, иногда при перезагрузке программы (ARDUINO IDI 2.1.1) возникает ситуация, когда либо время не определяется (год = 1970), либо при вставлении:
while(!timeClient.update())
{
timeClient.forceUpdate();
Serial.print(":");
delay(100);
}, куска, который должен обеспечивать правильное время, застреваем в этом while.

Помогает, только иногда, смена специального сервера. Или многочисленная перегрузка с контролем в Serial, что невозможно при автономной работе.

P.S. При правильной работе правильное время получается и без вставки и, иногда, вставка успешно проходится.
 

enjoynering

Well-known member
все очень просто - надо перестать пользоваться библиотекой NTPClient. Все давно есть в Arduino ESP8266 и оно даже умеет автоматически переводить летнее на зимнее и обратно - NTP-TZ-DST.ino Это полный пример показывающий все возможности встроеных функций NTP клиента и он может быть сложен для вас. Вот тут (NTP DST for the ESP8266) человек его у простил и все ражевал в коментариях.
 
В первой ссылке не хватает библиотеки TZ.h. Обычным способом ARDUINO IDE 2.1.1 она не подгружается.
Во втором примере:
#define MY_TZ "CET-1CEST,M3.5.0/02,M10.5.0/03" //Error
// invalid conversion from 'const char*' to 'long int' [-fpermissive]
 

enjoynering

Well-known member
Я к сожалению не телепат и не умею определять тип плат на расстоянии.

Вы правы в esp32 они почему-то не добавили TZ.h, но в примере simpleTime.ino все есть. Вы пользоваться Гуглом и поиском по GitHub умеете? Просто перейдите то ссылке из примера и скопируйте TZ.h в свой проект.
 
Я проверял ваши предложения без платы. По CNTR+R, задавая ESP 32 DEV Module.
Во всех предыдущих предложениях только модули *.ino. Последнее simpleTime компиляцию прошло.
No time available (yet)
 

enjoynering

Well-known member
По CNTR+R, задавая ESP 32 DEV Module. Во всех предыдущих предложениях только модули *.ino.
Последнее simpleTime компиляцию прошло.
No time available (yet)
Мне опять нужна пояснительная бригада. Я ничего не понял.

1. Что такое CNTR+R?

2. Что вы тут имели ввиду "Во всех предыдущих предложениях только модули *.ino."?

3. При каких условиях вы получили это "Последнее simpleTime компиляцию прошло. No time available (yet)"? Я поясню. Вы залили код в плату? До этого вы писали, что только компилировали без заливки, отсюда и такой дурацкий вопрос. Вы подключились ESP32 к точке доступа?

С вами тяжело. Я же говорю я не телепат. Вы прежде чем отправляете, перечитайте и представьте, что вы ни о чем не в курсе и можно ли по вашим вводным понять о чем речь с первого раза. Мне обычно такой подход помогает.
 
Извините, я ужасно не люблю сокращения, поэтому CNTR+R означает компиляцию без загрузки.
"Во всех предыдущих предложениях только модули *.ino. " означает, что никаких текстов библиотек в предложенных вами ссылках не наблюдалось.
No time available (yet)" получено после загрузки в плату ESP32 38 WROOM 32.Сообщение о подсоединении к wifi прошло перед сообщениями No time available (yet)", которые бесконечно повторялись
 

enjoynering

Well-known member
Теперь понятно. Спасибо. Попробуйте другой NTP сервер. Я пользуюсь самым надёжным из всех бесплатных - time.google.com

Теперь когда вы пользуетесь нормальным ntp клиентом, я могу ответить на ваш первый вопрос, про 1970 год. К сожалению, сейчас на работе, а все примеры дома. Можете подождать до завтра?
 

enjoynering

Well-known member
вот как я проверяю что соединение с NTP сервером #0 установлено и время получено:

Код:
  if ((sntp_getreachability(0) & 0x01) == 0x01)       //check 8-th bit of reachability shift register
  {
    Serial.printf_P(PSTR("packet from NTP server http://%s received\n"), ntpConfig.timeServer0.c_str());
  }
  else
  {
    Serial.printf_P(PSTR("Oops! connection to http://%s failed\n"), ntpConfig.timeServer0.c_str());
  }
 
Я попробовал все предложения, которые были сделаны в виде файлов *.ino . Все они не прошли. Одно потребовало библиотеку, одно выдало ошибку при компиляции, а самое успешное дошло да исполнения и не получило время. Тем самым, ответа на вопрос, почему при новых включениях программы, ранее успешно получавшей время, происходят устойчивые не подключения к серверу, я не получил.

Особенно содержательный ответ от ghost21.
 

enjoynering

Well-known member
я бы так категорично не заявлял. код из обоих файлов *.ino у меня прекрасно крутится вот в этом проекте - https://github.com/enjoyneering/MatrixClock

а вам похоже просто микрофон мешает.

пы.сы. и да, то что вы называете библиотекой, не библиотека, а header file (заголовочный файл). ваш кОпетан очевидность.
 

gromush

Member
Хм.

Код:
static const char ntpServerName[] = "us.pool.ntp.org";

void sendNTPpacket(WiFiUDP *UdpIn, IPAddress &address)
{
  byte packetBuffer[NTP_PACKET_SIZE];
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  packetBuffer[0] = 0b11100011; 
  packetBuffer[1] = 0;     
  packetBuffer[2] = 6;     
  packetBuffer[3] = 0xEC; 
 
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49; 
  packetBuffer[15] = 52; 
  UdpIn->beginPacket(address, 123);
  UdpIn->write(packetBuffer, NTP_PACKET_SIZE);
  UdpIn->endPacket();

}



time_t getNtpTime(void)
{
  IPAddress ntpServerIP;
  WiFiUDP UdpNTP;
  uint32_t beginWait;
  byte packetBuffer[NTP_PACKET_SIZE];

  UdpNTP.begin(UDP_PORT_NTP_LOCAL);
 
  WiFi.hostByName(ntpServerName, ntpServerIP); 
 
  sendNTPpacket(&UdpNTP, ntpServerIP);

  beginWait = millis();
  while ((millis() - beginWait) < NET_NTP_ANSWER_WAIT_TIME)
  {
    int size = UdpNTP.parsePacket();
    if (size == NTP_PACKET_SIZE) {

      UdpNTP.read(packetBuffer, NTP_PACKET_SIZE); 
      long secsSince1900;
      secsSince1900 =  (long)packetBuffer[40] << 24;
      secsSince1900 |= (long)packetBuffer[41] << 16;
      secsSince1900 |= (long)packetBuffer[42] << 8;
      secsSince1900 |= (long)packetBuffer[43];
      UdpNTP.stop();

      
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  UdpNTP.stop();
 
  // No NTP answer till timeout
  return 0;
}
Используйте обычный time

setSyncProvider(getNtpTime);
setSyncInterval(NTP_SYNC_TIMEOUT); // 3600 re-read per 1 hour
 

enjoynering

Well-known member
Ооо, знаменитая копипаста всея интернета. Вы можете мне объяснить, что значат цифры в packetBuffer?
 
Так и у меня все работает. Иногда без выключения неделю на четырех автономных постах. Три передают данные на четвертый, который раскидывает данные по файлам и, по запросу, выводит их на экран.
Но при внесении изменений в программу приходится долго дергаться пока не поймается правильное время.
Дергание заключается в нескольких restart, изменении имени сервера или отказе от куска программы, обеспечивающего получение правильного времени. Правильность времени проверяется по ВЕБ серверу, который или не подключается или показывает 1970 вместо 2024.
 

gromush

Member
Ооо, знаменитая копипаста всея интернета. Вы можете мне объяснить, что значат цифры в packetBuffer?
Reference
Identifier


Так и у меня все работает. Иногда без выключения неделю на четырех автономных постах. Три передают данные на четвертый, который раскидывает данные по файлам и, по запросу, выводит их на экран.
Но при внесении изменений в программу приходится долго дергаться пока не поймается правильное время.
Рестарты не бывают от того, что сервер вернул неправильное время, это ваш код либо вызывает критическую ошибку, либо трет чьи-то данные.
Отказ куска программы, вы описали как вечное ожидание, UDP протокол не гарантирует доставку пакета, напишите ожидание некоторое время с перезапросом.

Тот кусок выше работает всегда, кроме случаев потерь пакетов в сети. Перезапрос можно дописать очень легко.
 

enjoynering

Well-known member
понятно, не знаете. вы бы лучше разобрались что вы на NTP сервер посылаете.

Дергание заключается в нескольких restart, изменении имени сервера или отказе от куска программы, обеспечивающего получение правильного времени. Правильность времени проверяется по ВЕБ серверу, который или не подключается или показывает 1970 вместо 2024.
какая жесть
 
Сверху Снизу