From e2b92e59384b1d9b409fbf4b0e89cd30c6a775c4 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Mon, 14 Nov 2016 23:00:54 +0000 Subject: [PATCH 1/4] lib/HTTPUpdateServer: restructure to ease future work Semantically identical, but moving it in a single clean commit to ease review. We're going to introduce new privates that rely on public definitions. Signed-off-by: Karl Palsson --- .../src/ESP8266HTTPUpdateServer.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h index fbe1d211d1..51c5571b95 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h @@ -5,15 +5,6 @@ class ESP8266WebServer; class ESP8266HTTPUpdateServer { - private: - bool _serial_output; - ESP8266WebServer *_server; - static const char *_serverIndex; - static const char *_failedResponse; - static const char *_successResponse; - char * _username; - char * _password; - bool _authenticated; public: ESP8266HTTPUpdateServer(bool serial_debug=false); @@ -33,6 +24,16 @@ class ESP8266HTTPUpdateServer } void setup(ESP8266WebServer *server, const char * path, const char * username, const char * password); + + private: + bool _serial_output; + ESP8266WebServer *_server; + static const char *_serverIndex; + static const char *_failedResponse; + static const char *_successResponse; + char * _username; + char * _password; + bool _authenticated; }; From c02e72d47f159228db479e866b055e8821273dae Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Wed, 16 Nov 2016 21:48:08 +0000 Subject: [PATCH 2/4] lib/HTTPUpdateServer: whitespace and braces No semantic change. Added {} for all single line ifs. Avoids future mistakes. Consistently use 4 spaces for all indents, instead of a mix of 2 and 4. This makes it more inline with other libraries, and easier on the eyes for newcomers to the codebase. Signed-off-by: Karl Palsson --- .../src/ESP8266HTTPUpdateServer.cpp | 118 ++++++++++-------- .../src/ESP8266HTTPUpdateServer.h | 12 +- 2 files changed, 74 insertions(+), 56 deletions(-) diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp index 6ef4f93ae7..debb05bd61 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp @@ -17,11 +17,11 @@ const char* ESP8266HTTPUpdateServer::_successResponse = "on(path, HTTP_GET, [&](){ - if(_username != NULL && _password != NULL && !_server->authenticate(_username, _password)) - return _server->requestAuthentication(); - _server->send(200, "text/html", _serverIndex); + _server->on(path, HTTP_GET, [&]() { + if (_username != NULL && _password != NULL && !_server->authenticate(_username, _password)) { + return _server->requestAuthentication(); + } + _server->send(200, "text/html", _serverIndex); }); // handler for the /update form POST (once file upload finishes) - _server->on(path, HTTP_POST, [&](){ - if(!_authenticated) - return _server->requestAuthentication(); - _server->send(200, "text/html", Update.hasError() ? _failedResponse : _successResponse); - ESP.restart(); - },[&](){ - // handler for the file upload, get's the sketch bytes, and writes - // them through the Update object - HTTPUpload& upload = _server->upload(); - if(upload.status == UPLOAD_FILE_START){ - if (_serial_output) - Serial.setDebugOutput(true); - - _authenticated = (_username == NULL || _password == NULL || _server->authenticate(_username, _password)); - if(!_authenticated){ - if (_serial_output) - Serial.printf("Unauthenticated Update\n"); - return; + _server->on(path, HTTP_POST, [&]() { + if (!_authenticated) { + return _server->requestAuthentication(); } + _server->send(200, "text/html", Update.hasError() ? _failedResponse : _successResponse); + ESP.restart(); + }, [&]() { + // handler for the file upload, get's the sketch bytes, and writes + // them through the Update object + HTTPUpload& upload = _server->upload(); + if (upload.status == UPLOAD_FILE_START) { + if (_serial_output) { + Serial.setDebugOutput(true); + } - WiFiUDP::stopAll(); - if (_serial_output) - Serial.printf("Update: %s\n", upload.filename.c_str()); - uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; - if(!Update.begin(maxSketchSpace)){//start with max available size - if (_serial_output) Update.printError(Serial); - } - } else if(_authenticated && upload.status == UPLOAD_FILE_WRITE){ - if (_serial_output) Serial.printf("."); - if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){ - if (_serial_output) Update.printError(Serial); + _authenticated = (_username == NULL || _password == NULL || _server->authenticate(_username, _password)); + if (!_authenticated) { + if (_serial_output) { + Serial.printf("Unauthenticated Update\n"); + } + return; + } + WiFiUDP::stopAll(); + if (_serial_output) { + Serial.printf("Update: %s\n", upload.filename.c_str()); + } + uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; + if (!Update.begin(maxSketchSpace)) {//start with max available size + if (_serial_output) { + Update.printError(Serial); + } + } + } else if (_authenticated && upload.status == UPLOAD_FILE_WRITE) { + if (_serial_output) { + Serial.printf("."); + } + if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { + if (_serial_output) { + Update.printError(Serial); + } + } + } else if (_authenticated && upload.status == UPLOAD_FILE_END) { + if (Update.end(true)) { //true to set the size to the current progress + if (_serial_output) { + Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); + } + } else { + if (_serial_output) { + Update.printError(Serial); + } + } + if (_serial_output) { + Serial.setDebugOutput(false); + } + } else if (_authenticated && upload.status == UPLOAD_FILE_ABORTED) { + Update.end(); + if (_serial_output) { + Serial.println("Update was aborted"); + } } - } else if(_authenticated && upload.status == UPLOAD_FILE_END){ - if(Update.end(true)){ //true to set the size to the current progress - if (_serial_output) Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); - } else { - if (_serial_output) Update.printError(Serial); - } - if (_serial_output) Serial.setDebugOutput(false); - } else if(_authenticated && upload.status == UPLOAD_FILE_ABORTED){ - Update.end(); - if (_serial_output) Serial.println("Update was aborted"); - } - delay(0); + delay(0); }); } diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h index 51c5571b95..a8885486e7 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h @@ -5,27 +5,27 @@ class ESP8266WebServer; class ESP8266HTTPUpdateServer { - public: - ESP8266HTTPUpdateServer(bool serial_debug=false); +public: + ESP8266HTTPUpdateServer(bool serial_debug = false); void setup(ESP8266WebServer *server) { - setup(server, NULL, NULL); + setup(server, NULL, NULL); } void setup(ESP8266WebServer *server, const char * path) { - setup(server, path, NULL, NULL); + setup(server, path, NULL, NULL); } void setup(ESP8266WebServer *server, const char * username, const char * password) { - setup(server, "/update", username, password); + setup(server, "/update", username, password); } void setup(ESP8266WebServer *server, const char * path, const char * username, const char * password); - private: +private: bool _serial_output; ESP8266WebServer *_server; static const char *_serverIndex; From f0fd9a6f7909f73afc4876f89cc90568cfbfd1b6 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Wed, 16 Nov 2016 22:49:39 +0000 Subject: [PATCH 3/4] lib/HTTPUpdateServer: replace inline debug checks Use a single point wrapper function. Eventually we can let the user provide their own debug handler. Signed-off-by: Karl Palsson --- .../src/ESP8266HTTPUpdateServer.cpp | 27 +++++++++---------- .../src/ESP8266HTTPUpdateServer.h | 3 +++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp index debb05bd61..7d60f2bd7c 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp @@ -15,6 +15,13 @@ R"(
const char* ESP8266HTTPUpdateServer::_failedResponse = R"(Update Failed!)"; const char* ESP8266HTTPUpdateServer::_successResponse = "Update Success! Rebooting..."; +template +void ESP8266HTTPUpdateServer::debug(const char *fmt, Ts... args) { + if (_serial_output) { + Serial.printf(fmt, args...); + } +} + ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug) { _serial_output = serial_debug; @@ -56,16 +63,12 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, _authenticated = (_username == NULL || _password == NULL || _server->authenticate(_username, _password)); if (!_authenticated) { - if (_serial_output) { - Serial.printf("Unauthenticated Update\n"); - } + debug("Unauthenticated Update\n"); return; } WiFiUDP::stopAll(); - if (_serial_output) { - Serial.printf("Update: %s\n", upload.filename.c_str()); - } + debug("Update: %s\n", upload.filename.c_str()); uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; if (!Update.begin(maxSketchSpace)) {//start with max available size if (_serial_output) { @@ -73,9 +76,7 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, } } } else if (_authenticated && upload.status == UPLOAD_FILE_WRITE) { - if (_serial_output) { - Serial.printf("."); - } + debug("."); if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { if (_serial_output) { Update.printError(Serial); @@ -83,9 +84,7 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, } } else if (_authenticated && upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { //true to set the size to the current progress - if (_serial_output) { - Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); - } + debug("Update Success: %u\nRebooting...\n", upload.totalSize); } else { if (_serial_output) { Update.printError(Serial); @@ -96,9 +95,7 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, } } else if (_authenticated && upload.status == UPLOAD_FILE_ABORTED) { Update.end(); - if (_serial_output) { - Serial.println("Update was aborted"); - } + debug("Update was aborted"); } delay(0); }); diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h index a8885486e7..1e9007e887 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h @@ -34,6 +34,9 @@ class ESP8266HTTPUpdateServer char * _username; char * _password; bool _authenticated; +protected: + template + void debug(const char *fmt, Ts... args); }; From b8b7eace976ebaeb35030f931371a42e0341f305 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Mon, 14 Nov 2016 23:23:22 +0000 Subject: [PATCH 4/4] lib/HTTPUpdateServer: callbacks for events Provide basic callbacks for update start, end, error and progress. Progress callback provides as much information as we can, but because the filehandler processs as it receives data, we don't always know the entire file size in the first call. Signed-off-by: Karl Palsson --- .../src/ESP8266HTTPUpdateServer.cpp | 58 +++++++++++++++++++ .../src/ESP8266HTTPUpdateServer.h | 30 +++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp index 7d60f2bd7c..fc1320f5e8 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp @@ -60,10 +60,12 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, if (_serial_output) { Serial.setDebugOutput(true); } + handle_start(); _authenticated = (_username == NULL || _password == NULL || _server->authenticate(_username, _password)); if (!_authenticated) { debug("Unauthenticated Update\n"); + handle_error(1); return; } @@ -73,21 +75,28 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, if (!Update.begin(maxSketchSpace)) {//start with max available size if (_serial_output) { Update.printError(Serial); + handle_error(2); } } + handle_progress(0, upload.totalSize); } else if (_authenticated && upload.status == UPLOAD_FILE_WRITE) { debug("."); if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { if (_serial_output) { Update.printError(Serial); + handle_error(3); } } + handle_progress(upload.currentSize, upload.totalSize); } else if (_authenticated && upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { //true to set the size to the current progress debug("Update Success: %u\nRebooting...\n", upload.totalSize); + handle_progress(upload.totalSize, upload.totalSize); + handle_end(); } else { if (_serial_output) { Update.printError(Serial); + handle_error(4); } } if (_serial_output) { @@ -96,7 +105,56 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, } else if (_authenticated && upload.status == UPLOAD_FILE_ABORTED) { Update.end(); debug("Update was aborted"); + handle_error(5); } delay(0); }); } + +void ESP8266HTTPUpdateServer::onStart(THandlerFunction fn) +{ + _cb_start = fn; +} + +void ESP8266HTTPUpdateServer::onEnd(THandlerFunction fn) +{ + _cb_end = fn; +} + +void ESP8266HTTPUpdateServer::onError(THandlerFunction_Error fn) +{ + _cb_error = fn; +} + +void ESP8266HTTPUpdateServer::onProgress(THandlerFunction_Progress fn) +{ + _cb_progress = fn; +} + +void ESP8266HTTPUpdateServer::handle_start() +{ + if (_cb_start) { + _cb_start(); + } +} + +void ESP8266HTTPUpdateServer::handle_end() +{ + if (_cb_end) { + _cb_end(); + } +} + +void ESP8266HTTPUpdateServer::handle_error(int err) +{ + if (_cb_error) { + _cb_error(err); + } +} + +void ESP8266HTTPUpdateServer::handle_progress(unsigned int i, unsigned int j) +{ + if (_cb_progress) { + _cb_progress(i, j); + } +} diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h index 1e9007e887..41c9f8bec7 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h @@ -1,13 +1,18 @@ #ifndef __HTTP_UPDATE_SERVER_H #define __HTTP_UPDATE_SERVER_H +#include + class ESP8266WebServer; class ESP8266HTTPUpdateServer { public: - ESP8266HTTPUpdateServer(bool serial_debug = false); + typedef std::function THandlerFunction; + typedef std::function THandlerFunction_Error; // fixme enum? + typedef std::function THandlerFunction_Progress; + ESP8266HTTPUpdateServer(bool serial_debug = false); void setup(ESP8266WebServer *server) { setup(server, NULL, NULL); @@ -25,6 +30,19 @@ class ESP8266HTTPUpdateServer void setup(ESP8266WebServer *server, const char * path, const char * username, const char * password); + //This callback will be called when an update starts + void onStart(THandlerFunction fn); + + //This callback will be called when an update has finished + void onEnd(THandlerFunction fn); + + //This callback will be called when an update encounters any error + void onError(THandlerFunction_Error fn); + + //This callback will be called when an update is under way + void onProgress(THandlerFunction_Progress fn); + + private: bool _serial_output; ESP8266WebServer *_server; @@ -34,9 +52,19 @@ class ESP8266HTTPUpdateServer char * _username; char * _password; bool _authenticated; + + THandlerFunction _cb_start; + THandlerFunction _cb_end; + THandlerFunction_Error _cb_error; + THandlerFunction_Progress _cb_progress; protected: template void debug(const char *fmt, Ts... args); + void handle_start(); + void handle_end(); + void handle_error(int); + void handle_progress(unsigned int, unsigned int); + };