diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp index 6ef4f93ae7..fc1320f5e8 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp @@ -15,13 +15,20 @@ 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; - _server = NULL; - _username = NULL; - _password = NULL; - _authenticated = false; + _serial_output = serial_debug; + _server = NULL; + _username = NULL; + _password = NULL; + _authenticated = false; } void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, const char * username, const char * password) @@ -31,57 +38,123 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, _password = (char *)password; // handler for the /update form page - _server->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); + } + handle_start(); - 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) { + debug("Unauthenticated Update\n"); + handle_error(1); + return; + } + WiFiUDP::stopAll(); + 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) { + 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) { + Serial.setDebugOutput(false); + } + } else if (_authenticated && upload.status == UPLOAD_FILE_ABORTED) { + Update.end(); + debug("Update was aborted"); + handle_error(5); } - } 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); }); } + +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 fbe1d211d1..41c9f8bec7 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h @@ -1,38 +1,70 @@ #ifndef __HTTP_UPDATE_SERVER_H #define __HTTP_UPDATE_SERVER_H +#include + 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); +public: + 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); + 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); + + //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; + static const char *_serverIndex; + static const char *_failedResponse; + static const char *_successResponse; + 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); + };