Blame | Last modification | View Log | RSS feed
#ifdef ESP8266#include <ESP8266HTTPClient.h>#include <ESP8266httpUpdate.h>#elif defined(ESP32)#include <WiFiClientSecure.h>#include <HTTPClient.h>#include <HTTPUpdate.h>#endif#include <EEPROM.h> // For storing the firmware version#include <FS.h>#include <LittleFS.h>#include <AsyncFsWebServer.h> // https://github.com/cotestatnt/async-esp-fs-webserver/#define FILESYSTEM LittleFSAsyncFsWebServer server( FILESYSTEM, 80, "remoteOTA");#ifndef LED_BUILTIN#define LED_BUILTIN 2#endif// In order to set SSID and password open the /setup webserver page// const char* ssid;// const char* password;uint8_t ledPin = LED_BUILTIN;bool apMode = false;#ifdef ESP8266String fimwareInfo = "https://raw.githubusercontent.com/cotestatnt/async-esp-fs-webserver/master/examples/remoteOTA/version-esp8266.json";#elif defined(ESP32)String fimwareInfo = "https://raw.githubusercontent.com/cotestatnt/async-esp-fs-webserver/master/examples/remoteOTA/version-esp32.json";#endifchar fw_version[10] = {"0.0.0"};////////////////////////////// Firmware update /////////////////////////////////////////void doUpdate(const char* url, const char* version) {#ifdef ESP8266#define UPDATER ESPhttpUpdate#elif defined(ESP32)#define UPDATER httpUpdate#if ESP_ARDUINO_VERSION_MAJOR > 2esp_task_wdt_config_t twdt_config = {.timeout_ms = 15*1000,.idle_core_mask = (1 << portNUM_PROCESSORS) - 1, // Bitmask of all cores.trigger_panic = false,};ESP_ERROR_CHECK(esp_task_wdt_reconfigure(&twdt_config));#elseESP_ERROR_CHECK(esp_task_wdt_init(15, 0));#endif#endif// onProgress handling is missing with ESP32 libraryUPDATER.onProgress([](int cur, int total){static uint32_t sendT;if(millis() - sendT > 1000){sendT = millis();Serial.printf("Updating %d of %d bytes...\n", cur, total);}});WiFiClientSecure client;client.setInsecure();UPDATER.rebootOnUpdate(false);UPDATER.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);UPDATER.setLedPin(LED_BUILTIN, LOW);t_httpUpdate_return ret = UPDATER.update(client, url, fw_version);client.stop();switch (ret) {case HTTP_UPDATE_FAILED:Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", UPDATER.getLastError(), UPDATER.getLastErrorString().c_str());break;case HTTP_UPDATE_NO_UPDATES:Serial.println("HTTP_UPDATE_NO_UPDATES");break;case HTTP_UPDATE_OK:Serial.println("HTTP_UPDATE_OK");strcpy(fw_version, version);EEPROM.put(0, fw_version);EEPROM.commit();Serial.print("System will be restarted with the new version ");Serial.println(fw_version);delay(1000);ESP.restart();break;}}//////////////////////////////// Filesystem /////////////////////////////////////////bool startFilesystem() {if (FILESYSTEM.begin()){server.printFileList(FILESYSTEM, "/", 1, Serial);return true;}else {Serial.println("ERROR on mounting filesystem. It will be reformatted!");FILESYSTEM.format();ESP.restart();}return false;}//////////////////////////// HTTP Request Handlers ////////////////////////////////////void handleLed(AsyncWebServerRequest *request) {// http://xxx.xxx.xxx.xxx/led?val=1if(request->hasArg("val")) {int value = request->arg("val").toInt();digitalWrite(ledPin, value);}String reply = "LED is now ";reply += digitalRead(ledPin) ? "OFF" : "ON";request->send(200, "text/plain", reply);}/* Handle the update request from client.* The web page will check if is it necessary or not checking the actual version.* Info about firmware as version and remote url, are stored in "version.json" file** Using this example, the correct workflow for deploying a new firmware version is:- upload the new firmware.bin compiled on your web space (in this example Github is used)- update the "version.json" file with the new version number and the address of the binary file- on the update webpage, press the "UPDATE" button.*/void handleUpdate(AsyncWebServerRequest *request) {if(request->hasArg("version") && request->hasArg("url")) {const char* new_version = request->arg("version").c_str();const char* url = request->arg("url").c_str();String reply = "Firmware is going to be updated to version ";reply += new_version;reply += " from remote address ";reply += url;reply += "<br>Wait 10-20 seconds and then reload page.";request->send(200, "text/plain", reply );Serial.println(reply);doUpdate(url, new_version);}}/////////////////////////////////// SETUP ///////////////////////////////////////void setup(){pinMode(LED_BUILTIN, OUTPUT);Serial.begin(115200);EEPROM.begin(128);// FILESYSTEM INITstartFilesystem();// Try to connect to WiFi (will start AP if not connected after timeout)if (!server.startWiFi(10000)) {Serial.println("\nWiFi not connected! Starting AP mode...");server.startCaptivePortal("ESP_AP", "123456789", "/setup");}// Enable ACE FS file web editor and add FS info callback functionserver.enableFsCodeEditor();// Add custom handlers to webserverserver.on("/led", HTTP_GET, handleLed);server.on("/firmware_update", HTTP_GET, handleUpdate);// Add handler as lambda function (just to show a different method)server.on("/version", HTTP_GET, [](AsyncWebServerRequest *request) {server.getOptionValue("New firmware JSON", fimwareInfo);EEPROM.get(0, fw_version);if (fw_version[0] == 0xFF) // Still not stored in EEPROM (first run)strcpy(fw_version, "0.0.0");String reply = "{\"version\":\"";reply += fw_version;reply += "\", \"newFirmwareInfoJSON\":\"";reply += fimwareInfo;reply += "\"}";// Send to client actual firmware version and address where to check if new firmware availablerequest->send(200, "text/json", reply);});// Configure /setup page and start Web Serverserver.addOptionBox("Remote Update");server.addOption("New firmware JSON", fimwareInfo);// Start server with built-in websocket event handlerserver.init();Serial.print(F("ESP Web Server started on IP Address: "));Serial.println(server.getServerIP());Serial.println(F("This is \"remoteOTA.ino\" example.\n""Open /setup page to configure optional parameters.\n""Open /edit page to view, edit or upload example or your custom webserver source files."));}/////////////////////////////////// LOOP ///////////////////////////////////////void loop() {// This delay is required in order to avoid loopTask() WDT reset on ESP32delay(1);}