After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 228 KiB |
After Width: | Height: | Size: 144 KiB |
After Width: | Height: | Size: 217 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 775 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 252 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 204 KiB |
@ -0,0 +1,916 @@ |
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!doctype html> |
||||||
|
<html lang="en" class="no-js"> |
||||||
|
<head> |
||||||
|
|
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1"> |
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge"> |
||||||
|
|
||||||
|
<meta name="description" content="ESP8266/ESP32 WLAN configuration at run time with web interface"> |
||||||
|
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://Hieromon.github.io/AutoConnect/otaupdate.html"> |
||||||
|
|
||||||
|
|
||||||
|
<meta name="author" content="Hieromon Ikasamo"> |
||||||
|
|
||||||
|
|
||||||
|
<meta name="lang:clipboard.copy" content="Copy to clipboard"> |
||||||
|
|
||||||
|
<meta name="lang:clipboard.copied" content="Copied to clipboard"> |
||||||
|
|
||||||
|
<meta name="lang:search.language" content="en"> |
||||||
|
|
||||||
|
<meta name="lang:search.pipeline.stopwords" content="True"> |
||||||
|
|
||||||
|
<meta name="lang:search.pipeline.trimmer" content="True"> |
||||||
|
|
||||||
|
<meta name="lang:search.result.none" content="No matching documents"> |
||||||
|
|
||||||
|
<meta name="lang:search.result.one" content="1 matching document"> |
||||||
|
|
||||||
|
<meta name="lang:search.result.other" content="# matching documents"> |
||||||
|
|
||||||
|
<meta name="lang:search.tokenizer" content="[\s\-]+"> |
||||||
|
|
||||||
|
<link rel="shortcut icon" href="assets/images/favicon.png"> |
||||||
|
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.4.0"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<title>OTA Updates - AutoConnect for ESP8266/ESP32</title> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="assets/stylesheets/application.0284f74d.css"> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="assets/stylesheets/application-palette.01803549.css"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#3f51b5"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="assets/javascripts/modernizr.74668098.js"></script> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin> |
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono&display=fallback"> |
||||||
|
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style> |
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="assets/fonts/material-icons.css"> |
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/paragraph.css"> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/extra.css"> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script> |
||||||
|
window.ga = window.ga || function() { |
||||||
|
(ga.q = ga.q || []).push(arguments) |
||||||
|
} |
||||||
|
ga.l = +new Date |
||||||
|
/* Setup integration and send page view */ |
||||||
|
ga("create", "UA-116150854-1", "auto") |
||||||
|
ga("set", "anonymizeIp", true) |
||||||
|
ga("send", "pageview") |
||||||
|
/* Register handler to log search on blur */ |
||||||
|
document.addEventListener("DOMContentLoaded", () => { |
||||||
|
if (document.forms.search) { |
||||||
|
var query = document.forms.search.query |
||||||
|
query.addEventListener("blur", function() { |
||||||
|
if (this.value) { |
||||||
|
var path = document.location.pathname; |
||||||
|
ga("send", "pageview", path + "?q=" + this.value) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
</script> |
||||||
|
<script async src="https://www.google-analytics.com/analytics.js"></script> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<body dir="ltr" data-md-color-primary="indigo" data-md-color-accent="indigo"> |
||||||
|
|
||||||
|
<svg class="md-svg"> |
||||||
|
<defs> |
||||||
|
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448" id="__github"><path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg> |
||||||
|
|
||||||
|
</defs> |
||||||
|
</svg> |
||||||
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> |
||||||
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> |
||||||
|
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label> |
||||||
|
|
||||||
|
<a href="#ota-updates-with-autoconnect" tabindex="1" class="md-skip"> |
||||||
|
Skip to content |
||||||
|
</a> |
||||||
|
|
||||||
|
|
||||||
|
<header class="md-header" data-md-component="header"> |
||||||
|
<nav class="md-header-nav md-grid"> |
||||||
|
<div class="md-flex"> |
||||||
|
<div class="md-flex__cell md-flex__cell--shrink"> |
||||||
|
<a href="https://Hieromon.github.io/AutoConnect/" title="AutoConnect for ESP8266/ESP32" class="md-header-nav__button md-logo"> |
||||||
|
|
||||||
|
<img src="images/arduino-logo.svg" width="24" height="24"> |
||||||
|
|
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<div class="md-flex__cell md-flex__cell--shrink"> |
||||||
|
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label> |
||||||
|
</div> |
||||||
|
<div class="md-flex__cell md-flex__cell--stretch"> |
||||||
|
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title"> |
||||||
|
|
||||||
|
<span class="md-header-nav__topic"> |
||||||
|
AutoConnect for ESP8266/ESP32 |
||||||
|
</span> |
||||||
|
<span class="md-header-nav__topic"> |
||||||
|
|
||||||
|
OTA Updates |
||||||
|
|
||||||
|
</span> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="md-flex__cell md-flex__cell--shrink"> |
||||||
|
|
||||||
|
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label> |
||||||
|
|
||||||
|
<div class="md-search" data-md-component="search" role="dialog"> |
||||||
|
<label class="md-search__overlay" for="__search"></label> |
||||||
|
<div class="md-search__inner" role="search"> |
||||||
|
<form class="md-search__form" name="search"> |
||||||
|
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active"> |
||||||
|
<label class="md-icon md-search__icon" for="__search"></label> |
||||||
|
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1"> |
||||||
|
 |
||||||
|
</button> |
||||||
|
</form> |
||||||
|
<div class="md-search__output"> |
||||||
|
<div class="md-search__scrollwrap" data-md-scrollfix> |
||||||
|
<div class="md-search-result" data-md-component="result"> |
||||||
|
<div class="md-search-result__meta"> |
||||||
|
Type to start searching |
||||||
|
</div> |
||||||
|
<ol class="md-search-result__list"></ol> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="md-flex__cell md-flex__cell--shrink"> |
||||||
|
<div class="md-header-nav__source"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href="https://github.com/Hieromon/AutoConnect" title="Go to repository" class="md-source" data-md-source="github"> |
||||||
|
|
||||||
|
<div class="md-source__icon"> |
||||||
|
<svg viewBox="0 0 24 24" width="24" height="24"> |
||||||
|
<use xlink:href="#__github" width="24" height="24"></use> |
||||||
|
</svg> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="md-source__repository"> |
||||||
|
Hieromon/AutoConnect |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</nav> |
||||||
|
</header> |
||||||
|
|
||||||
|
<div class="md-container"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<main class="md-main"> |
||||||
|
<div class="md-main__inner md-grid" data-md-component="container"> |
||||||
|
|
||||||
|
|
||||||
|
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation"> |
||||||
|
<div class="md-sidebar__scrollwrap"> |
||||||
|
<div class="md-sidebar__inner"> |
||||||
|
<nav class="md-nav md-nav--primary" data-md-level="0"> |
||||||
|
<label class="md-nav__title md-nav__title--site" for="__drawer"> |
||||||
|
<a href="https://Hieromon.github.io/AutoConnect/" title="AutoConnect for ESP8266/ESP32" class="md-nav__button md-logo"> |
||||||
|
|
||||||
|
<img src="images/arduino-logo.svg" width="48" height="48"> |
||||||
|
|
||||||
|
</a> |
||||||
|
AutoConnect for ESP8266/ESP32 |
||||||
|
</label> |
||||||
|
|
||||||
|
<div class="md-nav__source"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href="https://github.com/Hieromon/AutoConnect" title="Go to repository" class="md-source" data-md-source="github"> |
||||||
|
|
||||||
|
<div class="md-source__icon"> |
||||||
|
<svg viewBox="0 0 24 24" width="24" height="24"> |
||||||
|
<use xlink:href="#__github" width="24" height="24"></use> |
||||||
|
</svg> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="md-source__repository"> |
||||||
|
Hieromon/AutoConnect |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="index.html" title="Overview" class="md-nav__link"> |
||||||
|
Overview |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="gettingstarted.html" title="Getting started" class="md-nav__link"> |
||||||
|
Getting started |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="menu.html" title="AutoConnect menu" class="md-nav__link"> |
||||||
|
AutoConnect menu |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="basicusage.html" title="Basic usage" class="md-nav__link"> |
||||||
|
Basic usage |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="advancedusage.html" title="Advanced usage" class="md-nav__link"> |
||||||
|
Advanced usage |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item md-nav__item--nested"> |
||||||
|
|
||||||
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-6" type="checkbox" id="nav-6"> |
||||||
|
|
||||||
|
<label class="md-nav__link" for="nav-6"> |
||||||
|
Custom Web pages |
||||||
|
</label> |
||||||
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1"> |
||||||
|
<label class="md-nav__title" for="nav-6"> |
||||||
|
Custom Web pages |
||||||
|
</label> |
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="acintro.html" title="Custom Web pages with AutoConnect" class="md-nav__link"> |
||||||
|
Custom Web pages with AutoConnect |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="acelements.html" title="AutoConnectElements" class="md-nav__link"> |
||||||
|
AutoConnectElements |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="acjson.html" title="Custom Web pages with JSON" class="md-nav__link"> |
||||||
|
Custom Web pages with JSON |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="achandling.html" title="Handling the custom Web pages" class="md-nav__link"> |
||||||
|
Handling the custom Web pages |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
</nav> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item md-nav__item--active md-nav__item--nested"> |
||||||
|
|
||||||
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-7" type="checkbox" id="nav-7" checked> |
||||||
|
|
||||||
|
<label class="md-nav__link" for="nav-7"> |
||||||
|
OTA Updates |
||||||
|
</label> |
||||||
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1"> |
||||||
|
<label class="md-nav__title" for="nav-7"> |
||||||
|
OTA Updates |
||||||
|
</label> |
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item md-nav__item--active"> |
||||||
|
|
||||||
|
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc"> |
||||||
|
|
||||||
|
|
||||||
|
<label class="md-nav__link md-nav__link--active" for="__toc"> |
||||||
|
OTA Updates |
||||||
|
</label> |
||||||
|
|
||||||
|
<a href="otaupdate.html" title="OTA Updates" class="md-nav__link md-nav__link--active"> |
||||||
|
OTA Updates |
||||||
|
</a> |
||||||
|
|
||||||
|
|
||||||
|
<nav class="md-nav md-nav--secondary"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="#ota-updates-with-autoconnect" title="OTA Updates with AutoConnect" class="md-nav__link"> |
||||||
|
OTA Updates with AutoConnect |
||||||
|
</a> |
||||||
|
|
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
|
||||||
|
</nav> |
||||||
|
|
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="otabrowser.html" title="Using Web Browser" class="md-nav__link"> |
||||||
|
Using Web Browser |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="otaserver.html" title="Using Update Server" class="md-nav__link"> |
||||||
|
Using Update Server |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
</nav> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item md-nav__item--nested"> |
||||||
|
|
||||||
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-8" type="checkbox" id="nav-8"> |
||||||
|
|
||||||
|
<label class="md-nav__link" for="nav-8"> |
||||||
|
Library APIs |
||||||
|
</label> |
||||||
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1"> |
||||||
|
<label class="md-nav__title" for="nav-8"> |
||||||
|
Library APIs |
||||||
|
</label> |
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="api.html" title="AutoConnect API" class="md-nav__link"> |
||||||
|
AutoConnect API |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="apiaux.html" title="AutoConnectAux API" class="md-nav__link"> |
||||||
|
AutoConnectAux API |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="apiconfig.html" title="AutoConnectConfig API" class="md-nav__link"> |
||||||
|
AutoConnectConfig API |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="apielements.html" title="AutoConnectElements API" class="md-nav__link"> |
||||||
|
AutoConnectElements API |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="apiupdate.html" title="AutoConnectUpdate API" class="md-nav__link"> |
||||||
|
AutoConnectUpdate API |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="apiextra.html" title="Something extra" class="md-nav__link"> |
||||||
|
Something extra |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
</nav> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item md-nav__item--nested"> |
||||||
|
|
||||||
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9"> |
||||||
|
|
||||||
|
<label class="md-nav__link" for="nav-9"> |
||||||
|
Examples |
||||||
|
</label> |
||||||
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1"> |
||||||
|
<label class="md-nav__title" for="nav-9"> |
||||||
|
Examples |
||||||
|
</label> |
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="howtoembed.html" title="How to embed" class="md-nav__link"> |
||||||
|
How to embed |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="datatips.html" title="Tips for data conversion" class="md-nav__link"> |
||||||
|
Tips for data conversion |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="menuize.html" title="Attach the menu" class="md-nav__link"> |
||||||
|
Attach the menu |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="wojson.html" title="Custom Web pages w/o JSON" class="md-nav__link"> |
||||||
|
Custom Web pages w/o JSON |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
</nav> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item md-nav__item--nested"> |
||||||
|
|
||||||
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-10" type="checkbox" id="nav-10"> |
||||||
|
|
||||||
|
<label class="md-nav__link" for="nav-10"> |
||||||
|
Appendix |
||||||
|
</label> |
||||||
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1"> |
||||||
|
<label class="md-nav__title" for="nav-10"> |
||||||
|
Appendix |
||||||
|
</label> |
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="lsbegin.html" title="Inside AutoConnect::begin" class="md-nav__link"> |
||||||
|
Inside AutoConnect::begin |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="credit.html" title="Saved credentials access" class="md-nav__link"> |
||||||
|
Saved credentials access |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="acupload.html" title="File upload handler" class="md-nav__link"> |
||||||
|
File upload handler |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="colorized.html" title="Custom colorized" class="md-nav__link"> |
||||||
|
Custom colorized |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
</nav> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="faq.html" title="FAQ" class="md-nav__link"> |
||||||
|
FAQ |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="changelog.html" title="Change log" class="md-nav__link"> |
||||||
|
Change log |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="license.html" title="License" class="md-nav__link"> |
||||||
|
License |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
</nav> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc"> |
||||||
|
<div class="md-sidebar__scrollwrap"> |
||||||
|
<div class="md-sidebar__inner"> |
||||||
|
|
||||||
|
<nav class="md-nav md-nav--secondary"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<label class="md-nav__title" for="__toc">Table of contents</label> |
||||||
|
<ul class="md-nav__list" data-md-scrollfix> |
||||||
|
|
||||||
|
<li class="md-nav__item"> |
||||||
|
<a href="#ota-updates-with-autoconnect" title="OTA Updates with AutoConnect" class="md-nav__link"> |
||||||
|
OTA Updates with AutoConnect |
||||||
|
</a> |
||||||
|
|
||||||
|
</li> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul> |
||||||
|
|
||||||
|
</nav> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
<div class="md-content"> |
||||||
|
<article class="md-content__inner md-typeset"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h1>OTA Updates</h1> |
||||||
|
|
||||||
|
<h2 id="ota-updates-with-autoconnect">OTA Updates with AutoConnect<a class="headerlink" href="#ota-updates-with-autoconnect" title="Permanent link">¶</a></h2> |
||||||
|
<p>AutoConnect provides <strong>two type platforms</strong> for updating the binary sketch in the ESP8266 or ESP32 module via OTA. They correspond to the <a href="https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#web-browser">Web Browser Update</a> and <a href="https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#http-server">HTTP Server Update</a> whiches mentioned in the <a href="https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#ota-updates">ESP8266 Arduino Core documentation</a>.</p> |
||||||
|
<p><a href="otabrowser.html"><strong>The update behavior using a web browser</strong></a> as the client that supplies the binary sketch file for update follows the scenario assumed by the ESP8266 Arduino core. Therefore, the user sketch must meet the requirements described in the ESP8266 Arduino Core documentation, but you can easily embed the update feature that able to handle with the web browser by AutoConnect. All you need to do is that <a href="api.html#join">join</a> the <a href="apiaux.html">AutoConnectAux</a> with embedded <strong>ESP8266HTTPUpdateServer</strong><sup id="fnref:1"><a class="footnote-ref" href="#fn:1" rel="footnote">1</a></sup> of the core library to AutoConnect.</p> |
||||||
|
<p><img src="images/webupdatemodel.png" width="420" /></p> |
||||||
|
<div class="admonition caution"> |
||||||
|
<p class="admonition-title">It is for the only the same network</p> |
||||||
|
<p>This method can apply only if the client browser and the ESP module belong to the same network segment. It cannot work correctly across networks.</p> |
||||||
|
</div> |
||||||
|
<p><a href="otaserver.html"><strong>Another update method using an update server</strong></a> can be applied more broadly than using a web browser. This method can also update the ESP module over the Internet if you can secure the correct route and transparency between the ESP module and the update server. To configure this platform, you need to have an <a href="otaserver.html#update-server-for-the-autoconnectupdate-class">update server</a> along with using the <a href="apiupdate.html">AutoConnectUpdate</a> class in your sketch.</p> |
||||||
|
<p><img src="images/updatemodel.png" width="540" /></p> |
||||||
|
<div class="admonition info"> |
||||||
|
<p class="admonition-title">Security Disclaimer</p> |
||||||
|
<p>The security level of the OTA update platform provided by AutoConnect is very weak. No guarantees as to the level of security for your application by the AutoConnect OTA Update is implied.</p> |
||||||
|
</div> |
||||||
|
<div class="footnote"> |
||||||
|
<hr /> |
||||||
|
<ol> |
||||||
|
<li id="fn:1"> |
||||||
|
<p>The AutoConnect library provides an implementation of the <strong>HTTPUpdateServer</strong> class that ported from ESP8266HTTPUpdateServer class for ESP32 intention. It is contained the <strong>WebUpdate</strong> under the examples folder. <a class="footnote-backref" href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text">↩</a></p> |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</article> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</main> |
||||||
|
|
||||||
|
|
||||||
|
<footer class="md-footer"> |
||||||
|
|
||||||
|
<div class="md-footer-nav"> |
||||||
|
<nav class="md-footer-nav__inner md-grid"> |
||||||
|
|
||||||
|
<a href="achandling.html" title="Handling the custom Web pages" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev"> |
||||||
|
<div class="md-flex__cell md-flex__cell--shrink"> |
||||||
|
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i> |
||||||
|
</div> |
||||||
|
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||||
|
<span class="md-flex__ellipsis"> |
||||||
|
<span class="md-footer-nav__direction"> |
||||||
|
Previous |
||||||
|
</span> |
||||||
|
Handling the custom Web pages |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
|
||||||
|
|
||||||
|
<a href="otabrowser.html" title="Using Web Browser" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next"> |
||||||
|
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> |
||||||
|
<span class="md-flex__ellipsis"> |
||||||
|
<span class="md-footer-nav__direction"> |
||||||
|
Next |
||||||
|
</span> |
||||||
|
Using Web Browser |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<div class="md-flex__cell md-flex__cell--shrink"> |
||||||
|
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i> |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
|
||||||
|
</nav> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="md-footer-meta md-typeset"> |
||||||
|
<div class="md-footer-meta__inner md-grid"> |
||||||
|
<div class="md-footer-copyright"> |
||||||
|
|
||||||
|
<div class="md-footer-copyright__highlight"> |
||||||
|
Copyright © 2018-2019 Hieromon Ikasamo |
||||||
|
</div> |
||||||
|
|
||||||
|
powered by |
||||||
|
<a href="https://www.mkdocs.org">MkDocs</a> |
||||||
|
and |
||||||
|
<a href="https://squidfunk.github.io/mkdocs-material/"> |
||||||
|
Material for MkDocs</a> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="md-footer-social"> |
||||||
|
<link rel="stylesheet" href="assets/fonts/font-awesome.css"> |
||||||
|
|
||||||
|
<a href="https://github.com/Hieromon" class="md-footer-social__link fa fa-github"></a> |
||||||
|
|
||||||
|
<a href="https://twitter.com/hieromon" class="md-footer-social__link fa fa-twitter"></a> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</footer> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<script src="assets/javascripts/application.245445c6.js"></script> |
||||||
|
|
||||||
|
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script> |
||||||
|
|
||||||
|
<script src="js/gifffer.min.js"></script> |
||||||
|
|
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,328 @@ |
|||||||
|
/*
|
||||||
|
ConfigIP.ino, Example for the AutoConnect library. |
||||||
|
Copyright (c) 2019, Hieromon Ikasamo |
||||||
|
https://github.com/Hieromon/AutoConnect
|
||||||
|
This software is released under the MIT License. |
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
This sketch implements an example of enabling a custom web page |
||||||
|
according to the state of an externally equipped switch. The custom |
||||||
|
web page configures and provides a static IP to the ESP module. |
||||||
|
This example needs to equip an external switch circuit that pulls up |
||||||
|
with a resistor (1K to 10K ohms) and then drops it to GND via a push |
||||||
|
switch to connect to any GPIO of the ESP module. |
||||||
|
|
||||||
|
An external switch circuit: |
||||||
|
3.3V |
||||||
|
--+-- |
||||||
|
| |
||||||
|
+-+ |
||||||
|
| | 1K ~ 10K |
||||||
|
+-+ |
||||||
|
| |
||||||
|
+--> D2 (for ESP8266, ex: GPIO16 in case of ESP32) |
||||||
|
| |
||||||
|
| O |
||||||
|
--+ |
||||||
|
| O |
||||||
|
| |
||||||
|
--+-- |
||||||
|
GND |
||||||
|
*/ |
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP8266) |
||||||
|
#include <ESP8266WiFi.h> |
||||||
|
#include <ESP8266WebServer.h> |
||||||
|
#define EXTERNAL_SWITCH_PIN D2 |
||||||
|
#elif defined(ARDUINO_ARCH_ESP32) |
||||||
|
#include <WiFi.h> |
||||||
|
#include <WebServer.h> |
||||||
|
#define EXTERNAL_SWITCH_PIN 16 |
||||||
|
#endif |
||||||
|
#include <AutoConnect.h> |
||||||
|
#include <EEPROM.h> |
||||||
|
|
||||||
|
static const char AUX_CONFIGIP[] PROGMEM = R"( |
||||||
|
{ |
||||||
|
"title": "Config IP", |
||||||
|
"uri": "/configip", |
||||||
|
"menu": true, |
||||||
|
"element": [ |
||||||
|
{ |
||||||
|
"name": "caption", |
||||||
|
"type": "ACText", |
||||||
|
"value": "<b>Module IP configuration</b>", |
||||||
|
"style": "color:steelblue" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "mac", |
||||||
|
"type": "ACText", |
||||||
|
"format": "MAC: %s" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "staip", |
||||||
|
"type": "ACInput", |
||||||
|
"label": "IP", |
||||||
|
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "gateway", |
||||||
|
"type": "ACInput", |
||||||
|
"label": "Gateway", |
||||||
|
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "netmask", |
||||||
|
"type": "ACInput", |
||||||
|
"label": "Netmask", |
||||||
|
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "dns1", |
||||||
|
"type": "ACInput", |
||||||
|
"label": "DNS", |
||||||
|
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "ok", |
||||||
|
"type": "ACSubmit", |
||||||
|
"value": "OK", |
||||||
|
"uri": "/restart" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "cancel", |
||||||
|
"type": "ACSubmit", |
||||||
|
"value": "Cancel", |
||||||
|
"uri": "/_ac" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
)"; |
||||||
|
|
||||||
|
static const char AUX_RESTART[] PROGMEM = R"( |
||||||
|
{ |
||||||
|
"title": "Config IP", |
||||||
|
"uri": "/restart", |
||||||
|
"menu": false, |
||||||
|
"element": [ |
||||||
|
{ |
||||||
|
"name": "caption", |
||||||
|
"type": "ACText", |
||||||
|
"value": "Settings", |
||||||
|
"style": "font-family:Arial;font-weight:bold;text-align:center;margin-bottom:10px;color:steelblue" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "staip", |
||||||
|
"type": "ACText", |
||||||
|
"format": "IP: %s", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "gateway", |
||||||
|
"type": "ACText", |
||||||
|
"format": "Gateway: %s", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "netmask", |
||||||
|
"type": "ACText", |
||||||
|
"format": "Netmask: %s", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "dns1", |
||||||
|
"type": "ACText", |
||||||
|
"format": "DNS1: %s", |
||||||
|
"global": true |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "result", |
||||||
|
"type": "ACText", |
||||||
|
"posterior": "par" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
)"; |
||||||
|
|
||||||
|
AutoConnect portal; |
||||||
|
AutoConnectConfig config; |
||||||
|
AutoConnectAux auxIPConfig; |
||||||
|
AutoConnectAux auxRestart; |
||||||
|
|
||||||
|
// Pin assignment for an external configuration switch
|
||||||
|
uint8_t ConfigPin = EXTERNAL_SWITCH_PIN; |
||||||
|
uint8_t ActiveLevel = LOW; |
||||||
|
|
||||||
|
// EEPROM saving structure
|
||||||
|
typedef union { |
||||||
|
struct { |
||||||
|
uint32_t ip; |
||||||
|
uint32_t gateway; |
||||||
|
uint32_t netmask; |
||||||
|
uint32_t dns1; |
||||||
|
} ipconfig; |
||||||
|
uint8_t ipraw[sizeof(uint32_t) * 4]; |
||||||
|
} IPCONFIG; |
||||||
|
|
||||||
|
// Load IP configuration from EEPROM
|
||||||
|
void loadConfig(IPCONFIG* ipconfig) { |
||||||
|
EEPROM.begin(sizeof(IPCONFIG)); |
||||||
|
int dp = 0; |
||||||
|
for (uint8_t i = 0; i < 4; i++) { |
||||||
|
for (uint8_t c = 0; c < sizeof(uint32_t); c++) |
||||||
|
ipconfig->ipraw[c + i * sizeof(uint32_t)] = EEPROM.read(dp++); |
||||||
|
} |
||||||
|
EEPROM.end(); |
||||||
|
|
||||||
|
// Unset value screening
|
||||||
|
if (ipconfig->ipconfig.ip == 0xffffffffL) |
||||||
|
ipconfig->ipconfig.ip = 0U; |
||||||
|
if (ipconfig->ipconfig.gateway == 0xffffffffL) |
||||||
|
ipconfig->ipconfig.gateway = 0U; |
||||||
|
if (ipconfig->ipconfig.netmask == 0xffffffffL) |
||||||
|
ipconfig->ipconfig.netmask = 0U; |
||||||
|
if (ipconfig->ipconfig.dns1 == 0xffffffffL) |
||||||
|
ipconfig->ipconfig.dns1 = 0U; |
||||||
|
|
||||||
|
Serial.println("IP configuration loaded"); |
||||||
|
Serial.printf("Sta IP :0x%08lx\n", ipconfig->ipconfig.ip); |
||||||
|
Serial.printf("Gateway:0x%08lx\n", ipconfig->ipconfig.gateway); |
||||||
|
Serial.printf("Netmask:0x%08lx\n", ipconfig->ipconfig.netmask); |
||||||
|
Serial.printf("DNS1 :0x%08lx\n", ipconfig->ipconfig.dns1); |
||||||
|
} |
||||||
|
|
||||||
|
// Save current IP configuration to EEPROM
|
||||||
|
void saveConfig(const IPCONFIG* ipconfig) { |
||||||
|
// EEPROM.begin will truncate the area to the size given by the argument.
|
||||||
|
// The part overflowing from the specified size is filled with 0xff,
|
||||||
|
// so if the argument value is too small, the credentials may be lost.
|
||||||
|
EEPROM.begin(128); |
||||||
|
|
||||||
|
int dp = 0; |
||||||
|
for (uint8_t i = 0; i < 4; i++) { |
||||||
|
for (uint8_t d = 0; d < sizeof(uint32_t); d++) |
||||||
|
EEPROM.write(dp++, ipconfig->ipraw[d + i * sizeof(uint32_t)]); |
||||||
|
} |
||||||
|
EEPROM.end(); |
||||||
|
delay(100); |
||||||
|
} |
||||||
|
|
||||||
|
// Custom web page handler to set current configuration to the page
|
||||||
|
String getConfig(AutoConnectAux& aux, PageArgument& args) { |
||||||
|
IPCONFIG ipconfig; |
||||||
|
loadConfig(&ipconfig); |
||||||
|
|
||||||
|
// Fetch MAC address
|
||||||
|
String macAddress; |
||||||
|
uint8_t mac[6]; |
||||||
|
WiFi.macAddress(mac); |
||||||
|
for (uint8_t i = 0; i < 6; i++) { |
||||||
|
char buf[3]; |
||||||
|
sprintf(buf, "%02X", mac[i]); |
||||||
|
macAddress += buf; |
||||||
|
if (i < 5) |
||||||
|
macAddress += ':'; |
||||||
|
} |
||||||
|
aux["mac"].value = macAddress; |
||||||
|
|
||||||
|
// Fetch each IP address configuration from EEPROM
|
||||||
|
IPAddress staip = IPAddress(ipconfig.ipconfig.ip); |
||||||
|
IPAddress gateway = IPAddress(ipconfig.ipconfig.gateway); |
||||||
|
IPAddress netmask = IPAddress(ipconfig.ipconfig.netmask); |
||||||
|
IPAddress dns1 = IPAddress(ipconfig.ipconfig.dns1); |
||||||
|
|
||||||
|
// Echo back the IP settings
|
||||||
|
aux["staip"].value = staip.toString(); |
||||||
|
aux["gateway"].value = gateway.toString(); |
||||||
|
aux["netmask"].value = netmask.toString(); |
||||||
|
aux["dns1"].value = dns1.toString(); |
||||||
|
|
||||||
|
return String(); |
||||||
|
} |
||||||
|
|
||||||
|
// Convert IP address from AutoConnectInput string value
|
||||||
|
void getIPAddress(String ipString, uint32_t* ip) { |
||||||
|
IPAddress ipAddress; |
||||||
|
|
||||||
|
if (ipString.length()) |
||||||
|
ipAddress.fromString(ipString); |
||||||
|
*ip = (uint32_t)ipAddress; |
||||||
|
} |
||||||
|
|
||||||
|
// Custom web page handler to save the configuration to AutoConnectConfig
|
||||||
|
String setConfig(AutoConnectAux& aux, PageArgument& args) { |
||||||
|
IPCONFIG ipconfig; |
||||||
|
|
||||||
|
// Retrieve each IP address from AutoConnectInput field
|
||||||
|
getIPAddress(aux["staip"].value, &ipconfig.ipconfig.ip); |
||||||
|
getIPAddress(aux["gateway"].value, &ipconfig.ipconfig.gateway); |
||||||
|
getIPAddress(aux["netmask"].value, &ipconfig.ipconfig.netmask); |
||||||
|
getIPAddress(aux["dns1"].value, &ipconfig.ipconfig.dns1); |
||||||
|
|
||||||
|
// Make a result message
|
||||||
|
if (auxIPConfig.isValid()) { |
||||||
|
saveConfig(&ipconfig); |
||||||
|
aux["result"].value = "Reset by AutoConnect menu will restart with the above."; |
||||||
|
} |
||||||
|
else |
||||||
|
aux["result"].value = "Invalid IP address specified."; |
||||||
|
return String(); |
||||||
|
} |
||||||
|
|
||||||
|
// Sense the external switch to enter the configuraton mode
|
||||||
|
bool senseSW(const uint8_t pin, const uint8_t activeLevel) { |
||||||
|
bool sw = digitalRead(pin) == activeLevel; |
||||||
|
if (sw) { |
||||||
|
// Cut-off the chattering noise
|
||||||
|
unsigned long tm = millis(); |
||||||
|
while (digitalRead(pin) == activeLevel) { |
||||||
|
if (millis() - tm > 1000) |
||||||
|
break; |
||||||
|
delay(1); |
||||||
|
} |
||||||
|
} |
||||||
|
return sw; |
||||||
|
} |
||||||
|
|
||||||
|
void setup() { |
||||||
|
delay(1000); |
||||||
|
Serial.begin(115200); |
||||||
|
Serial.println(); |
||||||
|
|
||||||
|
// Shift the credentials storage to reserve saving IPCONFIG
|
||||||
|
config.boundaryOffset = sizeof(IPCONFIG); |
||||||
|
|
||||||
|
// Load current IP configuration
|
||||||
|
IPCONFIG ipconfig; |
||||||
|
loadConfig(&ipconfig); |
||||||
|
|
||||||
|
// Configure pre-loaded static IPs
|
||||||
|
config.staip = IPAddress(ipconfig.ipconfig.ip); |
||||||
|
config.staGateway = IPAddress(ipconfig.ipconfig.gateway); |
||||||
|
config.staNetmask = IPAddress(ipconfig.ipconfig.netmask); |
||||||
|
config.dns1 = IPAddress(ipconfig.ipconfig.dns1); |
||||||
|
portal.config(config); |
||||||
|
|
||||||
|
// Sense the configuration button (external switch)
|
||||||
|
pinMode(ConfigPin, INPUT); |
||||||
|
if (senseSW(ConfigPin, ActiveLevel)) { |
||||||
|
Serial.println("IP configuration enable"); |
||||||
|
auxIPConfig.load(AUX_CONFIGIP); |
||||||
|
auxIPConfig.on(getConfig); |
||||||
|
auxRestart.load(AUX_RESTART); |
||||||
|
auxRestart.on(setConfig); |
||||||
|
portal.join({ auxIPConfig, auxRestart }); |
||||||
|
} |
||||||
|
|
||||||
|
portal.begin(); |
||||||
|
} |
||||||
|
|
||||||
|
void loop() { |
||||||
|
// User sketch process is here.
|
||||||
|
|
||||||
|
portal.handleClient(); |
||||||
|
} |
@ -0,0 +1,184 @@ |
|||||||
|
/*
|
||||||
|
Update.ino, Example for the AutoConnect library. |
||||||
|
Copyright (c) 2019, Hieromon Ikasamo |
||||||
|
https://github.com/Hieromon/AutoConnect
|
||||||
|
This software is released under the MIT License. |
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
This example presents the simplest OTA Updates scheme. |
||||||
|
*/ |
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP8266) |
||||||
|
#include <ESP8266WiFi.h> |
||||||
|
#include <ESP8266WebServer.h> |
||||||
|
using WebServerClass = ESP8266WebServer; |
||||||
|
#elif defined(ARDUINO_ARCH_ESP32) |
||||||
|
#include <WiFi.h> |
||||||
|
#include <WebServer.h> |
||||||
|
using WebServerClass = WebServer; |
||||||
|
#endif |
||||||
|
#include <AutoConnect.h> |
||||||
|
|
||||||
|
// Update server setting page
|
||||||
|
static const char SETUP_PAGE[] PROGMEM = R"( |
||||||
|
{ |
||||||
|
"title": "Update setup", |
||||||
|
"uri": "/setup", |
||||||
|
"menu": true, |
||||||
|
"element": [ |
||||||
|
{ |
||||||
|
"name": "caption", |
||||||
|
"type": "ACText", |
||||||
|
"value": "OTA update setup", |
||||||
|
"style": "" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "isvalid", |
||||||
|
"type": "ACText", |
||||||
|
"style": "color:red" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "server", |
||||||
|
"type": "ACInput", |
||||||
|
"label": "Update server", |
||||||
|
"pattern": "^((([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9]))|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})$", |
||||||
|
"placeholder": "Your update server address" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "port", |
||||||
|
"type": "ACInput", |
||||||
|
"label": "port", |
||||||
|
"pattern": "[0-9]{1,4}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "path", |
||||||
|
"type": "ACInput", |
||||||
|
"label": "path" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "apply", |
||||||
|
"type": "ACSubmit", |
||||||
|
"value": "Apply", |
||||||
|
"uri": "/apply" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "cancel", |
||||||
|
"type": "ACSubmit", |
||||||
|
"value": "Discard", |
||||||
|
"uri": "/" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
)"; |
||||||
|
|
||||||
|
// The /apply handler validates the update server settings entered on
|
||||||
|
// the setup page. APPLY_PAGE exists to enable the /apply handler,
|
||||||
|
// and its role is a page redirector. If the /apply handler detects some
|
||||||
|
// errors, the page will redirect to the /setup page with error message.
|
||||||
|
static const char APPLY_PAGE[] PROGMEM = R"( |
||||||
|
{ |
||||||
|
"title": "Update setup", |
||||||
|
"uri": "/apply", |
||||||
|
"menu": false, |
||||||
|
"element": [ |
||||||
|
{ |
||||||
|
"name": "redirect", |
||||||
|
"type": "ACElement", |
||||||
|
"value": "<script type=\"text/javascript\">location.href='__REDIRECT__';</script>" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
)"; |
||||||
|
|
||||||
|
WebServerClass server; |
||||||
|
AutoConnect portal(server); |
||||||
|
AutoConnectAux setupPage; |
||||||
|
AutoConnectAux applyPage; |
||||||
|
AutoConnectUpdate update; |
||||||
|
|
||||||
|
#define UPDATESERVER_URL "" // Define to suit your environment
|
||||||
|
#define UPDATESERVER_PORT 8000 |
||||||
|
#define UPDATESERVER_PATH "bin" |
||||||
|
|
||||||
|
void loadAux() { |
||||||
|
setupPage.load(SETUP_PAGE); |
||||||
|
setupPage["server"].value = UPDATESERVER_URL; |
||||||
|
setupPage["port"].value = String(UPDATESERVER_PORT); |
||||||
|
setupPage["path"].value = UPDATESERVER_PATH; |
||||||
|
applyPage.load(APPLY_PAGE); |
||||||
|
} |
||||||
|
|
||||||
|
// The onSetup handler clears the error message field of the /setup page.
|
||||||
|
// Its field will be cleared after the /setup page generating by the
|
||||||
|
// effect of the AC_EXIT_LATER option.
|
||||||
|
String onSetup(AutoConnectAux& aux, PageArgument& arg) { |
||||||
|
setupPage["isvalid"].value = String(); |
||||||
|
return String(); |
||||||
|
} |
||||||
|
|
||||||
|
// The onApply handler validates the update server configuration.
|
||||||
|
// It does not do any semantic analysis but only verifies that the
|
||||||
|
// settings match the pattern defined in each field.
|
||||||
|
// The AutoConnectInput isValid function checks if the current value
|
||||||
|
// matches the pattern.
|
||||||
|
String onApply(AutoConnectAux& aux, PageArgument& arg) { |
||||||
|
String returnUri; |
||||||
|
|
||||||
|
AutoConnectInput& host = setupPage["server"].as<AutoConnectInput>(); |
||||||
|
AutoConnectInput& port = setupPage["port"].as<AutoConnectInput>(); |
||||||
|
AutoConnectInput& path = setupPage["path"].as<AutoConnectInput>(); |
||||||
|
|
||||||
|
Serial.printf("host: %s\n", host.value.c_str()); |
||||||
|
Serial.printf("port: %s\n", port.value.c_str()); |
||||||
|
Serial.printf("uri: %s\n", path.value.c_str()); |
||||||
|
|
||||||
|
if (host.isValid() & port.isValid()) { |
||||||
|
update.host = host.value; |
||||||
|
update.port = port.value.toInt(); |
||||||
|
update.uri = path.value; |
||||||
|
setupPage["isvalid"].value = String(); |
||||||
|
returnUri = "/"; |
||||||
|
} |
||||||
|
else { |
||||||
|
setupPage["isvalid"].value = String("Incorrect value specified."); |
||||||
|
returnUri = "/setup"; |
||||||
|
} |
||||||
|
applyPage["redirect"].value.replace("__REDIRECT__", returnUri); |
||||||
|
return String(); |
||||||
|
} |
||||||
|
|
||||||
|
void setup() { |
||||||
|
delay(1000); |
||||||
|
Serial.begin(115200); |
||||||
|
Serial.println(); |
||||||
|
|
||||||
|
// Responder of root page and apply page handled directly from WebServer class.
|
||||||
|
server.on("/", []() { |
||||||
|
String content = R"( |
||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
Place the root page with the sketch application.  |
||||||
|
__AC_LINK__ |
||||||
|
</body> |
||||||
|
</html> |
||||||
|
)"; |
||||||
|
content.replace("__AC_LINK__", String(AUTOCONNECT_LINK(COG_16))); |
||||||
|
server.send(200, "text/html", content); |
||||||
|
}); |
||||||
|
|
||||||
|
// AUX page loading
|
||||||
|
loadAux();
|
||||||
|
setupPage.on(onSetup, AC_EXIT_LATER); |
||||||
|
applyPage.on(onApply); |
||||||
|
portal.join({ setupPage, applyPage }); |
||||||
|
portal.begin(); |
||||||
|
update.attach(portal); |
||||||
|
} |
||||||
|
|
||||||
|
void loop() { |
||||||
|
portal.handleClient(); |
||||||
|
} |
@ -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
|
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 228 KiB |
After Width: | Height: | Size: 144 KiB |
After Width: | Height: | Size: 217 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 775 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 252 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 204 KiB |
@ -0,0 +1,111 @@ |
|||||||
|
## Updates with the Web Browser |
||||||
|
|
||||||
|
You can implement the user sketch as described in the [ESP8266 Arduino Core documentation](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#implementation-overview) to realize using the web browser as an update client. By incorporating the ESP8266HTTPUpdateServer class into AutoConnect, you can operate the dialog page for selecting the updating binary sketch file owned by ESP8266HTTPUpdateServer from the AutoConnect menu. |
||||||
|
|
||||||
|
Update feature with a web browser is implemented using ESP8266HTTPUpdateServer class and ESP8266mDNS class. However, **ESP32 Arduino core does not provide a class implementation equivalent to ESP8266HTTPUpdateServer**. Therefore, it is necessary to implement an HTTPUpdateServer class for ESP32 to realize the update using a Web browser. **The AutoConnect library includes an implementation of the HTTPUpdateServer class for ESP32 to make it easy for you to experience**. [^1] |
||||||
|
|
||||||
|
[^1]: You can find the implementation of the **HTTPUpdateServer** class in the **WebUpdate** folder included in the **AutoConnect library examples folder**. |
||||||
|
|
||||||
|
<img src="images/webupdate.png" width="480" /> |
||||||
|
|
||||||
|
!!! warning "For the client devices equipped with Android OS" |
||||||
|
Depending on the state of Android OS configuration, Bonjour service may not be incorporated. This method does not work with some Android devices as the client. |
||||||
|
|
||||||
|
### <i class="fa fa-edit"></i> How to embed ESP8266HTTPUpdateServer in AutoConnect |
||||||
|
|
||||||
|
To embed the ESP8266HTTPUpdateServer class with AutoConnect into your sketch, basically follow these steps: |
||||||
|
|
||||||
|
1. Include `ESP8266mDNS.h` and `ESP8266HTTPUpdateServer.h`, also `WiFiClient.h`, in addition to the usual directives as `ESP8266WebServer.h` and `AutoConnect.h`. |
||||||
|
2. Declare an ESP8266WebServer object. (In ESP32, as WebServer) |
||||||
|
3. Declare an ESP8266HTTPUpdateServer object. |
||||||
|
4. Declare an AutoConnect object with an ESP8266WebServer object as an argument. |
||||||
|
5. Declare an AutoConnectAux object for the update operation page. |
||||||
|
6. Assign `/update` to the URI of the update dialog page. |
||||||
|
7. Assign any title as the AutoConnect menu for the update dialog page. |
||||||
|
8. Declare additional AutoConnectAux pages for your application intention if needed. |
||||||
|
9. Perform the following procedure steps in the `setup()` function: |
||||||
|
1. Invokes `ESP8288HTTPUpdateServer::setup` function, specifies the **USERNAME** and the **PASSWORD** as needed. |
||||||
|
2. Load the AutoConnectAux pages declared in step #8 for your application. (Except the update dialog page) |
||||||
|
3. Join these pages to AutoConnect along with the update dialog page declared in step #5. |
||||||
|
4. Invokes [AutoConnect::begin](api.md#begin) function. |
||||||
|
5. Call the `MDNS.begin` and `MDNS.addServer` functions to start the multi cast DNS service. |
||||||
|
10. Perform the following procedure steps in the `loop()` function: |
||||||
|
1. Call the `MDNS.update` function to parse requests for mDNS. (No needed as ESP32) |
||||||
|
2. Invokes [AutoConnect::handleClient](api.md#handleclient) function. |
||||||
|
|
||||||
|
```cpp |
||||||
|
#include <ESP8266WiFi.h> |
||||||
|
#include <ESP8266WebServer.h> |
||||||
|
#include <ESP8266HTTPUpdateServer.h> // Step #1 |
||||||
|
#include <ESP8266mDNS.h> // Step #1 |
||||||
|
#include <WiFiClient.h> // Step #1 |
||||||
|
#include <AutoConnect.h> |
||||||
|
|
||||||
|
static const char HELLO_PAGE[] PROGMEM = R"( |
||||||
|
{ "title": "Hello world", "uri": "/", "menu": true, "element": [ |
||||||
|
{ "name": "caption", "type": "ACText", "value": "<h2>Hello, world</h2>", "style": "text-align:center;color:#2f4f4f;padding:10px;" }, |
||||||
|
{ "name": "content", "type": "ACText", "value": "In this page, place the custom web page handled by the sketch application." } ] |
||||||
|
} |
||||||
|
)"; |
||||||
|
|
||||||
|
ESP8266WebServer httpServer; // Step #2 |
||||||
|
ESP8266HTTPUpdateServer httpUpdate; // Step #3 |
||||||
|
AutoConnect portal(httpServer); // Step #4 |
||||||
|
AutoConnectAux update("/update", "UPDATE"); // Step #5, #6, #7 |
||||||
|
AutoConnectAux hello; // Step #8 |
||||||
|
|
||||||
|
void setup() { |
||||||
|
httpUpdate.setup(&httpServer, "USERNAME", "PASSWORD"); // Step #9.a |
||||||
|
hello.load(HELLO_PAGE); // Step #9.b |
||||||
|
portal.join({ hello, update }); // Step #9.c |
||||||
|
if (portal.begin()) { // Step #9.d |
||||||
|
if (MDNS.begin("esp-webupdate")) // Step #9.e |
||||||
|
MDNS.addService("http", "tcp", 80); // Step #9.e |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void loop() { |
||||||
|
MDNS.update(); // Step #10.a |
||||||
|
portal.handleClient(); // Step #10.b |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
!!! hint "For ESP32" |
||||||
|
This procedure is equally applicable to ESP32. If the target module is ESP32, change the following items: |
||||||
|
|
||||||
|
- Change the include directives appropriately for the ESP32 environment. |
||||||
|
- Change ESP8266HTTPUpdaetServer to HTTPUpdateServer using an implementation provided from AutoConnect library example code. |
||||||
|
- Remove `MDNS.update` line from the sketch code. |
||||||
|
|
||||||
|
!!! example "Share an ESP8266WebServer" |
||||||
|
AutoConnect shares the ESP8266WebServer instance with the ESP8266HTTPUpdateServer class. You can give the same instance as ESP8266WebServer instance given to AutoConnect to ESP8266HTTPUpdateServer class. |
||||||
|
```cpp |
||||||
|
ESP8266WebServer httpServer; |
||||||
|
ESP8266HTTPUpdateServer updateServer; |
||||||
|
AutoConnect portal(httpServer); |
||||||
|
updateServer(&httpServer); |
||||||
|
``` |
||||||
|
This sharing specification is the same for ESP32. |
||||||
|
|
||||||
|
The result of the above sketch should be as follows. [^2] |
||||||
|
|
||||||
|
[^2]: The authentication dialog is displayed first. |
||||||
|
|
||||||
|
<span style="display:block;margin-left:auto;margin-right:auto;width:282px;height:362px;border:1px solid lightgrey;"><img data-gifffer="images/webupdate.gif" data-gifffer-height="360" data-gifffer-width="280" /></span> |
||||||
|
|
||||||
|
!!! faq "How LED ticking during updates" |
||||||
|
You **cannot** get the ticker with LED during updates by using this way. It is since the current implementation of the ESP8266HTTPUpdateServer class of the Arduino core **library does not assign an LED PIN** to the ESP8266HTTPUpdate class. |
||||||
|
|
||||||
|
### <i class="fa fa-wrench"></i> How to make the binary sketch |
||||||
|
|
||||||
|
Binary sketch files for updating can be retrieved using the Arduino IDE. Open the **Sketch** menu and select the **Export compiled Binary**, then starts compilation. |
||||||
|
|
||||||
|
<img src="images/export_binary.png" width="450" /> |
||||||
|
|
||||||
|
When the compilation is complete, a binary sketch will save with the extension `.bin` in the same folder as the sketch. |
||||||
|
|
||||||
|
<script> |
||||||
|
window.onload = function() { |
||||||
|
Gifffer(); |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,175 @@ |
|||||||
|
## Updates with the update server |
||||||
|
|
||||||
|
Since the v1.0.0 release, AutoConnect provides new feature for updating sketch firmware of ESP8266 or ESP32 modules via OTA using the [AutoConnectUpdate](apiupdate.md#autoconnectupdate) class that is an implementation of the sketch binary update by the HTTP server mentioned in the [OTA update](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#http-server) of the ESP8266 Arduino Core documentation, which inherits from the ESP8266HTTPUpdate class (as HTTPUpdate class in the case of ESP32). It acts as a client agent for a series of update operations. |
||||||
|
|
||||||
|
This method allows you to remotely update the ESP module's firmware beyond the network segments from the update server, as long as you can ensure proper routing and forwarding. |
||||||
|
|
||||||
|
<img src="images/updateserver.png" width="380" /> |
||||||
|
|
||||||
|
If you choose this update method, you need to prepare the server process as a variant of the HTTP server that supplies the binary sketch files to the updating client agent. Its server requires to be able to handle the HTTP headers extended by ESP8266HTTPUpdate class as described in the [ESP8266 Arduino Core documentation](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#server-request-handling). There are various implementations of the update server that provide binary sketch files. For example, the ESP8266 Arduino Core documentation suggests an [advanced updater](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#id5) php script that can be fully communicated with the client agent using the ESP8266HTTPUpdate class. That is, the update server for AutoConnect must work with the client agent, and its implementation should make the handshake well with the AutoConnectUpdate class which wraps an ESP8266HTTPUpdate class. |
||||||
|
The AutoConnect library provides an update server script implemented in Python that can combine with the AutoConnectUpdate class. |
||||||
|
|
||||||
|
### <i class="fa fa-edit"></i> How to embed AutoConnectUpdate to your sketch |
||||||
|
|
||||||
|
To embed the AutoConnectUpdate class into your sketch, basically follow these steps: |
||||||
|
|
||||||
|
1. Declare an ESP8266WebServer object. (In ESP32, as WebServer) |
||||||
|
2. Declare an AutoConnect object with an ESP8266WebServer object. |
||||||
|
3. Declare an [AutoConnectUpdate](apiupdate.md) object with the update server address and the HTTP port as parameters. |
||||||
|
4. Invokes [AutoConnect::begin](api.md#begin) function. |
||||||
|
5. Attach the AutoConnectUpdate object to AutoConnect using [AutoConnectUpdate::attach](apiupdate.md#attach) function. |
||||||
|
6. Invokes [AutoConnect::handleClient](api.md#handleclient) function in the `loop()`. |
||||||
|
|
||||||
|
```cpp |
||||||
|
#include <ESP8266WiFi.h> |
||||||
|
#include <ESP8266WebServer.h> |
||||||
|
#include <AutoConnect.h> |
||||||
|
|
||||||
|
ESP8266WebServer server; // Step #1 |
||||||
|
AutoConnect portal; // Step #2 |
||||||
|
AutoConnectUpdate update("192.168.0.100", 8000); // Step #3 |
||||||
|
|
||||||
|
void setup() { |
||||||
|
if (portal.begin()) { // Step #4 |
||||||
|
update.attach(portal); // Step #5 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void loop() { |
||||||
|
portal.handleClient(); // Step #6 |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
<span style="display:block;margin-left:auto;margin-right:auto;width:282px;height:362px;border:1px solid lightgrey;"><img data-gifffer="images/serverupdate.gif" data-gifffer-height="360" data-gifffer-width="280" /></span> |
||||||
|
|
||||||
|
### <i class="fas fa-desktop"></i> Behavior of the AutoConnectUpdate class |
||||||
|
|
||||||
|
A sketch incorporating the AutoConnectUpdate class has an extended menu item as **UPDATE** in the AutoConnect menu. **UPDATE** as menu item will be attached by the AutoConnectUpdate automatically. |
||||||
|
|
||||||
|
When an UPDATE item started, its first action is requesting a [catalog list](#2-the-catalog-list-content) of updatable binary sketch files to the [update server](#update-server-for-the-autoconnectupdate-class). Then the update server sends back the catalog list of stored binary sketch files to a client which is the ESP module. The AutoConnectUpdate class will display responded list to a custom Web page[^1] on the browser. |
||||||
|
|
||||||
|
[^1]: You can scroll horizontally on the browser to see the timestamp and file size that the catalog list contains. |
||||||
|
|
||||||
|
<img align="top" src="images/updatemenu.png" width="240" /> |
||||||
|
<img style="margin-left:30px;" src="images/updatelist.png" width="240" /> |
||||||
|
|
||||||
|
The substance of Available firmware list is a custom Web page by AutoConnectAux, and you can select the target binary sketch file with the radio button (AutoConnectRadio). A progress bar will appear to notify the updating status once the update has begun. When the update finished, the ESP module will reset automatically to launch a new firmware. |
||||||
|
|
||||||
|
<img src="images/updating.png" width="240" /> |
||||||
|
<img style="margin-left:30px;" src="images/updated.png" width="240" /> |
||||||
|
|
||||||
|
The AutoConnectUpdate class performs the above series of operations in conjunction with the update server. All you need to do is attach the AutoConnectUpdate class to AutoConnect and execute the [AutoConnect::handleClient](api.md#handleclient) function in the `loop()`. |
||||||
|
|
||||||
|
### <i class="fas fa-server"></i> Update server for the AutoConnectUpdate class |
||||||
|
|
||||||
|
The above series of operations using AutoConnectUpdate class requires an update server that can work with it. AutoConnect provides an update server script implemented in Python. This server script conforms to a sketch that uses the AutoConnectUpdate class as an update client agent.[^2] |
||||||
|
|
||||||
|
In the OTA platform, you can place the update server operated by the script in a location that is reachable from the ESP module on the network. |
||||||
|
|
||||||
|
[^2]: The folders containing the script: |
||||||
|
For Python2: *AUTOCONNECT\_LIBRARY\_PATH*/src/updateserver/python2 |
||||||
|
For Python3: *AUTOCONNECT\_LIBRARY\_PATH*/src/updateserver/python3 |
||||||
|
|
||||||
|
```bash |
||||||
|
updateserver.py [-h] [--port PORT] [--bind IP_ADDRESS] [--catalog CATALOG] [--log LOG_LEVEL] |
||||||
|
``` |
||||||
|
<dl class="apidl"> |
||||||
|
<dt></dt> |
||||||
|
<dd><span class="apidef">**--help | -h**</span><span class="apidesc">Show help message and exit.</span> |
||||||
|
<dd><span class="apidef">**--port | -p**</span><span class="apidesc">Specifies **PORT** number (Default: 8000)</span> |
||||||
|
<dd><span class="apidef">**--bind | -b**</span><span class="apidesc">Specifies the IP address to which the update server binds. Usually, it is the host address of the update server. When multiple NICs configured, specify one of the IP addresses. (Default: HOST IP or 127.0.0.0)</span> |
||||||
|
<dd><span class="apidef">**--catalog | -d**</span><span class="apidesc">Specifies the directory path on the update server that contains the binary sketch files. (Default: The current directory)</span> |
||||||
|
<dd><span class="apidef">**--log | -l**</span><span class="apidesc">Specifies the level of logging output. It accepts the [Logging Levels](https://docs.python.org/3/library/logging.html?highlight=logging#logging-levels) specified in the Python logging module.</span> |
||||||
|
</dl> |
||||||
|
|
||||||
|
!!! example "updateserver.py usage" |
||||||
|
1. Python |
||||||
|
First, prepare a Python environment. It is also possible with a tiny single-board computer like the [raspberry pi](https://www.raspberrypi.org/). Popular distributions such as Ubuntu for Linux include Python. You can easily set up a Python 2 or 3 environment. If you are using a Mac, you already have the Python 2 environment. macOS is equipped with Python 2.7 by default. In the case of Windows OS, it is necessary to install the Python environment intentionally. Please refer to the [Python official page](https://wiki.python.org/moin/BeginnersGuide/Download) to install Python in your environment. |
||||||
|
|
||||||
|
2. Deploy the binary sketch files |
||||||
|
Use the Arduino IDE to output a binary file of sketches and deploy it[^3] under the update server. The path which specifies for the **--catalog** option of updateServer.py is the path of the binary sketch files you deployed. |
||||||
|
|
||||||
|
3. Start updateserver.py |
||||||
|
For example, to start the update server on the host with IP address 172.16.1.10 using 8080 port[^4], execute the following command: |
||||||
|
```bash |
||||||
|
python updateserver.py --port 8080 --bind 172.16.1.10 --catalog bin --log debug |
||||||
|
``` |
||||||
|
In this example assumes that the binary sketch files are deployed under the path `bin` from the current directory. |
||||||
|
|
||||||
|
[^3]: Deploying the binary sketch file output by Arduino IDE is usually just copying to the folder for deployment. However, its folder must be accessible from the updateserver.py script. |
||||||
|
[^4]: The port of the update server and the port used by the AutoConnectUpdate class must be the same. |
||||||
|
|
||||||
|
!!! note "Limitations of the updateserver.py" |
||||||
|
The updateserver.py script equips only the minimum facility because it assumes a private small OTA platform without identifying individual modules and version restrictions etc. To operate a larger OTA platform, it is necessary to identify the individual ESP module and to consider version control and security. |
||||||
|
|
||||||
|
### <i class="far fa-handshake"></i> HTTP contents and the sequence for the AutoConnectUpdate class |
||||||
|
|
||||||
|
You can also equip an update server that works with the AutoConnectUpdate class. It can be improved more widely applicable by adding extensions such as version control and authentication to the updateserver.py script. It is necessary to understand the specifications related to HTTP data streams and sequences to enhance the update server that the AutoConnectUpdate class assumes. |
||||||
|
|
||||||
|
This section describes the contents of the HTTP data stream required by the communication with AutoConnectUpdate class. To work correctly with the AutoConnectUpdate class, the update server must meet two requirements: |
||||||
|
|
||||||
|
- The update server notifies the catalog list of updatable binary files which stored in the update server to the client agent. [^5] |
||||||
|
- Send an updating binary file and MD5 hash to a client in response to URI request (HTTP GET). [^6] |
||||||
|
|
||||||
|
[^5]: The **client agent** is an instance of the AutoConnectUpdate class. |
||||||
|
[^6]: The client agent will send its URI request to the update server. |
||||||
|
|
||||||
|
Above requirements will be implemented on along the HTTP protocol. The AutoConnectUpdate class requests an update server to notify the client for a catalog list of binary sketch files using an HTTP URL query string. The specifications of the HTTP query and the contents of the catalog list to be returned are as follows: |
||||||
|
|
||||||
|
#### 1. HTTP URL query for the catalog list of the updatable |
||||||
|
|
||||||
|
``` |
||||||
|
[address]/_catalog?op=list&path=[path] |
||||||
|
``` |
||||||
|
<dl class="apidl"> |
||||||
|
<dt></dt> |
||||||
|
<dd><span class="apidef">**address**</span><span class="apidesc">URL of the update server</span> |
||||||
|
<dd><span class="apidef">**/_catalog**</span><span class="apidesc">Request path, it is fixed.</span> |
||||||
|
<dd><span class="apidef">**op**</span><span class="apidesc">Operation command for the update server. Currently, only '**list**' occurs.</span> |
||||||
|
<dd><span class="apidef">**path**</span><span class="apidesc">Path containing the updatable binary files on the update server.</span> |
||||||
|
</dl> |
||||||
|
|
||||||
|
#### 2. The catalog list content |
||||||
|
|
||||||
|
The response (that is, the catalog list) to the above query from the server is the following specification in JSON format. |
||||||
|
|
||||||
|
```js |
||||||
|
{ |
||||||
|
"name" : FILE_NAME, |
||||||
|
"type" : FILE_TYPE, |
||||||
|
"date" : FILE_TIMESTAMP_DATED, |
||||||
|
"time" : FILE_TIMESTAMP_TIMED, |
||||||
|
"size" : FILE_SIZE |
||||||
|
} |
||||||
|
``` |
||||||
|
<dl class="apidl"> |
||||||
|
<dt></dt> |
||||||
|
<dd><span class="apidef">**name**</span><span class="apidesc">Binary sketch file name for update (String)</span> |
||||||
|
<dd><span class="apidef">**type**</span><span class="apidesc">One of '**bin**', '**directory**' or '**file**'. AutoConnect Update recognizes only file types of '**bin**' as update targets. (String)</span> |
||||||
|
<dd><span class="apidef">**date**</span><span class="apidesc">File update date. AutoConnect v1.0.0 treats the file update date as an annotation and is not equip the version control feature yet. (String)</span> |
||||||
|
<dd><span class="apidef">**time**</span><span class="apidesc">File update time. AutoConnect v1.0.0 treats the file update date as an annotation and is not equip the version control feature yet. (String)</span> |
||||||
|
<dd><span class="apidef">**size**</span><span class="apidesc">File byte count (Numeric)</span> |
||||||
|
</dl> |
||||||
|
|
||||||
|
The above JSON object is one entry. The actual catalog list is an array of this entry since it assumes that an update server will provide multiple update binary files in production. The update server should respond with the MIME type specified as `application/json` for the catalog list.[^7] |
||||||
|
|
||||||
|
[^7]: It should be represented as `Content-Type: application/json` in the HTTP response header. |
||||||
|
|
||||||
|
#### 3. The binary sketch file used for updating |
||||||
|
|
||||||
|
The AutoConnectUpdate class issues a HTTP GET request with the specified host address and URI. The update server responds by sending back a binary sketch file with the following header: |
||||||
|
|
||||||
|
``` |
||||||
|
Content-Type: application/octet-stream |
||||||
|
Content-Disposition: attachment; filename="BINARY_SKETCH_FILE_NAME" |
||||||
|
Content-Length: LENGTH_OF_CONTENT |
||||||
|
x-MD5: HEXDIGEST |
||||||
|
``` |
||||||
|
|
||||||
|
The header **x-MD5** is a 128-bit hash value (digest in hexadecimal) that represents the checksum of the binary sketch file for updates required for the ESP8266HTTPUpdate class. |
||||||
|
|
||||||
|
<script> |
||||||
|
window.onload = function() { |
||||||
|
Gifffer(); |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,19 @@ |
|||||||
|
## OTA Updates with AutoConnect |
||||||
|
|
||||||
|
AutoConnect provides **two type platforms** for updating the binary sketch in the ESP8266 or ESP32 module via OTA. They correspond to the [Web Browser Update](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#web-browser) and [HTTP Server Update](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#http-server) whiches mentioned in the [ESP8266 Arduino Core documentation](https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#ota-updates). |
||||||
|
|
||||||
|
[**The update behavior using a web browser**](otabrowser.md) as the client that supplies the binary sketch file for update follows the scenario assumed by the ESP8266 Arduino core. Therefore, the user sketch must meet the requirements described in the ESP8266 Arduino Core documentation, but you can easily embed the update feature that able to handle with the web browser by AutoConnect. All you need to do is that [join](api.md#join) the [AutoConnectAux](apiaux.md) with embedded **ESP8266HTTPUpdateServer**[^1] of the core library to AutoConnect. |
||||||
|
|
||||||
|
[^1]: The AutoConnect library provides an implementation of the **HTTPUpdateServer** class that ported from ESP8266HTTPUpdateServer class for ESP32 intention. It is contained the **WebUpdate** under the examples folder. |
||||||
|
|
||||||
|
<img src="images/webupdatemodel.png" width="420" /> |
||||||
|
|
||||||
|
!!! caution "It is for the only the same network" |
||||||
|
This method can apply only if the client browser and the ESP module belong to the same network segment. It cannot work correctly across networks. |
||||||
|
|
||||||
|
[**Another update method using an update server**](otaserver.md) can be applied more broadly than using a web browser. This method can also update the ESP module over the Internet if you can secure the correct route and transparency between the ESP module and the update server. To configure this platform, you need to have an [update server](otaserver.md#update-server-for-the-autoconnectupdate-class) along with using the [AutoConnectUpdate](apiupdate.md) class in your sketch. |
||||||
|
|
||||||
|
<img src="images/updatemodel.png" width="540" /> |
||||||
|
|
||||||
|
!!! info "Security Disclaimer" |
||||||
|
The security level of the OTA update platform provided by AutoConnect is very weak. No guarantees as to the level of security for your application by the AutoConnect OTA Update is implied. |