Tidied browser update by adding new browserupload class.

Adding RTC register storage for frequent NV updates (fuel gauge, desired temp etc)
This commit is contained in:
Ray Jones 2019-07-18 22:28:40 +10:00
parent e50d93bb8c
commit a543ba0748
14 changed files with 229 additions and 142 deletions

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -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();

View file

@ -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);

View file

@ -128,3 +128,5 @@ extern const BITMAP_INFO UpdateIconInfo;
// Bitmap sizes for www
extern const BITMAP_INFO WWWIconInfo;
extern const BITMAP_INFO BowserIconInfo;

View file

@ -24,7 +24,7 @@
#include "BTCDateTime.h"
#include "TimerManager.h"
#include <Wire.h>
#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<len; i++) {
Wire._I2C_WRITE(*pData++);
}
Wire.endTransmission();
}
void RTC_DS3231Ex::readData(uint8_t* pData, int len, int ofs) {
Wire.beginTransmission(DS3231_ADDRESS);
Wire._I2C_WRITE((byte)(7+ofs)); // start at alarm bytes
Wire.endTransmission();
Wire.requestFrom(DS3231_ADDRESS, len);
for(int i=0; i<len; i++) {
*pData++ = Wire._I2C_READ();
}
Wire.endTransmission();
}
void storeFuelGauge(float val)
{
Clock.saveData((uint8_t*)&val, 4, 0);
}
void getStoredFuelGauge(float& val)
{
Clock.readData((uint8_t*)&val, 4, 0);
}
void storeDesiredTemp(uint8_t val)
{
Clock.saveData((uint8_t*)&val, 1, 4);
}
void getStoredDesiredTemp(uint8_t& val)
{
Clock.readData((uint8_t*)&val, 1, 4);
}
void storeDesiredPump(uint8_t val)
{
Clock.saveData((uint8_t*)&val, 1, 5);
}
void getStoredDesiredPump(uint8_t& val)
{
Clock.readData((uint8_t*)&val, 1, 5);
}

View file

@ -22,15 +22,23 @@
#ifndef __BTC_CLOCK_H__
#define __BTC_CLOCK_H__
#include "../Libraries/RTClib/RTClib.h"
#include "BTCDateTime.h"
#include "../cfg/BTCConfig.h"
class RTC_DS3231Ex : public RTC_DS3231 {
public:
void writeData(uint8_t* pData, int len, int ofs=0);
void readData(uint8_t* pData, int len, int ofs=0);
};
class CClock {
// allow use of ONE of the RTClib supported RTC chips
// reference to the selected rtc stored here
#if RTC_USE_DS3231 == 1
RTC_DS3231& _rtc;
// RTC_DS3231& _rtc;
RTC_DS3231Ex& _rtc;
#elif RTC_USE_DS1307 == 1
RTC_DS1307& _rtc;
#elif RTC_USE_PCF8523 == 1
@ -45,7 +53,8 @@ class CClock {
public:
// constructors for ONE of the RTClib supported RTC chips
#if RTC_USE_DS3231 == 1
CClock(RTC_DS3231& rtc) : _rtc(rtc) {};
// CClock(RTC_DS3231& rtc) : _rtc(rtc) {};
CClock(RTC_DS3231Ex& rtc) : _rtc(rtc) {};
#elif RTC_USE_DS1307 == 1
CClock(RTC_1307& rtc) : _rtc(rtc) {};
#elif RTC_USE_PCF8523 == 1
@ -57,6 +66,8 @@ public:
const BTCDateTime& update();
const BTCDateTime& get() const;
void set(const DateTime& newTime);
void saveData(uint8_t* pData, int len, int ofs);
void readData(uint8_t* pData, int len, int ofs);
};
extern CClock Clock;

View file

@ -124,6 +124,11 @@ CESP32_NVStorage::validatedLoad(const char* key, float& val, float defVal, float
return true;
}
bool finBounds(float test, float minLim, float maxLim)
{
return INBOUNDS(test, minLim, maxLim);
}
bool u8inBounds(uint8_t test, uint8_t minLim, uint8_t maxLim)
{
return INBOUNDS(test, minLim, maxLim);

View file

@ -26,6 +26,7 @@
#include <functional>
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);

View file

@ -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();
}

View file

@ -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;

View file

@ -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);

View file

@ -39,6 +39,7 @@
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include "BrowserUpload.h"
#include <Update.h>
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);