Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 970877b

Browse filesBrowse files
committed
added httpota example
1 parent f4e8cab commit 970877b
Copy full SHA for 970877b

File tree

3 files changed

+250
-26
lines changed
Filter options

3 files changed

+250
-26
lines changed
+227Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
Small example sketch demonstrating how to perform OTA via HTTP/S
3+
utilizing a MKRGSM 1400 and the storage on the integrated
4+
SARA U-201 GSM module.
5+
6+
Please, be careful because no verification is done on the
7+
received OTA file, apart size verification of the transmitted
8+
bytes using the HTTP Content-Length header.
9+
10+
For production-grade OTA procedure you might want to implement
11+
a content verification procedure using a CRC calculation
12+
or an hash (eg. MD5 or SHA256) comparison.
13+
14+
Circuit:
15+
* MKR GSM 1400 board
16+
* Antenna
17+
* SIM card with a data plan
18+
19+
Steps to update a sketch:
20+
21+
1) Create a new sketch or update an existing one to be updated over-the-air.
22+
The sketch needs to contain also the code below for future OTAs.
23+
The sketch must include the SSU library via
24+
#include <SSU.h>
25+
26+
2) In the IDE select: Sketch -> Export compiled Binary.
27+
28+
3) Open the location of the sketch (Sketch -> Show Sketch Folder) and upload
29+
the .bin file to your HTTP/S server.
30+
31+
4) Upload this sketch after configuring the server, port and filename variables.
32+
33+
The sketch will download the OTA file, store it into the U-201 storage, and
34+
will reset the board to trigger the SSU update procedure.
35+
36+
37+
created 25 June 2020
38+
by Giampaolo Mancini
39+
*/
40+
41+
#include <MKRGSM.h>
42+
43+
// This includes triggers the firmware update procedure
44+
// in the bootloader after reset.
45+
#include <SSU.h>
46+
47+
// Do not change! SSU will look for these files!
48+
constexpr char UPDATE_FILE_NAME[] = "UPDATE.BIN";
49+
static constexpr char CHECK_FILE_NAME[] = "UPDATE.OK";
50+
51+
#include "arduino_secrets.h"
52+
const char PINNUMBER[] = SECRET_PINNUMBER;
53+
// APN data
54+
const char GPRS_APN[] = SECRET_GPRS_APN;
55+
const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN;
56+
const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD;
57+
58+
// Change to GSMClient for non-SSL/TLS connection.
59+
// Not recommended.
60+
GSMSSLClient client;
61+
GPRS gprs;
62+
GSM gsmAccess;
63+
64+
GSMFileUtils fileUtils;
65+
66+
bool isHeaderComplete = false;
67+
String httpHeader;
68+
69+
bool isDownloadComplete = false;
70+
unsigned int fileSize = 0;
71+
unsigned int totalWritten = 0;
72+
73+
constexpr char server[] = "example.org";
74+
constexpr int port = 443;
75+
76+
// Name of the new firmware file to be updated.
77+
constexpr char filename[] = "update.bin";
78+
79+
80+
void setup()
81+
{
82+
unsigned long timeout = millis();
83+
84+
Serial.begin(9600);
85+
while (!Serial && millis() - timeout < 5000)
86+
;
87+
88+
Serial.println("Starting OTA Update via HTTP and Arduino SSU.");
89+
Serial.println();
90+
91+
bool connected = false;
92+
93+
Serial.print("Connecting to cellular network... ");
94+
while (!connected) {
95+
if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
96+
connected = true;
97+
} else {
98+
Serial.println("Not connected");
99+
delay(1000);
100+
}
101+
}
102+
103+
Serial.println("Connected.");
104+
Serial.println();
105+
106+
// Modem has already been initialized in the sketch:
107+
// begin FileUtils without MODEM initialization.
108+
fileUtils.begin(false);
109+
110+
Serial.print("Connecting to ");
111+
Serial.print(server);
112+
Serial.print(":");
113+
Serial.print(port);
114+
Serial.print("... ");
115+
if (client.connect(server, port)) {
116+
Serial.println("Connected.");
117+
Serial.print("Downloading ");
118+
Serial.println(filename);
119+
Serial.print("... ");
120+
// Make the HTTP request:
121+
client.print("GET /");
122+
client.print(filename);
123+
client.println(" HTTP/1.1");
124+
client.print("Host: ");
125+
client.println(server);
126+
client.println("Connection: close");
127+
client.println();
128+
} else {
129+
Serial.println("Connection failed");
130+
}
131+
}
132+
133+
void loop()
134+
{
135+
while (client.available()) {
136+
// Skip the HTTP header
137+
if (!isHeaderComplete) {
138+
const char c = client.read();
139+
httpHeader += c;
140+
if (httpHeader.endsWith("\r\n\r\n")) {
141+
isHeaderComplete = true;
142+
143+
// Get the size of the OTA file from the
144+
// HTTP Content-Length header.
145+
fileSize = getContentLength();
146+
147+
Serial.println();
148+
Serial.print("HTTP header complete. ");
149+
Serial.print("OTA file size is ");
150+
Serial.print(fileSize);
151+
Serial.println(" bytes.");
152+
if (fileSize == 0) {
153+
Serial.println("Unable to get OTA file size.");
154+
while (true)
155+
;
156+
}
157+
}
158+
} else {
159+
// Read the OTA file in len-bytes blocks to preserve RAM.
160+
constexpr size_t len { 512 };
161+
char buf[len] { 0 };
162+
163+
// Read len bytes from HTTP client...
164+
uint32_t read = client.readBytes(buf, len);
165+
// and append them to the update file.
166+
uint32_t written = fileUtils.appendFile(UPDATE_FILE_NAME, buf, read);
167+
168+
if (written != read) {
169+
Serial.println("Error while saving data.");
170+
while (true)
171+
;
172+
}
173+
174+
// Update the received byte counter
175+
totalWritten += written;
176+
177+
// Check for full file received and stored
178+
isDownloadComplete = totalWritten == fileSize;
179+
180+
Serial.print("Received: ");
181+
Serial.print(totalWritten);
182+
Serial.print("/");
183+
Serial.println(fileSize);
184+
}
185+
}
186+
if (isDownloadComplete) {
187+
Serial.println();
188+
Serial.println("Download complete.");
189+
Serial.println("Enabling checkpoint.");
190+
Serial.println();
191+
192+
// Create the checkpoint file: will be removed by SSU
193+
// after successful update.
194+
auto status = fileUtils.downloadFile(CHECK_FILE_NAME, { 0 }, 1);
195+
if (status != 1) {
196+
Serial.println("Unable to create checkpoint file.");
197+
while (true)
198+
;
199+
}
200+
201+
Serial.println("Resetting MCU in order to trigger SSU...");
202+
Serial.println();
203+
delay(500);
204+
NVIC_SystemReset();
205+
}
206+
}
207+
208+
int getContentLength()
209+
{
210+
const String contentLengthHeader = "Content-Length:";
211+
const auto contentLengthHeaderLen = contentLengthHeader.length();
212+
213+
auto indexContentLengthStart = httpHeader.indexOf(contentLengthHeader);
214+
if (indexContentLengthStart < 0) {
215+
Serial.println("Unable to find Content-Length header (Start)");
216+
return 0;
217+
}
218+
auto indexContentLengthStop = httpHeader.indexOf("\r\n", indexContentLengthStart);
219+
if (indexContentLengthStart < 0) {
220+
Serial.println("Unable to find Content-Length header (Stop)");
221+
return 0;
222+
}
223+
auto contentLength = httpHeader.substring(indexContentLengthStart + contentLengthHeaderLen + 1, indexContentLengthStop);
224+
225+
contentLength.trim();
226+
return contentLength.toInt();
227+
}
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#define SECRET_PINNUMBER ""
2+
#define SECRET_GPRS_APN "GPRS_APN" // replace your GPRS APN
3+
#define SECRET_GPRS_LOGIN "login" // replace with your GPRS login
4+
#define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password
+19-26Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,49 @@
11
/*
22
Usage
3-
This example demonstrates how to use the SAMD SFU library to update a
4-
sketch on any Arduino MKR board connected to a MKRMEM Shield. This sketch
5-
prints out the date and time the sketch was compiled.
6-
7-
Steps to update sketch via MKRMEM shield:
8-
9-
1) Upload this sketch or another sketch that includes the SFU library
10-
via #include <SFU.h>
11-
3+
This example demonstrates how to use the SAMD SSU library to update a
4+
sketch on any Arduino MKR board via the storage on the SARA U-201 GSM module.
5+
This sketch prints out the date and time the sketch was compiled.
6+
Steps to update sketch:
7+
1) Upload this sketch or another sketch that includes the SSU library
8+
via #include <SSU.h>
129
2) Update the sketch as desired. For this example the sketch prints out
1310
the compiled date and time so no updates are needed.
14-
1511
3) In the IDE select: Sketch -> Export compiled Binary
16-
1712
4) Open the location of the sketch and convert the .bin file to a C byte array.
1813
cat SKETCH.bin | xxd --include > Binary.h
19-
20-
5) Copy Binary.h file from the sketch's folder to the SFU_LoadBinary sketch
21-
and load it to the MKRMEM via SFU_LoadBinary sketch.
14+
5) Copy Binary.h file from the sketch's folder to the SSU_LoadBinary sketch
15+
and load it to the U-201 via SSU_LoadBinary sketch.
2216
*/
2317

2418
/*
25-
Include the SFU library
19+
Include the SSU library
2620
2721
This will add some code to the sketch before setup() is called
28-
to check if UPDATE.bin is present on the flash chip of the MKRMEM
29-
shield. If this theck is positive the file is used to update the sketch
30-
running on the board. After this UPDATE.BIN is deleted from the flash.
22+
to check if UPDATE.BIN and UPDATE.OK are present on the storage of
23+
the U-201 module. If this theck is positive UPDATE.BIN is used to update
24+
the sketch running on the board.
25+
After this UPDATE.BIN and UPDATE.OK are deleted from the flash.
3126
*/
3227

3328

3429
#include <SSU.h>
3530

36-
37-
void setup() {
31+
void setup()
32+
{
3833
Serial.begin(9600);
39-
while(!Serial) { }
40-
34+
while (!Serial) { }
4135
// wait a bit
4236
delay(1000);
43-
4437
String message;
4538
message += "Sketch compile date and time: ";
4639
message += __DATE__;
4740
message += " ";
4841
message += __TIME__;
49-
5042
// print out the sketch compile date and time on the serial port
5143
Serial.println(message);
5244
}
5345

54-
void loop() {
46+
void loop()
47+
{
5548
// add you own code here
56-
}
49+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.