Как изменить тайм-аут загрузки ArduinoOTA?

Я использую ESP8266WiFiMulti, ESP8266WebServer и ArduinoOTA для связи с моим устройством и выполнения обновлений по воздуху. Все работало отлично, пока я не переместил ESP8266 дальше от Wi-Fi-маршрутизатора. Загрузка OTA замедлилась, что привело к тайм-аутам загрузки через 5 секунд. Каждый раз он терпит неудачу в разных точках, обычно между 30% и 60%.

Как увеличить тайм-аут OTA до 30 секунд?

Вот код настройки, дайте мне знать, если вам нужно больше:

void startWiFi() {
    ESP8266WiFiMulti wifiMulti;
    wifiMulti.addAP(ssid, password);
    wifiMulti.run();
}

void startOTA() {
    ArduinoOTA.setHostname(_hostname);
    ArduinoOTA.setPassword(_password);

    ArduinoOTA.onStart([]() {
        Serial.println("Start OTA");
    });
    ArduinoOTA.onEnd([]() {
        Serial.println("\nEnd OTA");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
        Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
        Serial.printf("Error[%u]: ", error);
        if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
        else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
        else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
        else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
        else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });
    ArduinoOTA.begin();
}

, 👍0


1 ответ


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

2

Единственный тайм-аут, который я могу найти, находится в espota.py сам сценарий. Это пронизано такими строками, как:

sock.settimeout(10)

Вам нужно будет прочесать эту программу и изменить их все.

Однако

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

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

Вам следует подумать о переходе на более надежную систему обновления, которая использует TCP вместо UDP - например, загрузить обновление с веб-сайта с помощью ESP8266httpUpdate.

Обновление:

ArduinoOTA использует комбинацию UDP (для инициализации и аутентификации соединения) и TCP (для создания "обратного канала" подключения к вашему компьютеру) для загрузки фактического двоичного файла.

То же самое относится и к вам: вам нужно будет изменить espota.py программа для изменения своих таймаутов (sock2-это объект обратного канала), но есть также одна строка в ArduinoOTA.cpp это нужно будет изменить, чтобы увеличить таймауты. Строка 294:

int waited = 1000;

Это не совсем количество миллисекунд для ожидания входящих данных, но оно не за горами - это задержка в 1 миллисекунду в цикле при поиске входящих данных. Увеличение этого количества позволит ESP8266 больше времени ждать поступления данных.

Но, конечно, с нестабильным Wi-Fi-соединением YMMV...

,

Спасибо за ответ! Какой смысл использовать UDP для обновления прошивки, критической функции? Я использую файловую систему LittleFS, поэтому я также могу загрузить файл, а затем найти библиотеку для переключения программы., @DV82XL

Это быстрый, простой в реализации пакет, легкий вес и достаточно надежный для большинства применений. Ты - угловой случай., @Majenko

Я имел в виду, почему ArduinoOTA использует UDP вместо TCP? Это похоже на плохое дизайнерское решение. Обновления прошивки должны быть без потерь., @DV82XL

По причинам, которые я только что изложил. Значительно проще, легче и быстрее написать протокол на основе пакетов с использованием UDP по сравнению с TCP., @Majenko

Нет! Это не ненадежное программное обеспечение. UDP-это *ненадежный* протокол. Не то чтобы это было бледно или плохо написано. Это *ненадежно*. Это официальный термин для такого рода протокола. Протокол без встроенного средства ретрансляции называется *ненадежным*. ArduinoOTA очень хорошо написана и сама по себе очень надежна и безопасна. Тот факт, что он не работает в вашей сети, объясняется тем, что ваша сеть теряет пакеты. Получите лучший сигнал Wi-Fi или не используйте ArduinoOTA. Он предназначен для разработки, а не для производства. Никто в здравом уме не стал бы использовать ArduinoOTA для производства, они бы использовали HTTP - сервер., @Majenko

Вы правы, я просто выбрал не ту библиотеку для своих нужд. Я должен был быть спроектирован так, чтобы иметь возможность менять комнаты. Я найду более надежное решение. Спасибо за ваш ответ!, @DV82XL

@Majenko Официальный термин [*connectionless*](https://en.wikipedia.org/wiki/Connectionless_communication) что просто означает, что протокол UDP не предусматривает для получателя пакета отправки Подтверждения, чтобы сообщить отправителю, что каждый пакет был получен. Это не значит, что вы не можете создавать надежные протоколы, используя UDP. Надежность должна исходить от протоколов более высокого уровня, построенных поверх UDP., @StarCat

@Majenko, espota.py а библиотека ArduinoOTA использует TCP для передачи двоичного файла, @Juraj

@Juraj Так оно и есть. Сначала он инициирует соединение с UDP а затем ESP8266 устанавливает обратное соединение с запущенным компьютером espota.py чтобы вытащить двоичный файл. Поделом мне, если я попытаюсь расшифровать Python в 2 часа ночи. Это достаточно плохо в лучшие времена, когда я сыт кофе..., @Majenko

@StarCat Еще когда я учился в университете, это называлось ненадежной и надежной передачей. Передача, которая не повторяется, против передачи, которая повторяется. Может быть, это что-то региональное., @Majenko

@Majenko, похоже, вы тоже правы, хотя есть разница между определением ненадежного протокола и протоколом без подключения (пришлось его поискать). Для UDP верно и то, и другое., @StarCat

@StarCat Connectionless-это состояние, надежность-это повторная отправка пакетов. Эти два метода обычно используются или не используются в тандеме. Я предполагаю, что у вас может быть надежный протокол без состояния (connectionless) или ненадежный протокол с сохранением состояния (connectionful?)..., @Majenko