|
@@ -59,6 +59,7 @@
|
|
|
#include <Adafruit_NeoPixel.h>
|
|
#include <Adafruit_NeoPixel.h>
|
|
|
#include "FS.h"
|
|
#include "FS.h"
|
|
|
#include <LittleFS.h>
|
|
#include <LittleFS.h>
|
|
|
|
|
+#include <Update.h>
|
|
|
|
|
|
|
|
//=============================================================
|
|
//=============================================================
|
|
|
// WiFi / UI
|
|
// WiFi / UI
|
|
@@ -74,6 +75,7 @@ WiFiServer tcpServer(8086);
|
|
|
WebServer httpServer(80);
|
|
WebServer httpServer(80);
|
|
|
|
|
|
|
|
#include "index_html.h"
|
|
#include "index_html.h"
|
|
|
|
|
+#include "ota_html.h"
|
|
|
|
|
|
|
|
hd44780_I2Cexp lcd;
|
|
hd44780_I2Cexp lcd;
|
|
|
static bool s_lcdOk = false;
|
|
static bool s_lcdOk = false;
|
|
@@ -441,6 +443,63 @@ static void handleUploadStream() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+// HTTP OTA handlers
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+static void handleOtaPage() {
|
|
|
|
|
+ String html = FPSTR(OTA_HTML);
|
|
|
|
|
+ html.replace("{{IP}}", WiFi.localIP().toString());
|
|
|
|
|
+ httpServer.send(200, "text/html; charset=utf-8", html);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void handleOtaDone() {
|
|
|
|
|
+ if (Update.hasError()) {
|
|
|
|
|
+ String err = "OTA failed: " + String(Update.errorString());
|
|
|
|
|
+ Serial.println(err);
|
|
|
|
|
+ httpServer.send(500, "text/plain", err);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ httpServer.send(200, "text/plain", "Firmware updated — rebooting now.");
|
|
|
|
|
+ Serial.println("OTA success — rebooting");
|
|
|
|
|
+ delay(500);
|
|
|
|
|
+ ESP.restart();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void handleOtaStream() {
|
|
|
|
|
+ HTTPUpload& up = httpServer.upload();
|
|
|
|
|
+
|
|
|
|
|
+ if (up.status == UPLOAD_FILE_START) {
|
|
|
|
|
+ Serial.printf("OTA start: %s\n", up.filename.c_str());
|
|
|
|
|
+ ledCyan();
|
|
|
|
|
+ if (!Update.begin(UPDATE_SIZE_UNKNOWN)) {
|
|
|
|
|
+ Serial.print("OTA begin failed: ");
|
|
|
|
|
+ Update.printError(Serial);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (up.status == UPLOAD_FILE_WRITE) {
|
|
|
|
|
+ if (Update.write(up.buf, up.currentSize) != up.currentSize) {
|
|
|
|
|
+ Serial.print("OTA write failed: ");
|
|
|
|
|
+ Update.printError(Serial);
|
|
|
|
|
+ ledErrorFlash();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (up.status == UPLOAD_FILE_END) {
|
|
|
|
|
+ if (Update.end(true)) {
|
|
|
|
|
+ Serial.printf("OTA end: %u bytes written\n", up.totalSize);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Serial.print("OTA end failed: ");
|
|
|
|
|
+ Update.printError(Serial);
|
|
|
|
|
+ ledErrorFlash();
|
|
|
|
|
+ }
|
|
|
|
|
+ ledOff();
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (up.status == UPLOAD_FILE_ABORTED) {
|
|
|
|
|
+ Update.abort();
|
|
|
|
|
+ Serial.println("OTA aborted");
|
|
|
|
|
+ ledOff();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
//=============================================================
|
|
//=============================================================
|
|
|
// Setup
|
|
// Setup
|
|
|
//=============================================================
|
|
//=============================================================
|
|
@@ -487,6 +546,8 @@ void setup() {
|
|
|
httpServer.on("/", HTTP_GET, handleRoot);
|
|
httpServer.on("/", HTTP_GET, handleRoot);
|
|
|
httpServer.on("/status", HTTP_GET, handleStatus);
|
|
httpServer.on("/status", HTTP_GET, handleStatus);
|
|
|
httpServer.on("/upload", HTTP_POST, handleUploadDone, handleUploadStream);
|
|
httpServer.on("/upload", HTTP_POST, handleUploadDone, handleUploadStream);
|
|
|
|
|
+ httpServer.on("/ota", HTTP_GET, handleOtaPage);
|
|
|
|
|
+ httpServer.on("/ota_do", HTTP_POST, handleOtaDone, handleOtaStream);
|
|
|
httpServer.onNotFound([]() {
|
|
httpServer.onNotFound([]() {
|
|
|
String uri = httpServer.uri();
|
|
String uri = httpServer.uri();
|
|
|
if (streamFromFS(uri)) return;
|
|
if (streamFromFS(uri)) return;
|