Skip to content

Commit 800794d

Browse files
earlephilhowerdevyte
authored andcommitted
Add callbacks for ESP8266HTTPUpdate (#6796)
Replaces abandoned #1817 and #2694 Add optional std::function callback (so it supports lambdas and normal functions) via ::onStart, ::onEnd, ::onProgress, and ::onError methods. Update example with their use. From @baruch's original pull request: The callback is called when the upgrade actually starts rather than just the initial query so that the user can know that it will not take longer and can also prepare for the upgrade by shutting down other works. From @karlp's original pull request: Incomplete: I've not updated any documentation yet. If this style looks good, I'll happily go and update the documentation (likewise for the examples)
1 parent 36f9034 commit 800794d

File tree

3 files changed

+89
-22
lines changed

3 files changed

+89
-22
lines changed

Diff for: libraries/ESP8266httpUpdate/examples/httpUpdate/httpUpdate.ino

+23
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ void setup() {
4343

4444
}
4545

46+
void update_started() {
47+
USE_SERIAL.println("CALLBACK: HTTP update process started");
48+
}
49+
50+
void update_finished() {
51+
USE_SERIAL.println("CALLBACK: HTTP update process finished");
52+
}
53+
54+
void update_progress(int cur, int total) {
55+
USE_SERIAL.printf("CALLBACK: HTTP update process at %d of %d bytes...\n", cur, total);
56+
}
57+
58+
void update_error(int err) {
59+
USE_SERIAL.printf("CALLBACK: HTTP update fatal error code %d\n", err);
60+
}
61+
62+
4663
void loop() {
4764
// wait for WiFi connection
4865
if ((WiFiMulti.run() == WL_CONNECTED)) {
@@ -57,6 +74,12 @@ void loop() {
5774
// value is used to put the LED on. If the LED is on with HIGH, that value should be passed
5875
ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW);
5976

77+
// Add optional callback notifiers
78+
ESPhttpUpdate.onStart(update_started);
79+
ESPhttpUpdate.onEnd(update_finished);
80+
ESPhttpUpdate.onProgress(update_progress);
81+
ESPhttpUpdate.onError(update_error);
82+
6083
t_httpUpdate_return ret = ESPhttpUpdate.update(client, "http://server/file.bin");
6184
// Or:
6285
//t_httpUpdate_return ret = ESPhttpUpdate.update(client, "server", 80, "file.bin");

Diff for: libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp

+34-14
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
294294

295295
if(code <= 0) {
296296
DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http.errorToString(code).c_str());
297-
_lastError = code;
297+
_setLastError(code);
298298
http.end();
299299
return HTTP_UPDATE_FAILED;
300300
}
@@ -334,10 +334,14 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
334334
}
335335
}
336336

337-
if(!startUpdate) {
338-
_lastError = HTTP_UE_TOO_LESS_SPACE;
337+
if (!startUpdate) {
338+
_setLastError(HTTP_UE_TOO_LESS_SPACE);
339339
ret = HTTP_UPDATE_FAILED;
340340
} else {
341+
// Warn main app we're starting up...
342+
if (_cbStart) {
343+
_cbStart();
344+
}
341345

342346
WiFiClient * tcp = http.getStreamPtr();
343347

@@ -360,15 +364,15 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
360364
uint8_t buf[4];
361365
if(tcp->peekBytes(&buf[0], 4) != 4) {
362366
DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n");
363-
_lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED;
367+
_setLastError(HTTP_UE_BIN_VERIFY_HEADER_FAILED);
364368
http.end();
365369
return HTTP_UPDATE_FAILED;
366370
}
367371

368372
// check for valid first magic byte
369373
if(buf[0] != 0xE9) {
370374
DEBUG_HTTP_UPDATE("[httpUpdate] Magic header does not start with 0xE9\n");
371-
_lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED;
375+
_setLastError(HTTP_UE_BIN_VERIFY_HEADER_FAILED);
372376
http.end();
373377
return HTTP_UPDATE_FAILED;
374378

@@ -379,7 +383,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
379383
// check if new bin fits to SPI flash
380384
if(bin_flash_size > ESP.getFlashChipRealSize()) {
381385
DEBUG_HTTP_UPDATE("[httpUpdate] New binary does not fit SPI Flash size\n");
382-
_lastError = HTTP_UE_BIN_FOR_WRONG_FLASH;
386+
_setLastError(HTTP_UE_BIN_FOR_WRONG_FLASH);
383387
http.end();
384388
return HTTP_UPDATE_FAILED;
385389
}
@@ -388,6 +392,10 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
388392
ret = HTTP_UPDATE_OK;
389393
DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n");
390394
http.end();
395+
// Warn main app we're all done
396+
if (_cbEnd) {
397+
_cbEnd();
398+
}
391399

392400
#ifdef ATOMIC_FS_UPDATE
393401
if(_rebootOnUpdate) {
@@ -403,7 +411,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
403411
}
404412
}
405413
} else {
406-
_lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE;
414+
_setLastError(HTTP_UE_SERVER_NOT_REPORT_SIZE);
407415
ret = HTTP_UPDATE_FAILED;
408416
DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length was 0 or wasn't set by Server?!\n");
409417
}
@@ -413,15 +421,15 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
413421
ret = HTTP_UPDATE_NO_UPDATES;
414422
break;
415423
case HTTP_CODE_NOT_FOUND:
416-
_lastError = HTTP_UE_SERVER_FILE_NOT_FOUND;
424+
_setLastError(HTTP_UE_SERVER_FILE_NOT_FOUND);
417425
ret = HTTP_UPDATE_FAILED;
418426
break;
419427
case HTTP_CODE_FORBIDDEN:
420-
_lastError = HTTP_UE_SERVER_FORBIDDEN;
428+
_setLastError(HTTP_UE_SERVER_FORBIDDEN);
421429
ret = HTTP_UPDATE_FAILED;
422430
break;
423431
default:
424-
_lastError = HTTP_UE_SERVER_WRONG_HTTP_CODE;
432+
_setLastError(HTTP_UE_SERVER_WRONG_HTTP_CODE);
425433
ret = HTTP_UPDATE_FAILED;
426434
DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code);
427435
//http.writeToStream(&Serial1);
@@ -444,32 +452,44 @@ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, const String& md5,
444452

445453
StreamString error;
446454

455+
if (_cbProgress) {
456+
Update.onProgress(_cbProgress);
457+
}
458+
447459
if(!Update.begin(size, command, _ledPin, _ledOn)) {
448-
_lastError = Update.getError();
460+
_setLastError(Update.getError());
449461
Update.printError(error);
450462
error.trim(); // remove line ending
451463
DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n", error.c_str());
452464
return false;
453465
}
454466

467+
if (_cbProgress) {
468+
_cbProgress(0, size);
469+
}
470+
455471
if(md5.length()) {
456472
if(!Update.setMD5(md5.c_str())) {
457-
_lastError = HTTP_UE_SERVER_FAULTY_MD5;
473+
_setLastError(HTTP_UE_SERVER_FAULTY_MD5);
458474
DEBUG_HTTP_UPDATE("[httpUpdate] Update.setMD5 failed! (%s)\n", md5.c_str());
459475
return false;
460476
}
461477
}
462478

463479
if(Update.writeStream(in) != size) {
464-
_lastError = Update.getError();
480+
_setLastError(Update.getError());
465481
Update.printError(error);
466482
error.trim(); // remove line ending
467483
DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n", error.c_str());
468484
return false;
469485
}
470486

487+
if (_cbProgress) {
488+
_cbProgress(size, size);
489+
}
490+
471491
if(!Update.end()) {
472-
_lastError = Update.getError();
492+
_setLastError(Update.getError());
473493
Update.printError(error);
474494
error.trim(); // remove line ending
475495
DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n", error.c_str());

Diff for: libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h

+32-8
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@
4747
#endif
4848

4949
/// note we use HTTP client errors too so we start at 100
50-
#define HTTP_UE_TOO_LESS_SPACE (-100)
51-
#define HTTP_UE_SERVER_NOT_REPORT_SIZE (-101)
52-
#define HTTP_UE_SERVER_FILE_NOT_FOUND (-102)
53-
#define HTTP_UE_SERVER_FORBIDDEN (-103)
54-
#define HTTP_UE_SERVER_WRONG_HTTP_CODE (-104)
55-
#define HTTP_UE_SERVER_FAULTY_MD5 (-105)
56-
#define HTTP_UE_BIN_VERIFY_HEADER_FAILED (-106)
57-
#define HTTP_UE_BIN_FOR_WRONG_FLASH (-107)
50+
//TODO - in v3.0.0 make this an enum
51+
constexpr int HTTP_UE_TOO_LESS_SPACE = (-100);
52+
constexpr int HTTP_UE_SERVER_NOT_REPORT_SIZE = (-101);
53+
constexpr int HTTP_UE_SERVER_FILE_NOT_FOUND = (-102);
54+
constexpr int HTTP_UE_SERVER_FORBIDDEN = (-103);
55+
constexpr int HTTP_UE_SERVER_WRONG_HTTP_CODE = (-104);
56+
constexpr int HTTP_UE_SERVER_FAULTY_MD5 = (-105);
57+
constexpr int HTTP_UE_BIN_VERIFY_HEADER_FAILED = (-106);
58+
constexpr int HTTP_UE_BIN_FOR_WRONG_FLASH = (-107);
5859

5960
enum HTTPUpdateResult {
6061
HTTP_UPDATE_FAILED,
@@ -64,6 +65,11 @@ enum HTTPUpdateResult {
6465

6566
typedef HTTPUpdateResult t_httpUpdate_return; // backward compatibility
6667

68+
using HTTPUpdateStartCB = std::function<void()>;
69+
using HTTPUpdateEndCB = std::function<void()>;
70+
using HTTPUpdateErrorCB = std::function<void(int)>;
71+
using HTTPUpdateProgressCB = std::function<void(int, int)>;
72+
6773
class ESP8266HTTPUpdate
6874
{
6975
public:
@@ -124,6 +130,11 @@ class ESP8266HTTPUpdate
124130
#endif
125131
t_httpUpdate_return updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion = "");
126132

133+
// Notification callbacks
134+
void onStart(HTTPUpdateStartCB cbOnStart) { _cbStart = cbOnStart; }
135+
void onEnd(HTTPUpdateEndCB cbOnEnd) { _cbEnd = cbOnEnd; }
136+
void onError(HTTPUpdateErrorCB cbOnError) { _cbError = cbOnError; }
137+
void onProgress(HTTPUpdateProgressCB cbOnProgress) { _cbProgress = cbOnProgress; }
127138

128139
int getLastError(void);
129140
String getLastErrorString(void);
@@ -132,12 +143,25 @@ class ESP8266HTTPUpdate
132143
t_httpUpdate_return handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs = false);
133144
bool runUpdate(Stream& in, uint32_t size, const String& md5, int command = U_FLASH);
134145

146+
// Set the error and potentially use a CB to notify the application
147+
void _setLastError(int err) {
148+
_lastError = err;
149+
if (_cbError) {
150+
_cbError(err);
151+
}
152+
}
135153
int _lastError;
136154
bool _rebootOnUpdate = true;
137155
private:
138156
int _httpClientTimeout;
139157
bool _followRedirects;
140158

159+
// Callbacks
160+
HTTPUpdateStartCB _cbStart;
161+
HTTPUpdateEndCB _cbEnd;
162+
HTTPUpdateErrorCB _cbError;
163+
HTTPUpdateProgressCB _cbProgress;
164+
141165
int _ledPin;
142166
uint8_t _ledOn;
143167
};

0 commit comments

Comments
 (0)