forked from arduino/ArduinoCore-samd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
227 changes: 227 additions & 0 deletions
227
libraries/SSU/examples/SSU_LZSS_HttpOta/SSU_LZSS_HttpOta.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
/* | ||
Small example sketch demonstrating how to perform OTA via HTTP/S | ||
utilizing a MKRGSM 1400 and the storage on the integrated | ||
SARA U-201 GSM module. | ||
Please, be careful because no verification is done on the | ||
received OTA file, apart size verification of the transmitted | ||
bytes using the HTTP Content-Length header. | ||
For production-grade OTA procedure you might want to implement | ||
a content verification procedure using a CRC calculation | ||
or an hash (eg. MD5 or SHA256) comparison. | ||
Circuit: | ||
* MKR GSM 1400 board | ||
* Antenna | ||
* SIM card with a data plan | ||
Steps to update a sketch: | ||
1) Create a new sketch or update an existing one to be updated over-the-air. | ||
The sketch needs to contain also the code below for future OTAs. | ||
The sketch must include the SSU library via | ||
#include <SSU.h> | ||
2) In the IDE select: Sketch -> Export compiled Binary. | ||
3) Open the location of the sketch (Sketch -> Show Sketch Folder) and upload | ||
the .bin file to your HTTP/S server. | ||
4) Upload this sketch after configuring the server, port and filename variables. | ||
The sketch will download the OTA file, store it into the U-201 storage, and | ||
will reset the board to trigger the SSU update procedure. | ||
created 25 June 2020 | ||
by Giampaolo Mancini | ||
*/ | ||
|
||
#include <MKRGSM.h> | ||
|
||
// This includes triggers the firmware update procedure | ||
// in the bootloader after reset. | ||
#include <SSU.h> | ||
|
||
// Do not change! SSU will look for these files! | ||
constexpr char UPDATE_FILE_NAME[] = "UPDATE.BIN.LZSS"; | ||
static constexpr char CHECK_FILE_NAME[] = "UPDATE.OK"; | ||
|
||
#include "arduino_secrets.h" | ||
const char PINNUMBER[] = SECRET_PINNUMBER; | ||
// APN data | ||
const char GPRS_APN[] = SECRET_GPRS_APN; | ||
const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; | ||
const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; | ||
|
||
// Change to GSMClient for non-SSL/TLS connection. | ||
// Not recommended. | ||
GSMSSLClient client; | ||
GPRS gprs; | ||
GSM gsmAccess; | ||
|
||
GSMFileUtils fileUtils; | ||
|
||
bool isHeaderComplete = false; | ||
String httpHeader; | ||
|
||
bool isDownloadComplete = false; | ||
unsigned int fileSize = 0; | ||
unsigned int totalWritten = 0; | ||
|
||
constexpr char server[] = "example.org"; | ||
constexpr int port = 443; | ||
|
||
// Name of the new firmware file to be updated. | ||
constexpr char filename[] = "update.lzss"; | ||
|
||
|
||
void setup() | ||
{ | ||
unsigned long timeout = millis(); | ||
|
||
Serial.begin(9600); | ||
while (!Serial && millis() - timeout < 5000) | ||
; | ||
|
||
Serial.println("Starting OTA Update via HTTP and Arduino SSU."); | ||
Serial.println(); | ||
|
||
bool connected = false; | ||
|
||
Serial.print("Connecting to cellular network... "); | ||
while (!connected) { | ||
if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { | ||
connected = true; | ||
} else { | ||
Serial.println("Not connected"); | ||
delay(1000); | ||
} | ||
} | ||
|
||
Serial.println("Connected."); | ||
Serial.println(); | ||
|
||
// Modem has already been initialized in the sketch: | ||
// begin FileUtils without MODEM initialization. | ||
fileUtils.begin(false); | ||
|
||
Serial.print("Connecting to "); | ||
Serial.print(server); | ||
Serial.print(":"); | ||
Serial.print(port); | ||
Serial.print("... "); | ||
if (client.connect(server, port)) { | ||
Serial.println("Connected."); | ||
Serial.print("Downloading "); | ||
Serial.println(filename); | ||
Serial.print("... "); | ||
// Make the HTTP request: | ||
client.print("GET /"); | ||
client.print(filename); | ||
client.println(" HTTP/1.1"); | ||
client.print("Host: "); | ||
client.println(server); | ||
client.println("Connection: close"); | ||
client.println(); | ||
} else { | ||
Serial.println("Connection failed"); | ||
} | ||
} | ||
|
||
void loop() | ||
{ | ||
while (client.available()) { | ||
// Skip the HTTP header | ||
if (!isHeaderComplete) { | ||
const char c = client.read(); | ||
httpHeader += c; | ||
if (httpHeader.endsWith("\r\n\r\n")) { | ||
isHeaderComplete = true; | ||
|
||
// Get the size of the OTA file from the | ||
// HTTP Content-Length header. | ||
fileSize = getContentLength(); | ||
|
||
Serial.println(); | ||
Serial.print("HTTP header complete. "); | ||
Serial.print("OTA file size is "); | ||
Serial.print(fileSize); | ||
Serial.println(" bytes."); | ||
if (fileSize == 0) { | ||
Serial.println("Unable to get OTA file size."); | ||
while (true) | ||
; | ||
} | ||
} | ||
} else { | ||
// Read the OTA file in len-bytes blocks to preserve RAM. | ||
constexpr size_t len { 512 }; | ||
char buf[len] { 0 }; | ||
|
||
// Read len bytes from HTTP client... | ||
uint32_t read = client.readBytes(buf, len); | ||
// and append them to the update file. | ||
uint32_t written = fileUtils.appendFile(UPDATE_FILE_NAME, buf, read); | ||
|
||
if (written != read) { | ||
Serial.println("Error while saving data."); | ||
while (true) | ||
; | ||
} | ||
|
||
// Update the received byte counter | ||
totalWritten += written; | ||
|
||
// Check for full file received and stored | ||
isDownloadComplete = totalWritten == fileSize; | ||
|
||
Serial.print("Received: "); | ||
Serial.print(totalWritten); | ||
Serial.print("/"); | ||
Serial.println(fileSize); | ||
} | ||
} | ||
if (isDownloadComplete) { | ||
Serial.println(); | ||
Serial.println("Download complete."); | ||
Serial.println("Enabling checkpoint."); | ||
Serial.println(); | ||
|
||
// Create the checkpoint file: will be removed by SSU | ||
// after successful update. | ||
auto status = fileUtils.downloadFile(CHECK_FILE_NAME, { 0 }, 1); | ||
if (status != 1) { | ||
Serial.println("Unable to create checkpoint file."); | ||
while (true) | ||
; | ||
} | ||
|
||
Serial.println("Resetting MCU in order to trigger SSU..."); | ||
Serial.println(); | ||
delay(500); | ||
NVIC_SystemReset(); | ||
} | ||
} | ||
|
||
int getContentLength() | ||
{ | ||
const String contentLengthHeader = "Content-Length:"; | ||
const auto contentLengthHeaderLen = contentLengthHeader.length(); | ||
|
||
auto indexContentLengthStart = httpHeader.indexOf(contentLengthHeader); | ||
if (indexContentLengthStart < 0) { | ||
Serial.println("Unable to find Content-Length header (Start)"); | ||
return 0; | ||
} | ||
auto indexContentLengthStop = httpHeader.indexOf("\r\n", indexContentLengthStart); | ||
if (indexContentLengthStart < 0) { | ||
Serial.println("Unable to find Content-Length header (Stop)"); | ||
return 0; | ||
} | ||
auto contentLength = httpHeader.substring(indexContentLengthStart + contentLengthHeaderLen + 1, indexContentLengthStop); | ||
|
||
contentLength.trim(); | ||
return contentLength.toInt(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#define SECRET_PINNUMBER "" | ||
#define SECRET_GPRS_APN "GPRS_APN" // replace your GPRS APN | ||
#define SECRET_GPRS_LOGIN "login" // replace with your GPRS login | ||
#define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password |