Безопасный при опрокидывании 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 ответ


Лучший ответ:

4

Эта реализация превосходна. Расчеты производятся с числа без знака, поэтому они, естественно, безопасны при переносе. День НТП время переворачивается, secsSince1900 станет очень маленьким числом, и вычитание из него SEVENZYYEARS вызовет дополнительный перенос. из-за по правилам модульной арифметики эти два переноса компенсируют и вы гарантированно получите правильный результат по модулю 232 с.

В конце вы получите время Unix в виде 32-битного целого числа без знака. Unix-время имеет традиционную подпись, поэтому 32-битное представление сменяется в январе 2038 года. Вместо этого авторы этой библиотеки выбрали представлять его как число без знака, что означает, что оно будет перевернуто через февраль 2106 г.

,

Хм. Это на самом деле довольно круто. Я знал о подобном методе для millis(), но не знал, что это работает и для NTP. Спасибо!, @RDragonrydr

@RDragonrydr: перенос распространяется от низкого к высокому сложению/вычитанию. Младшие биты результата *не* зависят от более высоких битовых позиций, поэтому, если вы хотите получить 32-битный результат, всегда безопасно обрезать ваши входные данные вместо 64-битного вычитания и усечения результата. То же самое для сдвига влево или умножения младших N битов N x N. См. Также [Какие целочисленные операции с дополнением до 2 можно использовать без обнуления старших битов во входных данных, если требуется только младшая часть результата?](//stackoverflow.com/q/34377711), @Peter Cordes

Я знал это, но я не знал, что метод Arduino сможет обрабатывать опрокидывание в NTP, не совсем случайно, но без необходимости обнаруживать его как таковое. Я полагал, что, поскольку время представляет собой абсолютную дельту после определенной даты начала, любое пролонгирование ДОЛЖНО давать неправильное время, как только оно произойдет., @RDragonrydr