Skip to content

Commit 78def8d

Browse files
authored
Merge pull request #15 from pennam/sven
Fix OTA binary header download timeout
2 parents 63ee8ca + 8994d20 commit 78def8d

File tree

11 files changed

+197
-4
lines changed

11 files changed

+197
-4
lines changed

Diff for: .github/workflows/compile-examples.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ jobs:
4949
libraries: |
5050
- name: Arduino_DebugUtils
5151
sketch-paths: |
52-
- examples/OTA
52+
- examples/OTA_Arduino_Server
53+
- examples/OTA_GitHub_Server
5354
- examples/LOLIN_32_Blink
5455
- board:
5556
type: arduino_esp32
@@ -58,7 +59,8 @@ jobs:
5859
libraries: |
5960
- name: Arduino_DebugUtils
6061
sketch-paths: |
61-
- examples/OTA
62+
- examples/OTA_Arduino_Server
63+
- examples/OTA_GitHub_Server
6264
- examples/NANO_ESP32_Blink
6365
6466
steps:

Diff for: examples/LOLIN_32_Blink/LOLIN_32_Blink.ino.ota

159 KB
Binary file not shown.

Diff for: examples/NANO_ESP32_Blink/NANO_ESP32_Blink.ino.ota

197 KB
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.

Diff for: examples/OTA_GitHub_Server/OTA_GitHub_Server.ino

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* This example demonstrates how to use to update the firmware using Arduino_ESP_OTA library
3+
*
4+
* Steps:
5+
* 1) Create a sketch for your ESP board and verify
6+
* that it both compiles and works.
7+
* 2) In the IDE select: Sketch -> Export compiled Binary.
8+
* 3) Create an OTA update file utilising the tools 'lzss.py' and 'bin2ota.py' stored in
9+
* https://github.com/arduino-libraries/ArduinoIoTCloud/tree/master/extras/tools .
10+
* A) ./lzss.py --encode SKETCH.bin SKETCH.lzss
11+
* B) ./bin2ota.py ESP SKETCH.lzss SKETCH.ota
12+
* 4) Upload the OTA file to a network reachable location, e.g. LOLIN_32_Blink.ino.ota
13+
* has been uploaded to: http://downloads.arduino.cc/ota/LOLIN_32_Blink.ino.ota
14+
* 5) Verify if a custom ca_cert is needed by default Amazon root CA are used
15+
* https://www.amazontrust.com/repository/
16+
* 6) Perform an OTA update via steps outlined below.
17+
*/
18+
19+
/******************************************************************************
20+
* INCLUDE
21+
******************************************************************************/
22+
23+
#include <Arduino_ESP32_OTA.h>
24+
25+
#include <WiFi.h>
26+
27+
#include "arduino_secrets.h"
28+
29+
#include "root_ca.h"
30+
31+
/******************************************************************************
32+
* CONSTANT
33+
******************************************************************************/
34+
35+
/* Please enter your sensitive data in the Secret tab/arduino_secrets.h */
36+
static char const SSID[] = SECRET_SSID; /* your network SSID (name) */
37+
static char const PASS[] = SECRET_PASS; /* your network password (use for WPA, or use as key for WEP) */
38+
39+
40+
#if defined(ARDUINO_NANO_ESP32)
41+
static char const OTA_FILE_LOCATION[] = "https://raw.githubusercontent.com/arduino-libraries/Arduino_ESP32_OTA/main/examples/NANO_ESP32_Blink/NANO_ESP32_Blink.ino.ota";
42+
#else
43+
static char const OTA_FILE_LOCATION[] = "https://raw.githubusercontent.com/arduino-libraries/Arduino_ESP32_OTA/main/examples/LOLIN_32_Blink/LOLIN_32_Blink.ino.ota";
44+
#endif
45+
46+
/******************************************************************************
47+
* SETUP/LOOP
48+
******************************************************************************/
49+
50+
void setup()
51+
{
52+
Serial.begin(9600);
53+
while (!Serial) {}
54+
55+
while (WiFi.status() != WL_CONNECTED)
56+
{
57+
Serial.print ("Attempting to connect to '");
58+
Serial.print (SSID);
59+
Serial.println("'");
60+
WiFi.begin(SSID, PASS);
61+
delay(2000);
62+
}
63+
Serial.print ("You're connected to '");
64+
Serial.print (WiFi.SSID());
65+
Serial.println("'");
66+
67+
Arduino_ESP32_OTA ota;
68+
Arduino_ESP32_OTA::Error ota_err = Arduino_ESP32_OTA::Error::None;
69+
70+
/* Configure custom Root CA */
71+
ota.setCACert(root_ca);
72+
73+
Serial.println("Initializing OTA storage");
74+
if ((ota_err = ota.begin()) != Arduino_ESP32_OTA::Error::None)
75+
{
76+
Serial.print ("Arduino_ESP_OTA::begin() failed with error code ");
77+
Serial.println((int)ota_err);
78+
return;
79+
}
80+
81+
82+
Serial.println("Starting download to flash ...");
83+
int const ota_download = ota.download(OTA_FILE_LOCATION);
84+
if (ota_download <= 0)
85+
{
86+
Serial.print ("Arduino_ESP_OTA::download failed with error code ");
87+
Serial.println(ota_download);
88+
return;
89+
}
90+
Serial.print (ota_download);
91+
Serial.println(" bytes stored.");
92+
93+
94+
Serial.println("Verify update integrity and apply ...");
95+
if ((ota_err = ota.update()) != Arduino_ESP32_OTA::Error::None)
96+
{
97+
Serial.print ("ota.update() failed with error code ");
98+
Serial.println((int)ota_err);
99+
return;
100+
}
101+
102+
Serial.println("Performing a reset after which the bootloader will start the new firmware.");
103+
#if defined(ARDUINO_NANO_ESP32)
104+
Serial.println("Hint: Arduino NANO ESP32 will blink Red Green and Blue.");
105+
#else
106+
Serial.println("Hint: LOLIN32 will blink Blue.");
107+
#endif
108+
delay(1000); /* Make sure the serial message gets out before the reset. */
109+
ota.reset();
110+
}
111+
112+
void loop()
113+
{
114+
115+
}

Diff for: examples/OTA_GitHub_Server/arduino_secrets.h

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define SECRET_SSID ""
2+
#define SECRET_PASS ""

Diff for: examples/OTA_GitHub_Server/root_ca.h

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const char* root_ca = \
2+
/*DigiCert TLS Hybrid ECC SHA384 2020 CA1*/
3+
"-----BEGIN CERTIFICATE-----\n" \
4+
"MIIEFzCCAv+gAwIBAgIQB/LzXIeod6967+lHmTUlvTANBgkqhkiG9w0BAQwFADBh\n" \
5+
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \
6+
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \
7+
"QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaMFYxCzAJBgNVBAYTAlVT\n" \
8+
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMDAuBgNVBAMTJ0RpZ2lDZXJ0IFRMUyBI\n" \
9+
"eWJyaWQgRUNDIFNIQTM4NCAyMDIwIENBMTB2MBAGByqGSM49AgEGBSuBBAAiA2IA\n" \
10+
"BMEbxppbmNmkKaDp1AS12+umsmxVwP/tmMZJLwYnUcu/cMEFesOxnYeJuq20ExfJ\n" \
11+
"qLSDyLiQ0cx0NTY8g3KwtdD3ImnI8YDEe0CPz2iHJlw5ifFNkU3aiYvkA8ND5b8v\n" \
12+
"c6OCAYIwggF+MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAq8CCkXjKU5\n" \
13+
"bXoOzjPHLrPt+8N6MB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA4G\n" \
14+
"A1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYI\n" \
15+
"KwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j\n" \
16+
"b20wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp\n" \
17+
"Q2VydEdsb2JhbFJvb3RDQS5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny\n" \
18+
"bDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDA9BgNVHSAE\n" \
19+
"NjA0MAsGCWCGSAGG/WwCATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgG\n" \
20+
"BmeBDAECAzANBgkqhkiG9w0BAQwFAAOCAQEAR1mBf9QbH7Bx9phdGLqYR5iwfnYr\n" \
21+
"6v8ai6wms0KNMeZK6BnQ79oU59cUkqGS8qcuLa/7Hfb7U7CKP/zYFgrpsC62pQsY\n" \
22+
"kDUmotr2qLcy/JUjS8ZFucTP5Hzu5sn4kL1y45nDHQsFfGqXbbKrAjbYwrwsAZI/\n" \
23+
"BKOLdRHHuSm8EdCGupK8JvllyDfNJvaGEwwEqonleLHBTnm8dqMLUeTF0J5q/hos\n" \
24+
"Vq4GNiejcxwIfZMy0MJEGdqN9A57HSgDKwmKdsp33Id6rHtSJlWncg+d0ohP/rEh\n" \
25+
"xRqhqjn1VtvChMQ1H3Dau0bwhr9kAMQ+959GG50jBbl9s08PqUU643QwmA==\n" \
26+
"-----END CERTIFICATE-----\n"
27+
/*DigiCert TLS RSA SHA256 2020 CA1*/
28+
"-----BEGIN CERTIFICATE-----\n" \
29+
"MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBh\n" \
30+
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \
31+
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \
32+
"QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaME8xCzAJBgNVBAYTAlVT\n" \
33+
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBS\n" \
34+
"U0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\n" \
35+
"AQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6a\n" \
36+
"qXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddn\n" \
37+
"g9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuW\n" \
38+
"raKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGB\n" \
39+
"Afr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21r\n" \
40+
"eacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBgjCCAX4wEgYDVR0TAQH/BAgwBgEB\n" \
41+
"/wIBADAdBgNVHQ4EFgQUt2ui6qiqhIx56rTaD5iyxZV2ufQwHwYDVR0jBBgwFoAU\n" \
42+
"A95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG\n" \
43+
"CCsGAQUFBwMBBggrBgEFBQcDAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGG\n" \
44+
"GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2Nh\n" \
45+
"Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDBCBgNV\n" \
46+
"HR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRH\n" \
47+
"bG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwCwYJYIZIAYb9bAIBMAcGBWeBDAEB\n" \
48+
"MAgGBmeBDAECATAIBgZngQwBAgIwCAYGZ4EMAQIDMA0GCSqGSIb3DQEBCwUAA4IB\n" \
49+
"AQCAMs5eC91uWg0Kr+HWhMvAjvqFcO3aXbMM9yt1QP6FCvrzMXi3cEsaiVi6gL3z\n" \
50+
"ax3pfs8LulicWdSQ0/1s/dCYbbdxglvPbQtaCdB73sRD2Cqk3p5BJl+7j5nL3a7h\n" \
51+
"qG+fh/50tx8bIKuxT8b1Z11dmzzp/2n3YWzW2fP9NsarA4h20ksudYbj/NhVfSbC\n" \
52+
"EXffPgK2fPOre3qGNm+499iTcc+G33Mw+nur7SpZyEKEOxEXGlLzyQ4UfaJbcme6\n" \
53+
"ce1XR2bFuAJKZTRei9AqPCCcUZlM51Ke92sRKw2Sfh3oius2FkOH6ipjv3U/697E\n" \
54+
"A7sKPPcw7+uvTPyLNhBzPvOk\n" \
55+
"-----END CERTIFICATE-----\n";

Diff for: src/Arduino_ESP32_OTA.cpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,30 @@ int Arduino_ESP32_OTA::download(const char * ota_url)
182182
DEBUG_VERBOSE("%s: Length of OTA binary according to HTTP header = %d bytes", __FUNCTION__, content_length_val);
183183

184184
/* Read the OTA header ... */
185-
_client->read(_ota_header.buf, sizeof(OtaHeader));
185+
bool is_ota_header_timeout = false;
186+
unsigned long const start = millis();
187+
for (int i = 0; i < sizeof(OtaHeader);)
188+
{
189+
is_ota_header_timeout = (millis() - start) > ARDUINO_ESP32_OTA_BINARY_HEADER_RECEIVE_TIMEOUT_ms;
190+
if (is_ota_header_timeout) break;
191+
192+
if (_client->available())
193+
{
194+
_ota_header.buf[i++] = _client->read();
195+
}
196+
}
197+
198+
/* ... check for header download timeout ... */
199+
if (is_ota_header_timeout) {
200+
return static_cast<int>(Error::OtaHeaderTimeout);
201+
}
186202

187-
/* ... and check first length ... */
203+
/* ... then check if OTA header length field matches HTTP content length... */
188204
if (_ota_header.header.len != (content_length_val - sizeof(_ota_header.header.len) - sizeof(_ota_header.header.crc32))) {
189205
return static_cast<int>(Error::OtaHeaderLength);
190206
}
191207

208+
/* ... and OTA magic number */
192209
if (_ota_header.header.magic_number != ARDUINO_ESP32_OTA_MAGIC)
193210
{
194211
return static_cast<int>(Error::OtaHeaterMagicNumber);

Diff for: src/Arduino_ESP32_OTA.h

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
******************************************************************************/
4040

4141
static uint32_t const ARDUINO_ESP32_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms = 10000;
42+
static uint32_t const ARDUINO_ESP32_OTA_BINARY_HEADER_RECEIVE_TIMEOUT_ms = 10000;
4243
static uint32_t const ARDUINO_ESP32_OTA_BINARY_BYTE_RECEIVE_TIMEOUT_ms = 2000;
4344

4445
/******************************************************************************
@@ -71,6 +72,7 @@ class Arduino_ESP32_OTA
7172
OtaHeaderCrc = -10,
7273
OtaHeaterMagicNumber = -11,
7374
OtaDownload = -12,
75+
OtaHeaderTimeout = -13
7476
};
7577

7678
Arduino_ESP32_OTA();

0 commit comments

Comments
 (0)