OTA через MQTT для ESP32

Прежде чем приступить к работе, я просто исследую, как я могу достичь OTA по сравнению с MQTT в ESP32 с помощью Arduino IDE. Процесс, который, как я понимаю, esp прослушивает сообщения MQTT, а затем получает этот файл через MQTT(не полностью сразу, может быть, по частям). А затем сохранил это во флэш-памяти по определенному адресу. А затем измените конфигурацию загрузчика для выполнения новой прошивки.

Здесь я в замешательстве, как я могу изменить настройки конфигурации загрузчика для выполнения нового адреса памяти прошивки ?? Любая помощь будет признательна.

есть ли какая-либо готовая библиотека, доступная для этой работы? Пожалуйста, поделитесь ссылкой. Я могу взять справку оттуда.

Спасибо

, 👍2

Обсуждение

Все делается для вас с помощью библиотеки " Обновление`. Просто скормите ему нужные данные., @Majenko

@Majenko Я слежу за тем, чтобы вы были в курсе. Спасибо, @Abhishek bhatia

@Majenko Я надеюсь, что библиотека обновлений также может использоваться с бесплатными., @Abhishek bhatia

библиотека обновлений является частью пакета поддержки плат esp32 для Arduino от Espressif, @Juraj


1 ответ


2

Я не знаком с OTA для ESP32, но с SAMD21, использующим библиотеку ArduinoOTA, и там загрузка выполняется не через MQTT, а по протоколу HTTPS.

Ссылка для загрузки отправляется по MQTT, но на этом она заканчивается, загрузка по HTTPS, проверка полученных данных с использованием контрольной суммы и количества байтов, а после выполнения InternalStorage.apply() заменяет загруженную программу на более старую версию и перезагружается.

ОТРЕДАКТИРОВАНО:

Согласно запросу Юрая, я добавляю код в качестве руководства, которое вы можете использовать для получения идей. Вы не можете запустить его как есть, вам нужно будет добавить объявление переменной и обернуть ее в функцию.

Поскольку обновление неправильного файла, скорее всего, приведет к блокировке вашей платы, я бы просто добавил, что перед запуском этого кода я проверяю имя файла, чтобы убедиться, что это правильное место для загрузки платы, я использую константы, такие как WI-Fi, GSM и название платы, и ожидаю увидеть их в имени файла.

Я также отправляю длину файла с сервера в рамках запроса на обновление MQTT и сверяю ее с моим собственным количеством байтов, и я не полагаюсь на TCP, чтобы выдать ошибку в поврежденных данных и выполнить свой собственный тест контрольной суммы.

#include <ArduinoOTA.h>  // https://github.com/jandrassy/ArduinoOTA

// Доступ к файлу
HttpClient client(*transport, upgradeServer, upgradePort); 
client.get(upgradePath);

int statusCode = client.responseStatusCode();
  /*
   0   HTTP_SUCCESS
  -1  HTTP_ERROR_CONNECTION_FAILED  Отправлен Конец заголовков достигнут.  Это приводит к тому, что "\n " Не удалось подключиться к серверу
  -2  HTTP_ERROR_API                Этот вызов был выполнен, когда класс HttpClient не ожидал, что он будет вызван.
                                    Обычно указывает на то, что ваш код неправильно использует класс
  -3  HTTP_ERROR_TIMED_OUT          Слишком долго ждал ответа
  -4  HTTP_ERROR_INVALID_RESPONSE   Ответ с сервера недействителен, это определенно HTTP-сервер?
  */

if (statusCode != 200) {
  client.stop();
  // здесь вы можете сделать что-то с кодом состояния, например, уведомить через MQTT
}

long length = client.contentLength();
if (length == HttpClient::kNoContentLengthHeader) {
  client.stop();
  //Сервер не предоставил заголовок длины содержимого, прервать.
  return; 
}
  
if (!InternalStorage.open(length)) {
  client.stop();
  // Недостаточно места для хранения файла, прервать.
  return;
}

// Начать обновление, длина содержит размер файла в байтах

client.setTimeout(5000);
byte b;
bool ok;
long fileLength = length;
unsigned long otaStartMillis = millis();
int localChecksum = 0;

while (length > 0) {

  ok = client.readBytes(&b, 1);
  if (!ok) {
   // Прерывание, остановлено после ((millis() - otaStartMillis)/1000) Sec
    return;
  }

  InternalStorage.write(b);
  int bValue = (int)b;
  localChecksum = localChecksum + bValue;
  
  length--;
}

InternalStorage.close();
client.stop();

if (localChecksum != remoteCkecksum) {
 // Несоответствие контрольной суммы, отмена.
  return;
}

  
if (length > 0) {
  // Тайм-аут длиной в байт, прервать.
  return;
}

InternalStorage.apply(); // это не возвращается, плата должна перезапуститься

Serial.println("Update failed"); //отображается только в случае сбоя обновления

Еще одна возможность поблагодарить Юрака за эту библиотеку!

,

В моем случае ESP32 не имеет доступа к общедоступной сети. Поэтому я предпочту отправить файл через MQTT со стороны сервера, и клиент(ESP 32) получит его и выполнит необходимые действия., @Abhishek bhatia

@Abhishekbhatia, как ESP32 выполняет MQTT без доступа к серверу?, @Juraj

@Juraj Я упомянул, что в моем случае ESP 32 не имеет доступа к общедоступной сети. Он подключается к серверу MQTT, размещенному на пограничном устройстве(они находятся в частной сети) . Я просто не хотел использовать http., @Abhishek bhatia

@Juraj не могли бы вы подсказать мне, какую библиотеку лучше использовать для моего варианта использования ArduinoOTA или обновления ??, @Abhishek bhatia

@Abhishekbhatia Обновление. потому что в пакете поддержки плат esp32 есть libray с именем ArduinoOTA. вам придется удалить его, чтобы использовать общий ArduinoOTA. Универсальная ArduinoOTA обертывает только библиотеку обновлений. Универсальный ArduinoOTA полезен для esp32 с модулем Ethernet W5500 или enc28j60., @Juraj