2

Before starting working, I am just researching around how can I achieve OTA over MQTT in ESP32 in using Arduino IDE. The process I understand the esp listen to MQTT messages and then received that file over MQTT(not fully at once may be in chunks). And then stored that in flash at specific address. And then change boot loader configuration for executing new firmware.

Here I am confused how can I change boot loader configuration settings to execute the new firmware memory address ?? Any help is appreciated.

is there any out of box library available for this work? Please share reference. I can take reference from there.

Thanks

4
  • 2
    Everything is done for you using the Update library. Just feed it the right data.
    – Majenko
    Aug 10, 2021 at 9:38
  • @Majenko I am looking in to that will keep you posted. Thanks Aug 10, 2021 at 14:34
  • @Majenko I hope Update library can be used with FreeRTOS as well. Aug 11, 2021 at 4:37
  • the Update library is part of the esp32 Arduino boards support package by Espressif
    – Juraj
    Aug 11, 2021 at 11:50

1 Answer 1

2

I am not familiar with OTA for ESP32 but with SAMD21 using ArduinoOTA library and there the download is not done over MQTT but HTTPS.

Link to download is sent over MQTT but that's where it ends, download over HTTPS, verification of received data using checksum and bytes count and once InternalStorage.apply() executed it swaps the program downloaded with the older version and reboot.

EDIT:

As per Juraj request, I am adding the code as a guide you can use to get ideas. You can't run it as is, you would need to add variable declaration and wrap it in a function.

As updating wrong file will most likely brick your board, I would just add that before running this code I check the filename to make sure it is the correct BIN for the board downloading it, I am using constants like WIFI, GSM, and board name and expect to see them in the filename.

I also send the file length from the server as part of the MQTT update request and check it against my own bytes count and I am not relying on TCP to provide an error on corrupted data and do a my own checksum test.

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

// Access the file
HttpClient client(*transport, upgradeServer, upgradePort); 
client.get(upgradePath);

int statusCode = client.responseStatusCode();
  /*
   0   HTTP_SUCCESS
  -1  HTTP_ERROR_CONNECTION_FAILED  The end of the headers has been reached.  This consumes the '\n' Could not connect to the server
  -2  HTTP_ERROR_API                This call was made when the HttpClient class wasn't expecting it to be called.
                                    Usually indicates your code is using the class incorrectly
  -3  HTTP_ERROR_TIMED_OUT          Spent too long waiting for a reply
  -4  HTTP_ERROR_INVALID_RESPONSE   The response from the server is invalid, is it definitely an HTTP server?
  */

if (statusCode != 200) {
  client.stop();
  // here you can do something with statusCode like notifying over MQTT
}

long length = client.contentLength();
if (length == HttpClient::kNoContentLengthHeader) {
  client.stop();
  //Server didn't provide Content-length header, abort.
  return; 
}
  
if (!InternalStorage.open(length)) {
  client.stop();
  // Not enough space to store the file, abort.
  return;
}

// Start update, length holds the file size in bytes

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) {
   // Abort, stopped after ((millis() - otaStartMillis)/1000) Sec
    return;
  }

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

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

if (localChecksum != remoteCkecksum) {
 // Checksum mismatch, abort.
  return;
}

  
if (length > 0) {
  // Timeout at byte length, abort.
  return;
}

InternalStorage.apply(); // this doesn't return, board should restart

Serial.println("Update failed"); //shown only if update failed

Another opportunity to thank Jurak for this library!

5
  • In my case, the ESP32 doesn't have access to public network. So I will prefer to send the file over MQTT from server side and client(ESP 32) will receive that and do the required things. Aug 11, 2021 at 9:37
  • @Abhishekbhatia, how does the ESP32 do MQTT without access to the server?
    – Juraj
    Aug 11, 2021 at 11:52
  • 1
    @Juraj I mentioned that, In my use case ESP 32 doesn't have access to public network. It is connect to MQTT server hosted on edge device(They are on private network) . I just don't wanted to use http. Aug 11, 2021 at 15:20
  • @Juraj would you suggest me which library is better to use for my use case ArduinoOTA or update ?? Aug 11, 2021 at 15:26
  • @Abhishekbhatia Update. because esp32 boards support package has a libray named ArduinoOTA. you would have to delete it to use the generic ArduinoOTA. The generic ArduinoOTA only wraps the Update library. Generic ArduinoOTA is useful for esp32 with W5500 or enc28j60 Ethernet module.
    – Juraj
    Aug 11, 2021 at 15:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.