esp8266 OTA update with Web Browser: custom web interface – 3
OTA (Over the Air) update is the process of uploading firmware to an ESP module using a Wi-Fi connection rather than a serial port. Such functionality becomes extremely useful in case of limited or no physical access to the module.
OTA may be done using:
- Arduino IDE
- Web Browser
- HTTP Server
First of all read the tutorial “esp8266: flash firmware binary (.bin) compiled and signed“.
In this article,e we are going to explain OTA updates via Web Browser with a custom web page.
Custom web interface
I already explain how to manage WebPage and how to do a REST calls, now we are going to manage the existing endpoint of ArduinoOTA with a custom WebPage.
First of all we are going to analize the original web page.
Original ArduinoOTA page description
The ESP8266HTTPUpdateServer wrap ESP8266WebServer and add an endpoint that in GET response with a simple page
static const char serverIndex[] PROGMEM =
R"(<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'/>
</head>
<body>
<form method='POST' action='' enctype='multipart/form-data'>
Firmware:<br>
<input type='file' accept='.bin,.bin.gz' name='firmware'>
<input type='submit' value='Update Firmware'>
</form>
<form method='POST' action='' enctype='multipart/form-data'>
FileSystem:<br>
<input type='file' accept='.bin,.bin.gz' name='filesystem'>
<input type='submit' value='Update FileSystem'>
</form>
</body>
</html>)";
static const char successResponse[] PROGMEM =
"<META http-equiv=\"refresh\" content=\"15;URL=/\">Update Success! Rebooting...";
Here the handle
// 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);
});
Original ArduinoOTA end points description
In POST check the name of input (firmware or filesystem) to understand if the file is for FLASH or FileSystem, then upload the file and Update service do the work, here the POST code.
// 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, gets the sketch bytes, and writes
// them through the Update object
HTTPUpload& upload = _server->upload();
if(upload.status == UPLOAD_FILE_START){
_updaterError.clear();
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.printf("Unauthenticated Update\n");
return;
}
WiFiUDP::stopAll();
if (_serial_output)
Serial.printf("Update: %s\n", upload.filename.c_str());
if (upload.name == "filesystem") {
size_t fsSize = ((size_t) &_FS_end - (size_t) &_FS_start);
close_all_fs();
if (!Update.begin(fsSize, U_FS)){//start with max available size
if (_serial_output) Update.printError(Serial);
}
} else {
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace, U_FLASH)){//start with max available size
_setUpdaterError();
}
}
} else if(_authenticated && upload.status == UPLOAD_FILE_WRITE && !_updaterError.length()){
if (_serial_output) Serial.printf(".");
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);
});
The page do a submit without action
<form method='POST' action='' enctype='multipart/form-data'>
so if the page url is http://esp8266-webupdate.local/update
the post point to the same url, the difference is that the page came in GET the submit of the data is in POST.
So _server->on(path.c_str(), HTTP_GET, [&](){
serve the web page and _server->on(path.c_str(), HTTP_POST, [&](){
manage the submit of the form data.
The POST manage firmware and filesystem binary,
if (upload.name == "filesystem") {
size_t fsSize = ((size_t) &_FS_end - (size_t) &_FS_start);
close_all_fs();
if (!Update.begin(fsSize, U_FS)){//start with max available size
if (_serial_output) Update.printError(Serial);
}
} else {
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace, U_FLASH)){//start with max available size
_setUpdaterError();
}
}
and use the name of input file
<input type='file' accept='.bin,.bin.gz' name='firmware'>
name equal firmware
to save sketch compiled binary
<input type='file' accept='.bin,.bin.gz' name='filesystem'>
name equal filesytem
to save filesystem binary. The upload is managed via standard multipart/form-data
.
Web pages
For this test I create 2 web pages all in vanilla js and CSS.
You can find a simple project with these pages here on GitHub.
Download the project with the relative link or via GitHub client.
In the main directory of the project launch these commands
npm i
npm run dist
Now you can find in minified direcotry these files:
- index_black_white.html
- index_black_white.html.gz
- index_black_white_ita.html
- index_black_white_ita.html.gz
- index_color.html
- index_color.html.gz
- index_color_ita.html
- index_color_ita.html.gz
The result of these 2 simple pages is this.
Color version
Here the page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload OTA data</title>
<style type="text/css">
* {
box-sizing: border-box;
}
body {
@import url("https://fonts.googleapis.com/css?family=Roboto:400,400i,700");
font-family: Roboto, sans-serif;
text-align: center;
min-width: 360px;
}
.button-send {
width: 100%;
display: inline-block;
padding: 5px 55px;
font-size: 16px;
cursor: pointer;
text-align: center;
text-decoration: none;
outline: none;
color: #fff;
background-color: #337ab7;
border: none;
border-radius: 15px;
box-shadow: 2px 2px #999;
}
.button-send:hover {
background-color: #2e6da4
}
.button-send:active {
background-color: #337ab7;
box-shadow: 1px 1px #666;
transform: translateY(4px);
}
.button-send:disabled {
background-color: #9c9c9c;
box-shadow: 1px 1px #666;
transform: translateY(4px);
}
.container {
padding-top: 80px;
display: flex;
justify-content: center;
}
.form-container {
min-width: 380px;
}
.progress {
width: 100%;
height: 8px;
background: #e1e4e8;
border-radius: 4px;
overflow: hidden;
}
.progress .progress-bar {
display: block;
height: 100%;
background: linear-gradient(90deg, #ffd33d, #ea4aaa 17%, #b34bff 34%, #01feff 51%, #ffd33d 68%, #ea4aaa 85%, #b34bff);
background-size: 300% 100%;
-webkit-animation: progress-animation 2s linear infinite;
animation: progress-animation 2s linear infinite;
}
.input-file {
width: 100%;
border: 0px transparent;
padding: 4px 4px 4px 4px;
margin-top: 20px;
margin-bottom: 20px;
border-radius: 7px;
background-color: rgba(51, 122, 183, 0.3);
}
.additional-info {
height: 67px;
}
@-webkit-keyframes progress-animation {
0% {
background-position: 100%;
}
100% {
background-position: 0;
}
}
@keyframes progress-animation {
0% {
background-position: 100%;
}
100% {
background-position: 0;
}
}
.tile-container {
display: flex;
justify-content: center;
}
.title-image {
background-image: url(data:image/png;base64,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);
background-repeat: no-repeat;
background-position: center;
background-size: 40px;
width: 40px;
margin-right: 20px;
}
.footer-desc {
position: fixed;
display: flex;
bottom: 20px;
right: 20px;
align-items: center;
}
.footer-link {
font-size: x-small;
color: black;
text-decoration: none;
padding-left: 10px;
}
.button-o {
cursor: pointer;
height: 25px;
font-size: 15px;
background: none;
outline: none;
border: 1px solid rgba(0, 0, 0, 0.35);
width: 50%;
background: rgba(51, 122, 183, 0.3);
}
.button-o.selected {
background-color: #337ab7;
color: white;
}
.button-o.left {
border-radius: 14px 0px 0px 14px;
margin-right: -3px;
}
.button-o.right {
border-radius: 0px 14px 14px 0px;
margin-left: -3px;
}
#overlay {
position: fixed; /* Sit on top of the page content */
display: none; /* Hidden by default */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.06); /* Black background with opacity */
z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
cursor: pointer; /* Add a pointer on hover */
}
</style>
</head>
<body>
<div id="overlay"></div>
<div class="footer-desc"><img
src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQIAdgB2AAD/4SdCRXhpZgAASUkqAAgAAAAHAA4BAgASAAAAYgAAABoBBQABAAAAdAAAABsBBQABAAAAfAAAACgBAwABAAAAAwAAADEBAgANAAAAhAAAADIBAgAUAAAAkgAAAGmHBAABAAAApgAAAN4AAABDcmVhdGVkIHdpdGggR0lNUAB2AAAAAQAAAHYAAAABAAAAR0lNUCAyLjEwLjE0AAAyMDIwOjA1OjE5IDE2OjA5OjUxAAIAhpIHABkAAADEAAAAAaADAAEAAAABAAAAAAAAAAAAAAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVAACAAAAQQAAQAAAAABAAABAQQAAQAAAAABAAACAQMAAwAAAEQBAAADAQMAAQAAAAYAAAAGAQMAAQAAAAYAAAAVAQMAAQAAAAMAAAABAgQAAQAAAEoBAAACAgQAAQAAAO8lAAAAAAAACAAIAAgA/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAEAAQADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiimkkGgB1FNBJNOoAKKKKACiiigAooqNmIPWgCSimgnNOoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAIpCA3PpXiXj3VrG28a6hFLPtdfLyNjH/lmp9K9tkQs2RjpXg/xD8K32oeOtSuopbdUfysB2YHiJB6e1Jl07X1KfgPXtNbxpp4Fzz+8/gb/nm3tXuunaha3VwyQy7mCEkbSOMj1FfJ3gy8j0/wAWWV1KrMieZkIMnlGH9a9/8DeILTU9bmhhjmVltmcl1AGNyjsfeohK6Na9NReh6N1oqMSrjoaa1yinBDVoc5NRmoRcoxwA1K0ygdDQBl6tqVpaXSxzy7GKBgNpPGT6CvB/Hmt6d/wmmof6R/zz/gb/AJ5r7V3/AMQ/E1lpWvwQTxXDM1qrgooIxvcdyPSvB/Fd7HqfiW7u4VdY5NmA4APCKO30rOcrLQ6aFNSep7J4I1WyuPF9jFFNudvMwNpH/LNvavYkILfhXifgPwxe6f400+6llt2RPMyEZieY2Hp717ZGpDfhVowna+hJRRRTJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKADFcfreiW13q888jyhm25CkY4UD0rrySDXOanIw1GUA+n8hQxo+R7a4ezuFuIwpdM4DdORj+tdt4H8balpmtTTQwWjM1uyEOjEY3KezD0ripY1WIkDmm2t3PZymS3fY5XaTgHj8fpXKpOLPUlBTiz2W/+MfiG0nWOOz0sgrn5opPU/7dY1x8c/EyTsosdIwMf8sZPT/rpXnE2o3dw4eWXcwGM7QOPyqq7M7lmOSabqPoZwoRW6PUrb45eJnuFU2OkYOekMnp/wBdK2LL4w+ILuYxyWemABd3yxSe3+3XiqO0bBlOGHQ1Yh1O8gctFNtYjGdoP9KFUfUc6EX8KOt8e+K77WdcguLiK2V1tlQCNWAwGY9yfWuUYfaT5z8M3UDp6VFc3c97IJLh97gbQcAcfh9as2yg26kj1/nSvzMtRUIqx9XaVoltaalFPG8pZc4DEY5BHpXSgYrCsJpGvYwW457exrcUkmuo8tjqKKKBBRRRQAUUUUAFFFFABRRRQAUUUUAFFGaaXAOOaAHZFJkVi3PiaytLdp5IrgquMhVGeTj1rFvviXo1jCssttflS235Y0znB/2valcaTZ2TSopwT+lJ9oiH8X6GvMbz41eHIZgrWWqklc8RR/8Axyqb/HLwyGI+w6v/AN+Y/wD45S5kWqU30PXN6+tNkmjiXc7YGcdK85tfjJ4durlIUs9UDNnBaKPHTP8Afq1efErRpIQBbX/3s8xp/wDFU7olwaDxj4q0XTNXigvL3ypGgDgeU7cbmHYH0NeB+NNStNS8W313aTeZBJ5e1tpGcRqDwRnqDW38S/EVpq/iO3uLeOdUW0VCJFAOd7nsT61wE8gkmZwDg+tYzmdtClbVljTI2k1CJEGWOcD8DXU2drNHMS6YG3HUVzWjSCPVoGOcDd0/3TXYQ3CSuVUNnGea5pHSPCkDpUEsEjSEhcj6ireaaZlU4INRdgcHLbSxxlmTAHfIqsa0bq6SS2dQGycdfrWbWxSCiiigDr/Beq2Wn+LbG6upvLhTzNzbWOMxsBwBnqRXvXhHxTo2q6tLBZXnmyLAXK+U68blGeQPUV8uW0iw3CyMCQM9PpXoPw28T2WkeIri4uIrhka0ZAI1UnO9D3I9K2hPucleldXPpuOVJFypyM46U7eo71wFr8TtFSIg2uofe/55p/8AF1VufjL4dtrhonstULLjOIo8dM/362ucShJ9D0YTxE4DfoacJFY4BryNPjj4ZLj/AEHV/wDvzH/8cq9afGrw5PKVWy1UELnmKP8A+OUuZFOlNdD0/IoyK42x+JOj38DSxW1+qhtvzxoDnAP973rYtvElndQLMkc4Vs4DKM9cetURZo26KaGBNOoEFFFFABSGg8CszWrue0s0kgfaxkAJwDxg+tADr+/ltZ1RFQgrn5gfU+9cBr3xE1fTNauLOG3smjj24Lo5PKg9m965P4ieN/EWmeIIIbPUfLja1VyPJjPO9x3X2FcFc+ItV1C4a6urrzJnxuby1GcDA4Ax0AqHLU3jSdrmncfFfXbuBoJLTTgrYyVjfPBz/fqta+IrvXpDa3UcCIg8wGJSDkcdyfWu/wBI+H/he51SGGbTN0bbsj7RKP4SezV2mnfDDwdb3DPFo+1ihGftMx4yP9up5ZdzSVSklojxuPw5Z6ivnTSTqwO3CMAMde496Y/gzTi5/fXX/fa//E19AxeBfDcKFU03Azn/AF8n/wAVTz4I8Ok5Onf+RpP/AIqq5DNVmtj5yls49MjN5CWaSPoHORzx2x61Qu/El4kQIig+93U/419GXnw98LSWjo+l5U4yPtEvr/vVzWr/AA28JR2ildJwd4H/AB8y+h/2qiSaNIVIvdHz3f38uozrNMqKyrtwgIGMk9z71TPWvU/EHhHQrG/jitrHYhiDEea55yfVvavPdZtobXVp4YU2xrtwMk4yoPesWn1OuFSL0RTt5mt51lQAsucZ6dK1LbXLlJCRHD07g/41jZpysQeDUls6IeILsj/Vw/8AfJ/xqvL4guxIf3cP/fJ/xrH86QdG/Sml2Y5J5osgsxWkLDBAplFFMYUUUoHFACZq1Y6hLp87SxKjMV24cEjGQfX2q3olnBeaxBBPHvibdlckZwpPavRNB8GaBe3zx3FhvQRFgPOkHOR6N700mZzqRWjOOs/EN3JCSY4PvY4U/wCNakGnxanCt5OzrJJ1CEAccdwfSvWNI+GnhF7Ry2k5O8/8vMvoP9quks/h94XitURNMwozgfaJfX/eraKb3OSdSKfuo8NHgjTVORPd/wDfa/8AxNJL4cs9NUTQyTszHaQ7AjHXsPavoH/hDPD/AP0D/wDyNJ/8VUU3gXw3MgWTTsgHP+vk/wDiqvlM3Wb3PnO58TXugSC1tYrd43HmEyqScnjsR6CrNt8WdetYFhS000qucFo3z1z/AH69o1L4YeDri5V5dH3MEAz9pmHGT/t1xmrfD/wvbanNDDpm2NduB9olP8IPdqlxl0ZpGpSa1R0mgfEHVtT1u3s5reyWOTdkojg8KT3Y+ld/ZXslxMUdUAC54FfKmn+JdXsb6O4t7vZKmdreWhxkEdx6GvSvh34y1/VfEE8F7f8Amxras4XyY153oM8KPU1SkZzotK57hRVDTLiW4tmeVtzByM4A7Crw6VZgZ2t31vY6RPc3MmyFNu5tpOMsB0Hua8a+J+vabqfhq2hs7nzJFvFcjy2XjY47j3Fd78RNXt7fwJqUrpKVXys4Az/rUHrXhSSr4qP2GxBjlj/fEz8Lgcds8/MKiT6G1KD+IteGfDmrazpslxYWnnRLMULeYi4bAOOSPUV7X4Q0XULLwvZ29xb7JU37l3qcZdj2PvWT8LvDt3p/hm5ilkgZjeM3yMSMbEHp7V6TaQtDbJGxBIz0+tOKFVnd2RKAc06iiqMgooooAD0qKZGZAAM81LRSauBk3MTiQcdvWuev7C5lvZHSLKnGDuHoPeutuYmeQEEdKz5kKysDiuacbO5tGXQ+dNZ8F+ILbSppptP2xrtyfOjP8QHZq4270y8sohJcQ7ELbQdwPP4H2r6d17SLjUtFuLSF4lkk24LkgcMD2HtXlXjDwNqdvpMTvPaEGcDh2/ut/s1O51U520PKjSVd1HTZtMuFhmaNmZA4KEkYyR3HtVI9aR1J3CilxV7S9Ln1a5aCB41dULkyEgYyB2B9aAbsLY6Pf6hC0trB5iBtpO9RzgHufeu50TwX4gm0eB00/Kndg+dH/eP+1Wt4L8EakdHm/f2n/Hw38bf3V/2a9S0XTZtP0iC1laNnTdkoSRyxPp709jlqVL6DrGxuI7yNmjwozk7h6Gt61jfzTx29aihQtKoGK0LeMpISSOlXCN9TlnJksSlVII71JRRXQjEhueIG/D+dU4mG489quXX/AB7P+H86oxfeP0rKfxFxWhfh5Q49afimW/8Aqz9alrWOxL3PP/Guh6jfeEb63t7ffK/l7V3qM4kU9z6CvEta8O6roVml1qVr5ELyCNW8xWyxBOMKSegNfUl9A1xZyRIQGbGM9Oory/4peGb298MW0cctuCLxW+Zj/cf296mS6mlKdnZmV8LNe0yx8MXMVzc7HN4zAeWx42J6D2r1/SLuC+0uG4t33xPu2tgjOGI7+4r5ktrpPCUZsL8NJLIfOBg5XaeO+OflNe8/D7VoLzwPp1xGkgR/NwGAzxI49fanF9B1Y68y2OM+JF9LN4B1ONlQA+V0B/56pXnnwos477xTdRSswUWTt8p5zvT/ABrtviCx/wCEH1Hn/nl/6MSuT+CwDeMbsH/oHv8A+jI6zl8aNqf8GR9BeGbGKy02SONnKmYt8xHoP8K0pLh45CoC4HrUOkqBatgfxn+Qpl0xFy4B9P5Vc3ZaHKldkn22T+6n5Gj7bJ/dT8jVHe3rRvb1rH2jL5UXvtsn91PyNH22T+6n5GqO9vWje3rR7RhyovfbZP7qfkalguHlcqwXGM8VmB2z1q3YkmZs/wB3+oqozbdhOJdYZNZ1yP37fh/KtI1nXP8Ax8N+H8qqotBR3KrKCMVla1o1vq1mkE7yqiyBwYyAc4I7g+ta1MdQwwa5zfY8N8deE7C21uFEmuSDbKeWX+83tXm+p2yWeoSwRliq4wW68gGvpDxHo9he6hHJcQb3EQUHew4yfQ+9eC+OLaGz8YX8ECbI18vC5JxmNT3ps6aMm3YzNJtI77U4baUsEfdkqeeAT/SvTfAvhDT31uYGa5/49m6Mv95f9muL8B2sN3400+CdN8beZlckZxGx7V77oWj2FjfPLbQbHMZUnex4yPU+1Aq0nexpaRpNvpdo8EDyMrOXJcgnOAOwHpWgBtGBQBt4FFI5y5bqPPX8f5VfA2nIqlbj9+v4/wAqtysVUEcc10Q0RhLceWNG41QmuJVcANjj0FR/apv7/wCgodRJhyMu3LE27fh/OqcR+Y/SmNcSuu1myD7Cmh2U5BrOU03cpRaRpQMQh+tS7jWULiVRgPj8BTvtU39/9BVqokTyM09xPFYXiyyjvdLijkZwonDfKR/db/Gr1vcSvOqs2Qc9h6VHrQDWaA8/vB/I1cZXQmrM+avijbJYeJraKIsymzVvn5Od7j+lep/DG8kT4d6UoVcDzuo/6avXmvxjUL4utAP+fBP/AEZJXcfDmV18B6aA2APN7f8ATV6iPxs6qi/cxZL8R7SePwFqbumFHlZOR/z1SvPfhPdQ2fim6kuH2IbJ1BwTzvT0+ley/EjR7i58AanCjxBm8rBYnH+tQ+leHaVA/hS6a+viJIpEMIEHLZJB744+U05L3kwpNOm4n0x4au4LvTZJIH3qJipOCOcD1rUdGZyQOK4D4Z+JLO+8N3EsUU4UXbL8yjP3E9/evQbeZbiBZUBCtnGevWtNGjlkmmReTJ/d/WjyX/u/rVqilyoVyr5L/wB39aPJf+7+tWqKOVBcq+U/939akiRlYkjtU1JmjlQXGsQDzWdcn9+34fyq5NIFcAg9Kz55AZmPNZ1HoXBEJO0ZPSs/VtUs9NtVmu5vLjZwoO0nnBPYexpmqa3babp0t3MkrRx4yEAJ5IHc+9eceNfHWmXejQxxwXgIuFPzIv8Adb/arBI3SbdjJ+IHiDS7rXoHhutyi1UE+Ww53N6ivNNSmjnv5ZI23I2MHGOwrYvLd/EUou7QqkaL5REvByOe2eORSxeCtSmjEiz2gB9Xb/4ms516cNJM6qcVHXqZOkXEVtqcM0zbY13ZOCf4SO1eoeAvEekw65O0l3gG2Yf6t/7y+1cBN4Rv7eJpXmtiq9cM2f8A0GnaZ/xT9y13d/PG6GMCLk5JB749DVQrQlsx1Kd0fS2m6nZ6jbNNaTeZGHKk7SOcA9x7irwIIyK8r8FeN9Ni0aZWguyftDHhF/ur/tV6Jpuqwajp8V1CkixyZwHAB4JHY+1U0cbVjct2Hnr+P8q0FIJ4rKhcLKpOavwSq7kAHpW9N6GE0yxijBpaK2IILof6O/4fzqjF94/Sr91/x7P+H86oRfeP0rGfxGkdi9bj92frU2DUVv8A6s/Wpq1WxD3G4rE8UXUNppkck77FMwUHBPO1vSte6uEtbZ5nDFVxkL164rzr4meKbG08N28kkVwQbtV+VV/uP70N2Q4pt2PIvipPFe+J7aS3begs1UnBHO9/X616f8MrSd/h5pbKmQfN7j/nq9eV3dlJ4vlGoaeyRRRr5JFwSrbh83bPGGFe6/DjSZ7HwFpltK8ZdPNyVJxzK59Pes4r3rnRVlamo9jpNf06HUtEuLSZnWOTbkoQDwwPce1eK/EvwvY6T4ct54Jbhma7VCJGUjGxz2A9K97kjWWMo4yp6iua8W+HtL1XSooL2182NZw4XzGXnawzwR6mraujCEuVngnhbxfqHhrTJbOzhtpI3mMpMysTkqo7MOPlFe2eEfE97qPhizu5ordZJN+QisBw7DufavGPHulWWg67Ba6bD5EL2yyMu4tlizDOWJPQCsm08ceI9KtUsrLUfKt4s7E8iNsZOTyVJ6k1HNynQ6ftNUfWQNOrz7SPEerXOqQwzXe6Nt2R5aD+EnsK7C0uppZSrvkbc9BWpy2NGimKxIp2TQIM1HI5RcjHWoriV0gZlbBGO3vWFqupXcNqrRzYJcD7o9D7VLlYpRuadzM3mDgdK53UNXuIL6SJUiKrjGQc9B71xniXxdrlnqUcdvfbEMIYjykPOT6r7V5zrXjzxKNWnA1Lj5f+WEf90f7Nc8u5006Texpaz8RdXvtJntpbaxCPtyVR88MD/e9q53T5W8STtZ3gCRovmgw8HIIHfPHzGk0OCPUdYgtLtfMgk3blzjOFJHI56gV6R4d8K6LDqEjJZYPlEf61/Ue9ebjcdChFrW9jrhTRB4W8G6c2mSEzXX+uP8S/3V/2a6iDwvZRQqiy3GB6sv8AhWlaWNtZRGO3j2IW3Ebiefx+lWQMCvkMRjqtSTak7HSoLqctf+F7JrKQGW47fxL6j2rjvEfheyj0+MiW4/1oHLL6H2r1K8jU2r8en86wr2wtruERzx71DZA3Ec8+ldeCxs4/E3ubqnGS0R49LqEvh5haWio8bjzSZQScnjsRxwK63RPiNrFpo8EEdtYlV3YLI+eWJ/vVLrvhzSnvULWuT5Y/5aN6n3riNUJ0/UZbW1/dwpjavXGQCeTz1Jr6rC4qNWKWpxVqFj6RsdXuJ7yONkiCtnoD6H3rftp2Eh4HSvmnQvHfiWTWbdW1LIO7jyI/7p/2a9J0DxVrV1fuk17uUREgeUg5yPQV2RutThnTtoz1+GQuhJA69qkzXLaVqd5LaszzZO8j7o9B7VvW00klurM2Sc9vet4yOeUbE9yMwMPp/OqcUYDHr0q8w3Lg8iomjVBlRg0ON3clSsPhGEP1p5NZd1dTQShY32grnoDXHax4n1i11WaGG82xrtwPKQ/wg9xVbBa5Y8Y+K77T/Ct7dQxWzOmzAdWI5dR2PvXi2ueK77xXZJYX8VvHFHIJgYFYNuAI7k8fMaov4z1/WkOn6hf+day/fj8mNc4+YchQeoFdJ4B0LTdW12eC9tvNiW2Zwu9l53KM8EeprO/NsdSh7Na7nRfDHwrY3vhu4kkluAReMvysv9xPb3r2DRrGLTtKgtYWdo492C5BPLE9vrWd4Y0LTdK02SCytvKiaYuV3s3OFGeSfQVvoiooVRgCtErI5py5ncdRRRTJKF7bSzTBkTI246j3rzfxJ4R12+1+5ubax3xPs2t5qDOFA6FvUV6vTGQls8Umhp2PkuX4beLYIjJJpO1F6n7TEf8A2aks/DGsaZMZryz8uNl2A+ah569j7GvpW+0C6ubOSFJIQzYwWY46g+lczqnw+1a9tVjjuLIEOG+Z39D/ALPvWfs1c6frMmrM8jhmjtEMc7bGJ3AYzx+FK2q2SnBm5/3T/hXaX/wg8QTzq6XmmABccyyep/2KzpPgt4jaQkXulf8Af2T/AOIptMSlHuee32oWstnIiS5Y4wNp9R7ViSurKAD3rY1Hwze6fYSXUstuyJjIRiTyQPT3rBrCTfU7aajbQM0tJilFSaHa2evaZFdI73OFGcny29PpWp/wlei/8/v/AJCf/CvNqTFclTB06ju2xWPSv+Er0T/n9/8AIT/4Uf8ACV6L/wA/v/kJ/wDCvNcUYrP+z6Xd/wBfIdj0eXxTozRkC85/65P/AIVWbxJpJH/H3/5Df/CuAoqo4GmurKTsd6fEelf8/X/kNv8ACsu71axlundJ8qcYOxvT6Vy+KUVtDDxg7oG7iUlLikxW5JNC6qhBPetuyv7aO0RHlwwzkbT6mufFdHpfhS/1PToryGW2WOTOA7MDwSOw9quNzKoopXZt/wBp2bcCbJ/3T/hUcrreKI4DvYHcR04/GuqT4LeI1cE3ulf9/ZP/AIitDT/hB4ggnZ3vNMIK44lk9R/sVskzjco9GebXPhjWNRkE1pZ+ZGBtJ81Bz17n3FPi+Gvi64jEsWk7kboftMQ/9mr23S/h9q1lbNHJcWRJct8rv6D/AGfauosNCurWyjheSEsuclScdSfSj2aY1iZLRHH+HfCet2OvW1zc2WyFN25vNQ4ypHQH1NeiWkEkcpLrgbcdRVsKQadWhzN3ExS0UUCCiiigAooooAKKKKAGMgJ700wqT1NS0UAfOPjCyji8K3rqz5GzqR/fWvOtIsIr+7eKVnChC3ykZzkf417H8QbO3i8D6i6R4YeVg5P/AD0SvJvDX/IRk/64n+YrjxLcU2j0cN8DOh0/wVpt3A0kk92CGx8rr6D/AGat/wDCAaV/z8Xn/fa//E12XhCxtrnSZXmj3MJyAdxHG1fSug/six/54f8Aj7f418niM1nTqON3odcYtq55b/wgGlf8/F5/32v/AMTR/wAIBpX/AD8Xn/fa/wDxNep/2PYf88P/AB9v8aP7Isf+eH/j7f41h/bM+7/ArkPLP+EA0r/n4vP++1/+Jo/4QDSv+fi8/wC+1/8Aia9T/six/wCeH/j7f40f2RY/88P/AB9v8aP7Zn3f4ByHlT+AdKVCRcXn/fa//E1XfwTpqDInu/8Avtf/AImvWbjSLEQMRB6fxt6/Ws2bS7PYP3Pf+8f8a3pZrOXVmkKVzzX/AIQzTv8Antdf99L/APE0n/CG6d/z2uv++l/+Jr0X+zLP/nj/AOPH/Gj+y7P/AJ4/+PH/ABrf+0Zd2a/Vzzr/AIQ3Tv8Antdf99L/APE1V1DwtY2sCuktwSWx8zL6H2r0/wDsuz/54/8Ajx/xrA8XWcFtpMTwx7WM4Gck8bW9a2o46c5pXZE6PLFs8r1C1S0uFjjLEFd3zfU16v4Hs45fB9g7MwJ8zof+mjV5drBzdpn/AJ5j+Zr234cWcEvgHTHePLHzcnJ/56vX0OH13PNxT9z5nsIjXPU05UCnIzTgKWuo80KKKKACiiigAooooAKKKKACiiigAooooAKKKKAOC+JWnXd58P8AU4IIt8reVhdwGcSoe5r5y1HRdQ0u3We9t/KjZwgberc4J7E+hr608RWUl9oVzbRMgd9uCxOOGB/pXh/xN8O3dj4bt5ZZICpvFX5WOfuP7e1Z1I3R00J2aiZXgTxLpGk6HNBfXflStcs4Xy3bjaozwD6Guzh8e+GViUHUuf8ArhJ/8TXhf/Ht8j8k88U4XSAYw1eDiMppVpuUm9fT/I9FSa2Pdf8AhP8Awx/0E/8AyBL/APE0f8J/4Y/6Cf8A5Ak/+Jrwv7Sno1H2lPRq5/7Do93+H+Q+eR7r/wAJ94Y/6Cf/AJAk/wDiaT/hP/DH/QT/APIEn/xNeGfaU9GpDdJno1H9h0O7/D/IOeR7fcePPDTwMq6lknH/ACwk9f8Adqg/jXw8V41D/wAgyf8AxNePG6Qjo1IbhD2atIZPRjs3+H+RcK0kj17/AITPw/8A8/8A/wCQZP8A4mj/AITPw/8A8/8A/wCQZP8A4mvIPPX0NHnr6GtP7Lpd3+H+Rf1iR63P4x0FoWAv+f8ArjJ/8TXJ+MNc07U9JihtLjzJFnDkbGHG1h3HuK5A3CEYw1LFE12xjjIBAz81b0cBTpyUk2RKs2tTa0HRtQ1Gxea0t/MjWQqTvUc4B7n3FfRvw6sbm08B6bBPHskXzcruBxmVz2rzb4YeHLy68NXLpJAALxh8zH+4ntXtOg2kljotvbSlS6bslTxyxP8AWvYgtDya87yaNOlooqznCiiigAooooAKKKKACiiigAooooAKKKKACiiigBk0YliKNnB9K4vx94as9Y0KC3uJZ1RblXBjYA52sO4PrXbnpVW8s4LyERzpvQNuAyRz+H1pMadnc+TPHWh22g63Da2skzo9sshMpBOSzDsB6CuYxX0N4/8ACmiXOvQPNZbmFsoz5rjjc3oa8Q8T2Vvp3iK6tbWPy4U2bV3E4yik8nnqTXPONnc9KhVUko9TJA5pSK0tAtYb3W7e3uE3xPu3LkjOFJ7fSvRtJ8HaBdXTJNYblCEgedIOcj0auLE4uFD4kzfc8moxmvcx8PvC5H/IL/8AJiX/AOKqvL4D8NLIQNNwB/03k/8Aiq4VnNBu1n+H+ZaptnieKcBXr3/CE+Hv+gf/AORpP/iqQ+CvDwH/ACD/APyNJ/8AFVt/adHs/wAP8zT2EjyPFNPBr0XVfDOkW10qQ2m1SgOPMc85Pqa4jV7eK21SaGFdsa7cDJP8IPeuulXjV1iZSi4vUoAc11vw+0S213Xp7W6eVES1aQGIgHIZR3B9azPCthbal4ktLS7j8yCTfuXcRnCMRyOeoFe5+AvCeiWWuzyW9lsc2zKT5rnjcvqfauqnG+pyV6qiuU6jwN4dtNG0Sa3t5J2RrhnJkYE52qOwHpXWRxiNAozgetRWttDaRGOBNqk5IyTz+NWK6Tz27u4UUUUCCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAjdSTwK4rXdB1O81m4ngtt8bbcN5ijOFA7mu5phUk0Bex8hX3gjxFp1nJd3Wn+XBHjc3nRnGSAOA2epFQaM66ZePPeHyo2jKA/e5yD2z6GvojxL4N1HU/D91ZwzWqySbMF2YDhwey+1eVa/wDCvXLSxSSS604gyhflkf0P+xXNVoqUXE76eI5viJtE8XaHa2bpNfbWMhIHlOeMD0Wt2DxNpE8KyR3e5G6Hy3H9K8k1TRLnRblba5eJ3ZBIDGSRgkjuB6VYs9Zt7O0S3kSUumclQMcnPr7141bK4Xur3+X+R30q1tj0+88S6RFau73eFGMny39fpXMa34n0e7skjgvNzCQEjynHGD6iuXu9WgvbV7eNJA74wWAxwc+vtUGleH7vWbpra2khV1QyEyMQMAgdgfWtMPl0Y66jqYjuJqCNqM6zWg8yNV2k9Ock9/qKv2PgbxHqNnHdWuneZC+drefGM4JB4LZ6g113h74Wa5c2EjpdacAJSOZH9B/sV6r4b8IahpmgW1nNNbNJHvyUZiOWJ7r7160KSSsedUxLT0J9E0PUbTV4J57fZGu7J3qcZUjsa7BFIPNOAwaWt7HCFFFFMAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAY8YdCpzg+lZupaDa6pbLBPJMqq4cFCAc4I7g+tatGKAPNNe+E+hanfJNNd6krLGEASRAMZJ7ofWuK1P4VaFbahLEl3qJVcYzImegP9yvfHgjkOWXJ6daoXGhabcTtLLbbnbGTvYdvrUuKZrGrJdTxXTPhToU+oxRtd6iFbPSRPQ/7FdroXwq0PS7154LvUWZoyhDyIRjIPZB6V20Gh6dbzLLFb7XXod7H+tXkhjQ5VcH60KKQpVZS3Zn6boltplu0MLysrOXJcgnOAOw9q0kQIgUZwPWnYoqjMKKKKACiiigAooooAKKKKACiiigAooooA//ZAP/iArBJQ0NfUFJPRklMRQABAQAAAqBsY21zBDAAAG1udHJSR0IgWFlaIAfkAAUAEwAOAAkABWFjc3BNU0ZUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD21gABAAAAANMtbGNtcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWRlc2MAAAEgAAAAQGNwcnQAAAFgAAAANnd0cHQAAAGYAAAAFGNoYWQAAAGsAAAALHJYWVoAAAHYAAAAFGJYWVoAAAHsAAAAFGdYWVoAAAIAAAAAFHJUUkMAAAIUAAAAIGdUUkMAAAIUAAAAIGJUUkMAAAIUAAAAIGNocm0AAAI0AAAAJGRtbmQAAAJYAAAAJGRtZGQAAAJ8AAAAJG1sdWMAAAAAAAAAAQAAAAxlblVTAAAAJAAAABwARwBJAE0AUAAgAGIAdQBpAGwAdAAtAGkAbgAgAHMAUgBHAEJtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABoAAAAcAFAAdQBiAGwAaQBjACAARABvAG0AYQBpAG4AAFhZWiAAAAAAAAD21gABAAAAANMtc2YzMgAAAAAAAQxCAAAF3v//8yUAAAeTAAD9kP//+6H///2iAAAD3AAAwG5YWVogAAAAAAAAb6AAADj1AAADkFhZWiAAAAAAAAAknwAAD4QAALbEWFlaIAAAAAAAAGKXAAC3hwAAGNlwYXJhAAAAAAADAAAAAmZmAADypwAADVkAABPQAAAKW2Nocm0AAAAAAAMAAAAAo9cAAFR8AABMzQAAmZoAACZnAAAPXG1sdWMAAAAAAAAAAQAAAAxlblVTAAAACAAAABwARwBJAE0AUG1sdWMAAAAAAAAAAQAAAAxlblVTAAAACAAAABwAcwBSAEcAQv/bAEMAEAsMDgwKEA4NDhIREBMYKBoYFhYYMSMlHSg6Mz08OTM4N0BIXE5ARFdFNzhQbVFXX2JnaGc+TXF5cGR4XGVnY//bAEMBERISGBUYLxoaL2NCOEJjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY//+ABRDcmVhdGVkIHdpdGggR0lNUAD/wgARCAAoACgDAREAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAwQFAgb/xAAYAQADAQEAAAAAAAAAAAAAAAAAAQMCBP/aAAwDAQACEAMQAAAB6ABBoMgUFkILUHNL+pvPIhsogYpf3NdhmosqD56b6cW6SOCicidK9Jttf//EAB0QAAICAgMBAAAAAAAAAAAAAAIDAAEEERITFCH/2gAIAQEAAQUCjDpYcq4gdMCE3RZTHdRXUxmO6hbskQvg6D0V9F8NQneQu+66LWMu7aChC5kIp4eUtoTSAn//xAAbEQABBQEBAAAAAAAAAAAAAAABAAIQESAhEv/aAAgBAwEBPwHQqCBjtYbD+SDS9BE3H//EAB0RAAEEAgMAAAAAAAAAAAAAAAEAAhEgEBIDMVL/2gAIAQIBAT8BscCmwmKcji1AjymGaaunvP8A/8QAJBAAAgEDAwQDAQAAAAAAAAAAAREAAhIxEBMhA0FCUSIjNFL/2gAIAQEABj8ChqOBLnxBUMHS2ik11QjbTyW5w4BttYLUtqpNNUrHlcXOTNyz6/c4lA8rgo8H2JaeqUmLp+imWjqlJ/GPJ9nRHPYy3aD/AKfEQz3On//EACEQAAEEAQQDAQAAAAAAAAAAAAEAESExQRBRcaFhgcGx/9oACAEBAAE/IU4HkZYRB38J4PA+kbBYEAclUZ0KFBiOVVnYoU5lQNHgqrrCb56ROETLKOp9+EYdMEKTdyfXSBDcNHYqC6YN1APDaFkuwkyNgctmc6UQD0L9yKXyL2af/9oADAMBAAIAAwAAABAUUP8AbuGBOBGuH//EABsRAQEBAAMBAQAAAAAAAAAAAAEAERAhMWFx/9oACAEDAQE/EINc4THOAjr2y2eyTHvVkPsQpZSP2AJd4RbdX2Rbx//EABwRAAMBAAIDAAAAAAAAAAAAAAABESEQMSBBYf/aAAgBAgEBPxDxoxo2FNH1p73RdcQQVKlFsYtanLVF8gSnH//EACIQAQEAAgEDBAMAAAAAAAAAAAERACExQVFxEGGR0YHB8P/aAAgBAQABPxDBIYWNecSt3O1pbhGEaDGelApC0p4po8c5tXoBHvONfGKIwRL07ZVZECL09P1ks7K0ROYafHOOSgg8tavGmGXBuugyNzTqPifzrhpJLTdxgUISGwGrxthslREztTk9nDa64EtidDNw4Db7YxgXFhsDqYIZcTc7V4PY9Ajc8Dl9YrEOHRO8t/GXrz0OX16f/9k="/><a
class="footer-link" href="mischianti.org">www.mischianti.org</a></div>
<div class="tile-container">
<div class="title-image"></div>
<h1>OTA Update</h1>
</div>
<div class="container">
<form enctype="multipart/form-data" class="form-container" id="upload_form" method="post">
<div id="switch-container">
<button class="button-o left selected" id="firmware-button" type="button">Firmware</button>
<button class="button-o right" id="filesystem-button" type="button">FileSystem</button>
</div>
<input accept='.bin,.bin.gz' class="input-file" id="file1" name='firmware' type="file"><br>
<div class="progress">
<span class="progress-bar" id="progressBar" style="width: 0%"></span>
</div>
<div class="additional-info">
<h3 id="status">Firmware upload</h3>
<p id="loaded_n_total"></p>
</div>
<hr/>
<button id="button-send" class="button-send" type="submit" disabled>Upload</button>
</form>
<script type="application/javascript">
function stringToBoolean(string){
switch(string.toLowerCase().trim()){
case "true": case "yes": case "1": return true;
case "false": case "no": case "0": case null: return false;
default: return Boolean(string);
}
}
const urlParams = new URLSearchParams(window.location.search);
const onlyFirmware = urlParams.get('onlyFirmware');
if (onlyFirmware && stringToBoolean(onlyFirmware)===true){
_('switch-container').style.display = 'none';
}
function disableAll() {
document.getElementById("overlay").style.display = "block";
}
function enableAll() {
document.getElementById("overlay").style.display = "none";
}
function _(el) {
return document.getElementById(el);
}
function uploadFile() {
var file = _("file1").files[0];
// alert(file.name+" | "+file.size+" | "+file.type);
var formdata = new FormData();
formdata.append(_("file1").name, file, file.name);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("loadstart", startHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "/update"); // http://www.developphp.com/video/JavaScript/File-Upload-Progress-Bar-Meter-Tutorial-Ajax-PHP
//use file_upload_parser.php from above url
ajax.setRequestHeader('Access-Control-Allow-Headers', '*');
ajax.setRequestHeader('Access-Control-Allow-Origin', '*');
ajax.send(formdata);
}
function progressHandler(event) {
_("loaded_n_total").innerHTML = "Uploaded " + event.loaded + " bytes of " + event.total;
var percent = Math.round((event.loaded / event.total) * 100);
_("progressBar").style = 'width: ' + percent + '%';
_("status").innerHTML = percent + "% uploaded... please wait";
}
function completeHandler(event) {
enableAll();
if (event.target.responseText.indexOf('error')>=0){
_("status").innerHTML = event.target.responseText;
}else {
_("status").innerHTML = 'Upload Success!'; //event.target.responseText;
}
_("progressBar").value = 0; //wil clear progress bar after successful upload
}
function startHandler(event) {
disableAll();
}
function errorHandler(event) {
enableAll();
_("status").innerHTML = "Upload Failed";
}
function abortHandler(event) {
enableAll();
_("status").innerHTML = "Upload Aborted";
}
_('upload_form').addEventListener('submit', (e) => {
e.preventDefault();
uploadFile();
});
_('firmware-button').addEventListener('click',
function (e) {
e.target.classList.add('selected');
_('filesystem-button').classList.remove('selected');
_("file1").name = 'firmware';
}
)
_('filesystem-button').addEventListener('click',
function (e) {
e.target.classList.add('selected');
_('firmware-button').classList.remove('selected');
_("file1").name = 'filesystem';
}
)
_('file1').addEventListener('change', function(e){
var file = _("file1").files[0];
if (file && file.name){
_('button-send').disabled = false;
}else{
_('button-send').disabled = true;
}
_('status').innerHTML = "Firmware Upload!";
_("loaded_n_total").innerHTML = "";
});
</script>
</div>
</body>
</html>
Black white
And here the code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload OTA data</title>
<style type="text/css">
* {
box-sizing: border-box;
}
body {
@import url("https://fonts.googleapis.com/css?family=Roboto:400,400i,700");
font-family: Roboto, sans-serif;
background: #555;
text-align: center;
min-width: 360px;
}
.button-send {
width: 100%;
border: 0;
background: #FFF;
line-height: 23px;
font-weight: bold;
color: #555;
border-radius: 4px;
box-shadow: inset 0 -2px 3px rgba(0,0,0,.4), 0 2px 5px rgba(0,0,0,0.5);
}
.button-send:hover {
background-color: #dedede;
}
.button-send:active {
background-color: #dedede;
box-shadow: 1px 1px #666;
transform: translateY(4px);
}
.button-send:disabled {
background-color: #9c9c9c;
}
.container {
padding-top: 80px;
display: flex;
justify-content: center;
}
.form-container {
min-width: 380px;
}
progress {
display: block; /* default: inline-block */
width: 100%;
margin: 2em auto;
padding: 4px;
border: 0 none;
background: #444;
border-radius: 14px;
box-shadow: inset 0px 1px 1px rgba(0,0,0,0.5), 0px 1px 0px rgba(255,255,255,0.2);
}
progress::-moz-progress-bar {
border-radius: 12px;
background: #FFF;
box-shadow: inset 0 -2px 4px rgba(0,0,0,0.4), 0 2px 5px 0px rgba(0,0,0,0.3);
}
/* webkit */
@media screen and (-webkit-min-device-pixel-ratio:0) {
progress {
height: 25px;
}
}
progress::-webkit-progress-bar {
background: transparent;
}
progress::-webkit-progress-value {
border-radius: 12px;
background: #FFF;
box-shadow: inset 0 -2px 4px rgba(0,0,0,0.4), 0 2px 5px 0px rgba(0,0,0,0.3);
}
/* environnement styles */
h1 {
color: #eee;
font: 50px Helvetica, Arial, sans-serif;
text-shadow: 0px 1px black;
text-align: center;
-webkit-font-smoothing: antialiased;
}
.input-file {
width: 100%;
border: 0px transparent;
padding: 4px 4px 4px 4px;
margin-top: 20px;
margin-bottom: 0px;
border-radius: 7px;
background-color: rgb(255 255 255);
}
.additional-info {
color: white;
height: 67px;
}
@-webkit-keyframes progress-animation {
0% {
background-position: 100%;
}
100% {
background-position: 0;
}
}
@keyframes progress-animation {
0% {
background-position: 100%;
}
100% {
background-position: 0;
}
}
.tile-container {
display: flex;
justify-content: center;
}
.title-image {
background-image: url(data:image/png;base64,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);
background-repeat: no-repeat;
background-position: center;
background-size: 40px;
width: 40px;
margin-right: 20px;
}
.footer-desc {
position: fixed;
display: flex;
bottom: 20px;
right: 20px;
align-items: center;
}
.footer-link {
font-size: x-small;
color: black;
text-decoration: none;
padding-left: 10px;
}
.button-o {
cursor: pointer;
height: 25px;
font-size: 15px;
background: none;
outline: none;
border: 1px solid rgba(0, 0, 0, 0.35);
width: 50%;
color: white;
background: black;
}
.button-o.selected {
background-color: white;
color: black;
}
.button-o.left {
border-radius: 14px 0px 0px 14px;
margin-right: -3px;
}
.button-o.right {
border-radius: 0px 14px 14px 0px;
margin-left: -3px;
}
#overlay {
position: fixed; /* Sit on top of the page content */
display: none; /* Hidden by default */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.06); /* Black background with opacity */
z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
cursor: pointer; /* Add a pointer on hover */
}
</style>
</head>
<body>
<div id="overlay"></div>
<div class="footer-desc"><img
src="data:image/png;base64,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"/><a
class="footer-link" href="mischianti.org">www.mischianti.org</a></div>
<div class="tile-container">
<div class="title-image"></div>
<h1>OTA Update</h1>
</div>
<div class="container">
<form enctype="multipart/form-data" class="form-container" id="upload_form" method="post">
<div id="switch-container">
<button class="button-o left selected" id="firmware-button" type="button">Firmware</button>
<button class="button-o right" id="filesystem-button" type="button">FileSystem</button>
</div>
<input accept='.bin,.bin.gz' class="input-file" id="file1" name='firmware' type="file"><br>
<progress id="progressBar" max="100" value="0"></progress>
<div class="additional-info">
<h3 id="status">Firmware upload</h3>
<p id="loaded_n_total"></p>
</div>
<hr/>
<button id="button-send" class="button-send" type="submit" disabled>Upload</button>
</form>
<script type="application/javascript">
function stringToBoolean(string){
switch(string.toLowerCase().trim()){
case "true": case "yes": case "1": return true;
case "false": case "no": case "0": case null: return false;
default: return Boolean(string);
}
}
const urlParams = new URLSearchParams(window.location.search);
const onlyFirmware = urlParams.get('onlyFirmware');
if (onlyFirmware && stringToBoolean(onlyFirmware)===true){
_('switch-container').style.display = 'none';
}
function disableAll() {
document.getElementById("overlay").style.display = "block";
}
function enableAll() {
document.getElementById("overlay").style.display = "none";
}
function _(el) {
return document.getElementById(el);
}
function uploadFile() {
var file = _("file1").files[0];
// alert(file.name+" | "+file.size+" | "+file.type);
var formdata = new FormData();
formdata.append(_("file1").name, file, file.name);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("loadstart", startHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "/update"); // http://www.developphp.com/video/JavaScript/File-Upload-Progress-Bar-Meter-Tutorial-Ajax-PHP
//use file_upload_parser.php from above url
ajax.setRequestHeader('Access-Control-Allow-Headers', '*');
ajax.setRequestHeader('Access-Control-Allow-Origin', '*');
ajax.send(formdata);
}
function progressHandler(event) {
_("loaded_n_total").innerHTML = "Uploaded " + event.loaded + " bytes of " + event.total;
var percent = Math.round((event.loaded / event.total) * 100);
_("progressBar").value = percent;
_("status").innerHTML = percent + "% uploaded... please wait";
}
function completeHandler(event) {
enableAll();
_("status").innerHTML = 'Upload Success!'; //event.target.responseText;
_("progressBar").value = 0; //wil clear progress bar after successful upload
}
function startHandler(event) {
disableAll();
}
function errorHandler(event) {
enableAll();
_("status").innerHTML = "Upload Failed";
}
function abortHandler(event) {
enableAll();
_("status").innerHTML = "Upload Aborted";
}
_('upload_form').addEventListener('submit', (e) => {
e.preventDefault();
uploadFile();
});
_('firmware-button').addEventListener('click',
function (e) {
e.target.classList.add('selected');
_('filesystem-button').classList.remove('selected');
_("file1").name = 'firmware';
}
)
_('filesystem-button').addEventListener('click',
function (e) {
e.target.classList.add('selected');
_('firmware-button').classList.remove('selected');
_("file1").name = 'filesystem';
}
)
_('file1').addEventListener('change', function(e){
var file = _("file1").files[0];
if (file && file.name){
_('button-send').disabled = false;
_("progressBar").value = 0; //wil clear progress bar after successful upload
}else{
_('button-send').disabled = true;
}
_('status').innerHTML = "Firmware Upload!";
_("loaded_n_total").innerHTML = "";
});
</script>
</div>
</body>
</html>
Code info
The code is quite simple, I use standard XMLHttpRequest to execute POST and I change the target (firmware or filesystem).
The form remain very simple.
<form enctype="multipart/form-data" class="form-container" id="upload_form" method="post">
<div id="switch-container">
<button class="button-o left selected" id="firmware-button" type="button">Firmware</button>
<button class="button-o right" id="filesystem-button" type="button">FileSystem</button>
</div>
<input accept='.bin,.bin.gz' class="input-file" id="file1" name='firmware' type="file"><br>
<progress id="progressBar" max="100" value="0"></progress>
<div class="additional-info">
<h3 id="status">Firmware upload</h3>
<p id="loaded_n_total"></p>
</div>
<hr/>
<button id="button-send" class="button-send" type="submit" disabled>Upload</button>
</form>
You can see that there isn’t the name of the input “filesystem” this because I manage It via JavaScript. The submit is stopped with this listener.
_('upload_form').addEventListener('submit', (e) => {
e.preventDefault();
uploadFile();
});
Then the uploadFile function is called.
function uploadFile() {
var file = _("file1").files[0];
var formdata = new FormData();
formdata.append(_("file1").name, file, file.name);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("loadstart", startHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "/update");
// Enable CORS for testing
ajax.setRequestHeader('Access-Control-Allow-Headers', '*');
ajax.setRequestHeader('Access-Control-Allow-Origin', '*');
ajax.send(formdata);
}
I create new FormData and add only the file, than with the handlers
- “progress”: I manage scrollbar;
- “load”: manage the result;
- “loadstart”: I put an overlay to prevent clicking;
- “error” and “abort”: to manage errors.
Manage custom OTA page
We have 2 option to add this page to the sketch fully explained on this article “Web Server with esp8266 and esp32: byte array, gzipped pages and SPIFFS“, you can add it to the filesystem or as a bytearray. I use gzipped for all methods, you can check the simple version on linked article.
Add the page to filesystem
To upload a content to the filesystem you must install the relative plugin, select one of this
WeMos D1 mini (esp8266), integrated SPIFFS Filesystem (deprecated)
WeMos D1 mini (esp8266), integrated LittleFS Filesystem (reccomended)
So we are going to add data folder to the sketch and we put the gzipped page we want, now i put
index_color.html.gz
index_black_white.html.gz
for testing purpose. After that operation you can use the plugin like usual to upload the pages.
Sketch with LittleFS gzipped custom OTA page
Now we are going to change the WebUpdater.ino
file.
/*
* Custom OTA page from LittleFS file system
*
* Renzo Mischianti <www.mischianti.org>
*
* www.mischianti.org
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#include <LittleFS.h>
#ifndef STASSID
#define STASSID "reef-casa-sopra"
#define STAPSK "aabbccdd77"
#endif
const char* host = "esp8266-webupdate";
const char* ssid = STASSID;
const char* password = STAPSK;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += httpServer.uri();
message += "\nMethod: ";
message += (httpServer.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += httpServer.args();
message += "\n";
for (uint8_t i = 0; i < httpServer.args(); i++) {
message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
}
httpServer.send(404, "text/plain", message);
}
bool loadFromFS(String path, String dataType) {
Serial.print("Requested page -> ");
Serial.println(path);
if (LittleFS.exists(path)){
File dataFile = LittleFS.open(path, "r");
if (!dataFile) {
handleNotFound();
return false;
}
if (httpServer.streamFile(dataFile, dataType) != dataFile.size()) {
Serial.println("Sent less data than expected!");
}else{
Serial.println("Page served!");
}
dataFile.close();
}else{
handleNotFound();
return false;
}
return true;
}
void handleRoot() {
// loadFromFS("/index_color.html.gz", "text/html");
loadFromFS("/index_black_white.html.gz", "text/html");
}
void setup(void) {
Serial.begin(115200);
Serial.println();
Serial.println("Booting Sketch...");
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
WiFi.begin(ssid, password);
Serial.println("WiFi failed, retrying.");
}
Serial.print(F("Inizializing FS..."));
if (LittleFS.begin()){
Serial.println(F("done."));
}else{
Serial.println(F("fail."));
}
MDNS.begin(host);
// handler for the /update form page
httpServer.on("/update", HTTP_GET, handleRoot);
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
Serial.printf("HTTPUpdateServer modified ready! Open http://%s.local/update in your browser\n", host);
}
void loop(void) {
httpServer.handleClient();
MDNS.update();
}
You can see the code explained in the linked article, and with
httpServer.on("/update", HTTP_GET, handleRoot);
I override the standard page on /update
GET, the handle
bool loadFromFS(String path, String dataType) {
Serial.print("Requested page -> ");
Serial.println(path);
if (LittleFS.exists(path)){
File dataFile = LittleFS.open(path, "r");
if (!dataFile) {
handleNotFound();
return false;
}
if (httpServer.streamFile(dataFile, dataType) != dataFile.size()) {
Serial.println("Sent less data than expected!");
}else{
Serial.println("Page served!");
}
dataFile.close();
}else{
handleNotFound();
return false;
}
return true;
}
void handleRoot() {
// loadFromFS("/index_color.html.gz", "text/html");
loadFromFS("/index_black_white.html.gz", "text/html");
}
read the selected page in handleRoot from LittleFS and return the stream.
Add custom page as bytearray
Get ready to use page
In the article linked before is explained in deep the bytearray page management, now in the repository of the pages you can grab the page with html extension,
https://github.com/xreef/ArduinoOTA_reusable_custom_web_page/minified
and put It in the bytearray converter by select the correct file (like index_color.html), and take the generated gzipped filearray.
Sketch with bytearray gzipped custom OTA page
Then we can go to modify the WebUpdater.ino
to response the selected page.
/*
* Custom OTA page in bytearray format
*
* Renzo Mischianti <www.mischianti.org>
*
* www.mischianti.org
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#ifndef STASSID
#define STASSID "<YOUR-SSID>"
#define STAPSK "<YOUR-PASSWD>"
#endif
const char* host = "esp8266-webupdate";
const char* ssid = STASSID;
const char* password = STAPSK;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
//File: index_color.html.gz, Size: 33264
#define index_color_html_gz_len 33264
const uint8_t index_color_html_gz[] PROGMEM = {
0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xB4, 0xBB, 0xE7, 0x92, 0xF4, 0xD8,
0x75, 0x2D, 0xF8, 0x2A, 0x3D, 0x64, 0x28, 0x42, 0xBA, 0x60, 0x13, 0xDE, 0x75, 0x4B, 0x1A, 0xC1,
0xBB, 0x84, 0x37, 0x09, 0xE0, 0x1F, 0xBC, 0xF7, 0x48, 0x98, 0x64, 0xF0, 0xDD, 0x07, 0x5F, 0x93,
[...]
};
void setup(void) {
Serial.begin(115200);
Serial.println();
Serial.println("Booting Sketch...");
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
WiFi.begin(ssid, password);
Serial.println("WiFi failed, retrying.");
}
MDNS.begin(host);
httpServer.on("/update", HTTP_GET, [&](){
httpServer.sendHeader(F("Content-Encoding"), F("gzip"));
httpServer.send_P(200, "text/html", (const char*)index_color_html_gz, (int)index_color_html_gz_len);
});
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
Serial.printf("HTTPUpdateServer modified ready! Open http://%s.local/update in your browser\n", host);
}
void loop(void) {
httpServer.handleClient();
MDNS.update();
}
You must add the complete bytearray of the page, in the code there is only a little part
the core code is very simple,
httpServer.on("/update", HTTP_GET, [&](){
httpServer.sendHeader(F("Content-Encoding"), F("gzip"));
httpServer.send_P(200, "text/html", (const char*)index_color_html_gz, (int)index_color_html_gz_len);
});
the send_P stream all the bytearray with Content-Encoding gzip, you can use the non gzipped bytearray but the size grow.
Thanks
- Firmware management
- OTA update with Arduino IDE
- OTA update with Web Browser
- Self OTA uptate from HTTP server
- Non standard Firmware update
I couldn’t get it to access page when using:
http://esp8266-webupdate.local/update
but it did work when using
192.168.1.xxx/update.
I used your example file from github.
Hi James,
as described on
esp8266 OTA update with Web Browser: firmware, filesystem and authentication – 1
you need an mDNS service on your PC or your router block that service.
Bye Renzo
How could you have the user set their own SSID and network password maybe in a text file without having to edit Arduino code and recompile? Would it be possible to do it via web browser interface?
Hi Steve,
yes It’s possible and not so difficult. In the project of Aurora Inverter Monitor I implement It.
I use a web interface to write a json file and store It in the internal flash, and ad reboot I check It, If exist I use that to configure the WiFi.
ABB Aurora Web Inverter Monitor (WIM): upload the sketch and front end – 9
Bye Renzo
Hello Renzo,
there seems to be a problem with your sketch. You change the original handle. The upload didn’t work for me. After changing the handle from “update” to “upload” and not overwriting the original handle, the upload worked. However, it immediately showed me 100% and after the upload time “Upload success”. But then nothing happens anymore, but the ESP boots properly.
I wrote a completely different update page for myself and call it up with “upload”. In the form I have set “action” to “update”. Then the page for waiting for the boot is called up automatically after the upload and then forwarded to the main page.
I downloaded your source code from Github. So I think that a typo is excluded.
greeting
Frank
Hi Frank,
I re-test all the process described in the tutorial with an WeMos D1 and the last core 3.1.2 and It’s work correctly for me.
Bye Renzo