ntp сервер на ардуино накинул день
- Войдите на сайт для отправки комментариев
Втр, 01/03/2022 - 12:37
сегодня был озадачен такой проблемой, NTP сервер возвращает Timestamp на 70 лет больше 3855190435
что в переводе Sat, 01 Mar 2092 06:13:55 GMT
void processNTP() { int packetSize = Udp.parsePacket(); if (packetSize) { digitalWrite(ledLAN, HIGH); Udp.read(packetBuffer, NTP_PACKET_SIZE); IPAddress remote = Udp.remoteIP(); int portNum = Udp.remotePort(); // if (debugNTP == true) { Serial.println(); Serial.print("From: "); for (int i = 0; i < 4; i++) { Serial.print(remote[i], DEC); if (i < 3) { Serial.print("."); } } Serial.print(" port "); Serial.print(portNum); } // Упаковываем данные в ответный пакет: packetBuffer[0] = 0b00100100; // версия, режим packetBuffer[1] = 1; // стратум packetBuffer[2] = 6; // интервал опроса packetBuffer[3] = 0xFA; // точность packetBuffer[7] = 0; // задержка packetBuffer[8] = 0; packetBuffer[9] = 8; packetBuffer[10] = 0; packetBuffer[11] = 0; // дисперсия packetBuffer[12] = 0; packetBuffer[13] = 0xC; packetBuffer[14] = 0; //getRTCDateTime(); tmElements_t tm; if (RTC.read(tm)) { // Serial.print("Ok, Time = "); // print2digits(tm.Hour); // Serial.write(':'); // print2digits(tm.Minute); // Serial.write(':'); // print2digits(tm.Second); // Serial.print(", Date (D/M/Y) = "); // Serial.print(tm.Day); // Serial.write('/'); // Serial.print(tm.Month); // Serial.write('/'); // Serial.print(tmYearToCalendar(tm.Year)); // Serial.println(); } timestamp = numberOfSecondsSince1900Epoch(tmYearToCalendar(tm.Year), tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second); if (debugNTP == true) { Serial.println(" Timestamp = " + (String)timestamp); } tempval = timestamp; packetBuffer[12] = 71; //"G"; packetBuffer[13] = 80; //"P"; packetBuffer[14] = 83; //"S"; packetBuffer[15] = 0; //"0"; // Относительное время packetBuffer[16] = (tempval >> 24) & 0xFF; tempval = timestamp; packetBuffer[17] = (tempval >> 16) & 0xFF; tempval = timestamp; packetBuffer[18] = (tempval >> 8) & 0xFF; tempval = timestamp; packetBuffer[19] = (tempval) & 0xFF; packetBuffer[20] = 0; packetBuffer[21] = 0; packetBuffer[22] = 0; packetBuffer[23] = 0; // Копируем метку времени клиента packetBuffer[24] = packetBuffer[40]; packetBuffer[25] = packetBuffer[41]; packetBuffer[26] = packetBuffer[42]; packetBuffer[27] = packetBuffer[43]; packetBuffer[28] = packetBuffer[44]; packetBuffer[29] = packetBuffer[45]; packetBuffer[30] = packetBuffer[46]; packetBuffer[31] = packetBuffer[47]; // Метка времени packetBuffer[32] = (tempval >> 24) & 0xFF; tempval = timestamp; packetBuffer[33] = (tempval >> 16) & 0xFF; tempval = timestamp; packetBuffer[34] = (tempval >> 8) & 0xFF; tempval = timestamp; packetBuffer[35] = (tempval) & 0xFF; packetBuffer[36] = 0; packetBuffer[37] = 0; packetBuffer[38] = 0; packetBuffer[39] = 0; // Записываем метку времени packetBuffer[40] = (tempval >> 24) & 0xFF; tempval = timestamp; packetBuffer[41] = (tempval >> 16) & 0xFF; tempval = timestamp; packetBuffer[42] = (tempval >> 8) & 0xFF; tempval = timestamp; packetBuffer[43] = (tempval) & 0xFF; packetBuffer[44] = 0; packetBuffer[45] = 0; packetBuffer[46] = 0; packetBuffer[47] = 0; // Отправляем NTP ответ Udp.beginPacket(remote, portNum); Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); digitalWrite(ledLAN, LOW); } } const uint8_t daysInMonth [] PROGMEM = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // число дней в месяцах const unsigned long seventyYears = 2208988800UL; // перевод времени unix в эпоху // Формирует метку времени от момента 01.01.1900 static unsigned long int numberOfSecondsSince1900Epoch(uint16_t y, uint8_t m, uint8_t d, uint8_t h, uint8_t mm, uint8_t s) { if (y >= 1970) { y -= 1970; } uint16_t days = d; for (uint8_t i = 1; i < m; ++i) { days += pgm_read_byte(daysInMonth + i - 1); } if (m > 2 && y % 4 == 0) { ++days; } days += 365 * y + (y + 3) / 4 - 1; return days * 24L * 3600L + h * 3600L + mm * 60L + s + seventyYears; }
при этом функция
tmElements_t tm; if (RTC.read(tm)) { Serial.print("Time RTC UTC+0: "); Serial.print ((String)char (27) + "[30;43m"); print2digits(tm.Hour); Serial.write(':'); print2digits(tm.Minute); Serial.write(':'); print2digits(tm.Second); Serial.print(" "); Serial.print(tm.Day); Serial.write('/'); Serial.print(tm.Month); Serial.write('/'); Serial.print(tmYearToCalendar(tm.Year)); Serial.println();
выводит правильное значение времени
может кто сталкивался с таким поведением или сможет помочь
может кто сталкивался с таким поведением или сможет помочь
А чего тут помогать.
Вы считаете (не знаю, кто Вам сказал), что NTP возвращает время в секундах с 1900 года и используете функцию numberOfSecondsSince1900Epoch, а он на самом деле, возвращает с 1970. Вот и Ваши 70 лет. Просто смещайте на константу.
А вообще, лучше бы Вам не использовать самогонных функций. Есть же системная библиотека времени - она всё делает, если надо и время восхода и заката посчитает. Там, кстати, есть и готовая константа для пересчёта секунд от 1900 в секунды от 1970. Вернее, две
Разница между ними и есть нужное Вам смещение.
посмотрел https://wikihandbk.com/wiki/Arduino:%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8/Time
описание библиотеки и не нашел как вернуть с помощью нее время в unix формате.
или же речь идет про другую библиотеку?
или же тут речь идет что время возвращается в - now()
посмотрел https://wikihandbk.com/wiki/Arduino:%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8/Time
описание библиотеки и не нашел как вернуть с помощью нее время в unix формате.
Я вообще не понял о чём Вы? Я о системной библиотеке time, которая описана в стандарте языка и есть абсолютно во всех реализациях С и С++, а вовсе не о самогоне, от которого я Вам как раз советовал воздерживаться. Вы же опять какой-то самогон нашли.
Вот здесь есть описание библиотеки, а вот здесь я приводил примеры для Ардуино с NTP (в стартовом посте) и (пониже) со временем восхода и заката.
Ещё раз, она системная, её не нужно ниоткуда скачивать и ставить, она есть везде.
посмотрел описание библиотеки и не нашел как вернуть с помощью нее время в unix формате.
читать не умеете? цитата:
Функция now() считывает время, прошедшее с 1 января 1970 года (в секундах).
Вас смутило слово "считывает" ? - это кривой перевод с английского. тут правильно будет "возвращает"
Вроде еще не некротема.
Ковыряю этот же код (лежащий в открытом доступе), вдруг автор топика еще не разобрался.
Цитата:
Метки времени
Изначально NTP использовал 64-битные метки времени, состоявшие из 32-битной части для секунд и 32-битной части для долей секунды, что давало временную шкалу, которая прокручивалась бы каждые 232 секунды (136 лет) и давало теоретическое разрешение 2-32 секунды (233 пикосекунды). Отсчет времени начинался с 1 января 1900 года, поэтому первая эпоха закончилась бы 7 февраля 2036 года.
Последняя версия протокола NTPv4 вводит 128-битный формат представления времени: 64 бита для секунд и 64 бита для долей секунды, что дает временную шкалу более 584 млрд лет и разрешение в 0,05 аттосекунд. Дополнительно было введено 32-битное поле номера эры, которое устранило даже ставшей теоретической проблему окончания каждой эпохи.