diff --git a/libraries/Update/examples/AWS_S3_OTA_Update/AWS_S3_OTA_Update.ino b/libraries/Update/examples/AWS_S3_OTA_Update/AWS_S3_OTA_Update.ino new file mode 100644 index 00000000..432f2eeb --- /dev/null +++ b/libraries/Update/examples/AWS_S3_OTA_Update/AWS_S3_OTA_Update.ino @@ -0,0 +1,276 @@ +/** + AWS S3 OTA Update + Date: 14th June 2017 + Author: Arvind Ravulavaru + Purpose: Perform an OTA update from a bin located in Amazon S3 (HTTP Only) + + Upload: + Step 1 : Download the sample bin file from the examples folder + Step 2 : Upload it to your Amazon S3 account, in a bucket of your choice + Step 3 : Once uploaded, inside S3, select the bin file >> More (button on top of the file list) >> Make Public + Step 4 : You S3 URL => http://bucket-name.s3.ap-south-1.amazonaws.com/sketch-name.ino.bin + 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 + Step 6: Plug in your SSID, Password, S3 Host and Bin file below + + Build & upload + Step 1 : Menu > Sketch > Export Compiled Library. The bin file will be saved in the sketch folder (Menu > Sketch > Show Sketch folder) + Step 2 : Upload bin to S3 and continue the above process + + // Check the bottom of this sketch for sample serial monitor log, during and after successful OTA Update +*/ + +#include +#include + +WiFiClient client; + +// Variables to validate +// response from S3 +int contentLength = 0; +bool isValidContentType = false; + +// Your SSID and PSWD that the chip needs +// to connect to +char* SSID = "YOUR-SSID"; +char* PSWD = "YOUR-SSID-PSWD"; + +// S3 Bucket Config +String host = "bucket-name.s3.ap-south-1.amazonaws.com"; // Host => bucket-name.s3.region.amazonaws.com +int port = 80; // Non https. For HTTPS 443. As of today, HTTPS doesn't work. +String bin = "/sketch-name.ino.bin"; // bin file name with a slash in front. + +// Utility to extract header value from headers +String getHeaderValue(String header, String headerName) { + return header.substring(strlen(headerName.c_str())); +} + +// OTA Logic +void execOTA() { + Serial.println("Connecting to: " + String(host)); + // Connect to S3 + if (client.connect(host.c_str(), port)) { + // Connection Succeed. + // Fecthing the bin + Serial.println("Fetching Bin: " + String(bin)); + + // Get the contents of the bin file + client.print(String("GET ") + bin + " HTTP/1.1\r\n" + + "Host: " + host + "\r\n" + + "Cache-Control: no-cache\r\n" + + "Connection: close\r\n\r\n"); + + // Check what is being sent + // Serial.print(String("GET ") + bin + " HTTP/1.1\r\n" + + // "Host: " + host + "\r\n" + + // "Cache-Control: no-cache\r\n" + + // "Connection: close\r\n\r\n"); + + delay(100); + // Once the response is available, + // check stuff + + /* + Response Structure + HTTP/1.1 200 OK + x-amz-id-2: NVKxnU1aIQMmpGKhSwpCBh8y2JPbak18QLIfE+OiUDOos+7UftZKjtCFqrwsGOZRN5Zee0jpTd0= + x-amz-request-id: 2D56B47560B764EC + Date: Wed, 14 Jun 2017 03:33:59 GMT + Last-Modified: Fri, 02 Jun 2017 14:50:11 GMT + ETag: "d2afebbaaebc38cd669ce36727152af9" + Accept-Ranges: bytes + Content-Type: application/octet-stream + Content-Length: 357280 + Server: AmazonS3 + + {{BIN FILE CONTENTS}} + + */ + while (client.available()) { + // read line till /n + String line = client.readStringUntil('\n'); + // remove space, to check if the line is end of headers + line.trim(); + + // if the the line is empty, + // this is end of headers + // break the while and feed the + // remaining `client` to the + // Update.writeStream(); + if (!line.length()) { + //headers ended + break; // and get the OTA started + } + + // Check if the HTTP Response is 200 + // else break and Exit Update + if (line.startsWith("HTTP/1.1")) { + if (line.indexOf("200") < 0) { + Serial.println("Got a non 200 status code from server. Exiting OTA Update."); + break; + } + } + + // extract headers here + // Start with content length + if (line.startsWith("Content-Length: ")) { + contentLength = atoi((getHeaderValue(line, "Content-Length: ")).c_str()); + Serial.println("Got " + String(contentLength) + " bytes from server"); + } + + // Next, the content type + if (line.startsWith("Content-Type: ")) { + String contentType = getHeaderValue(line, "Content-Type: "); + Serial.println("Got " + contentType + " payload."); + if (contentType == "application/octet-stream") { + isValidContentType = true; + } + } + } + } else { + // Connect to S3 failed + // May be try? + // Probably a choppy network? + Serial.println("Connection to " + String(host) + " failed. Please check your setup"); + // retry?? + // execOTA(); + } + + // Check what is the contentLength and if content type is `application/octet-stream` + Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType)); + + // check contentLength and content type + if (contentLength && isValidContentType) { + // Check if there is enough to OTA Update + bool canBegin = Update.begin(contentLength); + + // If yes, begin + if (canBegin) { + Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!"); + // No activity would appear on the Serial monitor + // So be patient. This may take 2 - 5mins to complete + size_t written = Update.writeStream(client); + + if (written == contentLength) { + Serial.println("Written : " + String(written) + " successfully"); + } else { + Serial.println("Written only : " + String(written) + "/" + String(contentLength) + ". Retry?" ); + // retry?? + // execOTA(); + } + + if (Update.end()) { + Serial.println("OTA done!"); + if (Update.isFinished()) { + Serial.println("Update successfully completed. Rebooting."); + ESP.restart(); + } else { + Serial.println("Update not finished? Something went wrong!"); + } + } else { + Serial.println("Error Occurred. Error #: " + String(Update.getError())); + } + } else { + // not enough space to begin OTA + // Understand the partitions and + // space availability + Serial.println("Not enough space to begin OTA"); + client.flush(); + } + } else { + Serial.println("There was no content in the response"); + client.flush(); + } +} + +void setup() { + //Begin Serial + Serial.begin(115200); + delay(10); + + Serial.println("Connecting to " + String(SSID)); + + // Connect to provided SSID and PSWD + WiFi.begin(SSID, PSWD); + + // Wait for connection to establish + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); // Keep the serial monitor lit! + delay(500); + } + + // Connection Succeed + Serial.println(""); + Serial.println("Connected to " + String(SSID)); + + // Execute OTA Update + execOTA(); +} + +void loop() { + // chill +} + +/* + * Serial Monitor log for this sketch + * + * If the OTA succeeded, it would load the preference sketch, with a small modification. i.e. + * Print `OTA Update succeeded!! This is an example sketch : Preferences > StartCounter` + * And then keeps on restarting every 10 seconds, updating the preferences + * + * + rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0x00 + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:1 + load:0x3fff0008,len:8 + load:0x3fff0010,len:160 + load:0x40078000,len:10632 + load:0x40080000,len:252 + entry 0x40080034 + Connecting to SSID + ...... + Connected to SSID + Connecting to: bucket-name.s3.ap-south-1.amazonaws.com + Fetching Bin: /StartCounter.ino.bin + Got application/octet-stream payload. + Got 357280 bytes from server + contentLength : 357280, isValidContentType : 1 + Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience! + Written : 357280 successfully + OTA done! + Update successfully completed. Rebooting. + ets Jun 8 2016 00:22:57 + + rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0x00 + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:1 + load:0x3fff0008,len:8 + load:0x3fff0010,len:160 + load:0x40078000,len:10632 + load:0x40080000,len:252 + entry 0x40080034 + + OTA Update succeeded!! This is an example sketch : Preferences > StartCounter + Current counter value: 1 + Restarting in 10 seconds... + E (102534) wifi: esp_wifi_stop 802 wifi is not init + ets Jun 8 2016 00:22:57 + + rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0x00 + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:1 + load:0x3fff0008,len:8 + load:0x3fff0010,len:160 + load:0x40078000,len:10632 + load:0x40080000,len:252 + entry 0x40080034 + + OTA Update succeeded!! This is an example sketch : Preferences > StartCounter + Current counter value: 2 + Restarting in 10 seconds... + + .... + * + */ diff --git a/libraries/Update/examples/AWS_S3_OTA_Update/StartCounter.ino.bin b/libraries/Update/examples/AWS_S3_OTA_Update/StartCounter.ino.bin new file mode 100644 index 00000000..14732a0a Binary files /dev/null and b/libraries/Update/examples/AWS_S3_OTA_Update/StartCounter.ino.bin differ