From 07331d630e7086163cead64e195cea91e8da9387 Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Fri, 10 May 2019 19:17:19 +0900 Subject: [PATCH] Change to the progress meter --- src/AutoConnectDefs.h | 5 ++++ src/AutoConnectUpdate.cpp | 56 +++++++++++++++++++++++++++++++++++-- src/AutoConnectUpdate.h | 14 ++++------ src/AutoConnectUpdatePage.h | 10 ++++--- 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index 6416caf..b02fc0e 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -192,6 +192,11 @@ #define AUTOCONNECT_UPDATE_CATALOG_JSONBUFFER_SIZE 2048 #endif // !AUTOCONNECT_UPDATE_CATALOG_JSONBUFFER_SIZE +// Default WebSocket port for the update progress measur +#ifndef AUTOCONNECT_WEBSOCKETPORT +#define AUTOCONNECT_WEBSOCKETPORT 81 +#endif // !AUTOCONNECT_WEBSOCKETPORT + // Explicitly avoiding unused warning with token handler of PageBuilder #define AC_UNUSED(expr) do { (void)(expr); } while (0) diff --git a/src/AutoConnectUpdate.cpp b/src/AutoConnectUpdate.cpp index a4dbd0c..4f4d8f2 100644 --- a/src/AutoConnectUpdate.cpp +++ b/src/AutoConnectUpdate.cpp @@ -74,6 +74,7 @@ AutoConnectUpdate::~AutoConnectUpdate() { _progress.reset(nullptr); _result.reset(nullptr); _WiFiClient.reset(nullptr); + _ws.reset(nullptr); } /** @@ -98,8 +99,8 @@ void AutoConnectUpdate::attach(AutoConnect& portal) { _buildAux(updatePage, &_auxResult, lengthOf(_elmResult)); _result.reset(updatePage); _catalog->on(std::bind(&AutoConnectUpdate::_onCatalog, this, std::placeholders::_1, std::placeholders::_2), AC_EXIT_AHEAD); - _result->on(std::bind(&AutoConnectUpdate::_onResult, this, std::placeholders::_1, std::placeholders::_2), AC_EXIT_AHEAD); _progress->on(std::bind(&AutoConnectUpdate::_onUpdate, this, std::placeholders::_1, std::placeholders::_2), AC_EXIT_AHEAD); + _result->on(std::bind(&AutoConnectUpdate::_onResult, this, std::placeholders::_1, std::placeholders::_2), AC_EXIT_AHEAD); portal.join(*_catalog.get()); portal.join(*_progress.get()); @@ -180,6 +181,11 @@ void AutoConnectUpdate::handleUpdate(void) { * @return AC_UPDATESTATUS_t */ AC_UPDATESTATUS_t AutoConnectUpdate::update(void) { + // Crawl queued requests. + if (_ws) + _ws->loop(); + + // Start update String uriBin = uri + '/' + _binName; if (_binName.length()) { AC_DBG("%s:%d/%s update in progress...", host.c_str(), port, uriBin.c_str()); @@ -203,6 +209,12 @@ AC_UPDATESTATUS_t AutoConnectUpdate::update(void) { break; } _WiFiClient.reset(nullptr); + // Request the client to close the WebSocket. + if (_ws) { + String cmdClose = String("#e"); + _ws->sendTXT(_wsClient, cmdClose); + _ws->loop(); + } } else { AC_DBG("An update has not specified"); @@ -362,9 +374,27 @@ String AutoConnectUpdate::_onCatalog(AutoConnectAux& catalog, PageArgument& args */ String AutoConnectUpdate::_onUpdate(AutoConnectAux& progress, PageArgument& args) { AC_UNUSED(args); - AutoConnectText& flash = progress.getElement(String(F("flash"))); + // launch the WebSocket server + WebSocketsServer* ws = new WebSocketsServer(AUTOCONNECT_WEBSOCKETPORT); + if (ws) { + ws->begin(); + ws->onEvent(std::bind(&AutoConnectUpdate::_wsEvent, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + } + else { + AC_DBG("WebSocketsServer allocation failed\n"); + } + _ws.reset(ws); + + // Constructs the dialog page. + AutoConnectText& binName = progress.getElement(String(F("binname"))); _binName = _catalog->getElement(String(F("firmwares"))).value(); - flash.value = _binName; + binName.value = _binName; + AutoConnectText& url = progress.getElement(String("url")); + url.value = host + ':' + port; + AutoConnectElement& inprogress = progress.getElement(String(F("inprogress"))); + String js = inprogress.value; + js.replace(String(F("#wsserver#")), WiFi.localIP().toString() + ':' + AUTOCONNECT_WEBSOCKETPORT); + inprogress.value = js; _status = UPDATE_START; return String(""); } @@ -406,3 +436,23 @@ String AutoConnectUpdate::_onResult(AutoConnectAux& result, PageArgument& args) _status = UPDATE_RESET; return String(""); } + +void AutoConnectUpdate::_inProgress(size_t amount, size_t size) { + if (_ws) { + _amount = amount; + _binSize = size; + String payload = "#p," + String(_amount) + ':' + String(_binSize); + _ws->sendTXT(_wsClient, payload); + _ws->loop(); + } +} + +void AutoConnectUpdate::_wsEvent(uint8_t client, WStype_t event, uint8_t* payload, size_t length) { + AC_DBG("WS event(%d)\n", event); + if (event == WStype_CONNECTED) + _wsClient = client; + else if (event == WStype_DISCONNECTED) { + if (client == _wsClient) + _ws.reset(nullptr); + } +} diff --git a/src/AutoConnectUpdate.h b/src/AutoConnectUpdate.h index 49427b6..30894d5 100644 --- a/src/AutoConnectUpdate.h +++ b/src/AutoConnectUpdate.h @@ -40,6 +40,7 @@ using HTTPUpdateClass = ESP8266HTTPUpdate; #include using HTTPUpdateClass = HTTPUpdate; #endif +#include #include "AutoConnectDefs.h" #if defined(AUTOCONNECT_USE_UPDATE) #ifndef AUTOCONNECT_USE_JSON @@ -115,25 +116,22 @@ class AutoConnectUpdate : public HTTPUpdateClass { String _onUpdate(AutoConnectAux& update, PageArgument& args); String _onResult(AutoConnectAux& result, PageArgument& args); size_t _insertCatalog(AutoConnectRadio& radio, JsonVariant & responseBody); -#ifdef ARDUINO_ARCH_ESP32 - void _inProgress(size_t amount, size_t size) { - _amount = amount; - _binSize = size; - AC_DBG_DUMB("."); - } -#endif + void _wsEvent(uint8_t client, WStype_t event, uint8_t* payload, size_t length); + void _inProgress(size_t amount, size_t size); std::unique_ptr _catalog; /**< A catalog page for internally generated update binaries */ std::unique_ptr _progress; /**< An update in-progress page */ std::unique_ptr _result; /**< A update result page */ + std::unique_ptr _ws; /**< Reports the update progress measure */ + uint8_t _wsClient; /**< WebSocket client id */ size_t _amount; /**< Received amound bytes */ size_t _binSize; /**< Updater binary size */ private: AC_UPDATESTATUS_t _status; String _binName; /**< .bin name to update */ - unsigned long _period; /**< Duration of WiFiClient holding */ + unsigned long _period; /**< Duration of WiFiClient holding for the connection with the update server */ std::unique_ptr _WiFiClient; /**< Provide to HTTPUpdate class */ static const ACPage_t _auxCatalog PROGMEM; diff --git a/src/AutoConnectUpdatePage.h b/src/AutoConnectUpdatePage.h index 44912a3..b0a4527 100644 --- a/src/AutoConnectUpdatePage.h +++ b/src/AutoConnectUpdatePage.h @@ -25,10 +25,12 @@ const AutoConnectUpdate::ACPage_t AutoConnectUpdate::_auxCatalog PROGMEM = { // Define the AUTOCONNECT_URI_UPDATE_ACT page to display during the // update process. const AutoConnectUpdate::ACElementProp_t AutoConnectUpdate::_elmProgress[] PROGMEM = { - { AC_Element, "spinner", "", nullptr }, - { AC_Text, "caption", "Update start...", "
%s
" }, - { AC_Text, "flash", nullptr, "
%s
" }, - { AC_Element, "inprogress", "", nullptr } + { AC_Element, "caption", "
" }, + { AC_Element, "progress", "
Updating... 
", nullptr }, + { AC_Text, "status", nullptr, nullptr }, + { AC_Element, "inprogress", "", nullptr } }; const AutoConnectUpdate::ACPage_t AutoConnectUpdate::_auxProgress PROGMEM = { AUTOCONNECT_URI_UPDATE_ACT, "Update", false, AutoConnectUpdate::_elmProgress