diff --git a/libraries/ESP8266httpUpdate/examples/httpUpdateSPIFFS/httpUpdateSPIFFS.ino b/libraries/ESP8266httpUpdate/examples/httpUpdateSPIFFS/httpUpdateSPIFFS.ino new file mode 100644 index 000000000..3d746af6c --- /dev/null +++ b/libraries/ESP8266httpUpdate/examples/httpUpdateSPIFFS/httpUpdateSPIFFS.ino @@ -0,0 +1,65 @@ +/** + * httpUpdateSPIFFS.ino + * + * Created on: 05.12.2015 + * + */ + +#include + +#include +#include + +#include +#include + +#define USE_SERIAL Serial + +ESP8266WiFiMulti WiFiMulti; + +void setup() { + + USE_SERIAL.begin(115200); + // USE_SERIAL.setDebugOutput(true); + + USE_SERIAL.println(); + USE_SERIAL.println(); + USE_SERIAL.println(); + + for(uint8_t t = 4; t > 0; t--) { + USE_SERIAL.printf("[SETUP] WAIT %d...\n", t); + USE_SERIAL.flush(); + delay(1000); + } + + WiFiMulti.addAP("SSID", "PASSWORD"); + +} + +void loop() { + // wait for WiFi connection + if((WiFiMulti.run() == WL_CONNECTED)) { + + USE_SERIAL.println("Update SPIFFS..."); + t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs("https://server/spiffs.bin"); + if(ret == HTTP_UPDATE_OK) { + USE_SERIAL.println("Update sketch..."); + ret = ESPhttpUpdate.update("https://server/file.bin"); + + switch(ret) { + case HTTP_UPDATE_FAILED: + USE_SERIAL.println("HTTP_UPDATE_FAILD"); + break; + + case HTTP_UPDATE_NO_UPDATES: + USE_SERIAL.println("HTTP_UPDATE_NO_UPDATES"); + break; + + case HTTP_UPDATE_OK: + USE_SERIAL.println("HTTP_UPDATE_OK"); + break; + } + } + } +} + diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 39ba0555c..785258de9 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -23,9 +23,11 @@ * */ - #include "ESP8266httpUpdate.h" +#include +extern "C" uint32_t _SPIFFS_start; +extern "C" uint32_t _SPIFFS_end; ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) { } @@ -46,6 +48,19 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(const char * url, const char * cur return handleUpdate(&http, current_version); } +/** + * + * @param url const char * + * @param current_version const char * + * @param httpsFingerprint const char * + * @return t_httpUpdate_return + */ +t_httpUpdate_return ESP8266HTTPUpdate::updateSpiffs(const char * url, const char * current_version, const char * httpsFingerprint) { + HTTPClient http; + http.begin(url, httpsFingerprint); + return handleUpdate(&http, current_version, false, true); +} + /** * * @param host const char * @@ -73,7 +88,7 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(String host, uint16_t port, String * @param current_version const char * * @return t_httpUpdate_return */ -t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const char * current_version) { +t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const char * current_version, bool reboot, bool spiffs) { t_httpUpdate_return ret = HTTP_UPDATE_FAILED; @@ -85,6 +100,12 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha http->addHeader("x-ESP8266-chip-size", String(ESP.getFlashChipRealSize())); http->addHeader("x-ESP8266-sdk-version", ESP.getSdkVersion()); + if(spiffs) { + http->addHeader("x-ESP8266-mode", "spiffs"); + } else { + http->addHeader("x-ESP8266-mode", "sketch"); + } + if(current_version && current_version[0] != 0x00) { http->addHeader("x-ESP8266-version", current_version); } @@ -99,6 +120,12 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha int code = http->GET(); int len = http->getSize(); + if(code <= 0) { + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http->errorToString(code).c_str()); + http->end(); + return HTTP_UPDATE_FAILED; + } + DEBUG_HTTP_UPDATE("[httpUpdate] Header read fin.\n"); DEBUG_HTTP_UPDATE("[httpUpdate] Server header:\n"); DEBUG_HTTP_UPDATE("[httpUpdate] - code: %d\n", code); @@ -117,11 +144,24 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha } switch(code) { - case 200: ///< OK (Start Update) + case HTTP_CODE_OK: ///< OK (Start Update) if(len > 0) { - if(len > ESP.getFreeSketchSpace()) { + bool startUpdate = true; + if(spiffs) { + size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); + if(len > (int) spiffsSize) { + DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); + startUpdate = false; + } + } else { + if(len > (int) ESP.getFreeSketchSpace()) { + DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); + startUpdate = false; + } + } + + if(!startUpdate) { ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); } else { WiFiClient * tcp = http->getStreamPtr(); @@ -131,11 +171,25 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha delay(100); - if(runUpdate(*tcp, len, http->header("x-MD5"))) { + int command; + + if(spiffs) { + command = U_SPIFFS; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n"); + } else { + command = U_FLASH; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); + } + + if(runUpdate(*tcp, len, http->header("x-MD5"), command)) { ret = HTTP_UPDATE_OK; DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); http->end(); - ESP.restart(); + + if(reboot) { + ESP.restart(); + } + } else { ret = HTTP_UPDATE_FAILED; DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); @@ -146,19 +200,18 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n"); } break; - case 304: + case HTTP_CODE_NOT_MODIFIED: ///< Not Modified (No updates) ret = HTTP_UPDATE_NO_UPDATES; break; - case 403: - ///< Forbidden - // todo handle login default: ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] Code is (%d)\n", code); + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); + //http->writeToStream(&Serial1); break; } + http->end(); return ret; @@ -171,10 +224,14 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha * @param md5 String * @return true if Update ok */ -bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5) { +bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command) { - if(!Update.begin(size)) { - DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed!\n"); + StreamString error; + + if(!Update.begin(size, command)) { + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n", error.c_str()); return false; } @@ -183,12 +240,16 @@ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5) { } if(Update.writeStream(in) != size) { - DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed!\n"); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n", error.c_str()); return false; } if(!Update.end()) { - DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed!\n"); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n", error.c_str()); return false; } diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index a494695ff..d3fe4ca19 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -53,9 +53,11 @@ class ESP8266HTTPUpdate { t_httpUpdate_return update(const char * host, uint16_t port, const char * url = "/", const char * current_version = "", bool https = false, const char * httpsFingerprint = ""); t_httpUpdate_return update(String host, uint16_t port, String url = "/", String current_version = "", bool https = false, String httpsFingerprint = ""); + t_httpUpdate_return updateSpiffs(const char * url, const char * current_version = "", const char * httpsFingerprint = ""); + protected: - t_httpUpdate_return handleUpdate(HTTPClient * http, const char * current_version); - bool runUpdate(Stream& in, uint32_t size, String md5); + t_httpUpdate_return handleUpdate(HTTPClient * http, const char * current_version, bool reboot = true, bool spiffs = false); + bool runUpdate(Stream& in, uint32_t size, String md5, int command = U_FLASH); }; extern ESP8266HTTPUpdate ESPhttpUpdate;