Skip to content

Commit ce3e5af

Browse files
committed
OTA: implement fetchChunk
1 parent 1f6dc8a commit ce3e5af

File tree

2 files changed

+111
-1
lines changed

2 files changed

+111
-1
lines changed

src/ota/interface/OTAInterfaceDefault.cpp

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,113 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() {
9898
}
9999

100100
OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetchChunk() {
101-
return OtaDownloadFail;
101+
OTACloudProcessInterface::State res = Fetch;
102+
int http_res = 0;
103+
uint32_t start = millis();
104+
char range[128] = {0};
105+
106+
/* stop connected client */
107+
http_client->stop();
108+
109+
/* request chunk */
110+
http_client->beginRequest();
111+
http_res = http_client->get(context->parsed_url.path());
112+
113+
if(username != nullptr && password != nullptr) {
114+
http_client->sendBasicAuth(username, password);
115+
}
116+
117+
size_t rangeSize = context->downloadedSize + context->maxChunkSize > context->contentLength ? context->contentLength - context->downloadedSize : context->maxChunkSize;
118+
sprintf(range, "bytes=%d-%d", context->downloadedSize, context->downloadedSize + rangeSize);
119+
DEBUG_VERBOSE("OTA downloading range: %s", range);
120+
http_client->sendHeader("Range", range);
121+
http_client->endRequest();
122+
123+
if(http_res == HTTP_ERROR_CONNECTION_FAILED) {
124+
DEBUG_VERBOSE("OTA ERROR: http client error connecting to server \"%s:%d\"",
125+
context->parsed_url.host(), context->parsed_url.port());
126+
return ServerConnectErrorFail;
127+
} else if(http_res == HTTP_ERROR_TIMED_OUT) {
128+
DEBUG_VERBOSE("OTA ERROR: http client timeout \"%s\"", OTACloudProcessInterface::context->url);
129+
return OtaHeaderTimeoutFail;
130+
} else if(http_res != HTTP_SUCCESS) {
131+
DEBUG_VERBOSE("OTA ERROR: http client returned %d on get \"%s\"", res, OTACloudProcessInterface::context->url);
132+
return OtaDownloadFail;
133+
}
134+
135+
int statusCode = http_client->responseStatusCode();
136+
137+
if(statusCode != 206) {
138+
DEBUG_VERBOSE("OTA ERROR: get response on \"%s\" returned status %d", OTACloudProcessInterface::context->url, statusCode);
139+
return HttpResponseFail;
140+
}
141+
142+
http_client->skipResponseHeaders();
143+
144+
/* download chunk */
145+
context->downloadedChunkSize = 0;
146+
do {
147+
if(!http_client->connected()) {
148+
res = OtaDownloadFail;
149+
goto exit;
150+
}
151+
152+
if(http_client->available() == 0) {
153+
/* Avoid tight loop and allow yield */
154+
delay(1);
155+
continue;
156+
}
157+
158+
http_res = http_client->read(context->buffer, context->bufLen);
159+
160+
if(http_res < 0) {
161+
DEBUG_VERBOSE("OTA ERROR: Download read error %d", http_res);
162+
res = OtaDownloadFail;
163+
goto exit;
164+
}
165+
166+
parseOta(context->buffer, http_res);
167+
168+
if(context->writeError) {
169+
DEBUG_VERBOSE("OTA ERROR: File write error");
170+
res = ErrorWriteUpdateFileFail;
171+
goto exit;
172+
}
173+
174+
context->downloadedChunkSize += http_res;
175+
176+
} while((context->downloadState == OtaDownloadFile || context->downloadState == OtaDownloadHeader) &&
177+
(context->downloadedChunkSize < rangeSize));
178+
179+
// TODO verify that the information present in the ota header match the info in context
180+
if(context->downloadState == OtaDownloadCompleted) {
181+
// Verify that the downloaded file size is matching the expected size ??
182+
// this could distinguish between consistency of the downloaded bytes and filesize
183+
184+
// validate CRC
185+
context->calculatedCrc32 ^= 0xFFFFFFFF; // finalize CRC
186+
if(context->header.header.crc32 == context->calculatedCrc32) {
187+
DEBUG_VERBOSE("Ota download completed successfully");
188+
res = FlashOTA;
189+
} else {
190+
res = OtaHeaderCrcFail;
191+
}
192+
} else if(context->downloadState == OtaDownloadError) {
193+
DEBUG_VERBOSE("OTA ERROR: OtaDownloadError");
194+
195+
res = OtaDownloadFail;
196+
} else if(context->downloadState == OtaDownloadMagicNumberMismatch) {
197+
DEBUG_VERBOSE("OTA ERROR: Magic number mismatch");
198+
res = OtaHeaderMagicNumberFail;
199+
}
200+
201+
exit:
202+
if(res != Fetch) {
203+
http_client->stop(); // close the connection
204+
delete http_client;
205+
http_client = nullptr;
206+
}
207+
return res;
102208
}
103209

104210
OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetchTime() {
@@ -265,6 +371,7 @@ OTADefaultCloudProcessInterface::Context::Context(
265371
, lastReportTime(0)
266372
, contentLength(0)
267373
, writeError(false)
374+
, downloadedChunkSize(0)
268375
, decoder(putc) { }
269376

270377
static const uint32_t crc_table[256] = {

src/ota/interface/OTAInterfaceDefault.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ class OTADefaultCloudProcessInterface: public OTACloudProcessInterface {
7979
uint32_t contentLength;
8080
bool writeError;
8181

82+
uint32_t downloadedChunkSize;
83+
static constexpr size_t maxChunkSize = 1024 * 10;
84+
8285
// LZSS decoder
8386
LZSSDecoder decoder;
8487

0 commit comments

Comments
 (0)