Skip to content

Commit 8965358

Browse files
arvindr21me-no-dev
authored andcommitted
added OTA Update S3 example with a sample bin (espressif#445)
* added OTA Update S3 example with a sample bin * Update as per comments
1 parent bf60ca7 commit 8965358

File tree

2 files changed

+276
-0
lines changed

2 files changed

+276
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
/**
2+
AWS S3 OTA Update
3+
Date: 14th June 2017
4+
Author: Arvind Ravulavaru <https://github.com/arvindr21>
5+
Purpose: Perform an OTA update from a bin located in Amazon S3 (HTTP Only)
6+
7+
Upload:
8+
Step 1 : Download the sample bin file from the examples folder
9+
Step 2 : Upload it to your Amazon S3 account, in a bucket of your choice
10+
Step 3 : Once uploaded, inside S3, select the bin file >> More (button on top of the file list) >> Make Public
11+
Step 4 : You S3 URL => http://bucket-name.s3.ap-south-1.amazonaws.com/sketch-name.ino.bin
12+
Step 5 : Build the above URL and fire it either in your browser or curl it `curl -I -v http://bucket-name.ap-south-1.amazonaws.com/sketch-name.ino.bin` to validate the same
13+
Step 6: Plug in your SSID, Password, S3 Host and Bin file below
14+
15+
Build & upload
16+
Step 1 : Menu > Sketch > Export Compiled Library. The bin file will be saved in the sketch folder (Menu > Sketch > Show Sketch folder)
17+
Step 2 : Upload bin to S3 and continue the above process
18+
19+
// Check the bottom of this sketch for sample serial monitor log, during and after successful OTA Update
20+
*/
21+
22+
#include <WiFi.h>
23+
#include <Update.h>
24+
25+
WiFiClient client;
26+
27+
// Variables to validate
28+
// response from S3
29+
int contentLength = 0;
30+
bool isValidContentType = false;
31+
32+
// Your SSID and PSWD that the chip needs
33+
// to connect to
34+
char* SSID = "YOUR-SSID";
35+
char* PSWD = "YOUR-SSID-PSWD";
36+
37+
// S3 Bucket Config
38+
String host = "bucket-name.s3.ap-south-1.amazonaws.com"; // Host => bucket-name.s3.region.amazonaws.com
39+
int port = 80; // Non https. For HTTPS 443. As of today, HTTPS doesn't work.
40+
String bin = "/sketch-name.ino.bin"; // bin file name with a slash in front.
41+
42+
// Utility to extract header value from headers
43+
String getHeaderValue(String header, String headerName) {
44+
return header.substring(strlen(headerName.c_str()));
45+
}
46+
47+
// OTA Logic
48+
void execOTA() {
49+
Serial.println("Connecting to: " + String(host));
50+
// Connect to S3
51+
if (client.connect(host.c_str(), port)) {
52+
// Connection Succeed.
53+
// Fecthing the bin
54+
Serial.println("Fetching Bin: " + String(bin));
55+
56+
// Get the contents of the bin file
57+
client.print(String("GET ") + bin + " HTTP/1.1\r\n" +
58+
"Host: " + host + "\r\n" +
59+
"Cache-Control: no-cache\r\n" +
60+
"Connection: close\r\n\r\n");
61+
62+
// Check what is being sent
63+
// Serial.print(String("GET ") + bin + " HTTP/1.1\r\n" +
64+
// "Host: " + host + "\r\n" +
65+
// "Cache-Control: no-cache\r\n" +
66+
// "Connection: close\r\n\r\n");
67+
68+
delay(100);
69+
// Once the response is available,
70+
// check stuff
71+
72+
/*
73+
Response Structure
74+
HTTP/1.1 200 OK
75+
x-amz-id-2: NVKxnU1aIQMmpGKhSwpCBh8y2JPbak18QLIfE+OiUDOos+7UftZKjtCFqrwsGOZRN5Zee0jpTd0=
76+
x-amz-request-id: 2D56B47560B764EC
77+
Date: Wed, 14 Jun 2017 03:33:59 GMT
78+
Last-Modified: Fri, 02 Jun 2017 14:50:11 GMT
79+
ETag: "d2afebbaaebc38cd669ce36727152af9"
80+
Accept-Ranges: bytes
81+
Content-Type: application/octet-stream
82+
Content-Length: 357280
83+
Server: AmazonS3
84+
85+
{{BIN FILE CONTENTS}}
86+
87+
*/
88+
while (client.available()) {
89+
// read line till /n
90+
String line = client.readStringUntil('\n');
91+
// remove space, to check if the line is end of headers
92+
line.trim();
93+
94+
// if the the line is empty,
95+
// this is end of headers
96+
// break the while and feed the
97+
// remaining `client` to the
98+
// Update.writeStream();
99+
if (!line.length()) {
100+
//headers ended
101+
break; // and get the OTA started
102+
}
103+
104+
// Check if the HTTP Response is 200
105+
// else break and Exit Update
106+
if (line.startsWith("HTTP/1.1")) {
107+
if (line.indexOf("200") < 0) {
108+
Serial.println("Got a non 200 status code from server. Exiting OTA Update.");
109+
break;
110+
}
111+
}
112+
113+
// extract headers here
114+
// Start with content length
115+
if (line.startsWith("Content-Length: ")) {
116+
contentLength = atoi((getHeaderValue(line, "Content-Length: ")).c_str());
117+
Serial.println("Got " + String(contentLength) + " bytes from server");
118+
}
119+
120+
// Next, the content type
121+
if (line.startsWith("Content-Type: ")) {
122+
String contentType = getHeaderValue(line, "Content-Type: ");
123+
Serial.println("Got " + contentType + " payload.");
124+
if (contentType == "application/octet-stream") {
125+
isValidContentType = true;
126+
}
127+
}
128+
}
129+
} else {
130+
// Connect to S3 failed
131+
// May be try?
132+
// Probably a choppy network?
133+
Serial.println("Connection to " + String(host) + " failed. Please check your setup");
134+
// retry??
135+
// execOTA();
136+
}
137+
138+
// Check what is the contentLength and if content type is `application/octet-stream`
139+
Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType));
140+
141+
// check contentLength and content type
142+
if (contentLength && isValidContentType) {
143+
// Check if there is enough to OTA Update
144+
bool canBegin = Update.begin(contentLength);
145+
146+
// If yes, begin
147+
if (canBegin) {
148+
Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!");
149+
// No activity would appear on the Serial monitor
150+
// So be patient. This may take 2 - 5mins to complete
151+
size_t written = Update.writeStream(client);
152+
153+
if (written == contentLength) {
154+
Serial.println("Written : " + String(written) + " successfully");
155+
} else {
156+
Serial.println("Written only : " + String(written) + "/" + String(contentLength) + ". Retry?" );
157+
// retry??
158+
// execOTA();
159+
}
160+
161+
if (Update.end()) {
162+
Serial.println("OTA done!");
163+
if (Update.isFinished()) {
164+
Serial.println("Update successfully completed. Rebooting.");
165+
ESP.restart();
166+
} else {
167+
Serial.println("Update not finished? Something went wrong!");
168+
}
169+
} else {
170+
Serial.println("Error Occurred. Error #: " + String(Update.getError()));
171+
}
172+
} else {
173+
// not enough space to begin OTA
174+
// Understand the partitions and
175+
// space availability
176+
Serial.println("Not enough space to begin OTA");
177+
client.flush();
178+
}
179+
} else {
180+
Serial.println("There was no content in the response");
181+
client.flush();
182+
}
183+
}
184+
185+
void setup() {
186+
//Begin Serial
187+
Serial.begin(115200);
188+
delay(10);
189+
190+
Serial.println("Connecting to " + String(SSID));
191+
192+
// Connect to provided SSID and PSWD
193+
WiFi.begin(SSID, PSWD);
194+
195+
// Wait for connection to establish
196+
while (WiFi.status() != WL_CONNECTED) {
197+
Serial.print("."); // Keep the serial monitor lit!
198+
delay(500);
199+
}
200+
201+
// Connection Succeed
202+
Serial.println("");
203+
Serial.println("Connected to " + String(SSID));
204+
205+
// Execute OTA Update
206+
execOTA();
207+
}
208+
209+
void loop() {
210+
// chill
211+
}
212+
213+
/*
214+
* Serial Monitor log for this sketch
215+
*
216+
* If the OTA succeeded, it would load the preference sketch, with a small modification. i.e.
217+
* Print `OTA Update succeeded!! This is an example sketch : Preferences > StartCounter`
218+
* And then keeps on restarting every 10 seconds, updating the preferences
219+
*
220+
*
221+
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
222+
configsip: 0, SPIWP:0x00
223+
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
224+
mode:DIO, clock div:1
225+
load:0x3fff0008,len:8
226+
load:0x3fff0010,len:160
227+
load:0x40078000,len:10632
228+
load:0x40080000,len:252
229+
entry 0x40080034
230+
Connecting to SSID
231+
......
232+
Connected to SSID
233+
Connecting to: bucket-name.s3.ap-south-1.amazonaws.com
234+
Fetching Bin: /StartCounter.ino.bin
235+
Got application/octet-stream payload.
236+
Got 357280 bytes from server
237+
contentLength : 357280, isValidContentType : 1
238+
Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!
239+
Written : 357280 successfully
240+
OTA done!
241+
Update successfully completed. Rebooting.
242+
ets Jun 8 2016 00:22:57
243+
244+
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
245+
configsip: 0, SPIWP:0x00
246+
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
247+
mode:DIO, clock div:1
248+
load:0x3fff0008,len:8
249+
load:0x3fff0010,len:160
250+
load:0x40078000,len:10632
251+
load:0x40080000,len:252
252+
entry 0x40080034
253+
254+
OTA Update succeeded!! This is an example sketch : Preferences > StartCounter
255+
Current counter value: 1
256+
Restarting in 10 seconds...
257+
E (102534) wifi: esp_wifi_stop 802 wifi is not init
258+
ets Jun 8 2016 00:22:57
259+
260+
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
261+
configsip: 0, SPIWP:0x00
262+
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
263+
mode:DIO, clock div:1
264+
load:0x3fff0008,len:8
265+
load:0x3fff0010,len:160
266+
load:0x40078000,len:10632
267+
load:0x40080000,len:252
268+
entry 0x40080034
269+
270+
OTA Update succeeded!! This is an example sketch : Preferences > StartCounter
271+
Current counter value: 2
272+
Restarting in 10 seconds...
273+
274+
....
275+
*
276+
*/
Binary file not shown.

0 commit comments

Comments
 (0)