esp8266 self OTA update firmware from server – 1

Spread the love

OTA (Over the Air) update is the process of uploading firmware to an ESP module using a Wi-Fi connection rather than a serial port. Such functionality becomes extremely useful in case of limited or no physical access to the module.

esp8266 self OTA update firmware from server
esp8266 self OTA update firmware from server

OTA may be done using:

  • Arduino IDE
  • Web Browser
  • HTTP Server

First of all read the tutorial “esp8266: flash firmware binary (.bin) compiled and signed“.

In this article we will explain how to do an automatic update from an HTTP server.

Automatic OTA update every application start

ESPhttpUpdate class can check for updates and download a binary file from HTTP web server. It is possible to download updates from every IP or domain address on the network or Internet.

Note that by default this class closes all other connections except the one used by the update, this is because the update method blocks. This means that if there’s another application receiving data then TCP packets will build up in the buffer leading to out of memory errors causing the OTA update to fail. There’s also a limited number of receive buffers available and all may be used up by other applications.

There are some cases where you know that you won’t be receiving any data but would still like to send progress updates. It’s possible to disable the default behavior (and keep connections open) by calling closeConnectionsOnUpdate(false). (Cit.)

Create a basic web server

Now we are going o create a fast server to download the firmware, next to manage REST.

Prepare environment

  1. We use NodeJS, you can download It from here.
  2. After installation create a new directory OTAServer.
  3. CD inside the OTAServer folder.

Initialize application

  1. Inside folder launch npm init.
D:\Projects\IdeaProjects\OTAWebPages\OTAServer>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (otaserver)
version: (1.0.0)
description: Server to test HTTP server OTA update
entry point: (index.js)
test command:
git repository:
keywords: OTA esp8266 esp32 Server
author: Renzo Mischianti
license: (ISC)
About to write to D:\Projects\IdeaProjects\OTAWebPages\OTAServer\package.json:

{
  "name": "otaserver",
  "version": "1.0.0",
  "description": "Server to test HTTP server OTA update",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "OTA",
    "esp8266",
    "esp32",
    "Server"
  ],
  "author": "Renzo Mischianti",
  "license": "ISC"
}


Is this OK? (yes) yes
  1. Install express the basic server in NodeJS
    npm install express --save-dev

Basic web server code

  1. Create index.js.
  2. Add this content on index.js.
const express = require('express');
const { networkInterfaces } = require('os');

const app = express();
const nets = networkInterfaces();

// Server port
const PORT = 3000;

app.get('/', (request, response) => response.send('Hello from www.mischianti.org!'));

app.listen(PORT, () => {
    const results = {}; // Or just '{}', an empty object

    for (const name of Object.keys(nets)) {
        for (const net of nets[name]) {
            // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
            if (net.family === 'IPv4' && !net.internal) {
                if (!results[name]) {
                    results[name] = [];
                }
                results[name].push(net.address);
            }
        }
    }

    console.log('Listening on port '+PORT+'\n', results)
});
  1. Start the application with node index.js.
D:\Projects\IdeaProjects\OTAWebPages\OTAServer>node index.js
Listening on port 3000
 {
  'VirtualBox Host-Only Network': [ '192.168.56.1' ],
  'VMware Network Adapter VMnet1': [ '192.168.113.1' ],
  'VMware Network Adapter VMnet8': [ '192.168.116.1' ],
  Ethernet: [ '192.168.1.70' ]
}
  1. Grab correct IP from the console, we can’t use localhost or 127.0.0.1 for our test, so I print at start all the interfaces, and in my case the IP of the current application is Ethernet: [ '192.168.1.70' ]
  2. Put on the browser the url http://192.168.1.70:3000/.
  3. Check in the browser page the sentence “Hello from www.mischianti.org!”.

Create the initial sketch

We can use the basic example that you can find on File -> Examples -> ESP8266httpUpdate -> httpUpdate.

We change It to point at our new server.

/*
 * Basic Sketch for automatic update of firmware at start
 * 
 * Renzo Mischianti <www.mischianti.org>
 * 
 * https://mischianti.org
*/

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>

#ifndef APSSID
#define APSSID "<YOUR-SSID>"
#define APPSK  "<YOUR-PASSWD>"
#endif

ESP8266WiFiMulti WiFiMulti;

#define FIRMWARE_VERSION "0.2"

void update_started() {
  Serial.println("CALLBACK:  HTTP update process started");
}

void update_finished() {
  Serial.println("CALLBACK:  HTTP update process finished");
}

void update_progress(int cur, int total) {
  Serial.printf("CALLBACK:  HTTP update process at %d of %d bytes...\n", cur, total);
}

void update_error(int err) {
  Serial.printf("CALLBACK:  HTTP update fatal error code %d\n", err);
}

void setup() {

  Serial.begin(115200);
//   Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(APSSID, APPSK);

  Serial.print(F("Firmware version "));
  Serial.println(FIRMWARE_VERSION);
  delay(2000);
}


void loop() {
    // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {

    WiFiClient client;

    // The line below is optional. It can be used to blink the LED on the board during flashing
    // The LED will be on during download of one buffer of data from the network. The LED will
    // be off during writing that buffer to flash
    // On a good connection the LED should flash regularly. On a bad connection the LED will be
    // on much longer than it will be off. Other pins than LED_BUILTIN may be used. The second
    // value is used to put the LED on. If the LED is on with HIGH, that value should be passed
    ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW);

    // Add optional callback notifiers
    ESPhttpUpdate.onStart(update_started);
    ESPhttpUpdate.onEnd(update_finished);
    ESPhttpUpdate.onProgress(update_progress);
    ESPhttpUpdate.onError(update_error);

    ESPhttpUpdate.rebootOnUpdate(false); // remove automatic update

    Serial.println(F("Update start now!"));

    // t_httpUpdate_return ret = ESPhttpUpdate.update(client, "http://192.168.1.70:3000/firmware/httpUpdateNew.bin");
    // Or:
    t_httpUpdate_return ret = ESPhttpUpdate.update(client, "192.168.1.70", 3000, "/firmware/httpUpdateNew.bin");

    switch (ret) {
      case HTTP_UPDATE_FAILED:
        Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
        Serial.println(F("Retry in 10secs!"));
        delay(10000); // Wait 10secs
        break;

      case HTTP_UPDATE_NO_UPDATES:
        Serial.println("HTTP_UPDATE_NO_UPDATES");
        break;

      case HTTP_UPDATE_OK:
        Serial.println("HTTP_UPDATE_OK");
        delay(1000); // Wait a second and restart
        ESP.restart();
        break;
    }
  }
}

Remember to add your SSID and PASSWD

If you upload the sketch you will get this error on Serial output.

[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
CALLBACK:  HTTP update fatal error code -104
HTTP_UPDATE_FAILD Error (-104): Wrong HTTP Code

This because It can’t find the Firmware on path http://192.168.1.70:3000/firmware/httpUpdateNew.bin, and the server return an HTTP code 404 Not found.

If you stop the server receive

[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
Firmware version 0.1
Update start now!
CALLBACK:  HTTP update fatal error code -1
HTTP_UPDATE_FAILD Error (-1): HTTP error: connection failed
Retry in 10secs!

Generate binary file

Refer to the article “esp8266: flash del firmware binario(.bin) compilato e firmato”. to understand all type of compiled binary file.

Follow these steps to generate binary file:

  1. Click on Sketch -> Export Compiled Binary;
esp8266 esp32 Arduino Export compiled binary IDE menu
esp8266 esp32 Arduino Export compiled binary IDE menu
  1. Click on Sketch -> Open Sketch Folder;
  2. Rename the .bin file to httpUpdateNew.bin.

Create download url

Now return to OTAServer folder and:

  1. Create firmware folder.
  2. Put a httpUpdateNew.bin file inside the firmware folder.
  3. Add to your index.js the download URL in GET
const express = require('express');
const { networkInterfaces } = require('os');
const path = require('path');

const app = express();
const nets = networkInterfaces();

// Server port
const PORT = 3000;

app.get('/', (request, response) => response.send('Hello from www.mischianti.org!'));

let downloadCounter = 1;
app.get('/firmware/httpUpdateNew.bin', (request, response) => {
    response.download(path.join(__dirname, 'firmware/httpUpdateNew.bin'), 'httpUpdateNew.bin', (err)=>{
        if (err) {
            console.error("Problem on download firmware: ", err)
        }else{
            downloadCounter++;
        }
    });
    console.log('Your file has been downloaded '+downloadCounter+' times!')
})

app.listen(PORT, () => {
    const results = {}; // Or just '{}', an empty object

    for (const name of Object.keys(nets)) {
        for (const net of nets[name]) {
            // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
            if (net.family === 'IPv4' && !net.internal) {
                if (!results[name]) {
                    results[name] = [];
                }
                results[name].push(net.address);
            }
        }
    }

    console.log('Listening on port '+PORT+'\n', results)
});
  1. Restart application with Ctrl+C and node index.js.
  2. Test the URL by write in the Browser URL
    http://192.168.1.70:3000/firmware/httpUpdateNew.bin
    If all ok, the download start, and you can find in the console these lines
D:\Projects\IdeaProjects\OTAWebPages\OTAServer>node index.js
Listening on port 3000
 {
  'VirtualBox Host-Only Network': [ '192.168.56.1' ],
  'VMware Network Adapter VMnet1': [ '192.168.113.1' ],
  'VMware Network Adapter VMnet8': [ '192.168.116.1' ],
  Ethernet: [ '192.168.1.70' ]
}
Your file has been downloaded 1 times!
Your file has been downloaded 2 times!

Final test

Now if we change FIRMWARE_VERISON to 0.2 and retry the result become like so:

[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
Firmware version 0.1
Update start now!
CALLBACK:  HTTP update process started
CALLBACK:  HTTP update process at 0 of 307872 bytes...
CALLBACK:  HTTP update process at 0 of 307872 bytes...
CALLBACK:  HTTP update process at 4096 of 307872 bytes...
CALLBACK:  HTTP update process at 8192 of 307872 bytes...
CALLBACK:  HTTP update process at 12288 of 307872 bytes...
CALLBACK:  HTTP update process at 16384 of 307872 bytes...
CALLBACK:  HTTP update process at 20480 of 307872 bytes...
CALLBACK:  HTTP update process at 24576 of 307872 bytes...
CALLBACK:  HTTP update process at 28672 of 307872 bytes...
CALLBACK:  HTTP update process at 32768 of 307872 bytes...
CALLBACK:  HTTP update process at 36864 of 307872 bytes...
CALLBACK:  HTTP update process at 40960 of 307872 bytes...
CALLBACK:  HTTP update process at 45056 of 307872 bytes...
CALLBACK:  HTTP update process at 49152 of 307872 bytes...
CALLBACK:  HTTP update process at 53248 of 307872 bytes...
CALLBACK:  HTTP update process at 57344 of 307872 bytes...
CALLBACK:  HTTP update process at 61440 of 307872 bytes...
CALLBACK:  HTTP update process at 65536 of 307872 bytes...
CALLBACK:  HTTP update process at 69632 of 307872 bytes...
CALLBACK:  HTTP update process at 73728 of 307872 bytes...
CALLBACK:  HTTP update process at 77824 of 307872 bytes...
CALLBACK:  HTTP update process at 81920 of 307872 bytes...
CALLBACK:  HTTP update process at 86016 of 307872 bytes...
CALLBACK:  HTTP update process at 90112 of 307872 bytes...
CALLBACK:  HTTP update process at 94208 of 307872 bytes...
CALLBACK:  HTTP update process at 98304 of 307872 bytes...
CALLBACK:  HTTP update process at 102400 of 307872 bytes...
CALLBACK:  HTTP update process at 106496 of 307872 bytes...
CALLBACK:  HTTP update process at 110592 of 307872 bytes...
CALLBACK:  HTTP update process at 114688 of 307872 bytes...
CALLBACK:  HTTP update process at 118784 of 307872 bytes...
CALLBACK:  HTTP update process at 122880 of 307872 bytes...
CALLBACK:  HTTP update process at 126976 of 307872 bytes...
CALLBACK:  HTTP update process at 131072 of 307872 bytes...
CALLBACK:  HTTP update process at 135168 of 307872 bytes...
CALLBACK:  HTTP update process at 139264 of 307872 bytes...
CALLBACK:  HTTP update process at 143360 of 307872 bytes...
CALLBACK:  HTTP update process at 147456 of 307872 bytes...
CALLBACK:  HTTP update process at 151552 of 307872 bytes...
CALLBACK:  HTTP update process at 155648 of 307872 bytes...
CALLBACK:  HTTP update process at 159744 of 307872 bytes...
CALLBACK:  HTTP update process at 163840 of 307872 bytes...
CALLBACK:  HTTP update process at 167936 of 307872 bytes...
CALLBACK:  HTTP update process at 172032 of 307872 bytes...
CALLBACK:  HTTP update process at 176128 of 307872 bytes...
CALLBACK:  HTTP update process at 180224 of 307872 bytes...
CALLBACK:  HTTP update process at 184320 of 307872 bytes...
CALLBACK:  HTTP update process at 188416 of 307872 bytes...
CALLBACK:  HTTP update process at 192512 of 307872 bytes...
CALLBACK:  HTTP update process at 196608 of 307872 bytes...
CALLBACK:  HTTP update process at 200704 of 307872 bytes...
CALLBACK:  HTTP update process at 204800 of 307872 bytes...
CALLBACK:  HTTP update process at 208896 of 307872 bytes...
CALLBACK:  HTTP update process at 212992 of 307872 bytes...
CALLBACK:  HTTP update process at 217088 of 307872 bytes...
CALLBACK:  HTTP update process at 221184 of 307872 bytes...
CALLBACK:  HTTP update process at 225280 of 307872 bytes...
CALLBACK:  HTTP update process at 229376 of 307872 bytes...
CALLBACK:  HTTP update process at 233472 of 307872 bytes...
CALLBACK:  HTTP update process at 237568 of 307872 bytes...
CALLBACK:  HTTP update process at 241664 of 307872 bytes...
CALLBACK:  HTTP update process at 245760 of 307872 bytes...
CALLBACK:  HTTP update process at 249856 of 307872 bytes...
CALLBACK:  HTTP update process at 253952 of 307872 bytes...
CALLBACK:  HTTP update process at 258048 of 307872 bytes...
CALLBACK:  HTTP update process at 262144 of 307872 bytes...
CALLBACK:  HTTP update process at 266240 of 307872 bytes...
CALLBACK:  HTTP update process at 270336 of 307872 bytes...
CALLBACK:  HTTP update process at 274432 of 307872 bytes...
CALLBACK:  HTTP update process at 278528 of 307872 bytes...
CALLBACK:  HTTP update process at 282624 of 307872 bytes...
CALLBACK:  HTTP update process at 286720 of 307872 bytes...
CALLBACK:  HTTP update process at 290816 of 307872 bytes...
CALLBACK:  HTTP update process at 294912 of 307872 bytes...
CALLBACK:  HTTP update process at 299008 of 307872 bytes...
CALLBACK:  HTTP update process at 303104 of 307872 bytes...
CALLBACK:  HTTP update process at 307200 of 307872 bytes...
CALLBACK:  HTTP update process at 307872 of 307872 bytes...
CALLBACK:  HTTP update process at 307872 of 307872 bytes...
CALLBACK:  HTTP update process at 307872 of 307872 bytes...
CALLBACK:  HTTP update process finished
HTTP_UPDATE_OK

 ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x4010f000, len 3460, room 16 
tail 4
chksum 0xcc
load 0x3fff20b8, len 40, room 4 
tail 4
chksum 0xc9
csum 0xc9
v0005cd10
@cp:B0
ld



[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
Firmware version 0.2

To prevent continuously update you must use a timer or an action that do that work.

Automatic FileSystem OTA update every application start

As same manner we can manage filesystem update. Let’s go fast now, because It’s the same logic of firmware update.

Generate FileSystem binary file

To manage filesystem data you must install the relative plugin, select one of this

WeMos D1 mini (esp8266), integrated SPIFFS Filesystem (deprecated)

WeMos D1 mini (esp8266), integrated LittleFS Filesystem (reccomended)

Now we are going to add data directory to the sketch folder, and we create a file version.txt with this content

0.2

and use the plugin to upload.

esp8266 LittleFS plugin menu on ArduinoIDE
esp8266 LittleFS plugin menu on ArduinoIDE

In the console we find the right command to generate this file.

[LittleFS] data    : D:\Projects\Arduino\sloeber-workspace-OTA\ArduinoOTAesp8266_basic_fs_http_update\data
[LittleFS] size    : 2024
[LittleFS] page    : 256
[LittleFS] block   : 8192
/version.txt
[LittleFS] upload  : C:\Users\renzo\AppData\Local\Temp\arduino_build_649994/ArduinoOTAesp8266_basic_fs_http_update.mklittlefs.bin
[LittleFS] address : 0x200000
[LittleFS] reset   : --before default_reset --after hard_reset
[LittleFS] port    : COM17
[LittleFS] speed   : 921600
[LittleFS] python   : C:\Users\renzo\AppData\Local\Arduino15\packages\esp8266\tools\python3\3.7.2-post1\python3.exe
[LittleFS] uploader : C:\Users\renzo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\tools\upload.py

esptool.py v3.0
Serial port COM17
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: 68:c6:3a:a6:32:e5
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 2072576 bytes to 2279...
Writing at 0x00200000... (100 %)
Wrote 2072576 bytes (2279 compressed) at 0x00200000 in 0.1 seconds (effective 312864.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
[LittleFS] data    : D:\Projects\Arduino\sloeber-workspace-OTA\ArduinoOTAesp8266_basic_fs_http_update\data
[LittleFS] size    : 2024
[LittleFS] page    : 256
[LittleFS] block   : 8192
/version.txt
[LittleFS] upload  : C:\Users\renzo\AppData\Local\Temp\arduino_build_649994/ArduinoOTAesp8266_basic_fs_http_update.mklittlefs.bin
[LittleFS] address : 0x200000
[LittleFS] reset   : --before default_reset --after hard_reset
[LittleFS] port    : COM17
[LittleFS] speed   : 921600
[LittleFS] python   : C:\Users\renzo\AppData\Local\Arduino15\packages\esp8266\tools\python3\3.7.2-post1\python3.exe
[LittleFS] uploader : C:\Users\renzo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\tools\upload.py

esptool.py v3.0
Serial port COM17

Now we can grab a lot of information, like the file

[LittleFS] upload  : C:\Users\renzo\AppData\Local\Temp\arduino_build_649994/ArduinoOTAesp8266_basic_fs_http_update.mklittlefs.bin

Create sketch

Now we are going to modify the sketch already used for firmware.

/*
 * Basic Sketch for automatic update of filesystem at start
 *
 * Renzo Mischianti <www.mischianti.org>
 *
 * https://mischianti.org
*/

#include <Arduino.h>
#include "LittleFS.h"

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>

#ifndef APSSID
#define APSSID "<YOUR-SSID>"
#define APPSK  "<YOUR-PASSWD>"
#endif

ESP8266WiFiMulti WiFiMulti;

#define FIRMWARE_VERSION "0.1"

void update_started() {
  Serial.println("CALLBACK:  HTTP update process started");
}

void update_finished() {
  Serial.println("CALLBACK:  HTTP update process finished");
}

void update_progress(int cur, int total) {
  Serial.printf("CALLBACK:  HTTP update process at %d of %d bytes...\n", cur, total);
}

void update_error(int err) {
  Serial.printf("CALLBACK:  HTTP update fatal error code %d\n", err);
}

void setup() {

  Serial.begin(115200);
//   Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(APSSID, APPSK);

  Serial.print(F("Firmware version "));
  Serial.println(FIRMWARE_VERSION);

  Serial.print(F("Inizializing FS..."));
  if (LittleFS.begin()){
      Serial.println(F("done."));
  }else{
      Serial.println(F("fail."));
  }

  String fileSystemVersion = "Not set!";
  Serial.print(F("FileSystem version "));
  File versionFile = LittleFS.open(F("/version.txt"), "r");
  if (versionFile) {
	  fileSystemVersion = versionFile.readString();
	  versionFile.close();
  }
  Serial.println(fileSystemVersion);
  delay(2000);
}


void loop() {
    // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {

    WiFiClient client;

    // The line below is optional. It can be used to blink the LED on the board during flashing
    // The LED will be on during download of one buffer of data from the network. The LED will
    // be off during writing that buffer to flash
    // On a good connection the LED should flash regularly. On a bad connection the LED will be
    // on much longer than it will be off. Other pins than LED_BUILTIN may be used. The second
    // value is used to put the LED on. If the LED is on with HIGH, that value should be passed
    ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW);

    // Add optional callback notifiers
    ESPhttpUpdate.onStart(update_started);
    ESPhttpUpdate.onEnd(update_finished);
    ESPhttpUpdate.onProgress(update_progress);
    ESPhttpUpdate.onError(update_error);

    ESPhttpUpdate.rebootOnUpdate(false); // remove automatic update

    Serial.println(F("Update start now!"));

    t_httpUpdate_return ret = ESPhttpUpdate.updateFS(client, "http://192.168.1.70:3000/filesystem/httpUpdateNewFS.bin");

    switch (ret) {
      case HTTP_UPDATE_FAILED:
        Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
        Serial.println(F("Retry in 10secs!"));
        delay(10000); // Wait 10secs
        break;

      case HTTP_UPDATE_NO_UPDATES:
        Serial.println("HTTP_UPDATE_NO_UPDATES");
        break;

      case HTTP_UPDATE_OK:
        Serial.println("HTTP_UPDATE_OK");
        delay(1000); // Wait a second and restart
        ESP.restart();
        break;
    }
  }
}

At start you get on Serial output this result

[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
Firmware version 0.1
Inizializing FS...done.
FileSystem version 0.2
Update start now!
CALLBACK:  HTTP update fatal error code -102
HTTP_UPDATE_FAILD Error (-102): File Not Found (404)
Retry in 10secs!

The filesystem version if grabbed from version.txt file and show with this code

  String fileSystemVersion = "Not set!";
  Serial.print(F("FileSystem version "));
  File versionFile = LittleFS.open(F("/version.txt"), "r");
  if (versionFile) {
	  fileSystemVersion = versionFile.readString();
	  versionFile.close();
  }
  Serial.println(fileSystemVersion);

and the core line code is

    t_httpUpdate_return ret = ESPhttpUpdate.updateFS(client, "http://192.168.1.70:3000/filesystem/httpUpdateNewFS.bin");

that manage the download and update.

Create FileSystem download end-point

Now we add the download end point to the implementation of the server.

  1. In OTAServer create the folder filesystem,
  2. Change version to 0.3 in version.txt, regenerate without upload, and copy the file ArduinoOTAesp8266_basic_fs_http_update.mklittlefs.bin to the folder
  3. Rename in httpUpdateNewFS.bin.

Now modify the original by add the highlighted code.

const express = require('express');
const { networkInterfaces } = require('os');
const path = require('path');

const app = express();
const nets = networkInterfaces();

// Server port
const PORT = 3000;

app.get('/', (request, response) => response.send('Hello from www.mischianti.org!'));

let downloadCounter = 1;
app.get('/firmware/httpUpdateNew.bin', (request, response) => {
    response.download(path.join(__dirname, 'firmware/httpUpdateNew.bin'), 'httpUpdateNew.bin', (err)=>{
        if (err) {
            console.error("Problem on download firmware: ", err)
        }else{
            downloadCounter++;
        }
    });
    console.log('Your file has been downloaded '+downloadCounter+' times!')
})

let downloadFSCounter = 1;
app.get('/filesystem/httpUpdateNewFS.bin', (request, response) => {
    response.download(path.join(__dirname, 'filesystem/httpUpdateNewFS.bin'), 'httpUpdateNewFS.bin', (err)=>{
        if (err) {
            console.error("Problem on download filesystem: ", err)
        }else{
            downloadFSCounter++;
        }
    });
    console.log('Your file FS has been downloaded '+downloadFSCounter+' times!')
})

app.listen(PORT, () => {
    const results = {}; // Or just '{}', an empty object

    for (const name of Object.keys(nets)) {
        for (const net of nets[name]) {
            // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
            if (net.family === 'IPv4' && !net.internal) {
                if (!results[name]) {
                    results[name] = [];
                }
                results[name].push(net.address);
            }
        }
    }

    console.log('Listening on port '+PORT+'\n', results)
});

Final test

[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
Firmware version 0.1
Inizializing FS...done.
FileSystem version 0.2
Update start now!
CALLBACK:  HTTP update process started
CALLBACK:  HTTP update process at 0 of 2072576 bytes...
CALLBACK:  HTTP update process at 0 of 2072576 bytes...
CALLBACK:  HTTP update process at 4096 of 2072576 bytes...
CALLBACK:  HTTP update process at 8192 of 2072576 bytes...
CALLBACK:  HTTP update process at 12288 of 2072576 bytes...
CALLBACK:  HTTP update process at 16384 of 2072576 bytes...
CALLBACK:  HTTP update process at 20480 of 2072576 bytes...
CALLBACK:  HTTP update process at 24576 of 2072576 bytes...
CALLBACK:  HTTP update process at 28672 of 2072576 bytes...
CALLBACK:  HTTP update process at 32768 of 2072576 bytes...
CALLBACK:  HTTP update process at 36864 of 2072576 bytes...
CALLBACK:  HTTP update process at 40960 of 2072576 bytes...
CALLBACK:  HTTP update process at 45056 of 2072576 bytes...
CALLBACK:  HTTP update process at 49152 of 2072576 bytes...
CALLBACK:  HTTP update process at 53248 of 2072576 bytes...

[...]

CALLBACK:  HTTP update process at 1994752 of 2072576 bytes...
CALLBACK:  HTTP update process at 1998848 of 2072576 bytes...
CALLBACK:  HTTP update process at 2002944 of 2072576 bytes...
CALLBACK:  HTTP update process at 2007040 of 2072576 bytes...
CALLBACK:  HTTP update process at 2011136 of 2072576 bytes...
CALLBACK:  HTTP update process at 2015232 of 2072576 bytes...
CALLBACK:  HTTP update process at 2019328 of 2072576 bytes...
CALLBACK:  HTTP update process at 2023424 of 2072576 bytes...
CALLBACK:  HTTP update process at 2027520 of 2072576 bytes...
CALLBACK:  HTTP update process at 2031616 of 2072576 bytes...
CALLBACK:  HTTP update process at 2035712 of 2072576 bytes...
CALLBACK:  HTTP update process at 2039808 of 2072576 bytes...
CALLBACK:  HTTP update process at 2043904 of 2072576 bytes...
CALLBACK:  HTTP update process at 2048000 of 2072576 bytes...
CALLBACK:  HTTP update process at 2052096 of 2072576 bytes...
CALLBACK:  HTTP update process at 2056192 of 2072576 bytes...
CALLBACK:  HTTP update process at 2060288 of 2072576 bytes...
CALLBACK:  HTTP update process at 2064384 of 2072576 bytes...
CALLBACK:  HTTP update process at 2068480 of 2072576 bytes...
CALLBACK:  HTTP update process at 2072576 of 2072576 bytes...
CALLBACK:  HTTP update process at 2072576 of 2072576 bytes...
CALLBACK:  HTTP update process at 2072576 of 2072576 bytes...
CALLBACK:  HTTP update process finished
HTTP_UPDATE_OK

 ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x4010f000, len 3460, room 16 
tail 4
chksum 0xcc
load 0x3fff20b8, len 40, room 4 
tail 4
chksum 0xc9
csum 0xc9
v00065100
~ld



[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
Firmware version 0.1
Inizializing FS...done.
FileSystem version 0.3

Thanks

  1. Firmware management
    1. esp8266: flash firmware binary (.bin) compiled and signed
    2. esp8266: flash firmware and filesystem binary (.bin) compiled with GUI tools
  2. OTA update with Arduino IDE
    1. esp8266 OTA update with Arduino IDE: filesystem, signed and password
  3. OTA update with Web Browser
    1. esp8266 OTA update with Web Browser: firmware, filesystem and authentication
    2. esp8266 OTA update with Web Browser: sign the firmware and HTTPS (SSL/TLS)
    3. esp8266 OTA update with Web Browser: custom web interface
  4. Self OTA uptate from HTTP server
    1. esp8266 self OTA update firmware from server
    2. esp8266 self OTA update firmware from server with version check
    3. esp8266 self OTA update in HTTPS (SSL/TLS) with trusted self signed certificate
  5. Non standard Firmware update
    1. esp8266 firmware and filesystem update from SD card
    1. esp8266 firmware and filesystem update with FTP client


Spread the love

2 Responses

  1. Miguel says:

    Confused about the behaviour of the server you proposed (under JS) I tested the line python3 http.server 3000 and It works. No more is added. One code line, no more. I deal, by the moment, with the first step. This code line I suggest is able to manage GET asks proposed from the ESP8266. Greetings.

Leave a Reply

Your email address will not be published. Required fields are marked *