OTA images - initial release
BIN
doc/ota_updates/ota-ide-module-joined-wifi.png
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
doc/ota_updates/ota-ide-ota-port-selection.png
Normal file
After Width: | Height: | Size: 345 KiB |
BIN
doc/ota_updates/ota-ide-ota-upload-complete.png
Normal file
After Width: | Height: | Size: 202 KiB |
BIN
doc/ota_updates/ota-ide-ota-upload-configuration.png
Normal file
After Width: | Height: | Size: 298 KiB |
BIN
doc/ota_updates/ota-ide-python-configuration.png
Normal file
After Width: | Height: | Size: 240 KiB |
BIN
doc/ota_updates/ota-ide-serial-upload-configuration.png
Normal file
After Width: | Height: | Size: 273 KiB |
BIN
doc/ota_updates/ota-ide-sketch-selection.png
Normal file
After Width: | Height: | Size: 221 KiB |
BIN
doc/ota_updates/ota-ide-ssid-pass-entry.png
Normal file
After Width: | Height: | Size: 61 KiB |
@ -1,220 +1,220 @@
|
|||||||
---
|
---
|
||||||
title: OTA Update
|
title: OTA Update
|
||||||
---
|
---
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
* [Basic Requirements](#basic-requirements)
|
* [Basic Requirements](#basic-requirements)
|
||||||
* [Arduino IDE](#arduino-ide)
|
* [Arduino IDE](#arduino-ide)
|
||||||
* [HTTP Server](#http-server)
|
* [HTTP Server](#http-server)
|
||||||
* [Stream Interface](#stream-interface)
|
* [Stream Interface](#stream-interface)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
OTA (Over the Air) update is the process of loading the firmware to ESP module using WiFi connection rather that a serial port. Such functionality became extremely useful in case of limited or no physical access to the module. There is no imposed protection on OTA update process. Such protection should be implemented by developer to ensure that updates are allowed only from legitimate / trusted source.
|
OTA (Over the Air) update is the process of loading the firmware to ESP module using WiFi connection rather that a serial port. Such functionality became extremely useful in case of limited or no physical access to the module. There is no imposed protection on OTA update process. Such protection should be implemented by developer to ensure that updates are allowed only from legitimate / trusted source.
|
||||||
|
|
||||||
OTA may be done from:
|
OTA may be done from:
|
||||||
- Arduino IDE
|
- Arduino IDE
|
||||||
- HTTP server
|
- HTTP server
|
||||||
|
|
||||||
In any case first firmware upload have to be done over a serial port. If OTA routines are correctly implemented in sketch, then all subsequent uploads may be done over the air.
|
In any case first firmware upload have to be done over a serial port. If OTA routines are correctly implemented in sketch, then all subsequent uploads may be done over the air.
|
||||||
|
|
||||||
The following chapters provide more details and both methods of doing OTA.
|
The following chapters provide more details and both methods of doing OTA.
|
||||||
|
|
||||||
|
|
||||||
## Basic Requirements
|
## Basic Requirements
|
||||||
|
|
||||||
- Flash chip size is 2x the size of the sketch.
|
- Flash chip size is 2x the size of the sketch.
|
||||||
|
|
||||||
## Arduino IDE
|
## Arduino IDE
|
||||||
|
|
||||||
Uploading modules wirelessly from Arduino IDE is intended for the following typical scenarios:
|
Uploading modules wirelessly from Arduino IDE is intended for the following typical scenarios:
|
||||||
- during firmware development as a quicker alternative to loading over a serial
|
- during firmware development as a quicker alternative to loading over a serial
|
||||||
- for updating small quantity of modules
|
- for updating small quantity of modules
|
||||||
- only if modules are available on the same network as the computer with Arduino IDE
|
- only if modules are available on the same network as the computer with Arduino IDE
|
||||||
|
|
||||||
#### Requirements
|
#### Requirements
|
||||||
- The ESP and the computer must be connected to the same network.
|
- The ESP and the computer must be connected to the same network.
|
||||||
|
|
||||||
#### Let Us Do It
|
#### Let Us Do It
|
||||||
|
|
||||||
OTA process will be demonstrated using:
|
OTA process will be demonstrated using:
|
||||||
- DNS_SD_Arduino_OTA.ino sketch available from Arduino IDE
|
- DNS_SD_Arduino_OTA.ino sketch available from Arduino IDE
|
||||||
- NodeMCU 1.0 board with ESP-12E module
|
- NodeMCU 1.0 board with ESP-12E module
|
||||||
|
|
||||||
1. Before you begin, please make sure that you have the following installed:
|
1. Before you begin, please make sure that you have the following installed:
|
||||||
- Arduino IDE and ESP8266 board support as described under https://github.com/esp8266/Arduino#installing-with-boards-manager
|
- Arduino IDE and ESP8266 board support as described under https://github.com/esp8266/Arduino#installing-with-boards-manager
|
||||||
- Python 2.7.10 (do not install Python 3.5.0 that is not supported):
|
- Python 2.7.10 (do not install Python 3.5.0 that is not supported):
|
||||||
1. Upload Python from https://www.python.org/
|
1. Upload Python from https://www.python.org/
|
||||||
2. Start installer
|
2. Start installer
|
||||||
3. Select “Add python.exe to Path” (see below – that option is not selected by default)
|
3. Select “Add python.exe to Path” (see below – that option is not selected by default)
|
||||||
4. Complete remaining steps of installation
|
4. Complete remaining steps of installation
|
||||||
|
|
||||||
|
|
||||||
2. Now prepare the sketch and configuration for the upload over a serial port.
|
2. Now prepare the sketch and configuration for the upload over a serial port.
|
||||||
|
|
||||||
- Start Arduino IDE and load sketch DNS_SD_Arduino_OTA.ino available under File > Examples > ESP8266mDNS
|
- Start Arduino IDE and load sketch DNS_SD_Arduino_OTA.ino available under File > Examples > ESP8266mDNS
|
||||||
|
|
||||||
[PICTURE]
|
[PICTURE]
|
||||||
|
|
||||||
- Update ssid and pass in the sketch so the module can join your WiFi network
|
- Update ssid and pass in the sketch so the module can join your WiFi network
|
||||||
|
|
||||||
[PICTURE]
|
[PICTURE]
|
||||||
|
|
||||||
- Configure upload parameters as below (you may need to adjust configuration if you are using a different module):
|
- Configure upload parameters as below (you may need to adjust configuration if you are using a different module):
|
||||||
|
|
||||||
[PICTURE]
|
[PICTURE]
|
||||||
|
|
||||||
3. Upload the sketch (Ctrl+U). Once done open Serial Monitor (Ctrl+Shift+M) and check if the module has joined your WiFi network.
|
3. Upload the sketch (Ctrl+U). Once done open Serial Monitor (Ctrl+Shift+M) and check if the module has joined your WiFi network.
|
||||||
|
|
||||||
[PICTURE]
|
[PICTURE]
|
||||||
|
|
||||||
4. Only if module is connected, after a dozen (or two dozens) of seconds the esp8266-ota port will show up in Arduino IDE:
|
4. Only if module is connected, after a dozen (or two dozens) of seconds the esp8266-ota port will show up in Arduino IDE:
|
||||||
|
|
||||||
[PICTURE]
|
[PICTURE]
|
||||||
|
|
||||||
5. Now get ready for your first OTA upload by changing configuration settings as follows:
|
5. Now get ready for your first OTA upload by changing configuration settings as follows:
|
||||||
|
|
||||||
[PICTURE]
|
[PICTURE]
|
||||||
|
|
||||||
6. If you have successfully completed all the above steps, you can upload (Ctrl+U) the same (or any other) sketch over OTA:
|
6. If you have successfully completed all the above steps, you can upload (Ctrl+U) the same (or any other) sketch over OTA:
|
||||||
|
|
||||||
[PICTURE]
|
[PICTURE]
|
||||||
|
|
||||||
**Note**
|
**Note**
|
||||||
|
|
||||||
To be able to upload your sketch over and over again using OTA, you need to embed inside OTA routines. Please use DNS_SD_Arduino_OTA.ino as an example.
|
To be able to upload your sketch over and over again using OTA, you need to embed inside OTA routines. Please use DNS_SD_Arduino_OTA.ino as an example.
|
||||||
|
|
||||||
|
|
||||||
## HTTP Server
|
## HTTP Server
|
||||||
|
|
||||||
```ESPhttpUpdate``` class can check for updates and download a binary file from HTTP web server.
|
```ESPhttpUpdate``` class can check for updates and download a binary file from HTTP web server.
|
||||||
It is possible to download updates from every IP or domain address on the network or Internet.
|
It is possible to download updates from every IP or domain address on the network or Internet.
|
||||||
|
|
||||||
#### Requirements
|
#### Requirements
|
||||||
- web server
|
- web server
|
||||||
|
|
||||||
#### Arduino code
|
#### Arduino code
|
||||||
|
|
||||||
##### Simple updater
|
##### Simple updater
|
||||||
|
|
||||||
Simple updater downloads the file every time the function is called.
|
Simple updater downloads the file every time the function is called.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
ESPhttpUpdate.update("192.168.0.2", 80, "/arduino.bin");
|
ESPhttpUpdate.update("192.168.0.2", 80, "/arduino.bin");
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Advanced updater
|
##### Advanced updater
|
||||||
|
|
||||||
Its possible to point update function to a script at the server.
|
Its possible to point update function to a script at the server.
|
||||||
If version string argument is given, it will be sent to the server.
|
If version string argument is given, it will be sent to the server.
|
||||||
Server side script can use this to check if update should be performed.
|
Server side script can use this to check if update should be performed.
|
||||||
|
|
||||||
Server side script can respond as follows:
|
Server side script can respond as follows:
|
||||||
- response code 200, and send the firmware image,
|
- response code 200, and send the firmware image,
|
||||||
- or response code 304 to notify ESP that no update is required.
|
- or response code 304 to notify ESP that no update is required.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
t_httpUpdate_return ret = ESPhttpUpdate.update("192.168.0.2", 80, "/esp/update/arduino.php", "optional current version string here");
|
t_httpUpdate_return ret = ESPhttpUpdate.update("192.168.0.2", 80, "/esp/update/arduino.php", "optional current version string here");
|
||||||
switch(ret) {
|
switch(ret) {
|
||||||
case HTTP_UPDATE_FAILED:
|
case HTTP_UPDATE_FAILED:
|
||||||
Serial.println("[update] Update failed.");
|
Serial.println("[update] Update failed.");
|
||||||
break;
|
break;
|
||||||
case HTTP_UPDATE_NO_UPDATES:
|
case HTTP_UPDATE_NO_UPDATES:
|
||||||
Serial.println("[update] Update no Update.");
|
Serial.println("[update] Update no Update.");
|
||||||
break;
|
break;
|
||||||
case HTTP_UPDATE_OK:
|
case HTTP_UPDATE_OK:
|
||||||
Serial.println("[update] Update ok."); // may not called we reboot the ESP
|
Serial.println("[update] Update ok."); // may not called we reboot the ESP
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Server request handling
|
#### Server request handling
|
||||||
|
|
||||||
##### Simple updater
|
##### Simple updater
|
||||||
|
|
||||||
For the simple updater the server only needs to deliver the binary file for update.
|
For the simple updater the server only needs to deliver the binary file for update.
|
||||||
|
|
||||||
##### Advanced updater
|
##### Advanced updater
|
||||||
|
|
||||||
For advanced update management a script needs to run at the server side, for example a PHP script.
|
For advanced update management a script needs to run at the server side, for example a PHP script.
|
||||||
At every update request the the ESP sends some information in HTTP headers to the server.
|
At every update request the the ESP sends some information in HTTP headers to the server.
|
||||||
|
|
||||||
Example header data:
|
Example header data:
|
||||||
```
|
```
|
||||||
[HTTP_USER_AGENT] => ESP8266-http-Update
|
[HTTP_USER_AGENT] => ESP8266-http-Update
|
||||||
[HTTP_X_ESP8266_STA_MAC] => 18:FE:AA:AA:AA:AA
|
[HTTP_X_ESP8266_STA_MAC] => 18:FE:AA:AA:AA:AA
|
||||||
[HTTP_X_ESP8266_AP_MAC] => 1A:FE:AA:AA:AA:AA
|
[HTTP_X_ESP8266_AP_MAC] => 1A:FE:AA:AA:AA:AA
|
||||||
[HTTP_X_ESP8266_FREE_SPACE] => 671744
|
[HTTP_X_ESP8266_FREE_SPACE] => 671744
|
||||||
[HTTP_X_ESP8266_SKETCH_SIZE] => 373940
|
[HTTP_X_ESP8266_SKETCH_SIZE] => 373940
|
||||||
[HTTP_X_ESP8266_CHIP_SIZE] => 524288
|
[HTTP_X_ESP8266_CHIP_SIZE] => 524288
|
||||||
[HTTP_X_ESP8266_SDK_VERSION] => 1.3.0
|
[HTTP_X_ESP8266_SDK_VERSION] => 1.3.0
|
||||||
[HTTP_X_ESP8266_VERSION] => DOOR-7-g14f53a19
|
[HTTP_X_ESP8266_VERSION] => DOOR-7-g14f53a19
|
||||||
```
|
```
|
||||||
|
|
||||||
With this information the script now can check if a update is needed. It is also possible to deliver different binaries based on the MAC address for example.
|
With this information the script now can check if a update is needed. It is also possible to deliver different binaries based on the MAC address for example.
|
||||||
|
|
||||||
Script example:
|
Script example:
|
||||||
```php
|
```php
|
||||||
<?PHP
|
<?PHP
|
||||||
|
|
||||||
header('Content-type: text/plain; charset=utf8', true);
|
header('Content-type: text/plain; charset=utf8', true);
|
||||||
|
|
||||||
function check_header($name, $value = false) {
|
function check_header($name, $value = false) {
|
||||||
if(!isset($_SERVER[$name])) {
|
if(!isset($_SERVER[$name])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if($value && $_SERVER[$name] != $value) {
|
if($value && $_SERVER[$name] != $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendFile($path) {
|
function sendFile($path) {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 200 OK', true, 200);
|
header($_SERVER["SERVER_PROTOCOL"].' 200 OK', true, 200);
|
||||||
header('Content-Type: application/octet-stream', true);
|
header('Content-Type: application/octet-stream', true);
|
||||||
header('Content-Disposition: attachment; filename='.basename($path));
|
header('Content-Disposition: attachment; filename='.basename($path));
|
||||||
header('Content-Length: '.filesize($path), true);
|
header('Content-Length: '.filesize($path), true);
|
||||||
readfile($path);
|
readfile($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!check_header('HTTP_USER_AGENT', 'ESP8266-http-Update')) {
|
if(!check_header('HTTP_USER_AGENT', 'ESP8266-http-Update')) {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
||||||
echo "only for ESP8266 updater!\n";
|
echo "only for ESP8266 updater!\n";
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if(
|
||||||
!check_header('HTTP_X_ESP8266_STA_MAC') ||
|
!check_header('HTTP_X_ESP8266_STA_MAC') ||
|
||||||
!check_header('HTTP_X_ESP8266_AP_MAC') ||
|
!check_header('HTTP_X_ESP8266_AP_MAC') ||
|
||||||
!check_header('HTTP_X_ESP8266_FREE_SPACE') ||
|
!check_header('HTTP_X_ESP8266_FREE_SPACE') ||
|
||||||
!check_header('HTTP_X_ESP8266_SKETCH_SIZE') ||
|
!check_header('HTTP_X_ESP8266_SKETCH_SIZE') ||
|
||||||
!check_header('HTTP_X_ESP8266_CHIP_SIZE') ||
|
!check_header('HTTP_X_ESP8266_CHIP_SIZE') ||
|
||||||
!check_header('HTTP_X_ESP8266_SDK_VERSION') ||
|
!check_header('HTTP_X_ESP8266_SDK_VERSION') ||
|
||||||
!check_header('HTTP_X_ESP8266_VERSION')
|
!check_header('HTTP_X_ESP8266_VERSION')
|
||||||
) {
|
) {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
||||||
echo "only for ESP8266 updater! (header)\n";
|
echo "only for ESP8266 updater! (header)\n";
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = array(
|
$db = array(
|
||||||
"18:FE:AA:AA:AA:AA" => "DOOR-7-g14f53a19",
|
"18:FE:AA:AA:AA:AA" => "DOOR-7-g14f53a19",
|
||||||
"18:FE:AA:AA:AA:BB" => "TEMP-1.0.0"
|
"18:FE:AA:AA:AA:BB" => "TEMP-1.0.0"
|
||||||
);
|
);
|
||||||
|
|
||||||
if(isset($db[$_SERVER['HTTP_X_ESP8266_STA_MAC']])) {
|
if(isset($db[$_SERVER['HTTP_X_ESP8266_STA_MAC']])) {
|
||||||
if($db[$_SERVER['HTTP_X_ESP8266_STA_MAC']] != $_SERVER['HTTP_X_ESP8266_VERSION']) ) {
|
if($db[$_SERVER['HTTP_X_ESP8266_STA_MAC']] != $_SERVER['HTTP_X_ESP8266_VERSION']) ) {
|
||||||
sendFile("./bin/".$db[$_SERVER['HTTP_X_ESP8266_STA_MAC']]."bin");
|
sendFile("./bin/".$db[$_SERVER['HTTP_X_ESP8266_STA_MAC']]."bin");
|
||||||
} else {
|
} else {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 304 Not Modified', true, 304);
|
header($_SERVER["SERVER_PROTOCOL"].' 304 Not Modified', true, 304);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 500 no version for ESP MAC', true, 500);
|
header($_SERVER["SERVER_PROTOCOL"].' 500 no version for ESP MAC', true, 500);
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Updater class
|
## Updater class
|
||||||
|
|
||||||
TODO describe Updater class
|
TODO describe Updater class
|