/** * Declaration of AutoConnectUpdate class. * The AutoConnectUpdate class is a class for updating sketch binary * via OTA and inherits the HTTPUpdate class of the arduino core. * It declares the class implementations of both core libraries as * HTTPUpdateClass to absorb differences between ESP8266 and ESP32 * class definitions. * The AutoConnectUpdate class add ons three features to the HTTPupdate * class. * 1. Dialog pages for operating the update. * The dialog pages are all AutoConnectAux, and they select available * sketch binary, display during update processing, and display * update results. * 2. Dialog pages handler * In the dialog page, AUTOCONNECT_URI_UPDATE, AUTOCONNECT_URI_UPDATE_ACT, * AUTOCONNECT_URI_UPDATE_RESULT are assigned and there is a page * handler for each. * 3. Attach to the AutoConnect. * Attaching the AutoConnectUpdate class to AutoConnect makes the * sketch binary update function available, and the operation dialog * pages are incorporated into the AutoConnect menu. * @file AutoConnectUpdate.h * @author hieromon@gmail.com * @version 1.0.0 * @date 2019-08-15 * @copyright MIT license. */ #ifndef _AUTOCONNECTUPDATE_H_ #define _AUTOCONNECTUPDATE_H_ #include "AutoConnectDefs.h" #ifdef AUTOCONNECT_USE_UPDATE #ifndef AUTOCONNECT_USE_JSON #define AUTOCONNECT_USE_JSON #endif #include #define NO_GLOBAL_HTTPUPDATE #if defined(ARDUINO_ARCH_ESP8266) #include #include using HTTPUpdateClass = ESP8266HTTPUpdate; #elif defined(ARDUINO_ARCH_ESP32) #include #include using HTTPUpdateClass = HTTPUpdate; #endif // #include // Quote the true AutoConnectUpdate class according to AUTOCONNECT_USE_UPDATE. #define AutoConnectUpdate AutoConnectUpdateAct #else // !AUTOCONNECT_USE_UPDATE! #define AutoConnectUpdate AutoConnectUpdateVoid #endif #include "AutoConnect.h" // Support LED flashing only the board with built-in LED. #if defined(BUILTIN_LED) || defined(LED_BUILTIN) #define AC_SETLED(s) do {setLedPin(AUTOCONNECT_TICKER_PORT, s);} while(0) #else #define AC_SETLED(s) do {} while(0) #endif // Indicate an update process loop typedef enum AC_UPDATESTATUS { UPDATE_RESET, /**< Update process ended, need to reset */ UPDATE_IDLE, /**< Update process has not started */ UPDATE_START, /**< Update process has been started */ UPDATE_PROGRESS, /**< Update process in progress */ UPDATE_SUCCESS, /**< Update successfully completed */ UPDATE_NOAVAIL, /**< No available update */ UPDATE_FAIL /**< Update fails */ } AC_UPDATESTATUS_t; class AutoConnectUpdateVoid { public: explicit AutoConnectUpdateVoid(const String& host = String(""), const uint16_t port = AUTOCONNECT_UPDATE_PORT, const String& uri = String("."), const int timeout = AUTOCONNECT_UPDATE_TIMEOUT, const uint8_t ledOn = LOW) { AC_UNUSED(host); AC_UNUSED(port); AC_UNUSED(uri); AC_UNUSED(timeout); AC_UNUSED(ledOn); } AutoConnectUpdateVoid(AutoConnect& portal, const String& host = String(""), const uint16_t port = AUTOCONNECT_UPDATE_PORT, const String& uri = String("."), const int timeout = AUTOCONNECT_UPDATE_TIMEOUT, const uint8_t ledOn = LOW) { AC_UNUSED(portal); AC_UNUSED(host); AC_UNUSED(port); AC_UNUSED(uri); AC_UNUSED(timeout); AC_UNUSED(ledOn); } virtual ~AutoConnectUpdateVoid() {} virtual void attach(AutoConnect& portal) { AC_UNUSED(portal); } virtual void enable(void) {} virtual void disable(const bool activate = false) { AC_UNUSED(activate); } virtual void handleUpdate(void) {} virtual bool isEnabled(void) { return false; } virtual AC_UPDATESTATUS_t status(void) { return UPDATE_IDLE; } virtual AC_UPDATESTATUS_t update(void) { return UPDATE_IDLE; } }; #ifdef AUTOCONNECT_USE_UPDATE class AutoConnectUpdateAct : public AutoConnectUpdateVoid, public HTTPUpdateClass { public: explicit AutoConnectUpdateAct(const String& host = String(""), const uint16_t port = AUTOCONNECT_UPDATE_PORT, const String& uri = String("."), const int timeout = AUTOCONNECT_UPDATE_TIMEOUT, const uint8_t ledOn = AUTOCONNECT_UPDATE_LEDON) : HTTPUpdateClass(timeout), host(host), port(port), uri(uri), _amount(0), _binSize(0), _enable(false), _dialog(UPDATEDIALOG_LOADER), _status(UPDATE_IDLE), _binName(String()), _webServer(nullptr) { AC_SETLED(ledOn); /**< LED blinking during the update that is the default. */ rebootOnUpdate(false); /**< Default reboot mode */ } AutoConnectUpdateAct(AutoConnect& portal, const String& host = String(""), const uint16_t port = AUTOCONNECT_UPDATE_PORT, const String& uri = String("."), const int timeout = AUTOCONNECT_UPDATE_TIMEOUT, const uint8_t ledOn = AUTOCONNECT_UPDATE_LEDON) : HTTPUpdateClass(timeout), host(host), port(port), uri(uri), _amount(0), _binSize(0), _enable(false), _dialog(UPDATEDIALOG_LOADER), _status(UPDATE_IDLE), _binName(String()), _webServer(nullptr) { AC_SETLED(ledOn); rebootOnUpdate(false); attach(portal); } ~AutoConnectUpdateAct(); void attach(AutoConnect& portal) override; /**< Attach the update class to AutoConnect */ void enable(void) override; /**< Enable the AutoConnectUpdateAct */ void disable(const bool activte = false) override; /**< Disable the AutoConnectUpdateAct */ void handleUpdate(void) override; /**< Behaves the update process */ bool isEnabled(void) override { return _auxCatalog ? _auxCatalog->isMenu() : false; } /**< Returns current updater effectiveness */ AC_UPDATESTATUS_t status(void) override { return _status; } /**< reports the current update behavior status */ AC_UPDATESTATUS_t update(void) override; /**< behaves update */ String host; /**< Available URL of Update Server */ uint16_t port; /**< Port number of the update server */ String uri; /**< The path on the update server that contains the sketch binary to be updated */ // Indicate the type of progress dialog typedef enum { UPDATEDIALOG_LOADER, /**< Cyclic loader icon */ UPDATEDIALOG_METER /**< Progress meter */ } AC_UPDATEDIALOG_t; 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 AutoConnectUpdateAct::ACPage_t* page, const size_t elementNum); String _onCatalog(AutoConnectAux& catalog, PageArgument& args); String _onUpdate(AutoConnectAux& update, PageArgument& args); String _onResult(AutoConnectAux& result, PageArgument& args); void _inProgress(size_t amount, size_t size); /**< UpdateClass::THandlerFunction_Progress */ std::unique_ptr _auxCatalog; /**< A catalog page for internally generated update binaries */ std::unique_ptr _auxProgress; /**< An update in-progress page */ std::unique_ptr _auxResult; /**< A update result page */ size_t _amount; /**< Received amount bytes */ size_t _binSize; /**< Updater binary size */ private: void _progress(void); /**< A Handler that returns progress status to the web client */ bool _enable; /**< Validation status of the Update class */ AC_UPDATEDIALOG_t _dialog; /**< The type of updating dialog displayed on the client */ AC_UPDATESTATUS_t _status; /**< Status of update processing during the cycle of receiving a request */ String _binName; /**< .bin name to update */ WebServerClass* _webServer; /**< Hosted WebServer for XMLHttpRequest */ static const ACPage_t _pageCatalog PROGMEM; static const ACElementProp_t _elmCatalog[] PROGMEM; static const ACPage_t _pageProgress PROGMEM; static const ACElementProp_t _elmProgress[] PROGMEM; static const ACPage_t _pageResult PROGMEM; static const ACElementProp_t _elmResult[] PROGMEM; #if defined(ARDUINO_ARCH_ESP8266) friend ESP8266WebServer; #elif defined(ARDUINO_ARCH_ESP32) friend class WebServer; #endif }; #endif // !AUTOCONNECT_USE_UPDATE #endif // _AUTOCONNECTUPDATE_H_