// Arduino build process info: https://github.com/arduino/Arduino/wiki/Build-Process #define WEBOTA_VERSION "0.1.5" bool INIT_RUN = false; #include "WebOTA.h" #include #include #ifdef ESP32 #include #include #include #include WebServer OTAServer(9999); #endif #ifdef ESP8266 #include #include #include ESP8266WebServer OTAServer(9999); #endif WebOTA webota; //////////////////////////////////////////////////////////////////////////// int WebOTA::init(const unsigned int port, const char *path) { this->port = port; this->path = path; if (INIT_RUN == true) { return 0; } add_http_routes(&OTAServer, path); OTAServer.begin(port); Serial.printf("WebOTA url : http://%s.local:%d%s\r\n\r\n", this->mdns.c_str(), port, path); // Store that init has already run INIT_RUN = true; return 1; } // One param int WebOTA::init(const unsigned int port) { return WebOTA::init(port, "/webota"); } // No params int WebOTA::init() { return WebOTA::init(8080, "/webota"); } int WebOTA::handle() { static bool init_run = false; if (INIT_RUN == false) { WebOTA::init(); } OTAServer.handleClient(); MDNS.update(); } long WebOTA::max_sketch_size() { long ret = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; return ret; } // R Macro string literal https://en.cppreference.com/w/cpp/language/string_literal const char ota_html[] PROGMEM = "

WebOTA Version: " WEBOTA_VERSION "

" R"!^!(
)!^!"; #ifdef ESP8266 int WebOTA::add_http_routes(ESP8266WebServer *server, const char *path) { #endif #ifdef ESP32 int WebOTA::add_http_routes(WebServer *server, const char *path) { #endif // Index page server->on("/", HTTP_GET, [server]() { server->send(200, "text/html", "

WebOTA

"); }); // Upload firmware page server->on(path, HTTP_GET, [server,this]() { server->send_P(200, "text/html", ota_html); }); // Handling uploading firmware file server->on(path, HTTP_POST, [server,this]() { server->send(200, "text/plain", (Update.hasError()) ? "Update: fail\n" : "Update: OK!\n"); delay(500); ESP.restart(); }, [server,this]() { HTTPUpload& upload = server->upload(); if (upload.status == UPLOAD_FILE_START) { Serial.printf("Firmware update initiated: %s\r\n", upload.filename.c_str()); //uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; uint32_t maxSketchSpace = this->max_sketch_size(); if (!Update.begin(maxSketchSpace)) { //start with max available size Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_WRITE) { /* flashing firmware to ESP*/ if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { Update.printError(Serial); } // Store the next milestone to output uint16_t chunk_size = 51200; static uint32_t next = 51200; // Check if we need to output a milestone (100k 200k 300k) if (upload.totalSize >= next) { Serial.printf("%dk ", next / 1024); next += chunk_size; } } else if (upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { //true to set the size to the current progress Serial.printf("\r\nFirmware update successful: %u bytes\r\nRebooting...\r\n", upload.totalSize); } else { Update.printError(Serial); } } }); server->begin(); } // If the MCU is in a delay() it cannot respond to HTTP OTA requests // We do a "fake" looping delay and listen for incoming HTTP requests while waiting void WebOTA::delay(int ms) { int last = millis(); while ((millis() - last) < ms) { OTAServer.handleClient(); ::delay(5); } } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// int init_mdns(const char *host) { // Use mdns for host name resolution if (!MDNS.begin(host)) { Serial.println("Error setting up MDNS responder!"); return 0; } Serial.printf("mDNS started : %s.local\r\n", host); webota.mdns = host; return 1; } String ip2string(IPAddress ip) { String ret = String(ip[0]) + "." + String(ip[1]) + "." + String(ip[2]) + "." + String(ip[3]); return ret; } int init_wifi(const char *ssid, const char *password, const char *mdns_hostname) { WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println(""); Serial.print("Connecting to Wifi"); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.printf("Connected to '%s'\r\n\r\n",ssid); String ipaddr = ip2string(WiFi.localIP()); Serial.printf("IP address : %s\r\n", ipaddr.c_str()); Serial.printf("MAC address : %s \r\n", WiFi.macAddress().c_str()); init_mdns(mdns_hostname); }