Безопасный при опрокидывании NTP дизайн с ESP8266 (Curiosity)
Реализация Arduino NTP в некоторых отношениях довольно наивна. По сути, он просто берет время в секундах из необработанного пакета, а затем преобразует его во время Unix путем вычитания. Как можно было бы создать реализацию, защищенную, по крайней мере, от следующего обновления NTP (должно быть в 2036 году)? Я бы предпочел не разрабатывать что-то, что может неожиданно выйти из строя через десятилетие или два, если я забыл, почему это могло произойти (но это не так уж важно, если это не так просто исправить).
Если он сможет дотянуть до 2100, у меня будут большие проблемы (RTC сам себя испортит), так что просто этот перенос подойдет.
Существующая реализация (https://github.com/arduino-libraries/NTPClient/blob /мастер/NTPClient.cpp):
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
// объединяем четыре байта (два слова) в длинное целое
// это время NTP (секунды с 1 января 1900 года):
unsigned long secsSince1900 = highWord << 16 | lowWord;
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
@, 👍2
1 ответ
Лучший ответ:
Эта реализация превосходна. Расчеты производятся с
числа без знака, поэтому они, естественно, безопасны при переносе. День НТП время
переворачивается, secsSince1900
станет очень маленьким числом, и
вычитание из него SEVENZYYEARS
вызовет дополнительный перенос. из-за
по правилам модульной арифметики эти два переноса компенсируют и
вы гарантированно получите правильный результат по модулю
232 с.
В конце вы получите время Unix в виде 32-битного целого числа без знака. Unix-время имеет традиционную подпись, поэтому 32-битное представление сменяется в январе 2038 года. Вместо этого авторы этой библиотеки выбрали представлять его как число без знака, что означает, что оно будет перевернуто через февраль 2106 г.
- ESP8266: ошибка: 'getLocalTime' was not declared in this scope
- Как разобрать 20180810T143000Z в time_t
- Как найти разницу между двумя timestamp
- Установить time() на ESP8266
- ESP8266 ISO 8601 string to tm struct
- Каков идеальный способ проверить, готово ли время на ESP8266 через NTP?
- Время UNIX в мс в человеческую дату и время
- Не удалось изменить NtpClient для использования статического IP-адреса
Хм. Это на самом деле довольно круто. Я знал о подобном методе для millis(), но не знал, что это работает и для NTP. Спасибо!, @RDragonrydr
@RDragonrydr: перенос распространяется от низкого к высокому сложению/вычитанию. Младшие биты результата *не* зависят от более высоких битовых позиций, поэтому, если вы хотите получить 32-битный результат, всегда безопасно обрезать ваши входные данные вместо 64-битного вычитания и усечения результата. То же самое для сдвига влево или умножения младших
N
битовN x N
. См. Также [Какие целочисленные операции с дополнением до 2 можно использовать без обнуления старших битов во входных данных, если требуется только младшая часть результата?](//stackoverflow.com/q/34377711), @Peter CordesЯ знал это, но я не знал, что метод Arduino сможет обрабатывать опрокидывание в NTP, не совсем случайно, но без необходимости обнаруживать его как таковое. Я полагал, что, поскольку время представляет собой абсолютную дельту после определенной даты начала, любое пролонгирование ДОЛЖНО давать неправильное время, как только оно произойдет., @RDragonrydr