From 52e03c81fd573aacea66a35a1d4da11d9e01f48d Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Fri, 10 Apr 2020 00:17:23 +0900 Subject: [PATCH] Supports AutoConnectOTA --- examples/MyLabels/mylabels.h | 25 ++++ src/AutoConnect.cpp | 21 +++- src/AutoConnect.h | 11 +- src/AutoConnectAux.cpp | 12 +- src/AutoConnectDefs.h | 4 +- src/AutoConnectLabels.h | 29 ++++- src/AutoConnectOTA.cpp | 213 +++++++++++++++++++++++++++++++++++ src/AutoConnectOTA.h | 86 ++++++++++++++ src/AutoConnectOTAPage.h | 39 +++++++ src/AutoConnectUpload.h | 2 +- src/AutoConnectUploadImpl.h | 12 +- 11 files changed, 438 insertions(+), 16 deletions(-) create mode 100644 src/AutoConnectOTA.cpp create mode 100644 src/AutoConnectOTA.h create mode 100644 src/AutoConnectOTAPage.h diff --git a/examples/MyLabels/mylabels.h b/examples/MyLabels/mylabels.h index 1327d75..cbfbf8d 100644 --- a/examples/MyLabels/mylabels.h +++ b/examples/MyLabels/mylabels.h @@ -62,6 +62,11 @@ //#define AUTOCONNECT_BUTTONLABEL_RESET "NEW_STRING_YOU_WISH" //#endif // !AUTOCONNECT_BUTTONLABEL_RESET +// Button label: UPDATE +//#ifndef AUTOCONNECT_BUTTONLABEL_UPDATE +//#define AUTOCONNECT_BUTTONLABEL_UPDATE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_BUTTONLABEL_UPDATE + // Page title: Page not found //#ifdef AUTOCONNECT_PAGETITLE_NOTFOUND //#undef AUTOCONNECT_PAGETITLE_NOTFOUND @@ -212,6 +217,26 @@ //#define AUTOCONNECT_PAGETITLE_CREDENTIALS "NEW_STRING_YOU_WISH" //#endif // !AUTOCONNECT_PAGETITLE_CREDENTIALS +// Text: The update page caption +//#ifndef AUTOCONNECT_TEXT_UPDATINGFIRMWARE +//#define AUTOCONNECT_TEXT_UPDATINGFIRMWARE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_UPDATINGFIRMWARE + +// Text: The update page's file selection button label +//#ifndef AUTOCONNECT_TEXT_SELECTFIRMWARE +//#define AUTOCONNECT_TEXT_SELECTFIRMWARE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_SELECTFIRMWARE + +// Text: OTA success +//#ifndef AUTOCONNECT_TEXT_OTASUCCESS +//#define AUTOCONNECT_TEXT_OTASUCCESS "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_OTASUCCESS + +// Text: OTA failure +//#ifndef AUTOCONNECT_TEXT_OTAFAILURE +//#define AUTOCONNECT_TEXT_OTAFAILURE "NEW_STRING_YOU_WISH" +//#endif // !AUTOCONNECT_TEXT_OTAFAILURE + // Page title: AutoConnect connecting //#ifdef AUTOCONNECT_PAGETITLE_CONNECTING //#undef AUTOCONNECT_PAGETITLE_CONNECTING diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index feb832c..3644037 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -95,6 +95,13 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long _ticker->start(AUTOCONNECT_FLICKER_PERIODDC, (uint8_t)AUTOCONNECT_FLICKER_WIDTHDC); } + // Attach AutoConnectOTA if OTA is available. + if (_apConfig.ota) { + _ota.reset(new AutoConnectOTA()); + _ota->attach(*this); + _ota->setTicker(_apConfig.tickerPort, _apConfig.tickerOn); + } + // Advance configuration for STA mode. Restore previous configuration of STA. station_config_t current; if (_getConfigSTA(¤t)) { @@ -377,6 +384,9 @@ void AutoConnect::home(const String& uri) { void AutoConnect::end(void) { _responsePage.reset(); _currentPageElement.reset(); + _ticker.reset(); + _update.reset(); + _ota.reset(); _stopPortal(); _dnsServer.reset(); @@ -583,6 +593,15 @@ void AutoConnect::handleRequest(void) { // Handle the update behaviors for attached AutoConnectUpdate. if (_update) _update->handleUpdate(); + + // Indicate the reboot at the next handleClient turn + // with on completion of the update via OTA. + if (_ota) { + if (_ota->status() == AutoConnectOTA::OTA_RIP) { + _webServer->client().setNoDelay(true); + _rfReset = true; + } + } } /** @@ -850,7 +869,7 @@ String AutoConnect::_induceConnect(PageArgument& args) { // that occurs at connection establishment. // [WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128 // When connecting as a station, TCP reset caused by switching of the -// radio channel occurs. Although the Espressif's view is true. However, +// radio channel occurs. Although the Espressif view is true. However, // the actual TCP reset occurs not at the time of switching the channel. // It occurs at the connection from the ESP32 to the AP is established // and it is possible that TCP reset is occurring in other situations. diff --git a/src/AutoConnect.h b/src/AutoConnect.h index 42a898f..a331c9e 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -31,8 +31,12 @@ using WebServerClass = WebServer; #include "AutoConnectDefs.h" #include "AutoConnectPage.h" #include "AutoConnectCredential.h" -#include "AutoConnectAux.h" #include "AutoConnectTicker.h" +#include "AutoConnectAux.h" + +// The realization of AutoConnectOTA is effective only by the explicit +#include "AutoConnectOTA.h" +class AutoConnectOTA; // Reference to avoid circular // The realization of AutoConnectUpdate is effective only by the explicit // definition of AUTOCONNECT_USE_UPDATE @@ -125,6 +129,7 @@ class AutoConnectConfig { ticker(false), tickerPort(AUTOCONNECT_TICKER_PORT), tickerOn(LOW), + ota(false), hostName(String("")), homeUri(AUTOCONNECT_HOMEURI), title(AUTOCONNECT_MENU_TITLE), @@ -158,6 +163,7 @@ class AutoConnectConfig { ticker = o.ticker; tickerPort = o.tickerPort; tickerOn = o.tickerOn; + ota = o.ota; hostName = o.hostName; homeUri = o.homeUri; title = o.title; @@ -190,6 +196,7 @@ class AutoConnectConfig { bool ticker; /**< Drives LED flicker according to WiFi connection status. */ uint8_t tickerPort; /**< GPIO for flicker */ uint8_t tickerOn; /**< A signal for flicker turn on */ + bool ota; /**< Attach built-in OTA */ String hostName; /**< host name */ String homeUri; /**< A URI of user site */ String title; /**< Menu title */ @@ -304,6 +311,8 @@ class AutoConnect { String _prevUri; /**< Previous generated page uri */ /** Available updater, only reset by AutoConnectUpdate::attach is valid */ std::unique_ptr _update; + /** OTA updater */ + std::unique_ptr _ota; /** Saved configurations */ AutoConnectConfig _apConfig; diff --git a/src/AutoConnectAux.cpp b/src/AutoConnectAux.cpp index 0b84f01..7f9db61 100644 --- a/src/AutoConnectAux.cpp +++ b/src/AutoConnectAux.cpp @@ -53,14 +53,18 @@ const char AutoConnectAux::_PAGE_AUX[] PROGMEM = { "" "" "" "" diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index 3c407eb..aca44ce 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -185,7 +185,7 @@ #define AUTOCONNECT_JSONPSRAM_SIZE (16* 1024) #endif // !AUTOCONNECT_JSONPSRAM_SIZE -// Available HTTP port number for the update [ms] +// Available HTTP port number for the update #ifndef AUTOCONNECT_UPDATE_PORT #define AUTOCONNECT_UPDATE_PORT 8000 #endif // !AUTOCONNECT_UPDATE_PORT @@ -207,7 +207,7 @@ // Wait timer for rebooting after updated #ifndef AUTOCONNECT_UPDATE_WAITFORREBOOT -#define AUTOCONNECT_UPDATE_WAITFORREBOOT 9000 +#define AUTOCONNECT_UPDATE_WAITFORREBOOT 15000 #endif // !AUTOCONNECT_UPDATE_WAITFORREBOOT // A signal value that the board dependent LED turns on. diff --git a/src/AutoConnectLabels.h b/src/AutoConnectLabels.h index 60dab91..282778b 100644 --- a/src/AutoConnectLabels.h +++ b/src/AutoConnectLabels.h @@ -2,8 +2,8 @@ * AutoConnect proper menu label constant definition. * @file AutoConnectLabels.h * @author hieromon@gmail.com - * @version 1.1.4 - * @date 2020-02-13 + * @version 1.1.5 + * @date 2020-04-09 * @copyright MIT license. */ @@ -72,6 +72,11 @@ //#define AUTOCONNECT_BUTTONLABEL_RESET "Reboot" #endif // !AUTOCONNECT_BUTTONLABEL_RESET +// Button label: UPDATE +#ifndef AUTOCONNECT_BUTTONLABEL_UPDATE +#define AUTOCONNECT_BUTTONLABEL_UPDATE "UPDATE" +#endif // !AUTOCONNECT_BUTTONLABEL_UPDATE + // Page title: Page not found #ifndef AUTOCONNECT_PAGETITLE_NOTFOUND #define AUTOCONNECT_PAGETITLE_NOTFOUND "Page not found" @@ -222,6 +227,26 @@ #define AUTOCONNECT_TEXT_NOSAVEDCREDENTIALS "No saved credentials." #endif // !AUTOCONNECT_TEXT_NOSAVEDCREDENTIALS +// Text: The update page caption +#ifndef AUTOCONNECT_TEXT_UPDATINGFIRMWARE +#define AUTOCONNECT_TEXT_UPDATINGFIRMWARE "Updating firmware via OTA" +#endif // !AUTOCONNECT_TEXT_UPDATINGFIRMWARE + +// Text: The update page's file selection button label +#ifndef AUTOCONNECT_TEXT_SELECTFIRMWARE +#define AUTOCONNECT_TEXT_SELECTFIRMWARE "Select firmware: " +#endif // !AUTOCONNECT_TEXT_SELECTFIRMWARE + +// Text: OTA success +#ifndef AUTOCONNECT_TEXT_OTASUCCESS +#define AUTOCONNECT_TEXT_OTASUCCESS "Successfully updated, rebooting..." +#endif // !AUTOCONNECT_TEXT_OTASUCCESS + +// Text: OTA failure +#ifndef AUTOCONNECT_TEXT_OTAFAILURE +#define AUTOCONNECT_TEXT_OTAFAILURE "Failed to update: " +#endif // !AUTOCONNECT_TEXT_OTAFAILURE + // Menu Text: Connecting #ifndef AUTOCONNECT_MENUTEXT_CONNECTING #define AUTOCONNECT_MENUTEXT_CONNECTING "Connecting" diff --git a/src/AutoConnectOTA.cpp b/src/AutoConnectOTA.cpp new file mode 100644 index 0000000..aae2080 --- /dev/null +++ b/src/AutoConnectOTA.cpp @@ -0,0 +1,213 @@ +/** + * AutoConnectOTA class implementation. + * @file AutoConnectOTA.cpp + * @author hieromon@gmail.com + * @version 1.1.5 + * @date 2020-04-09 + * @copyright MIT license. + */ + +#include +#include "AutoConnectOTA.h" +#include "AutoConnectOTAPage.h" +#include + +/** + * A destructor. Release the OTA operation pages. + */ +AutoConnectOTA::~AutoConnectOTA() { + _auxUpdate.reset(nullptr); + _auxResult.reset(nullptr); +} + +/** + * Attach the AutoConnectOTA to hosted AutoConnect which constitutes + * the update process. This function creates an OTA operation page as + * AutoConnectAux instance and allows it to receive binary updates. + * @param portal A reference of AutoConnect + */ +void AutoConnectOTA::attach(AutoConnect& portal) { + AutoConnectAux* updatePage; + + updatePage = new AutoConnectAux(String(FPSTR(_pageUpdate.uri)), String(FPSTR(_pageUpdate.title)), _pageUpdate.menu); + _buildAux(updatePage, &_pageUpdate, lengthOf(_elmUpdate)); + _auxUpdate.reset(updatePage); + + updatePage = new AutoConnectAux(String(FPSTR(_pageResult.uri)), String(FPSTR(_pageResult.title)), _pageResult.menu); + _buildAux(updatePage, &_pageResult, lengthOf(_elmResult)); + _auxResult.reset(updatePage); + + _auxResult->on(std::bind(&AutoConnectOTA::_updated, this, std::placeholders::_1, std::placeholders::_2)); + _auxResult->onUpload(*this); + + portal.join(*_auxUpdate.get()); + portal.join(*_auxResult.get()); +} + +/** + * Create the update operation pages using a predefined page structure + * with two structures as ACPage_t and ACElementProp_t which describe + * for AutoConnectAux configuration. + * This function receives instantiated AutoConnectAux, instantiates + * defined AutoConnectElements by ACPage_t, and configures it into + * received AutoConnectAux. + * @param aux An instantiated AutoConnectAux that will configure according to ACPage_t. + * @param page Pre-defined ACPage_t + * @param elementNum Number of AutoConnectElements to configure. + */ +void AutoConnectOTA::_buildAux(AutoConnectAux* aux, const AutoConnectOTA::ACPage_t* page, const size_t elementNum) { + for (size_t n = 0; n < elementNum; n++) { + if (page->element[n].type == AC_Button) { + AutoConnectButton* element = new AutoConnectButton; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + if (page->element[n].peculiar) + element->action = String(FPSTR(page->element[n].peculiar)); + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_Element) { + AutoConnectElement* element = new AutoConnectElement; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_File) { + AutoConnectFile* element = new AutoConnectFile; + element->name = String(FPSTR(page->element[n].name)); + element->label = String(FPSTR(page->element[n].peculiar)); + element->store = ACFile_t::AC_File_Extern; + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_Style) { + AutoConnectStyle* element = new AutoConnectStyle; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + aux->add(reinterpret_cast(*element)); + } + else if (page->element[n].type == AC_Text) { + AutoConnectText* element = new AutoConnectText; + element->name = String(FPSTR(page->element[n].name)); + if (page->element[n].value) + element->value = String(FPSTR(page->element[n].value)); + if (page->element[n].peculiar) + element->style = String(FPSTR(page->element[n].peculiar)); + aux->add(reinterpret_cast(*element)); + } + } +} + +/** + * Check the space needed for the update + * This function overrides AutoConnectUploadHandler::_open. + * @param filename An updater bin file name + * @param mode File access mode, but it is not be used. + * @return true Ready for update + * @return false Not enough FLASH space to update. + */ +bool AutoConnectOTA::_open(const char* filename, const char* mode) { + AC_UNUSED(mode); + _binName = String(strchr(filename, '/') + sizeof(char)); + WiFiUDP::stopAll(); + uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; + // It only supports FLASH as a sketch area for updating. + if (Update.begin(maxSketchSpace, U_FLASH, _tickerPort, _tickerOn)) { + _status = OTA_START; + AC_DBG("%s updating start\n", filename); + return true; + } + _setError(); + return false; +} + +/** + * Writes received updater to the flash. + * This function overrides AutoConnectUploadHandler::_write. + * @param buf Buffer address where received update file was stored. + * @param size Size to be written. + * @return the amount written + */ +size_t AutoConnectOTA::_write(const uint8_t *buf, const size_t size) { + size_t wsz = 0; + if (!_err.length()) { + _status = OTA_PROGRESS; + wsz = Update.write(const_cast(buf), size); + if (wsz != size) + _setError(); + } + return wsz; +} + +/** + * All bytes are written, this call writes the config to reboot. + * If there is an error this will clear everything. + * This function overrides AutoConnectUploadHandler::_close. + * @param status Updater binary upload completion status. + */ +void AutoConnectOTA::_close(const HTTPUploadStatus status) { + if (!_err.length()) { + AC_DBG("OTA update "); + if (status == UPLOAD_FILE_END) { + if (Update.end(true)) { + _status = OTA_SUCCESS; + AC_DBG_DUMB("succeeds, turn to reboot.\n"); + } + else + _setError(); + } + else { + Update.end(false); + AC_DBG_DUMB(" aborted\n"); + } + } +} + +/** + * Callback of the update operation page as AutoConnectAux. + * Reflect the flash result of Update class to the page. + * @param result Upload post-process page + * @param args Unused + * @return none + */ +String AutoConnectOTA::_updated(AutoConnectAux& result, PageArgument& args) { + AC_UNUSED(args); + PGM_P stColor; + String st; + + // Build an updating result caption. + // Change the color of the bin name depending on the result of the update. + if (_status == OTA_SUCCESS) { + st = String(F(AUTOCONNECT_TEXT_OTASUCCESS)); + stColor = PSTR("3d7e9a"); + // Notify to the handleClient of loop() thread that it can reboot. + _status = OTA_RIP; + } + else { + st = String(F(AUTOCONNECT_TEXT_OTAFAILURE)) + _err; + stColor = PSTR("e66157"); + } + result["bin"].as().value = _binName; + result["bin"].as().style += String(stColor); + result["result"].as().value = st; + + // The rc element on the result page has an update return code + // which is a hidden field. + // By setting the error code of the Update class into its field, + // the homepage after reboot will automatically GET by the JavaScript + // on the result page. + result["rc"].value.replace("%d", String(Update.getError())); + return String(""); +} + +/** + * Save the last error + */ +void AutoConnectOTA::_setError(void) { + StreamString eStr; + Update.printError(eStr); + _err = String(eStr.c_str()); + AC_DBG("%s\n", _err.c_str()); + _status = OTA_FAIL; +} diff --git a/src/AutoConnectOTA.h b/src/AutoConnectOTA.h new file mode 100644 index 0000000..bca1cd1 --- /dev/null +++ b/src/AutoConnectOTA.h @@ -0,0 +1,86 @@ +/** + * Declaration of AutoConnectOTA class. + * The AutoConnecOTA class is a class for web updating a Sketch binary + * via OTA and implements with an AutoConnectAux page handler that + * inherits from AutoConnectUploadHandler. + * By overriding the _write function of AutoConnectUploadHandler to + * write the executable binary using the Update class, it can update + * the module firmware in synchronization with the upload of the sketch + * binary file. + * @file AutoConnectOTA.h + * @author hieromon@gmail.com + * @version 1.1.5 + * @date 2020-04-09 + * @copyright MIT license. + */ + +#ifndef _AUTOCONNECTOTA_H_ +#define _AUTOCONNECTOTA_H_ + +#include +#include "AutoConnect.h" +#include "AutoConnectUpload.h" + +class AutoConnectOTA : public AutoConnectUploadHandler { + public: + // Updating process status + typedef enum { + OTA_IDLE, /**< Update process has not started */ + OTA_START, /**< Update process has started */ + OTA_PROGRESS, /**< Update process in progress */ + OTA_SUCCESS, /**< A binary updater has uploaded fine */ + OTA_RIP, /**< Ready for module restart */ + OTA_FAIL /**< Failed to save binary updater by Update class */ + } AC_OTAStatus_t; + + AutoConnectOTA() : _status(OTA_IDLE), _tickerPort(-1), _tickerOn(LOW) {} + ~AutoConnectOTA(); + void attach(AutoConnect& portal); + String error(void) const { return _err; } + AC_OTAStatus_t status(void) const { return _status; } + void setTicker(uint8_t pin, uint8_t on) { _tickerPort = pin, _tickerOn = on; } + + protected: + // Attribute definition of the element to be placed on the update page. + typedef struct { + const ACElement_t type; + const char* name; /**< Name to assign to AutoConnectElement */ + const char* value; /**< Value owned by an element */ + const char* peculiar; /**< Specific ornamentation for the element */ + } ACElementProp_t; + + // Attributes to treat included update pages as AutoConnectAux. + typedef struct { + const char* uri; /**< URI for the page */ + const char* title; /**< Menu title of update page */ + const bool menu; /**< Whether to display in menu */ + const ACElementProp_t* element; + } ACPage_t; + + template constexpr + size_t lengthOf(T(&)[N]) noexcept { return N; } + void _buildAux(AutoConnectAux* aux, const AutoConnectOTA::ACPage_t* page, const size_t elementNum); + bool _open(const char* filename, const char* mode) override; + size_t _write(const uint8_t *buf, const size_t size) override; + void _close(const HTTPUploadStatus status) override; + String _updated(AutoConnectAux& result, PageArgument& args); + + std::unique_ptr _auxUpdate; /**< An update operation page */ + std::unique_ptr _auxResult; /**< An update result page */ + + private: + void _setError(void); + + AC_OTAStatus_t _status; /**< Status for update progress */ + uint8_t _tickerPort; /**< GPIO for flicker */ + uint8_t _tickerOn; /**< A signal for flicker turn on */ + String _binName; /**< An updater file name */ + String _err; /**< Occurred error stamp */ + + static const ACPage_t _pageUpdate PROGMEM; + static const ACElementProp_t _elmUpdate[] PROGMEM; + static const ACPage_t _pageResult PROGMEM; + static const ACElementProp_t _elmResult[] PROGMEM; +}; + +#endif // !_AUTOCONNECTOTA_H_ diff --git a/src/AutoConnectOTAPage.h b/src/AutoConnectOTAPage.h new file mode 100644 index 0000000..5ad293e --- /dev/null +++ b/src/AutoConnectOTAPage.h @@ -0,0 +1,39 @@ +/** + * Define pages to operate updates using the AutoConnectUpdate class. + * @file AutoConnectOTAPage.h + * @author hieromon@gmail.com + * @version 1.1.5 + * @date 2020-04-09 + * @copyright MIT license. + */ + +#ifndef _AUTOCONNECTOTAPAGE_H_ +#define _AUTOCONNECTOTAPAGE_H_ + +const AutoConnectOTA::ACElementProp_t AutoConnectOTA::_elmUpdate[] PROGMEM = { + { AC_Style, "s_rc", ".s_rc{display:none}", nullptr }, + { AC_Text, "caption", "

" AUTOCONNECT_TEXT_UPDATINGFIRMWARE "

", nullptr }, + { AC_File, "bin", nullptr, AUTOCONNECT_TEXT_SELECTFIRMWARE }, + { AC_Button, "update", AUTOCONNECT_BUTTONLABEL_UPDATE, "_upd(this, 'bin', '" AUTOCONNECT_URI_UPDATE_ACT "')" }, + { AC_Element, "js", "", nullptr } +}; + +// The definition of the OTA update operation page, which will be located to AUTOCONNECT_URI_UPDATE. +const AutoConnectOTA::ACPage_t AutoConnectOTA::_pageUpdate PROGMEM = { + AUTOCONNECT_URI_UPDATE, AUTOCONNECT_MENULABEL_UPDATE, true, AutoConnectOTA::_elmUpdate +}; + +const AutoConnectOTA::ACElementProp_t AutoConnectOTA::_elmResult[] PROGMEM = { + { AC_Text, "bin", nullptr, "margin-bottom:0.5em;font-size:1.2em;font-weight:bold;color:#" }, + { AC_Text, "result", nullptr, nullptr }, + { AC_Element, "rc", "
%d
", nullptr } +}; + +// The definition of the OTA update result display page. +// This page is assigned to AUTOCONNECT_URI_UPDATE_ACT, but the actual +// HTML document is dynamically rewritten on AUTOCONNECT_URI_UPDATE page +// by the JavaScript function included in the _pageUpdate AutoConnectAux. +const AutoConnectOTA::ACPage_t AutoConnectOTA::_pageResult PROGMEM = { + AUTOCONNECT_URI_UPDATE_ACT, AUTOCONNECT_MENULABEL_UPDATE, false, AutoConnectOTA::_elmResult +}; +#endif // !_AUTOCONNECTOTAPAGE_H_ diff --git a/src/AutoConnectUpload.h b/src/AutoConnectUpload.h index 9004991..ba8c603 100644 --- a/src/AutoConnectUpload.h +++ b/src/AutoConnectUpload.h @@ -32,7 +32,7 @@ class AutoConnectUploadHandler { protected: virtual bool _open(const char* filename, const char* mode) = 0; virtual size_t _write(const uint8_t *buf, const size_t size) = 0; - virtual void _close(void) = 0; + virtual void _close(const HTTPUploadStatus status) = 0; }; #endif // !_AUTOCONNECTUPLOAD_H_ diff --git a/src/AutoConnectUploadImpl.h b/src/AutoConnectUploadImpl.h index c181227..4e4276f 100644 --- a/src/AutoConnectUploadImpl.h +++ b/src/AutoConnectUploadImpl.h @@ -74,7 +74,7 @@ void AutoConnectUploadHandler::upload(const String& requestUri, const HTTPUpload break; case UPLOAD_FILE_ABORTED: case UPLOAD_FILE_END: - _close(); + _close(upload.status); break; } } @@ -83,7 +83,7 @@ void AutoConnectUploadHandler::upload(const String& requestUri, const HTTPUpload class AutoConnectUploadFS : public AutoConnectUploadHandler { public: explicit AutoConnectUploadFS(SPIFFST& media) : _media(&media) {} - ~AutoConnectUploadFS() { _close(); } + ~AutoConnectUploadFS() { _close(HTTPUploadStatus::UPLOAD_FILE_END); } protected: bool _open(const char* filename, const char* mode) override { @@ -106,7 +106,8 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler { return -1; } - void _close(void) override { + void _close(const HTTPUploadStatus status) override { + AC_UNUSED(status); if (_file) _file.close(); _media->end(); @@ -142,7 +143,7 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler { class AutoConnectUploadSD : public AutoConnectUploadHandler { public: explicit AutoConnectUploadSD(SDClassT& media, const uint8_t cs = AUTOCONNECT_SD_CS, const uint32_t speed = AUTOCONNECT_SD_SPEED) : _media(&media), _cs(cs), _speed(speed) {} - ~AutoConnectUploadSD() { _close(); } + ~AutoConnectUploadSD() { _close(HTTPUploadStatus::UPLOAD_FILE_END); } protected: bool _open(const char* filename, const char* mode) override { @@ -205,7 +206,8 @@ class AutoConnectUploadSD : public AutoConnectUploadHandler { return -1; } - void _close(void) override { + void _close(const HTTPUploadStatus status) override { + AC_UNUSED(status); if (_file) _file.close(); AutoConnectUtil::end(_media);