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-битное поле номера эры, которое устранило даже ставшей теоретической проблему окончания каждой эпохи.