How to copy the compiled bin file to a update server? This is the easy way!

Introduction

Eventuially you are done with your esp8266 software. Flash it, move it into production.

But then: an error! Remove the esp8266 module from production site, flash it, build it into the device again etc etc.

Life could so much be easier if there where a way to do a Wifi update!

What do you say? It all exists? You are right, the example httpupdate has all the details needed to include a update mechanism into your running esp program. It will look for an update server and flash itself, if it finds an update.

So far, so easy. But there are only three minor annoyances: where is this bin file created by the Arduino IDE, how to copy it to the update server and why must I do it by hand?

This guide will make it automatic. On/Off by a menue switch. Just build on your local maschine with your local device or build and distribute to all devices. One switch does it all.

(Warning: Windows ahead!)

Step One

Create a folder on your developing machine. Somewhere.

Select
C:\data\

Step Two

Locate boards.txt. It should be in a folder looking like this

C:\Users\yourusername\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0-rc2

Yes, it is that difficult. No, there is no easy way.

Make the following changes:

Select
menu.UploadSpeed=Upload Speed
menu.CpuFrequency=CPU Frequency
menu.FlashSize=Flash Size
menu.FlashMode=Flash Mode
menu.FlashFreq=Flash Frequency
menu.ResetMethod=Reset Method
menu.ESPModule=Module
menu.Debug=Debug port
menu.DebugLevel=Debug Level
menu.LwIPVariant=lwIP Variant
#add this>>>
menu.MoveToWebServer=Copy to UploadServer

##############################################################
generic.name=Generic ESP8266 Module

generic.upload.tool=esptool
generic.upload.speed=115200
generic.upload.resetmethod=ck
generic.upload.maximum_size=434160
generic.upload.maximum_data_size=81920
generic.upload.wait_for_upload_port=true
generic.serial.disableDTR=true
generic.serial.disableRTS=true

generic.build.mcu=esp8266
generic.build.f_cpu=80000000L
generic.build.board=ESP8266_ESP01
generic.build.core=esp8266
generic.build.variant=generic
generic.build.flash_mode=qio
generic.build.spiffs_pagesize=256
generic.build.debug_port=
generic.build.debug_level=

#add this>>>
generic.menu.MoveToWebServer.no=No
generic.menu.MoveToWebServer.no.webserver.move=no
generic.menu.MoveToWebServer.yes=Yes
generic.menu.MoveToWebServer.yes.webserver.move=yes

Step Three

Locate platform.txt. It is in the same folder like boards.txt.

Append the following changes to the end of the file:

Select

# ----------------------------------
recipe.hooks.objcopy.postobjcopy.01.pattern = cmd.exe /c "c:\data\doit.cmd {webserver.move} {build.path} {build.project_name}.bin c:\data\bin.dat"

Step Four

Now you need a web server. Somewhere in your net. This is beyond the scope of this paper. I took a Raspberry Pi because it was there. Any other would do.

You need network access to the documents folder of the web server. With that you can create a batch file in your data folder that copies the files from your local machine to the web server.

If you want to publish the file somewhere else: this is where you can do a ftp upload or whatever you want.

I named the batch "doit.cmd", look at the file names in step three. And my raspberry goes by PHORKYS.

Select
rem %1 yes/no from IDE menu
rem %2 build path
rem %3 build file name
if "%1"=="yes" (
  copy /b %2\%3 \\PHORKYS\Root\var\www\%3
)



Step Five

Prepared like this your Arduino Sketch can query the server and fetch the file, flash itself and reboot. I do it with this small routine.

You need to change the UpdateFileUrl fitting to your server and project folder name.

Select
//===================================================================================
const String UpdateFileUrl = "http://PHORKYS/sketchname.ino.bin";
const String UpdateSPIFFSFileName = "/.update.txt";

void CheckUpdateFile(void) {
  HTTPClient http;
  http.begin(UpdateFileUrl);
  const char * headerkeys[] = {"Last-Modified"} ;  // could use etag, too
  size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*);
  http.collectHeaders(headerkeys, headerkeyssize);
  int code = http.GET();
  int len = http.getSize();
  http.end();

  // nur sinnvoll, wenn überhaupt eine Datei gelesen
  if (code = 200) {
    // Header zusammensammeln
    String id = String(len);
    for (int i = 0; i < http.headers(); i++) {
      id += http.header(i);
    }
    String sid = "x";
    // Serial.println(id);

    // Update-Data lesen
    File file = SPIFFS.open(UpdateSPIFFSFileName, "r");
    if (file) {
      sid = file.readStringUntil('\n');
    }
    file.close();

    if (! sid.startsWith(id)) {
      Serial.println(F("Beginne Update"));

      // https://github.com/esp8266/Arduino/issues/1017
      // Automatic reboot after wdt reset
      // The only time software reset doesn't work is immediately following a serial 
      // upload. If you reset the module physically after serial upload and place it 
      // into normal (non-bootloader) mode, software reset will work.
      t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateFileUrl);
      switch (ret) {
        case HTTP_UPDATE_FAILED:
          Serial.print(F("Update error "));
          Serial.print(ESPhttpUpdate.getLastError());
          Serial.print(" = ");
          Serial.print(ESPhttpUpdate.getLastErrorString());
          Serial.println();
          break;
        case HTTP_UPDATE_NO_UPDATES:
          Serial.println(F("HTTP_UPDATE_NO_UPDATES"));
          break;

        case HTTP_UPDATE_OK:
          Serial.println(F("HTTP_UPDATE_OK"));
          break;
      }

      // Update-Data schreiben
      file = SPIFFS.open(UpdateSPIFFSFileName, "w");
      if (!file) {
        Serial.println(F("Panic: update file write access failed"));
      } else {
        file.println(id);
      }
      file.close();
    }
  }
}

It needs some includes, initialized SPIFFS and WIFI and all.

Select
#include "FS.h"
#include <ESP8266HTTPClient.h>  
#include <ESP8266httpUpdate.h>