Skip to content

allow SPIFFS update over http #1188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* httpUpdateSPIFFS.ino
*
* Created on: 05.12.2015
*
*/

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>

#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;
}
}
}
}

95 changes: 78 additions & 17 deletions libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
*
*/


#include "ESP8266httpUpdate.h"
#include <StreamString.h>

extern "C" uint32_t _SPIFFS_start;
extern "C" uint32_t _SPIFFS_end;

ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) {
}
Expand All @@ -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 *
Expand Down Expand Up @@ -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;

Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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();
Expand All @@ -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");
Expand All @@ -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;
Expand All @@ -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) {

StreamString error;

if(!Update.begin(size)) {
DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed!\n");
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;
}

Expand All @@ -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;
}

Expand Down
6 changes: 4 additions & 2 deletions libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down