From a543ba074849306aa1a4834378df1359b96987ed Mon Sep 17 00:00:00 2001 From: Ray Jones Date: Thu, 18 Jul 2019 22:28:40 +1000 Subject: [PATCH] Tidied browser update by adding new browserupload class. Adding RTC register storage for frequent NV updates (fuel gauge, desired temp etc) --- Arduino/Afterburner/Afterburner.ino | 15 +- src/Afterburner/Afterburner.cpp | 15 +- src/Afterburner/src/OLED/DetailedScreen.cpp | 36 +++- src/Afterburner/src/OLED/DetailedScreen.h | 1 + src/Afterburner/src/OLED/fonts/Icons.cpp | 23 +++ src/Afterburner/src/OLED/fonts/Icons.h | 2 + src/Afterburner/src/RTC/Clock.cpp | 68 +++++++- src/Afterburner/src/RTC/Clock.h | 15 +- src/Afterburner/src/Utility/NVCore.cpp | 5 + src/Afterburner/src/Utility/NVCore.h | 1 + src/Afterburner/src/Utility/NVStorage.cpp | 2 + src/Afterburner/src/Utility/NVStorage.h | 4 + src/Afterburner/src/Utility/helpers.h | 7 + src/Afterburner/src/WiFi/BTCWebServer.cpp | 177 ++++++-------------- 14 files changed, 229 insertions(+), 142 deletions(-) diff --git a/Arduino/Afterburner/Afterburner.ino b/Arduino/Afterburner/Afterburner.ino index d97ed0f..12ace0c 100644 --- a/Arduino/Afterburner/Afterburner.ino +++ b/Arduino/Afterburner/Afterburner.ino @@ -103,6 +103,7 @@ #include "src/Utility/BTC_JSON.h" #include "src/Utility/BTC_GPIO.h" #include "src/Utility/BoardDetect.h" +#include "src/Utility/FuelGauge.h" #include "src/OLED/ScreenManager.h" #include "src/OLED/KeyPad.h" #include "src/Utility/TempSense.h" @@ -173,6 +174,7 @@ CGPIOin GPIOin; CGPIOout GPIOout; CGPIOalg GPIOalg; + sRxLine PCline; long lastRxTime; // used to observe inter character delays bool bHasOEMController = false; @@ -184,6 +186,7 @@ __NOINIT_ATTR bool bForceInit; // = false; __NOINIT_ATTR bool bUserON; // = false; __NOINIT_ATTR uint8_t demandDegC; __NOINIT_ATTR uint8_t demandPump; +CFuelGauge FuelGauge; bool bReportBlueWireData = REPORT_RAW_DATA; bool bReportJSONData = REPORT_JSON_TRANSMIT; @@ -302,7 +305,9 @@ extern "C" unsigned long __wrap_millis() { void setup() { // ensure cyclic mode is disabled after power on - if(rtc_get_reset_reason(0) == 1 || bForceInit) { + bool bPowerUpInit = false; + if(rtc_get_reset_reason(0) == 1/* || bForceInit*/) { + bPowerUpInit = true; bForceInit = false; bUserON = false; demandPump = demandDegC = 22; @@ -437,6 +442,10 @@ void setup() { FilteredSamples.Fan.setAlpha(0.7); FilteredSamples.AmbientTemp.reset(-100.0); +// if(bPowerUpInit) { + FuelGauge.init(); +// } + delay(1000); // just to hold the splash screeen for while } @@ -775,8 +784,10 @@ void loop() ScreenManager.reqUpdate(); } - if(bHasHtrData) + if(bHasHtrData) { updateFilteredData(); + FuelGauge.Integrate(HeaterFrame2.getPump_Actual()); + } updateJSONclients(bReportJSONData); CommState.set(CommStates::Idle); NVstore.doSave(); // now is a good time to store to the NV storage, well away from any blue wire activity diff --git a/src/Afterburner/Afterburner.cpp b/src/Afterburner/Afterburner.cpp index d97ed0f..12ace0c 100644 --- a/src/Afterburner/Afterburner.cpp +++ b/src/Afterburner/Afterburner.cpp @@ -103,6 +103,7 @@ #include "src/Utility/BTC_JSON.h" #include "src/Utility/BTC_GPIO.h" #include "src/Utility/BoardDetect.h" +#include "src/Utility/FuelGauge.h" #include "src/OLED/ScreenManager.h" #include "src/OLED/KeyPad.h" #include "src/Utility/TempSense.h" @@ -173,6 +174,7 @@ CGPIOin GPIOin; CGPIOout GPIOout; CGPIOalg GPIOalg; + sRxLine PCline; long lastRxTime; // used to observe inter character delays bool bHasOEMController = false; @@ -184,6 +186,7 @@ __NOINIT_ATTR bool bForceInit; // = false; __NOINIT_ATTR bool bUserON; // = false; __NOINIT_ATTR uint8_t demandDegC; __NOINIT_ATTR uint8_t demandPump; +CFuelGauge FuelGauge; bool bReportBlueWireData = REPORT_RAW_DATA; bool bReportJSONData = REPORT_JSON_TRANSMIT; @@ -302,7 +305,9 @@ extern "C" unsigned long __wrap_millis() { void setup() { // ensure cyclic mode is disabled after power on - if(rtc_get_reset_reason(0) == 1 || bForceInit) { + bool bPowerUpInit = false; + if(rtc_get_reset_reason(0) == 1/* || bForceInit*/) { + bPowerUpInit = true; bForceInit = false; bUserON = false; demandPump = demandDegC = 22; @@ -437,6 +442,10 @@ void setup() { FilteredSamples.Fan.setAlpha(0.7); FilteredSamples.AmbientTemp.reset(-100.0); +// if(bPowerUpInit) { + FuelGauge.init(); +// } + delay(1000); // just to hold the splash screeen for while } @@ -775,8 +784,10 @@ void loop() ScreenManager.reqUpdate(); } - if(bHasHtrData) + if(bHasHtrData) { updateFilteredData(); + FuelGauge.Integrate(HeaterFrame2.getPump_Actual()); + } updateJSONclients(bReportJSONData); CommState.set(CommStates::Idle); NVstore.doSave(); // now is a good time to store to the NV storage, well away from any blue wire activity diff --git a/src/Afterburner/src/OLED/DetailedScreen.cpp b/src/Afterburner/src/OLED/DetailedScreen.cpp index d3dd15a..63bfc76 100644 --- a/src/Afterburner/src/OLED/DetailedScreen.cpp +++ b/src/Afterburner/src/OLED/DetailedScreen.cpp @@ -27,19 +27,28 @@ #include "../Utility/helpers.h" #include "../Protocol/Protocol.h" #include "../Utility/NVStorage.h" +#include "../Utility/FuelGauge.h" + +extern CFuelGauge FuelGauge; #define MINIFONT miniFontInfo -#define X_FAN_ICON 55 +//#define X_FAN_ICON 55 +#define X_FAN_ICON 49 #define Y_FAN_ICON 39 -#define X_FUEL_ICON 81 +//#define X_FUEL_ICON 81 +#define X_FUEL_ICON 74 #define Y_FUEL_ICON 39 -#define X_TARGET_ICON 31 +//#define X_TARGET_ICON 31 +#define X_TARGET_ICON 28 #define Y_TARGET_ICON 39 #define Y_BASELINE 58 -#define X_GLOW_ICON 97 +//#define X_GLOW_ICON 97 +#define X_GLOW_ICON 92 #define Y_GLOW_ICON 38 +#define X_BOWSER_ICON 91 +#define Y_BOWSER_ICON 43 #define X_BODY_BULB 119 #define X_BULB 1 // >= 1 #define Y_BULB 4 @@ -106,11 +115,13 @@ CDetailedScreen::show() _animateRPM = false; _animatePump = false; _animateGlow = false; + bool bGlowActive = false; if(runstate != 0 && runstate != 10) { // not idle modes float power = getHeaterInfo().getGlowPlug_Power(); if(power > 1) { showGlowPlug(power); + bGlowActive = true; } if(_showTarget) @@ -123,6 +134,9 @@ CDetailedScreen::show() showBodyThermometer(getHeaterInfo().getTemperature_HeatExchg()); } + if(!bGlowActive) { + showBowser(FuelGauge.Used_mL()); + } showRunState(runstate, errstate); return true; } @@ -431,6 +445,20 @@ CDetailedScreen::showFuel(float rate) } } +void +CDetailedScreen::showBowser(float used) +{ + _display.setTextColor(WHITE); + _drawBitmap(X_BOWSER_ICON, Y_BOWSER_ICON, BowserIconInfo); + char msg[16]; + sprintf(msg, "%.02fL", used * 0.001); +#ifdef MINI_FANLABEL + CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font +#endif + _printMenuText(X_BOWSER_ICON + (BowserIconInfo.width/2), Y_BASELINE, msg, false, eCentreJustify); +} + + void CDetailedScreen::showRunState(int runstate, int errstate) { diff --git a/src/Afterburner/src/OLED/DetailedScreen.h b/src/Afterburner/src/OLED/DetailedScreen.h index 51290b5..1be325b 100644 --- a/src/Afterburner/src/OLED/DetailedScreen.h +++ b/src/Afterburner/src/OLED/DetailedScreen.h @@ -48,6 +48,7 @@ class CDetailedScreen : public CScreenHeader void showFanV(float volts); void showFuel(float rate); void showRunState(int state, int errstate); + void showBowser(float used); public: CDetailedScreen(C128x64_OLED& display, CScreenManager& mgr); bool show(); diff --git a/src/Afterburner/src/OLED/fonts/Icons.cpp b/src/Afterburner/src/OLED/fonts/Icons.cpp index 3a6baa3..b852154 100644 --- a/src/Afterburner/src/OLED/fonts/Icons.cpp +++ b/src/Afterburner/src/OLED/fonts/Icons.cpp @@ -942,3 +942,26 @@ const uint8_t PROGMEM wwwIcon[] = const BITMAP_INFO WWWIconInfo(10, 9, wwwIcon); +// +// Image data for bowser +// + +const uint8_t PROGMEM bowserIcon[] = +{ + 0x7E, 0x80, // ###### # + 0x7E, 0xC0, // ###### ## + 0x42, 0xC0, // # # ## + 0x42, 0x40, // # # # + 0x42, 0x40, // # # # + 0x7E, 0x40, // ###### # + 0x7F, 0x40, // ####### # + 0x7F, 0x40, // ####### # + 0x7F, 0xC0, // ######### + 0x7E, 0x00, // ###### + 0x7E, 0x00, // ###### + 0xFF, 0x00, // ######## +}; + +const BITMAP_INFO BowserIconInfo(10, 12, bowserIcon); + + diff --git a/src/Afterburner/src/OLED/fonts/Icons.h b/src/Afterburner/src/OLED/fonts/Icons.h index e82387d..5d7fc44 100644 --- a/src/Afterburner/src/OLED/fonts/Icons.h +++ b/src/Afterburner/src/OLED/fonts/Icons.h @@ -128,3 +128,5 @@ extern const BITMAP_INFO UpdateIconInfo; // Bitmap sizes for www extern const BITMAP_INFO WWWIconInfo; + +extern const BITMAP_INFO BowserIconInfo; \ No newline at end of file diff --git a/src/Afterburner/src/RTC/Clock.cpp b/src/Afterburner/src/RTC/Clock.cpp index a19c339..2da6036 100644 --- a/src/Afterburner/src/RTC/Clock.cpp +++ b/src/Afterburner/src/RTC/Clock.cpp @@ -24,7 +24,7 @@ #include "BTCDateTime.h" #include "TimerManager.h" #include -#include "../Libraries/RTClib/RTClib.h" +//#include "DS3231Ex.h" #include "../Utility/helpers.h" #include "../Utility/NVStorage.h" #include "../Utility/DebugPort.h" @@ -32,7 +32,7 @@ // create ONE of the RTClib supported real time clock classes #if RTC_USE_DS3231 == 1 -RTC_DS3231 rtc; +RTC_DS3231Ex rtc; #elif RTC_USE_DS1307 == 1 RTC_DS1307 rtc; #elif RTC_USE_PCF8523 == 1 @@ -105,6 +105,17 @@ CClock::set(const DateTime& newTimeDate) _rtc.adjust(newTimeDate); } +void +CClock::saveData(uint8_t* pData, int len, int ofs) +{ + _rtc.writeData(pData, len, ofs); +} + +void +CClock::readData(uint8_t* pData, int len, int ofs) +{ + _rtc.readData(pData, len, ofs); +} void setDateTime(const char* newTime) @@ -139,3 +150,56 @@ void setTime(const char* newTime) } } +#define _I2C_WRITE write +#define _I2C_READ read + +void RTC_DS3231Ex::writeData(uint8_t* pData, int len, int ofs) { + Wire.beginTransmission(DS3231_ADDRESS); + Wire._I2C_WRITE((byte)(7+ofs)); // start at alarm bytes + for(int i=0; i +bool finBounds(float tets, float min, float max); bool u8inBounds(uint8_t test, uint8_t minLim, uint8_t maxLim); bool s8inBounds(int8_t test, int8_t minLim, int8_t maxLim); bool u8Match2(uint8_t test, uint8_t test1, uint8_t test2); diff --git a/src/Afterburner/src/Utility/NVStorage.cpp b/src/Afterburner/src/Utility/NVStorage.cpp index a00819e..bc508c6 100644 --- a/src/Afterburner/src/Utility/NVStorage.cpp +++ b/src/Afterburner/src/Utility/NVStorage.cpp @@ -235,6 +235,7 @@ sHeaterTuning::load() validatedLoad("systemVoltage", sysVoltage, 120, u8Match2, 120, 240); validatedLoad("fanSensor", fanSensor, 1, u8inBounds, 1, 2); validatedLoad("glowDrive", glowDrive, 5, u8inBounds, 1, 6); + validatedLoad("pumpCal", pumpCal, 0.02, 0.001, 1); preferences.end(); } @@ -251,6 +252,7 @@ sHeaterTuning::save() preferences.putUChar("systemVoltage", sysVoltage); preferences.putUChar("fanSensor", fanSensor); preferences.putUChar("glowDrive", glowDrive); + preferences.putFloat("pumpCal", pumpCal); preferences.end(); } diff --git a/src/Afterburner/src/Utility/NVStorage.h b/src/Afterburner/src/Utility/NVStorage.h index a9abb6c..37bd258 100644 --- a/src/Afterburner/src/Utility/NVStorage.h +++ b/src/Afterburner/src/Utility/NVStorage.h @@ -40,6 +40,7 @@ struct sHeaterTuning : public CESP32_NVStorage { uint8_t sysVoltage; uint8_t fanSensor; uint8_t glowDrive; + float pumpCal; bool valid() { bool retval = true; @@ -50,6 +51,7 @@ struct sHeaterTuning : public CESP32_NVStorage { retval &= sysVoltage == 120 || sysVoltage == 240; retval &= fanSensor == 1 || fanSensor == 2; retval &= INBOUNDS(glowDrive, 1, 6); + retval &= INBOUNDS(pumpCal, 0.001, 1.0); return retval; }; void init() { @@ -60,6 +62,7 @@ struct sHeaterTuning : public CESP32_NVStorage { sysVoltage = 120; fanSensor = 1; glowDrive = 5; + pumpCal = 0.02; }; void load(); void save(); @@ -71,6 +74,7 @@ struct sHeaterTuning : public CESP32_NVStorage { sysVoltage = rhs.sysVoltage; fanSensor = rhs.fanSensor; glowDrive = rhs.glowDrive; + pumpCal = rhs.pumpCal; return *this; } float getPmin() const; diff --git a/src/Afterburner/src/Utility/helpers.h b/src/Afterburner/src/Utility/helpers.h index ba38223..7346826 100644 --- a/src/Afterburner/src/Utility/helpers.h +++ b/src/Afterburner/src/Utility/helpers.h @@ -84,6 +84,13 @@ extern float getGlowCurrent(); extern float getFanSpeed(); extern int sysUptime(); +extern void storeFuelGauge(float val); +extern void getStoredFuelGauge(float& val); +extern void storeDesiredTemp(uint8_t val); +extern void getStoredDesiredTemp(uint8_t& val); +extern void storeDesiredPump(uint8_t val); +extern void getStoredDesiredPump(uint8_t& val); + extern void ShowOTAScreen(int percent=0, eOTAmodes updateType=eOTAnormal); diff --git a/src/Afterburner/src/WiFi/BTCWebServer.cpp b/src/Afterburner/src/WiFi/BTCWebServer.cpp index 80bd4c0..18768f7 100644 --- a/src/Afterburner/src/WiFi/BTCWebServer.cpp +++ b/src/Afterburner/src/WiFi/BTCWebServer.cpp @@ -39,6 +39,7 @@ #include #include #include +#include "BrowserUpload.h" #include extern WiFiManager wm; @@ -48,9 +49,7 @@ extern const char* updateIndex; extern const char* formatDoneContent; extern const char* rebootIndex; -File fsUploadFile; // a File object to temporarily store the received file -int SPIFFSupload = 0; - +sBrowserUpload BrowserUpload; WebServer server(80); WebSocketsServer webSocket = WebSocketsServer(81); @@ -85,15 +84,6 @@ void build500Response(String& content, String file); void initWebServer(void) { - Update - .onProgress([](unsigned int progress, unsigned int total) { - int percent = (progress / (total / 100)); - DebugPort.printf("Progress: %u%%\r", percent); - DebugPort.handle(); // keep telnet spy alive - ShowOTAScreen(percent, eOTAWWW); // WWW update in place - DebugPort.print("^"); - }); - if (MDNS.begin("Afterburner")) { DebugPort.println("MDNS responder started"); } @@ -299,11 +289,11 @@ function onWebSocket(event) { switch(key) { case 'progress': // actual data bytes received as fed back via web socket - var bytes = response[key]; - if(bytes >= 0) { + var progress = response[key]; + if(progress >= 0) { // normal progression - _('loaded_n_total').innerHTML = 'Uploaded ' + bytes + ' bytes of ' + sendSize; - var percent = Math.round( 100 * (bytes / sendSize)); + _('loaded_n_total').innerHTML = 'Uploaded ' + progress + ' bytes of ' + sendSize; + var percent = Math.round( 100 * (progress / sendSize)); _('progressBar').value = percent; _('status').innerHTML = percent+'% uploaded.. please wait'; uploadErr = ''; @@ -311,10 +301,12 @@ function onWebSocket(event) { else { // upload failure _('progressBar').value = 0; - if(bytes == -1) - uploadErr = 'SPIFFS UPLOAD ABORTED - FILE TOO LARGE'; - else - uploadErr = 'SPIFFS UPLOAD ABORTED - WRITE ERROR'; + switch(progress) { + case -1: uploadErr = 'File too large - SPIFFS upload ABORTED'; break; + case -2: uploadErr = 'Write error - SPIFFS upload ABORTED'; break; + case -3: uploadErr = 'Update error - Firmware upload ABORTED'; break; + case -4: uploadErr = 'Invalid file - Firmware upload ABORTED'; break; + } ajax.abort(); } break; @@ -328,6 +320,7 @@ function init() { } function uploadFile() { + _('upload_form').hidden = true; _('cancel').hidden = true; _('upload').hidden = true; _('progressBar').hidden = false; @@ -695,8 +688,8 @@ void onUploadCompletion() _SuppliedFileSize = 0; DebugPort.println("WEB: POST /updatenow completion"); // completion functionality - if(SPIFFSupload) { - if(SPIFFSupload == 1) { + if(BrowserUpload.isSPIFFSupload()) { + if(BrowserUpload.isOK()) { DebugPort.println("WEB: SPIFFS OK"); server.send(200, "text/plain", "OK - File uploaded to SPIFFS"); // javascript reselects the /update page! @@ -705,16 +698,16 @@ void onUploadCompletion() DebugPort.println("WEB: SPIFFS FAIL"); server.send(500, "text/plain", "500: couldn't create file"); } - SPIFFSupload = 0; + BrowserUpload.reset(); } else { - if(Update.hasError()) { - DebugPort.println("WEB: UPDATE FAIL"); - server.send(200, "text/plain", "FAIL - Afterburner will reboot shortly"); + if(BrowserUpload.isOK()) { + DebugPort.println("WEB: FIRMWARE UPDATE OK"); + server.send(200, "text/plain", "OK - Afterburner will reboot shortly"); } else { - DebugPort.println("WEB: UPDATE OK"); - server.send(200, "text/plain", "OK - Afterburner will reboot shortly"); + DebugPort.println("WEB: FIRMWARE UPDATE FAIL"); + server.send(200, "text/plain", "FAIL - Afterburner will reboot shortly"); } delay(1000); // javascript redirects to root page so we go there after reboot! @@ -748,130 +741,54 @@ void onUploadBegin() void onUploadProgression() { + char JSON[64]; + if(bUpdateAccessed) { // only allow progression via /update, attempts to directly access /updatenow will fail HTTPUpload& upload = server.upload(); String filename = upload.filename; if(!filename.startsWith("/")) filename = "/"+filename; if (upload.status == UPLOAD_FILE_START) { - DebugPort.setDebugOutput(true); - if(filename.endsWith(".bin")) { - // FIRMWARE UPLOAD START - DebugPort.printf("Firmware update: %s\r\n", filename.c_str()); // name without leading slash - - int sizetouse = -1; //start with max available size - if(_SuppliedFileSize) { - sizetouse = _SuppliedFileSize; // adapt to websocket supplied size - } - if (!Update.begin(sizetouse)) { - Update.printError(DebugPort); - } - } - else { - // SPIFFS UPLOAD START - DebugPort.printf("SPIFFS upload: %s\r\n", filename.c_str()); - - // calcualte a *very wild* guess of max size me *may* be able to cope with - int freebytes = SPIFFS.totalBytes() - SPIFFS.usedBytes(); - freebytes -= 8192; // at least 2 blocks must be kept free, each being 4k - int pageestimate = ((_SuppliedFileSize) / 256) + 1 + 1; // +1 for shortfall, +1 for metadata - freebytes -= pageestimate * 256; - - SPIFFSupload = 2; // assume SPIFFS error for now... - if(freebytes > 0) { - // *may* have enough space, open a file - fsUploadFile = SPIFFS.open(filename, "w"); // Open the file for writing in SPIFFS (create if it doesn't exist) - if(fsUploadFile) { - SPIFFSupload = 1; // opened OK, mark as SPIFFS uplaod in progress - } - } - // not enough space - return error to browser via web socket, javascript will report error - if(SPIFFSupload == 2) { - sendWebSocketString("{\"progress\":-1}"); // feedback -ve byte count of update to browser via websocket - } - DebugPort.printf("SPIFFS freespace test = %d\r\n", freebytes); // report our space estimate - } + int sts = BrowserUpload.begin(filename, _SuppliedFileSize); + sprintf(JSON, "{\"progress\":%d}", sts); + sendWebSocketString(JSON); // feedback proper byte count of update to browser via websocket } - // handle file segments of form upload + // handle file fragments of form upload else if (upload.status == UPLOAD_FILE_WRITE) { #if USE_SW_WATCHDOG == 1 feedWatchdog(); // we get stuck here for a while, don't let the watchdog bite! #endif - // SPIFFS upload in progress? - if(SPIFFSupload == 1) { - if(upload.totalSize) { - // feed back bytes received over web socket for browser javascript progressbar update - char JSON[64]; - sprintf(JSON, "{\"progress\":%d}", upload.totalSize); - sendWebSocketString(JSON); // feedback proper byte count of update to browser via websocket - } - // show percentage on OLED - int percent = 0; - if(_SuppliedFileSize) - percent = 100 * upload.totalSize / _SuppliedFileSize; - ShowOTAScreen(percent, eOTAbrowser); // browser update - } - - DebugPort.print("."); - - if(SPIFFSupload) { - // SPIFFS update (may be error state) - if(fsUploadFile) { - // file is open, add new segment of data to file opened for writing - if(fsUploadFile.write(upload.buf, upload.currentSize) != upload.currentSize) { // Write the received bytes to the file - // ERROR! write operation failed if length does not match! - Update.printError(DebugPort); - fsUploadFile.close(); // close the file (fsUploadFile becomes NULL) - sendWebSocketString("{\"progress\":-2}"); // feedback -ve byte count of update to browser via websocket - write error - SPIFFSupload = 2; // flag SPIFFS error! - DebugPort.printf("UPLOAD_FILE_WRITE error: removing %s\r\n", filename.c_str()); - SPIFFS.remove(filename.c_str()); // remove the bad file from SPIFFS - } - } + int sts = BrowserUpload.fragment(upload); + if(sts < 0) { + sprintf(JSON, "{\"progress\":%d}", sts); + sendWebSocketString(JSON); // feedback -ve byte count of update to browser via websocket - write error } else { - // Firmware update, add new segment to OTA partition - if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { - // ERROR ! - Update.printError(DebugPort); - sendWebSocketString("{\"progress\":-2}"); // feedback -ve byte count of update to browser via websocket - write error + // upload still in progress? + if(BrowserUpload.bUploadActive) { // show progress unless a write error has occured + DebugPort.print("."); + if(upload.totalSize) { + // feed back bytes received over web socket for progressbar update on browser (via javascript) + sprintf(JSON, "{\"progress\":%d}", upload.totalSize); + sendWebSocketString(JSON); // feedback proper byte count of update to browser via websocket + } + // show percentage on OLED + int percent = 0; + if(_SuppliedFileSize) + percent = 100 * upload.totalSize / _SuppliedFileSize; + ShowOTAScreen(percent, eOTAbrowser); // browser update } } } // handle end of upload else if (upload.status == UPLOAD_FILE_END) { - if(SPIFFSupload == 1) { - // SPIFFS completed OK up until the end - a winner! - // ensure 100% is shown on browser - char JSON[64]; - sprintf(JSON, "{\"progress\":%ld}", _SuppliedFileSize); - sendWebSocketString(JSON); // feedback proper byte count of update to browser via websocket - } + int sts = BrowserUpload.end(upload); + sprintf(JSON, "{\"progress\":%d}", sts); + sendWebSocketString(JSON); // feedback proper byte count of update to browser via websocket delay(2000); - if(SPIFFSupload) { - // any form of SPIFFS attempt (may be error) - // Close the file if still open (did not encounter write error) - if(fsUploadFile) { - fsUploadFile.close(); - DebugPort.printf("handleFileUpload Size: %d\r\n", upload.totalSize); - } - } - else { - // completion of firmware update - // check the added CRC we genertaed matches - // - this guards against malicious, badly formatted bin file attempts. - if(!CheckFirmwareCRC(_SuppliedFileSize)) - Update.abort(); - - if (Update.end()) { - DebugPort.printf("Update Success: %u\r\nRebooting...\r\n", upload.totalSize); - } else { - Update.printError(DebugPort); - } - } bUpdateAccessed = false; // close gate on POST to /updatenow } else { DebugPort.printf("Update Failed Unexpectedly (likely broken connection): status=%d\r\n", upload.status);