diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index a29ac80..667619f 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -205,13 +205,16 @@ // The purpose of this macro is to avoid the use of invalid member // functions due to differences in the version of the library which // AutoConnect depends on. -#define AC_HAS_FUNC(func) \ -template \ -struct has_func_##func { \ - static auto check(...) -> decltype(std::false_type()); \ - template \ - static auto check(U&) -> decltype(static_cast(&U::func), std::true_type()); \ - enum : bool { value = decltype(check(std::declval()))::value }; \ +#define AC_HAS_FUNC(func) \ +template \ +struct has_func_##func { \ + private: \ + typedef char one; \ + typedef long two; \ + template static one test(typeof(&U::func)); \ + template static two test(...); \ + public: \ + enum { value = sizeof(test(0)) == sizeof(char) }; \ } #endif // _AUTOCONNECTDEFS_H_ diff --git a/src/AutoConnectUpdate.cpp b/src/AutoConnectUpdate.cpp index 3d1bdea..8c783ca 100644 --- a/src/AutoConnectUpdate.cpp +++ b/src/AutoConnectUpdate.cpp @@ -85,17 +85,16 @@ namespace AutoConnectUtil { AC_HAS_FUNC(onProgress); template -typename std::enable_if::value, AutoConnectUpdate::AC_UPDATEDIALOG_t>::type onProgress(const T& updater, std::function fn) { +typename std::enable_if::value, AutoConnectUpdate::AC_UPDATEDIALOG_t>::type onProgress(T& updater, std::function fn) { updater.onProgress(fn); - AC_DBG("Callback enabled\n"); + AC_DBG("An updater keeps callback\n"); return AutoConnectUpdate::UPDATEDIALOG_METER; } template -typename std::enable_if::value, AutoConnectUpdate::AC_UPDATEDIALOG_t>::type onProgress(const T& updater, std::function fn) { +typename std::enable_if::value, AutoConnectUpdate::AC_UPDATEDIALOG_t>::type onProgress(T& updater, std::function fn) { (void)(updater); (void)(fn); - AC_DBG("Callback disabled\n"); return AutoConnectUpdate::UPDATEDIALOG_LOADER; } } @@ -143,11 +142,6 @@ void AutoConnectUpdate::attach(AutoConnect& portal) { _status = UPDATE_IDLE; - // Register the callback to inform the update progress - _dialog = AutoConnectUtil::onProgress(Update, std::bind(&AutoConnectUpdate::_inProgress, this, std::placeholders::_1, std::placeholders::_2)); - // Update.onProgress(std::bind(&AutoConnectUpdate::_inProgress, this, std::placeholders::_1, std::placeholders::_2)); - // _dialog = UPDATEDIALOG_METER; - // Adjust the client dialog pattern according to the callback validity // of the UpdateClass. AutoConnectElement* loader = _progress->getElement(String(F("loader"))); @@ -172,6 +166,9 @@ void AutoConnectUpdate::attach(AutoConnect& portal) { AC_DBG("AutoConnectUpdate attached\n"); if (WiFi.status() == WL_CONNECTED) enable(); + + // Register the callback to inform the update progress + _dialog = AutoConnectUtil::onProgress(Update, std::bind(&AutoConnectUpdate::_inProgress, this, std::placeholders::_1, std::placeholders::_2)); } /** @@ -217,17 +214,16 @@ void AutoConnectUpdate::handleUpdate(void) { // execute it accordingly. It is only this process point that // requests update processing. if (_status == UPDATE_START) { - _ws->loop(); // Crawl the connection request. unsigned long tm = millis(); - while (_ws->connectedClients() <= 0) { - if (millis() - tm > AUTOCONNECT_UPDATE_TIMEOUT) { + while (!_wsConnected) { + if (millis() - tm > 30 * 1000) { AC_DBG("WebSocket client connection timeout, update ignored\n"); break; } _ws->loop(); // Crawl the connection request. } // Launch the update - if (_ws->connectedClients()) + if (_wsConnected) update(); else _status = UPDATE_IDLE; @@ -276,7 +272,7 @@ AC_UPDATESTATUS_t AutoConnectUpdate::update(void) { } _WiFiClient.reset(nullptr); // Request the client to close the WebSocket. - _ws->sendTXT(_wsClient, "#e", 2); + _ws->sendTXT(_wsClient, "#e"); } else { AC_DBG("An update has not specified"); @@ -454,6 +450,7 @@ String AutoConnectUpdate::_onUpdate(AutoConnectAux& progress, PageArgument& args AutoConnectElement* wsurl = progress.getElement(String(F("wsurl"))); wsurl->value = "ws://" + WiFi.localIP().toString() + ':' + AUTOCONNECT_WEBSOCKETPORT; AC_DBG("Cast WS %s\n", wsurl->value.c_str()); + _wsConnected = false; _status = UPDATE_START; return String(""); } @@ -473,6 +470,8 @@ String AutoConnectUpdate::_onResult(AutoConnectAux& result, PageArgument& args) if (_ws) { _ws->close(); + while (_wsConnected) + _ws->loop(); _ws.reset(nullptr); } @@ -512,6 +511,10 @@ void AutoConnectUpdate::_inProgress(size_t amount, size_t size) { void AutoConnectUpdate::_wsEvent(uint8_t client, WStype_t event, uint8_t* payload, size_t length) { AC_DBG("WS client:%d event(%d)\n", client, event); - if (event == WStype_CONNECTED) + if (event == WStype_CONNECTED) { + _wsConnected = true; _wsClient = client; + } + else if (event == WStype_DISCONNECTED) + _wsConnected = false; } diff --git a/src/AutoConnectUpdate.h b/src/AutoConnectUpdate.h index 879d908..679dc1d 100644 --- a/src/AutoConnectUpdate.h +++ b/src/AutoConnectUpdate.h @@ -131,6 +131,7 @@ class AutoConnectUpdate : public HTTPUpdateClass { std::unique_ptr _ws; /**< Reports the update progress measure */ uint8_t _wsClient; /**< WebSocket client id */ + bool _wsConnected; /**< WebSocket connection status */ size_t _amount; /**< Received amound bytes */ size_t _binSize; /**< Updater binary size */ diff --git a/src/AutoConnectUpdatePage.h b/src/AutoConnectUpdatePage.h index 663f578..d6f5c6d 100644 --- a/src/AutoConnectUpdatePage.h +++ b/src/AutoConnectUpdatePage.h @@ -25,7 +25,7 @@ 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, "loader", "", nullptr }, + { AC_Element, "loader", "", nullptr }, { AC_Element, "c1", "
", nullptr }, { AC_Element, "binname", nullptr, nullptr }, { AC_Element, "c2", " from ", nullptr }, @@ -35,10 +35,10 @@ const AutoConnectUpdate::ACElementProp_t AutoConnectUpdate::_elmProgress[] PROGM { AC_Element, "progress_loader", "
", nullptr }, { AC_Element, "c4", "
", nullptr }, { AC_Text, "status", nullptr, nullptr }, - { AC_Element, "c5", "", nullptr }, }; diff --git a/src/AutoConnectUploadImpl.h b/src/AutoConnectUploadImpl.h index 2073e61..553bbc6 100644 --- a/src/AutoConnectUploadImpl.h +++ b/src/AutoConnectUploadImpl.h @@ -43,12 +43,12 @@ namespace AutoConnectUtil { AC_HAS_FUNC(end); template -typename std::enable_if::value, void>::type end(const T* media) { +typename std::enable_if::value, void>::type end(T* media) { media->end(); } template -typename std::enable_if::value, void>::type end(const T* media) { +typename std::enable_if::value, void>::type end(T* media) { (void)(media); } }