diff --git a/src/esp32FOTA.cpp b/src/esp32FOTA.cpp index eef9e55..fe37b35 100644 --- a/src/esp32FOTA.cpp +++ b/src/esp32FOTA.cpp @@ -385,7 +385,7 @@ bool esp32FOTA::execOTA() { setupStream(); - if( _flashFileSystemUrl != "" ) { // a data partition was specified in the json manifest, handle the spiffs partition first + if( !_flashFileSystemUrl.isEmpty() ) { // a data partition was specified in the json manifest, handle the spiffs partition first if( _fs ) { // Possible risk of overwriting certs and signatures, cancel flashing! Serial.println("Cowardly refusing to overwrite U_SPIFFS with "+_flashFileSystemUrl+". Use setCertFileSystem(nullptr) along with setPubKey()/setCAPem() to enable this feature."); return false; @@ -591,8 +591,8 @@ bool esp32FOTA::checkJSONManifest(JsonVariant doc) } log_i("Payload type in manifest %s matches current firmware %s", doc["type"].as(), _cfg.name ); - _flashFileSystemUrl = ""; - _firmwareUrl = ""; + _flashFileSystemUrl.clear(); + _firmwareUrl.clear(); if(doc["version"].is()) { uint16_t v = doc["version"].as(); @@ -611,26 +611,26 @@ bool esp32FOTA::checkJSONManifest(JsonVariant doc) debugSemVer("Payload firmware version", _payload_sem.ver() ); // Memoize some values to help with the decision tree - bool has_url = doc.containsKey("url") && doc["url"].is(); - bool has_firmware = doc.containsKey("bin") && doc["bin"].is(); - bool has_hostname = doc.containsKey("host") && doc["host"].is(); - bool has_port = doc.containsKey("port") && doc["port"].is(); - uint16_t portnum = has_port ? doc["port"].as() : 0; + bool has_url = doc["url"].is(); + bool has_firmware = doc["bin"].is(); + bool has_hostname = doc["host"].is(); + bool has_port = doc["port"].is(); + uint16_t portnum = doc["port"].as(); bool has_tls = has_port ? (portnum == 443 || portnum == 4433) : false; - bool has_spiffs = doc.containsKey("spiffs") && doc["spiffs"].is(); - bool has_littlefs = doc.containsKey("littlefs") && doc["littlefs"].is(); - bool has_fatfs = doc.containsKey("fatfs") && doc["fatfs"].is(); + bool has_spiffs = doc["spiffs"].is(); + bool has_littlefs = doc["littlefs"].is(); + bool has_fatfs = doc["fatfs"].is(); bool has_filesystem = has_littlefs || has_spiffs || has_fatfs; - String protocol = has_tls ? "https" : "http"; + String protocol(has_tls ? "https" : "http"); String flashFSPath = has_filesystem ? ( has_littlefs - ? doc["littlefs"].as() + ? doc["littlefs"].as() : has_spiffs - ? doc["spiffs"].as() - : doc["fatfs"].as() + ? doc["spiffs"].as() + : doc["fatfs"].as() ) : ""; @@ -643,14 +643,14 @@ bool esp32FOTA::checkJSONManifest(JsonVariant doc) ); if( has_url ) { // Basic scenario: a complete URL was provided in the JSON manifest, all other keys will be ignored - _firmwareUrl = doc["url"].as(); + _firmwareUrl = doc["url"].as(); if( has_hostname ) { // If the manifest provides both, warn the user log_w("Manifest provides both url and host - Using URL"); } } else if( has_firmware && has_hostname && has_port ) { // Precise scenario: Hostname, Port and Firmware Path were provided - _firmwareUrl = protocol + "://" + doc["host"].as() + ":" + String( portnum ) + doc["bin"].as(); + _firmwareUrl = protocol + "://" + doc["host"].as() + ":" + portnum + doc["bin"].as(); if( has_filesystem ) { // More complex scenario: the manifest also provides a [spiffs, littlefs or fatfs] partition - _flashFileSystemUrl = protocol + "://" + doc["host"].as() + ":" + String( portnum ) + flashFSPath; + _flashFileSystemUrl = protocol + "://" + doc["host"].as() + ":" + portnum + flashFSPath; } } else { // JSON was malformed - no firmware target was provided log_e("JSON manifest was missing one of the required keys :(" ); @@ -670,10 +670,15 @@ bool esp32FOTA::checkJSONManifest(JsonVariant doc) bool esp32FOTA::execHTTPcheck() { - String useURL = String( _cfg.manifest_url ); + if ((WiFi.status() != WL_CONNECTED)) { //Check the current connection status + log_i("WiFi not connected - skipping HTTP check"); + return false; // WiFi not connected + } + + String useURL(_cfg.manifest_url ); // being deprecated, soon unsupported! - if( useURL=="" && checkURL!="" ) { + if( useURL.isEmpty() && !checkURL.isEmpty() ) { Serial.println("checkURL will soon be unsupported, use FOTAConfig_t::manifest_url instead!!"); useURL = checkURL; } @@ -698,6 +703,7 @@ bool esp32FOTA::execHTTPcheck() log_i("Getting HTTP: %s", useURL.c_str()); log_i("------"); + _http.useHTTP10(true); if(! setupHTTP( useURL.c_str() ) ) { log_e("Unable to setup http, aborting!"); return false; @@ -718,19 +724,19 @@ bool esp32FOTA::execHTTPcheck() return false; } - String payload = _http.getString(); - _http.end(); // We're done with HTTP - free the resources - // TODO: use payload.length() to speculate on JSONResult buffer size #define JSON_FW_BUFF_SIZE 2048 DynamicJsonDocument JSONResult( JSON_FW_BUFF_SIZE ); - DeserializationError err = deserializeJson( JSONResult, payload.c_str() ); + + DeserializationError err = deserializeJson( JSONResult, _http.getStream() ); if (err) { // Check for errors in parsing, or JSON length may exceed buffer size - Serial.printf("JSON Parsing failed (%s, in=%d bytes, buff=%d bytes):\n%s\n", err.c_str(), payload.length(), JSON_FW_BUFF_SIZE, payload.c_str() ); + Serial.printf("JSON Parsing failed (%s, in=%d bytes, buff=%d bytes):\n", err.c_str(), _http.getSize(), JSON_FW_BUFF_SIZE ); return false; } + _http.end(); // We're done with HTTP - free the resources + if (JSONResult.is()) { // Although improbable given the size on JSONResult buffer, we already received an array of multiple firmware types and/or versions JsonArray arr = JSONResult.as(); @@ -761,7 +767,7 @@ String esp32FOTA::getDeviceID() // Force a firmware update regardless on current version -void esp32FOTA::forceUpdate(String firmwareURL, bool validate ) +void esp32FOTA::forceUpdate(const char* firmwareURL, bool validate ) { _firmwareUrl = firmwareURL; _cfg.check_sig = validate; @@ -769,10 +775,14 @@ void esp32FOTA::forceUpdate(String firmwareURL, bool validate ) } -void esp32FOTA::forceUpdate(String firmwareHost, uint16_t firmwarePort, String firmwarePath, bool validate ) +void esp32FOTA::forceUpdate(const char* firmwareHost, uint16_t firmwarePort, const char* firmwarePath, bool validate ) { - String firmwareURL = ( firmwarePort == 443 || firmwarePort == 4433 ) ? "https" : "http"; - firmwareURL += firmwareHost + ":" + String( firmwarePort ) + firmwarePath; + String firmwareURL("http"); + if ( firmwarePort == 443 || firmwarePort == 4433 ) firmwareURL += "s"; + firmwareURL += firmwareHost; + firmwareURL += ":"; + firmwareURL += firmwarePort; + firmwareURL += firmwarePath; forceUpdate( firmwareURL, validate ); } diff --git a/src/esp32FOTA.hpp b/src/esp32FOTA.hpp index a89a095..425c511 100644 --- a/src/esp32FOTA.hpp +++ b/src/esp32FOTA.hpp @@ -187,11 +187,12 @@ class esp32FOTA : public UpdateClass template void setPubKey( T* asset ) { _cfg.pub_key = (CryptoAsset*)asset; _cfg.check_sig = true; } template void setRootCA( T* asset ) { _cfg.root_ca = (CryptoAsset*)asset; _cfg.unsafe = false; } - //template static U& getInstance() { static U updater; return updater; } - - void forceUpdate(String firmwareHost, uint16_t firmwarePort, String firmwarePath, bool validate ); - void forceUpdate(String firmwareURL, bool validate ); + void forceUpdate(const char* firmwareHost, uint16_t firmwarePort, const char* firmwarePath, bool validate ); + void forceUpdate(const char* firmwareURL, bool validate ); + void forceUpdate(const String &firmwareHost, uint16_t firmwarePort, const String &firmwarePath, bool validate ){ forceUpdate(firmwareHost.c_str(), firmwarePort, firmwarePath.c_str(), validate ); }; + void forceUpdate(const String &firmwareURL, bool validate ){ forceUpdate(firmwareURL.c_str(), validate); }; void forceUpdate(bool validate ); + //template static U& getInstance() { static U updater; return updater; } bool execOTA(); bool execOTA( int partition, bool restart_after = true );