parent
da8bf23e93
commit
324c6b7d5c
@ -0,0 +1,130 @@ |
|||||||
|
/**
|
||||||
|
* Ported the ESP8266HTTPUpdateServer published by Arduino-core to |
||||||
|
* provide the web browser based OTA update on the ESP32 platform. |
||||||
|
* @file HTTPUpdateServer.cpp |
||||||
|
* @author hieromon@gmail.com |
||||||
|
* @version 0.9.10 |
||||||
|
* @date 2019-06-06 |
||||||
|
* @copyright MIT license. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32 |
||||||
|
// This class will available only EPS32 actually.
|
||||||
|
|
||||||
|
#include <Arduino.h> |
||||||
|
#include <WiFiClient.h> |
||||||
|
#include <WiFiServer.h> |
||||||
|
#include <WebServer.h> |
||||||
|
#include <WiFiUdp.h> |
||||||
|
#include <Update.h> |
||||||
|
#include "StreamString.h" |
||||||
|
#include "HTTPUpdateServer.h" |
||||||
|
|
||||||
|
static const char serverIndex[] PROGMEM = R"( |
||||||
|
<html><body> |
||||||
|
<form method='POST' action='' enctype='multipart/form-data'> |
||||||
|
<input type='file' name='update'> |
||||||
|
<input type='submit' value='Update'> |
||||||
|
</form> |
||||||
|
</body></html> |
||||||
|
)"; |
||||||
|
|
||||||
|
static const char successResponse[] PROGMEM =
|
||||||
|
"<meta http-equiv=\"refresh\" content=\"15;URL=/\">Update Success! Rebooting...\n"; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup for the web update. Register the authentication procedure and |
||||||
|
* binary file upload handler required to update the actual sketch binary by OTA. |
||||||
|
* @param server A pointer to the WebServer instance |
||||||
|
* @param path URI of the update handler |
||||||
|
* @param username Username for authentication |
||||||
|
* @arama password Password for authentication |
||||||
|
*/ |
||||||
|
void HTTPUpdateServer::setup(WebServer* server, const String& path, const String& username, const String& password) { |
||||||
|
_server = server; |
||||||
|
_username = username; |
||||||
|
_password = password; |
||||||
|
|
||||||
|
// handler for the /update form page
|
||||||
|
_server->on(path.c_str(), HTTP_GET, [&] () { |
||||||
|
if (_username != emptyString && _password != emptyString && !_server->authenticate(_username.c_str(), _password.c_str())) |
||||||
|
return _server->requestAuthentication(); |
||||||
|
_server->send_P(200, PSTR("text/html"), serverIndex); |
||||||
|
}); |
||||||
|
|
||||||
|
// handler for the /update form POST (once file upload finishes)
|
||||||
|
_server->on(path.c_str(), HTTP_POST, [&] () { |
||||||
|
if(!_authenticated) |
||||||
|
return _server->requestAuthentication(); |
||||||
|
if (Update.hasError()) { |
||||||
|
_server->send(200, F("text/html"), String(F("Update error: ")) + _updaterError); |
||||||
|
} |
||||||
|
else { |
||||||
|
_server->client().setNoDelay(true); |
||||||
|
_server->send_P(200, PSTR("text/html"), successResponse); |
||||||
|
delay(100); |
||||||
|
_server->client().stop(); |
||||||
|
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) { |
||||||
|
_updaterError = String(); |
||||||
|
if (_serial_output) |
||||||
|
Serial.setDebugOutput(true); |
||||||
|
|
||||||
|
_authenticated = (_username == emptyString || _password == emptyString || _server->authenticate(_username.c_str(), _password.c_str())); |
||||||
|
if (!_authenticated) { |
||||||
|
if (_serial_output) |
||||||
|
Serial.println("Unauthenticated Update"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
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
|
||||||
|
_setUpdaterError(); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (_authenticated && upload.status == UPLOAD_FILE_WRITE && !_updaterError.length()) { |
||||||
|
if (_serial_output) |
||||||
|
Serial.print('.'); |
||||||
|
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) |
||||||
|
_setUpdaterError(); |
||||||
|
} |
||||||
|
else if (_authenticated && upload.status == UPLOAD_FILE_END && !_updaterError.length()) { |
||||||
|
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 { |
||||||
|
_setUpdaterError(); |
||||||
|
} |
||||||
|
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); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the update error code to string for notation. |
||||||
|
*/ |
||||||
|
void HTTPUpdateServer::_setUpdaterError() { |
||||||
|
if (_serial_output) |
||||||
|
Update.printError(Serial); |
||||||
|
StreamString str; |
||||||
|
Update.printError(str); |
||||||
|
_updaterError = str.c_str(); |
||||||
|
} |
||||||
|
|
||||||
|
#endif // !ARDUINO_ARCH_ESP32
|
@ -0,0 +1,42 @@ |
|||||||
|
/**
|
||||||
|
* Ported the ESP8266HTTPUpdateServer published by Arduino-core to |
||||||
|
* provide the web browser based OTA update on the ESP32 platform. |
||||||
|
* @file HTTPUpdateServer.h |
||||||
|
* @author hieromon@gmail.com |
||||||
|
* @version 0.9.10 |
||||||
|
* @date 2019-06-06 |
||||||
|
* @copyright MIT license. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __HTTP_UPDATE_SERVER_H |
||||||
|
#define __HTTP_UPDATE_SERVER_H |
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32 |
||||||
|
// This class will available only EPS32 actually.
|
||||||
|
|
||||||
|
class WebServer; |
||||||
|
|
||||||
|
class HTTPUpdateServer { |
||||||
|
public: |
||||||
|
explicit HTTPUpdateServer(bool serial_debug = false) : _serial_output(serial_debug), _server(nullptr), _username(emptyString), _password(emptyString), _authenticated(false) {} |
||||||
|
~HTTPUpdateServer() {} |
||||||
|
void setup(WebServer* server) { setup(server, emptyString, emptyString); } |
||||||
|
void setup(WebServer* server, const String& path) { setup(server, path, emptyString, emptyString); } |
||||||
|
void setup(WebServer* server, const String& username, const String& password) { setup(server, "/update", username, password); } |
||||||
|
void setup(WebServer* server, const String& path, const String& username, const String& password); |
||||||
|
void updateCredentials(const String& username, const String& password) { _username = username; _password = password; } |
||||||
|
|
||||||
|
protected: |
||||||
|
void _setUpdaterError(); |
||||||
|
|
||||||
|
private: |
||||||
|
bool _serial_output; |
||||||
|
WebServer* _server; |
||||||
|
String _username; |
||||||
|
String _password; |
||||||
|
bool _authenticated; |
||||||
|
String _updaterError; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // !ARDUINO_ARCH_ESP32
|
||||||
|
#endif // !__HTTP_UPDATE_SERVER_H
|
Loading…
Reference in new issue