OTA and Update.h

jchastine
Posts: 1
Joined: Sun Jul 12, 2020 10:27 pm

OTA and Update.h

Postby jchastine » Sun Jul 12, 2020 10:48 pm

Good morning/evening! I'm trying to use the Update class for OTA but am having difficulty. What I'd like to do is read the file size from a server (via sockets), read a .bin file in chunks of 4K from the network and write those chunks to the updater, then end the update process. The basic code structure is:

Update.begin(<filesize>);
while (<more bytes to read>) {
read into buffer;
amountWritten = Update.write (buffer, bytes read);
}
Update.end();

It looks like subsequent calls to Update.write() after the first call return a value of 0, but the first time returns the value 4096. I think I have a wrong mental model for how this works, but looking at this, it should:

https://github.com/espressif/arduino-es ... c/Update.h

Unfortunately, I can't use the web browser version...

Thanks for any insight you have.

BobLynas
Posts: 1
Joined: Wed Apr 06, 2022 12:05 pm

Re: OTA and Update.h

Postby BobLynas » Wed Apr 06, 2022 12:15 pm

HI, I am also having very similar issues, but I believe the 4k is the size of the flash block, and the ESP32 has to erase and write this, but perhaps the first time (or couple of times) takes a bit longer, I have seen delays of a few seconds sometimes. But I am literally at the same point as you and if I can get over this and find a cure ill come back and let you know

pidloop
Posts: 2
Joined: Tue Jun 14, 2022 5:56 pm

Re: OTA and Update.h

Postby pidloop » Fri Jun 17, 2022 3:09 am

FWIW, I was able to add OTA to my ESP32 app very easily. I already had a WiFIServer instance anyway for RESTful commands so I added one called /update. It expects a POST command sent with curl as follows:

Code: Select all

curl -H "Content-Type: application/octet-stream" --data-binary @$BINFILE "http://PowerMeter.local:8010/upload" 
The key part of the code to perform the update is the following (error checking omitted):

Code: Select all

#include <Update.h>
char buf[4096];
int lr;
httpSkipHeader (client);	// my function
Update.begin(UPDATE_SIZE_UNKNOWN);
while ((lr = client.read(buf, sizeof(buf))) > 0)
    Update.write (buf, lr);
Update.end(true);
ESP.restart();
The buf size must be 4096, no other value works. Hope this helps someone someday. Cheers!

KhushalShah
Posts: 2
Joined: Sun Dec 15, 2019 2:49 pm

Re: OTA and Update.h

Postby KhushalShah » Sun Sep 10, 2023 7:10 pm

Hello,
I have been facing the same issue.
I have an ESP32 and I am trying to download an Arduino-compiled file - sketch.ino.bin from my nodeJS server.
Here is the NodeJS code -

Code: Select all

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/download') {
    const filePath = './sketch.ino.bin'; // Change to your file's path
    const fileName = 'sketch.ino'; // Change to your desired file name

    res.setHeader('Content-Disposition', `attachment; filename=${fileName}`);
    res.setHeader('Content-Type', 'application/octet-stream');

    const fileStream = fs.createReadStream(filePath);
    fileStream.pipe(res);
  } else {
    res.statusCode = 404;
    res.end('Not Found');
  }
});

const port = 3000; // Change to your desired port
server.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});
On the ESP-side, I have this -

Code: Select all

#include <WiFi.h>
#include <HTTPClient.h>
#include <Update.h>

const char* ssid = "khushal";
const char* password = "123456789";
const char* serverAddress = "192.168.29.81";
const int serverPort = 3000; // Change to your server's port
const String firmwareFileName = "sketch.bin"; // The name of the firmware file to be downloaded and flashed

void setup() {
  Serial.begin(115200);
  delay(100);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Specify the URL for the firmware file you want to download
  String url = "http://" + String(serverAddress) + ":" + String(serverPort) + "/download";

  HTTPClient http;
  http.begin(url);

  int httpCode = http.GET();
  if (httpCode == HTTP_CODE_OK) {
    Serial.println("Downloading firmware...");

    if (Update.begin(UPDATE_SIZE_UNKNOWN)) {
      
      int len = http.getSize();
      uint8_t buff[4096] = { 0 };

      // get tcp stream
      WiFiClient * stream = http.getStreamPtr();
      
      // read all data from server
      while(http.connected() && (len > 0 || len == -1)) {
        // get available data size
        size_t size = stream->available();
        if(size) {
          int act_size = ((size > sizeof(buff)) ? sizeof(buff) : size);
          int c = stream->readBytes(buff, act_size);
        
          // write it to Serial
          int writtenCount = Update.write(buff, c);
          Serial.println((String)"written:"+writtenCount+" act_size:"+act_size);

          if (writtenCount != act_size) {
            Serial.println("Error updating firmware here");
            break;
          }
          if(len > 0) {
            len -= c;
          }
        }
        delay(1);
      }

      if (Update.end()) {
        Serial.println("Firmware update successful!");
        delay(10000);
        ESP.restart();
      } else {
        Serial.println("Error updating firmware");
      }
    } else {
      Serial.println("Error starting update");
    }
  } else {
    Serial.println("Firmware download failed");
  }

  http.end();
}

void loop() {
}
When I try to run this code, I see that the ESP32 was able to write 4096 bytes, but after that, the Update.write() returns 0 and my code exits the loop.
What may be the possible cause of this?

Possibly any issue from the server-side code ?

antonins
Posts: 11
Joined: Sun Feb 12, 2023 12:45 pm

Re: OTA and Update.h

Postby antonins » Thu Dec 14, 2023 7:25 am

Hello KhushalShah ,

I'm facing a similar issue, have you solved your problem ?

Antonin

Who is online

Users browsing this forum: Majestic-12 [Bot] and 36 guests