diff --git a/data/favicon.ico b/data/favicon.ico index f225d9d..c7e2519 100644 Binary files a/data/favicon.ico and b/data/favicon.ico differ diff --git a/data/gauge.min.js.gz b/data/gauge.min.js.gz deleted file mode 100644 index eab2ab6..0000000 Binary files a/data/gauge.min.js.gz and /dev/null differ diff --git a/data/index.html.gz b/data/index.html.gz index 0cd0ccf..322a1ef 100644 Binary files a/data/index.html.gz and b/data/index.html.gz differ diff --git a/src/Afterburner.cpp b/src/Afterburner.cpp index 9c144f1..5504ea4 100644 --- a/src/Afterburner.cpp +++ b/src/Afterburner.cpp @@ -763,6 +763,7 @@ requestOn() DebugPort.println("Start Request!"); bool fuelOK = 2 != SmartError.checkfuelUsage(); if(!fuelOK) { + DebugPort.println("Start denied - Low fuel"); return CDemandManager::eStartLowFuel; } bool LVCOK = 2 != SmartError.checkVolts(FilteredSamples.FastipVolts.getValue(), FilteredSamples.FastGlowAmps.getValue()); @@ -785,6 +786,7 @@ requestOn() return startCode; } else { + DebugPort.println("Start denied - LVC"); return CDemandManager::eStartLVC; // LVC } } @@ -795,6 +797,7 @@ void requestOff() heaterOff(); RTC_Store.setCyclicEngaged(false); // for cyclic mode RTC_Store.setFrostOn(false); // cancel active frost mode + CTimerManager::cancelActiveTimer(); } void heaterOn() @@ -1215,9 +1218,7 @@ void doStreaming() doOTA(); #endif // USE_OTA #if USE_WEBSERVER == 1 -#ifdef OLD_WEBSOCKETHANDLER bHaveWebClient = doWebServer(); -#endif #endif //USE_WEBSERVER #if USE_MQTT == 1 // most MQTT is managed via callbacks, but need some sundry housekeeping diff --git a/src/OLED/ScreenManager.cpp b/src/OLED/ScreenManager.cpp index 7e9866b..e9622de 100644 --- a/src/OLED/ScreenManager.cpp +++ b/src/OLED/ScreenManager.cpp @@ -414,8 +414,8 @@ CScreenManager::_loadScreens() else if(NVstore.getUserSettings().menuMode == 2) { // no heater menu set menuloop.push_back(new CNoHeaterHomeMenuSelScreen(*_pDisplay, *this)); // No Heater Home menu settings screen menuloop.push_back(new CMenuSelScreen(*_pDisplay, *this)); // Menu mode screen - if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support ? - menuloop.push_back(new CGPIOSetupScreen(*_pDisplay, *this)); // GPIO settings screen + // if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support ? + // menuloop.push_back(new CGPIOSetupScreen(*_pDisplay, *this)); // GPIO settings screen } _Screens.push_back(menuloop); @@ -426,8 +426,8 @@ CScreenManager::_loadScreens() menuloop.push_back(new CWebPageUpdateScreen(*_pDisplay, *this)); // Web Page update screen if(NVstore.getUserSettings().menuMode == 0) { menuloop.push_back(new CHourMeterScreen(*_pDisplay, *this)); // Hour Meter screen + menuloop.push_back(new CWiFiScreen(*_pDisplay, *this)); } - menuloop.push_back(new CWiFiScreen(*_pDisplay, *this)); menuloop.push_back(new CWiFiSTAScreen(*_pDisplay, *this)); menuloop.push_back(new CMQTTScreen(*_pDisplay, *this)); menuloop.push_back(new CBTScreen(*_pDisplay, *this)); diff --git a/src/OLED/VersionInfoScreen.cpp b/src/OLED/VersionInfoScreen.cpp index 704b4d3..3c9d839 100644 --- a/src/OLED/VersionInfoScreen.cpp +++ b/src/OLED/VersionInfoScreen.cpp @@ -199,8 +199,10 @@ CVersionInfoScreen::keyHandler(uint8_t event) // UP press if(event & key_Up) { - _rowSel++; - UPPERLIMIT(_rowSel, 3); + if(NVstore.getUserSettings().menuMode != 2) { + _rowSel++; + UPPERLIMIT(_rowSel, 3); + } } // DOWN press if(event & key_Down) { diff --git a/src/RTC/TimerManager.cpp b/src/RTC/TimerManager.cpp index eff6ee0..92f319b 100644 --- a/src/RTC/TimerManager.cpp +++ b/src/RTC/TimerManager.cpp @@ -35,6 +35,7 @@ #include "../Utility/helpers.h" #include "../RTC/RTCStore.h" #include "../Utility/DemandManager.h" +#include "../Protocol/Protocol.h" // main array to hold information of which timer is active at any particular minute of the week // LSBs are used for the timerID + 1 @@ -42,6 +43,7 @@ uint8_t CTimerManager::_weekMap[7][CTimerManager::_dayMinutes]; // b[7] = repeat flag, b[3..0] = timer ID int CTimerManager::_activeTimer = 0; +int CTimerManager::_cancelledTimer = 0; int CTimerManager::_activeDow = 0; int CTimerManager::_nextTimer = 0; int CTimerManager::_nextStart = 0; @@ -58,6 +60,8 @@ bool CTimerManager::_timerChanged = false; } \ } +#define START_ON_TEMPERATURE_DROP + // create a bitmap that describes the pattern of on/off times void CTimerManager::createMap(int timerMask, uint16_t* pTimerMap, uint16_t* pTimerIDs) @@ -266,15 +270,17 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow) } if(newID) { - sTimer timer; - // get timer settings - int ID = (newID & 0xf) - 1; - NVstore.getTimerInfo(ID, timer); - CDemandManager::setFromTimer(timer.temperature); - DebugPort.printf("Start of timer interval, starting heater @ %dC\r\n", timer.temperature); - requestOn(); - _activeDow = dow; // dow when timer interval start was detected - retval = 1; + if(_cancelledTimer != newID) { + sTimer timer; + // get timer settings + int ID = (newID & 0xf) - 1; + NVstore.getTimerInfo(ID, timer); + CDemandManager::setFromTimer(timer.temperature); + DebugPort.printf("Start of timer interval, starting heater @ %dC\r\n", timer.temperature); + requestOn(); + _activeDow = dow; // dow when timer interval start was detected + retval = 1; + } } else { // if(!RTC_Store.getFrostOn() && !RTC_Store.getCyclicEngaged()) @@ -283,13 +289,31 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow) retval = 2; CDemandManager::reload(); DebugPort.printf("End of timer interval, stopping heater @ %dC\r\n", CDemandManager::getDegC()); + _cancelledTimer = 0; } _activeTimer = newID; } +#ifdef START_ON_TEMPERATURE_DROP + if((_activeTimer != 0) && + (_activeTimer != _cancelledTimer) && + (getHeaterInfo().getRunStateEx() == 0)) { + // heater is off, but timer is active and not cancelled + DebugPort.println("Timer re-attempting start"); + requestOn(); + } +#endif findNextTimer(hour, minute, dow); return retval; } +void +CTimerManager::cancelActiveTimer() +{ + if(_activeTimer) + DebugPort.printf("User off caused timer #%d cancellation\r\n", _activeTimer & 0xf); + _cancelledTimer = _activeTimer; +} + int CTimerManager::findNextTimer(int hour, int minute, int dow) { diff --git a/src/RTC/TimerManager.h b/src/RTC/TimerManager.h index 700a517..fb84e8c 100644 --- a/src/RTC/TimerManager.h +++ b/src/RTC/TimerManager.h @@ -52,8 +52,10 @@ public: static void getTimer(int idx, sTimer& timerInfo); static int setTimer(sTimer& timerInfo); static bool hasTimerChanged() { return _timerChanged; }; + static void cancelActiveTimer(); private: static int _activeTimer; + static int _cancelledTimer; static int _activeDow; static int _prevState; static int _nextTimer; diff --git a/src/Utility/DemandManager.cpp b/src/Utility/DemandManager.cpp index d89b8f5..9f55936 100644 --- a/src/Utility/DemandManager.cpp +++ b/src/Utility/DemandManager.cpp @@ -133,6 +133,7 @@ CDemandManager::checkStart() // alows honour cyclic stop threshold - immediate suspend transition if(deltaT > stopDeltaT) { + DebugPort.println("Immediate switch to suspend mode, too warm"); return eStartSuspend; } } @@ -142,11 +143,13 @@ CDemandManager::checkStart() // temperature exceeded the allowed margin // only deny start if actually using inbuilt thermostat mode if(isThermostat()) { + DebugPort.println("Start denied, too warm"); return eStartTooWarm; // too warm - deny start } } } + DebugPort.println("Start allowed"); return eStartOK; // allow start } diff --git a/src/Utility/NVStorage.cpp b/src/Utility/NVStorage.cpp index 2191f6d..f37c2ca 100644 --- a/src/Utility/NVStorage.cpp +++ b/src/Utility/NVStorage.cpp @@ -600,8 +600,8 @@ sCredentials::load() validatedLoad("APpassword", APpassword, 31, "thereisnospoon"); validatedLoad("webUpdateUser", webUpdateUsername, 31, "Afterburner"); validatedLoad("webUpdatePass", webUpdatePassword, 31, "BurnBabyBurn"); - validatedLoad("webUser", webUsername, 31, "Afterburner"); - validatedLoad("webPass", webPassword, 31, "WebAccess"); + validatedLoad("webUser", webUsername, 31, ""); + validatedLoad("webPass", webPassword, 31, ""); preferences.end(); } diff --git a/src/Utility/NVStorage.h b/src/Utility/NVStorage.h index b902adb..e8bc429 100644 --- a/src/Utility/NVStorage.h +++ b/src/Utility/NVStorage.h @@ -242,8 +242,8 @@ struct sCredentials : public CESP32_NVStorage { strcpy(APpassword, "thereisnospoon"); strcpy(webUpdateUsername, "Afterburner"); strcpy(webUpdatePassword, "BurnBabyBurn"); - strcpy(webUsername, "Afterburner"); - strcpy(webPassword, "WebAccess"); + strcpy(webUsername, ""); + strcpy(webPassword, ""); }; void load(); void save(); diff --git a/src/WiFi/BTCWebServer.cpp b/src/WiFi/BTCWebServer.cpp index 7a23e5e..ef3cd2f 100644 --- a/src/WiFi/BTCWebServer.cpp +++ b/src/WiFi/BTCWebServer.cpp @@ -84,9 +84,7 @@ HTTPSServer * secureServer; #endif HTTPServer * insecureServer; HTTPServer * WSserver; -#if USE_SSL_LOOP_TASK == 1 void SSLloopTask(void *); -#endif sBrowserUpload BrowserUpload; #ifdef OLD_SERVER @@ -100,6 +98,7 @@ bool bTxWebData = false; bool bUpdateAccessed = false; // flag used to ensure browser update always starts via GET /update. direct accesses to POST /update will FAIL bool bFormatAccessed = false; bool bFormatPerformed = false; +bool bStopWebServer = false; long _SuppliedFileSize = 0; bool checkFile(File &file); @@ -474,6 +473,8 @@ void initWebServer(void) { // setup task to handle webserver webSocketQueue = xQueueCreate(50, sizeof(char*) ); + + bStopWebServer = false; xTaskCreate(SSLloopTask, "Web server task", 8192, @@ -486,7 +487,8 @@ void initWebServer(void) { } void SSLloopTask(void *) { - for(;;) { + + while(!bStopWebServer) { WSserver->loop(); insecureServer->loop(); #if USE_HTTPS == 1 @@ -495,23 +497,32 @@ void SSLloopTask(void *) { processWebsocketQueue(); vTaskDelay(1); } + + WSserver->stop(); + insecureServer->stop(); +#if USE_HTTPS == 1 + secureServer->stop(); +#endif + + vTaskDelete(NULL); + bStopWebServer = false; } // called by main sketch loop() bool doWebServer(void) { -#if USE_SSL_LOOP_TASK != 1 - WSserver->loop(); - insecureServer->loop(); -#if USE_HTTPS == 1 - secureServer->loop(); -#endif -#endif - GetWebContent.manage(); return true; } +void stopWebServer() +{ + DebugPort.println("Requesting web server stop"); + bStopWebServer = true; + delay(100); +} + + String getContentType(String filename) { // convert the file extension to the MIME type if (filename.endsWith(".html")) return "text/html"; else if (filename.endsWith(".css")) return "text/css"; @@ -660,9 +671,6 @@ bool handleFileRead(String path, HTTPResponse *res) { // send the right file to if(wr > 0) { done += wr; if(done > progressdot) { -#if USE_SSL_LOOP_TASK != 1 - feedWatchdog(); -#endif DebugPort.print("."); progressdot += 1024; } @@ -1017,14 +1025,45 @@ function onformatClick() { )====="; +const char* wmConfigIndex = R"=====( + + + + + + + + +Launching Afterburner Wifi Manager + + +

Launching Afterburner Wifi Manager

+

+

This page will automatically reload in 15 seconds, please wait.

+ If auto reload fails, try manually refreshing the web page + +

You may need to reconnect to the Afterburner's AP following the reboot

+ + +)====="; void onWMConfig(HTTPRequest * req, httpsserver::HTTPResponse * res) { DebugPort.println("WEB: GET /wmconfig"); - res->print("Start Config Portal - Retaining credential"); + res->print(wmConfigIndex); DebugPort.println("Starting web portal for wifi config"); - delay(500); - wifiEnterConfigPortal(true, false, 3000); + wmReboot newMode(true); + newMode.startPortal = true; + newMode.eraseCreds = false; + newMode.delay = 500; + scheduleWMreboot(newMode); + + // delay(500); + // wifiEnterConfigPortal(true, false, 10000); } @@ -1033,8 +1072,13 @@ void onResetWifi(HTTPRequest * req, httpsserver::HTTPResponse * res) DebugPort.println("WEB: GET /resetwifi"); res->print("Start Config Portal - Resetting Wifi credentials!"); DebugPort.println("diconnecting client and wifi, then rebooting"); - delay(500); - wifiEnterConfigPortal(true, true, 3000); + wmReboot newMode(true); + newMode.startPortal = true; + newMode.eraseCreds = true; + newMode.delay = 500; + scheduleWMreboot(newMode); + // delay(500); + // wifiEnterConfigPortal(true, true, 3000); } @@ -1417,9 +1461,6 @@ void onUploadProgression(HTTPRequest * req, httpsserver::HTTPResponse * res) } while (!parser->endOfField()) { -#if USE_SSL_LOOP_TASK != 1 - feedWatchdog(); // we get stuck here for a while, don't let the watchdog bite! -#endif upload.currentSize = parser->read(upload.buf, HTTP_UPLOAD_BUFLEN); sts = BrowserUpload.fragment(upload, res); if(sts < 0) { diff --git a/src/WiFi/BTCWebServer.h b/src/WiFi/BTCWebServer.h index 447320c..c29d632 100644 --- a/src/WiFi/BTCWebServer.h +++ b/src/WiFi/BTCWebServer.h @@ -27,6 +27,7 @@ void initWebServer(); bool doWebServer(); +void stopWebServer(); bool sendWebSocketString(const char* Str); bool isWebSocketClientChange(); diff --git a/src/WiFi/BTCWifi.cpp b/src/WiFi/BTCWifi.cpp index aa75e3e..835980d 100644 --- a/src/WiFi/BTCWifi.cpp +++ b/src/WiFi/BTCWifi.cpp @@ -22,6 +22,7 @@ // Should be working - Jimmy C #include "BTCWifi.h" +#include "BTCWebServer.h" #include "../Utility/DebugPort.h" #include #include "../OLED/ScreenManager.h" @@ -46,6 +47,8 @@ char MACstr[2][20]; // MACstr[0] STA, MACstr[1] = AP int wifiButtonState = 0; unsigned long WifiReconnectHoldoff = 0; +wmReboot pendingWMreboot; + extern CScreenManager ScreenManager; @@ -164,6 +167,8 @@ bool initWifi() // call from main sketch loop() void doWiFiManager() { + manageWMreboot(); + if(NVstore.getUserSettings().wifiMode) { wm.process(); @@ -233,7 +238,8 @@ void wifiDisable(long rebootDelay) void wifiEnterConfigPortal(bool state, bool erase, long rebootDelay, bool STAonly) { - wm.disconnect(); + stopWebServer(); + wm.disconnect(); sUserSettings settings = NVstore.getUserSettings(); settings.wifiMode = STAonly ? 0x02 : 0x01; @@ -428,3 +434,22 @@ int isWifiButton() { return wifiButtonState; } + +void scheduleWMreboot(wmReboot& newMode) +{ + pendingWMreboot = newMode; +} + +void manageWMreboot() +{ + if(pendingWMreboot.delay) { + long tDelta = millis() - pendingWMreboot.started; + if(tDelta > pendingWMreboot.delay) { + wifiEnterConfigPortal(pendingWMreboot.startPortal, + pendingWMreboot.eraseCreds, + 3000); + pendingWMreboot.delay = 0; + } + } +} + diff --git a/src/WiFi/BTCWifi.h b/src/WiFi/BTCWifi.h index 5811f68..d2a60b8 100644 --- a/src/WiFi/BTCWifi.h +++ b/src/WiFi/BTCWifi.h @@ -24,6 +24,27 @@ #include +struct wmReboot { + bool startPortal; + bool eraseCreds; + unsigned long delay; + unsigned long started; + + wmReboot(bool timenow = false) { + startPortal = false; + eraseCreds = false; + delay = 0; + started = timenow ? millis() : 0; + }; + wmReboot& operator=(wmReboot& rhs) { + startPortal = rhs.startPortal; + eraseCreds = rhs.eraseCreds; + delay = rhs.delay; + started = rhs.started; + return *this; + }; +}; + void doWiFiManager(); bool initWifi(); const char* getWifiAPAddrStr(); @@ -46,4 +67,7 @@ void wifiDisable(long rebootDelay = 7000); void wifiFactoryDefault(); int isWifiButton(); +void scheduleWMreboot(wmReboot& newMode); +void manageWMreboot(); + #endif // __BTCWIFI_H__ diff --git a/src/WiFi/WebContentDL.cpp b/src/WiFi/WebContentDL.cpp index 54a4a20..277f7bb 100644 --- a/src/WiFi/WebContentDL.cpp +++ b/src/WiFi/WebContentDL.cpp @@ -64,7 +64,9 @@ void WebPageRequestCB(void* pClass, asyncHTTPrequest* request, int readyState) CWebContentDL::CWebContentDL() { +#ifdef DEBUG_WEBDL _request.setDebug(true); +#endif _request.onReadyStateChange(WebPageRequestCB, this); _request.onData(WebPageDataCB, this); _queue = NULL; @@ -108,7 +110,7 @@ void CWebContentDL::get(const char* filename) } // routine called regualrly by the "loop" task - ie not IRQL -// it is no safe to write to SPIFFS in the AsyncTCP callbacks! +// it is not safe to write to SPIFFS in the AsyncTCP callbacks! void CWebContentDL::process() {