/**
* 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 \n Rebooting... \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 ( ) ;
}
/**
* Shared empty String instance
*/
const String HTTPUpdateServer : : _emptyString ;
# endif // !ARDUINO_ARCH_ESP32