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"(<html><body><form method='POST' action='' enctype='multipart/form-data'>
const char* ESP8266HTTPUpdateServer::_failedResponse = R"(Update Failed!)";
const char* ESP8266HTTPUpdateServer::_successResponse = "<META http-equiv=\"refresh\" content=\"15;URL=\">Update Success! Rebooting...";
+template<class ...Ts>
+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 <functional>
+
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<void(void)> THandlerFunction;
+ typedef std::function<void(int)> THandlerFunction_Error; // fixme enum?
+ typedef std::function<void(unsigned int chunk, unsigned int total)> 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<class ...Ts>
+ void debug(const char *fmt, Ts... args);
+ void handle_start();
+ void handle_end();
+ void handle_error(int);
+ void handle_progress(unsigned int, unsigned int);
+
};