Skip to content

Commit 1c4b997

Browse files
authored
Merge pull request #325 from andreagilardoni/non-blocking-ota-download
Non blocking ota download
2 parents 428df2a + 3bd4ebd commit 1c4b997

File tree

5 files changed

+296
-0
lines changed

5 files changed

+296
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
OTANonBlocking
3+
4+
This sketch demonstrates how to make an OTA Update on the UNO R4 WiFi.
5+
Upload the sketch and wait for the invasion!
6+
7+
It requires at least version 0.5.0 of USB Wifi bridge firmware
8+
9+
*/
10+
11+
12+
#include "WiFiS3.h"
13+
#include "OTAUpdate.h"
14+
#include "root_ca.h"
15+
#include "arduino_secrets.h"
16+
17+
char ssid[] = SECRET_SSID; // your network SSID (name)
18+
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
19+
20+
int status = WL_IDLE_STATUS;
21+
22+
OTAUpdate ota;
23+
static char const OTA_FILE_LOCATION[] = "https://downloads.arduino.cc/ota/UNOR4WIFI_Animation.ota";
24+
25+
/* -------------------------------------------------------------------------- */
26+
void setup() {
27+
/* -------------------------------------------------------------------------- */
28+
//Initialize serial and wait for port to open:
29+
Serial.begin(115200);
30+
while (!Serial) {
31+
; // wait for serial port to connect. Needed for native USB port only
32+
}
33+
34+
// check for the Wi-Fi module:
35+
if (WiFi.status() == WL_NO_MODULE) {
36+
Serial.println("Communication with Wi-Fi module failed!");
37+
// don't continue
38+
while (true);
39+
}
40+
41+
String fv = WiFi.firmwareVersion();
42+
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
43+
Serial.println("Please upgrade the firmware");
44+
}
45+
46+
// attempt to connect to Wi-Fi network:
47+
while (status != WL_CONNECTED) {
48+
Serial.print("Attempting to connect to SSID: ");
49+
Serial.println(ssid);
50+
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
51+
status = WiFi.begin(ssid, pass);
52+
53+
// wait 1 seconds for connection:
54+
delay(1000);
55+
}
56+
57+
printWiFiStatus();
58+
59+
Serial.println("ota.begin()");
60+
int ret = ota.begin("/update.bin");
61+
if(ret != OTAUpdate::OTA_ERROR_NONE) {
62+
Serial.println("ota.begin() error: ");
63+
Serial.println((int)ret);
64+
return;
65+
}
66+
67+
Serial.println("ota.setCACert()");
68+
ret = ota.setCACert(root_ca);
69+
if(ret != OTAUpdate::OTA_ERROR_NONE) {
70+
Serial.println("ota.setCACert() error: ");
71+
Serial.println((int)ret);
72+
return;
73+
}
74+
75+
Serial.println("ota.startDownload()");
76+
int ota_size = ota.startDownload(OTA_FILE_LOCATION, "/update.bin");
77+
if(ota_size <= 0) {
78+
Serial.println("ota.startDownload() error: ");
79+
Serial.println(ota_size);
80+
Serial.println("Make sure your WiFi firmware version is at least 0.5.0");
81+
return;
82+
}
83+
84+
Serial.println("ota.downloadProgress()");
85+
while((ret = ota.downloadProgress()) < ota_size) {
86+
Serial.print("Progress ");
87+
Serial.print(ret);
88+
Serial.print("/");
89+
Serial.println(ota_size);
90+
delay(100);
91+
}
92+
93+
if(ret < 0){
94+
Serial.println("ota.downloadProgress() error: ");
95+
Serial.println((int)ret);
96+
return;
97+
}
98+
99+
Serial.println("ota.verify()");
100+
ret = ota.verify();
101+
if(ret != OTAUpdate::OTA_ERROR_NONE) {
102+
Serial.println("ota.verify() error: ");
103+
Serial.println((int)ret);
104+
return;
105+
}
106+
\
107+
Serial.println("ota.update()");
108+
ret = ota.update("/update.bin");
109+
if(ret != OTAUpdate::OTA_ERROR_NONE) {
110+
Serial.println("ota.update() error: ");
111+
Serial.println((int)ret);
112+
return;
113+
}
114+
}
115+
116+
/* -------------------------------------------------------------------------- */
117+
void loop() {
118+
/* -------------------------------------------------------------------------- */
119+
delay(1000);
120+
}
121+
122+
/* -------------------------------------------------------------------------- */
123+
void printWiFiStatus() {
124+
/* -------------------------------------------------------------------------- */
125+
// print the SSID of the network you're attached to:
126+
Serial.print("SSID: ");
127+
Serial.println(WiFi.SSID());
128+
129+
// print your board's IP address:
130+
IPAddress ip = WiFi.localIP();
131+
Serial.print("IP Address: ");
132+
Serial.println(ip);
133+
134+
// print the received signal strength:
135+
long rssi = WiFi.RSSI();
136+
Serial.print("signal strength (RSSI):");
137+
Serial.print(rssi);
138+
Serial.println(" dBm");
139+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define SECRET_SSID ""
2+
#define SECRET_PASS ""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
const char* root_ca = \
2+
/* GTS Root R1 */
3+
"-----BEGIN CERTIFICATE-----\n" \
4+
"MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" \
5+
"CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" \
6+
"MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" \
7+
"MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" \
8+
"Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" \
9+
"A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" \
10+
"27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" \
11+
"Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" \
12+
"TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" \
13+
"qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" \
14+
"szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" \
15+
"Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" \
16+
"MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" \
17+
"wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" \
18+
"aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" \
19+
"VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" \
20+
"AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" \
21+
"FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" \
22+
"C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" \
23+
"QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" \
24+
"h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" \
25+
"7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" \
26+
"ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" \
27+
"MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" \
28+
"Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" \
29+
"6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" \
30+
"0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" \
31+
"2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" \
32+
"bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" \
33+
"-----END CERTIFICATE-----\n" \
34+
/* GTS Root R2 */
35+
"-----BEGIN CERTIFICATE-----\n" \
36+
"MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw\n" \
37+
"CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" \
38+
"MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" \
39+
"MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" \
40+
"Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA\n" \
41+
"A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt\n" \
42+
"nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY\n" \
43+
"6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu\n" \
44+
"MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k\n" \
45+
"RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg\n" \
46+
"f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV\n" \
47+
"+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo\n" \
48+
"dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW\n" \
49+
"Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa\n" \
50+
"G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq\n" \
51+
"gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID\n" \
52+
"AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" \
53+
"FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H\n" \
54+
"vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8\n" \
55+
"0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC\n" \
56+
"B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u\n" \
57+
"NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg\n" \
58+
"yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev\n" \
59+
"HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6\n" \
60+
"xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR\n" \
61+
"TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg\n" \
62+
"JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV\n" \
63+
"7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl\n" \
64+
"6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL\n" \
65+
"-----END CERTIFICATE-----\n" \
66+
/* GTS Root R3 */
67+
"-----BEGIN CERTIFICATE-----\n" \
68+
"MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD\n" \
69+
"VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG\n" \
70+
"A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw\n" \
71+
"WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz\n" \
72+
"IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n" \
73+
"AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G\n" \
74+
"jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2\n" \
75+
"4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW\n" \
76+
"BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7\n" \
77+
"VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm\n" \
78+
"ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X\n" \
79+
"-----END CERTIFICATE-----\n" \
80+
/* GTS Root R4 */
81+
"-----BEGIN CERTIFICATE-----\n" \
82+
"MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD\n" \
83+
"VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG\n" \
84+
"A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw\n" \
85+
"WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz\n" \
86+
"IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n" \
87+
"AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi\n" \
88+
"QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR\n" \
89+
"HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW\n" \
90+
"BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D\n" \
91+
"9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8\n" \
92+
"p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD\n" \
93+
"-----END CERTIFICATE-----\n" \
94+
/* GlobalSign R4 */
95+
"-----BEGIN CERTIFICATE-----\n" \
96+
"MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD\n" \
97+
"VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh\n" \
98+
"bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw\n" \
99+
"MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g\n" \
100+
"UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT\n" \
101+
"BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx\n" \
102+
"uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV\n" \
103+
"HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/\n" \
104+
"+wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147\n" \
105+
"bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm\n" \
106+
"-----END CERTIFICATE-----\n";

libraries/OTAUpdate/src/OTAUpdate.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,49 @@ int OTAUpdate::download(const char* url, const char* file_path) {
8787
return ret;
8888
}
8989

90+
int OTAUpdate::startDownload(const char* url) {
91+
string res = "";
92+
int ret = -1;
93+
if ( url != nullptr && strlen(url) > 0) {
94+
modem.timeout(EXTENDED_MODEM_TIMEOUT);
95+
if(modem.write(string(PROMPT(_OTA_DOWNLOAD_START)), res, "%s%s\r\n", CMD_WRITE(_OTA_DOWNLOAD_START), url)) {
96+
ret = atoi(res.c_str());
97+
} else {
98+
ret = static_cast<int>(Error::Modem);
99+
}
100+
} else {
101+
ret = static_cast<int>(Error::Library);
102+
}
103+
modem.timeout(MODEM_TIMEOUT);
104+
return ret;
105+
}
106+
107+
int OTAUpdate::startDownload(const char* url, const char* file_path) {
108+
string res = "";
109+
int ret = -1;
110+
111+
if ( url != nullptr && strlen(url) > 0 && file_path != nullptr && strlen(file_path) >0) {
112+
modem.timeout(EXTENDED_MODEM_TIMEOUT);
113+
if(modem.write(string(PROMPT(_OTA_DOWNLOAD_START)), res, "%s%s,%s\r\n", CMD_WRITE(_OTA_DOWNLOAD_START), url, file_path)) {
114+
ret = atoi(res.c_str());
115+
} else {
116+
ret = static_cast<int>(Error::Modem);
117+
}
118+
} else {
119+
ret = static_cast<int>(Error::Library);
120+
}
121+
modem.timeout(MODEM_TIMEOUT);
122+
return ret;
123+
}
124+
125+
int OTAUpdate::downloadProgress() {
126+
string res = "";
127+
if (modem.write(string(PROMPT(_OTA_DOWNLOAD_PROGRESS)), res, "%s", CMD(_OTA_DOWNLOAD_PROGRESS))) {
128+
return atoi(res.c_str());
129+
}
130+
return static_cast<int>(Error::Modem);
131+
}
132+
90133
int OTAUpdate::verify() {
91134
string res = "";
92135
if (modem.write(string(PROMPT(_OTA_VERIFY)), res, "%s", CMD(_OTA_VERIFY))) {

libraries/OTAUpdate/src/OTAUpdate.h

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class OTAUpdate {
4242
int begin(const char* file_path);
4343
int download(const char* url);
4444
int download(const char* url, const char* file_path);
45+
46+
int startDownload(const char* url);
47+
int startDownload(const char* url, const char* file_path);
48+
49+
int downloadProgress();
50+
4551
int verify();
4652
int update();
4753
int update(const char* file_path);

0 commit comments

Comments
 (0)