diff --git a/lib/framework/FSPersistence.h b/lib/framework/FSPersistence.h index bba8cda10..a7176e8dc 100644 --- a/lib/framework/FSPersistence.h +++ b/lib/framework/FSPersistence.h @@ -6,93 +6,97 @@ template class FSPersistence { - public: - FSPersistence(JsonStateReader stateReader, - JsonStateUpdater stateUpdater, - StatefulService* statefulService, - FS* fs, - char const* filePath, - size_t bufferSize = DEFAULT_BUFFER_SIZE) : - _stateReader(stateReader), - _stateUpdater(stateUpdater), - _statefulService(statefulService), - _fs(fs), - _filePath(filePath), - _bufferSize(bufferSize), - _updateHandlerId(0) { - enableUpdateHandler(); - } + public: + FSPersistence(JsonStateReader stateReader, + JsonStateUpdater stateUpdater, + StatefulService * statefulService, + FS * fs, + char const * filePath, + size_t bufferSize = DEFAULT_BUFFER_SIZE) + : _stateReader(stateReader) + , _stateUpdater(stateUpdater) + , _statefulService(statefulService) + , _fs(fs) + , _filePath(filePath) + , _bufferSize(bufferSize) + , _updateHandlerId(0) { + enableUpdateHandler(); + } - void readFromFS() { - File settingsFile = _fs->open(_filePath, "r"); + void readFromFS() { + File settingsFile = _fs->open(_filePath, "r"); - if (settingsFile) { - DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); - DeserializationError error = deserializeJson(jsonDocument, settingsFile); - if (error == DeserializationError::Ok && jsonDocument.is()) { - JsonObject jsonObject = jsonDocument.as(); - _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater); + if (settingsFile) { + DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); + DeserializationError error = deserializeJson(jsonDocument, settingsFile); + if (error == DeserializationError::Ok && jsonDocument.is()) { + JsonObject jsonObject = jsonDocument.as(); + _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater); + settingsFile.close(); + return; + } + settingsFile.close(); + } + + // If we reach here we have not been successful in loading the config, + // hard-coded emergency defaults are now applied. + applyDefaults(); + } + + bool writeToFS() { + // create and populate a new json object + DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); + JsonObject jsonObject = jsonDocument.to(); + _statefulService->read(jsonObject, _stateReader); + + // serialize it to filesystem + File settingsFile = _fs->open(_filePath, "w"); + + // failed to open file, return false + if (!settingsFile) { + return false; + } + + // Serial.printf("Write File: %s: ", _filePath); + // serializeJson(jsonDocument, Serial); + // Serial.println(); + + // serialize the data to the file + serializeJson(jsonDocument, settingsFile); settingsFile.close(); - return; - } - settingsFile.close(); + return true; } - // If we reach here we have not been successful in loading the config, - // hard-coded emergency defaults are now applied. - applyDefaults(); - } - - bool writeToFS() { - // create and populate a new json object - DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); - JsonObject jsonObject = jsonDocument.to(); - _statefulService->read(jsonObject, _stateReader); - - // serialize it to filesystem - File settingsFile = _fs->open(_filePath, "w"); - - // failed to open file, return false - if (!settingsFile) { - return false; + void disableUpdateHandler() { + if (_updateHandlerId) { + _statefulService->removeUpdateHandler(_updateHandlerId); + _updateHandlerId = 0; + } } - // serialize the data to the file - serializeJson(jsonDocument, settingsFile); - settingsFile.close(); - return true; - } - - void disableUpdateHandler() { - if (_updateHandlerId) { - _statefulService->removeUpdateHandler(_updateHandlerId); - _updateHandlerId = 0; + void enableUpdateHandler() { + if (!_updateHandlerId) { + _updateHandlerId = _statefulService->addUpdateHandler([&](const String & originId) { writeToFS(); }); + } } - } - void enableUpdateHandler() { - if (!_updateHandlerId) { - _updateHandlerId = _statefulService->addUpdateHandler([&](const String& originId) { writeToFS(); }); + private: + JsonStateReader _stateReader; + JsonStateUpdater _stateUpdater; + StatefulService * _statefulService; + FS * _fs; + char const * _filePath; + size_t _bufferSize; + update_handler_id_t _updateHandlerId; + + protected: + // We assume the updater supplies sensible defaults if an empty object + // is supplied, this virtual function allows that to be changed. + virtual void applyDefaults() { + DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); + JsonObject jsonObject = jsonDocument.as(); + _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater); } - } - - private: - JsonStateReader _stateReader; - JsonStateUpdater _stateUpdater; - StatefulService* _statefulService; - FS* _fs; - char const* _filePath; - size_t _bufferSize; - update_handler_id_t _updateHandlerId; - - protected: - // We assume the updater supplies sensible defaults if an empty object - // is supplied, this virtual function allows that to be changed. - virtual void applyDefaults() { - DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); - JsonObject jsonObject = jsonDocument.as(); - _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater); - } }; -#endif // end FSPersistence +#endif // end FSPersistence diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 337b49858..2a905843f 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -786,21 +786,24 @@ void EMSESP::send_raw_telegram(const char * data) { // start all the core services // the services must be loaded in the correct order void EMSESP::start() { + // see if we need to migrate from previous versions + if (!system_.check_upgrade()) { +#ifdef ESP32 + SPIFFS.begin(true); +#elif defined(ESP8266) + LittleFS.begin(); +#endif + + esp8266React.begin(); // loads system settings (wifi, mqtt, etc) + emsespSettingsService.begin(); // load EMS-ESP specific settings + } + // Load our library of known devices. Names are stored in Flash mem. device_library_.reserve(80); device_library_ = { #include "device_library.h" }; -#ifdef ESP32 - SPIFFS.begin(true); -#elif defined(ESP8266) - LittleFS.begin(); -#endif - - esp8266React.begin(); // loads system settings (wifi, mqtt, etc) - emsespSettingsService.begin(); // load EMS-ESP specific settings - // system_.check_upgrade(); // see if we need to migrate from previous versions console_.start(); // telnet and serial console mqtt_.start(); // mqtt init system_.start(); // starts syslog, uart, sets version, initializes LED. Requires pre-loaded settings. diff --git a/src/system.cpp b/src/system.cpp index f11540b5c..7bb76f310 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -590,74 +590,71 @@ void System::console_commands(Shell & shell, unsigned int context) { Console::enter_custom_context(shell, context); } -// upgrade from previous versions of EMS-ESP -void System::check_upgrade() { - /* -// check for v1.9. It uses SPIFFS and only on the ESP8266 +// upgrade from previous versions of EMS-ESP, based on SPIFFS on an ESP8266 +// returns true if an upgrade was done +bool System::check_upgrade() { #if defined(ESP8266) - Serial.begin(115200); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - LittleFS.end(); - SPIFFS.begin(); - - // first file - File file = SPIFFS.open("/myesp.json", "r"); - if (!file) { - Serial.println(F("Old config doesn't exist.")); - SPIFFS.end(); - LittleFS.begin(); - return; + SPIFFSConfig cfg; + cfg.setAutoFormat(false); // prevent formatting when opening SPIFFS filesystem + SPIFFS.setConfig(cfg); + if (!SPIFFS.begin()) { + return false; // is not SPIFFS } + Serial.begin(115200); + + // open the two files + File file1 = SPIFFS.open("/myesp.json", "r"); + File file2 = SPIFFS.open("/customconfig.json", "r"); + if (!file1 || !file2) { + Serial.println(F("Unable to read the config files")); + file1.close(); + file2.close(); + SPIFFS.end(); + return false; // can't open files + } + + // read the content of the files DeserializationError error; - StaticJsonDocument<1024> doc; // for myESP settings - error = deserializeJson(doc, file); - if (error) { - Serial.printf("Error. Failed to deserialize json, error %s", error.c_str()); - file.close(); - SPIFFS.end(); - LittleFS.begin(); - return; - } - - file.close(); - - // second file - file = SPIFFS.open("/customconfig.json", "r"); - if (!file) { - Serial.println(F("Old custom config file doesn't exist")); - SPIFFS.end(); - LittleFS.begin(); - return; - } - + StaticJsonDocument<1024> doc1; // for myESP settings StaticJsonDocument<1024> doc2; // for custom EMS-ESP settings - error = deserializeJson(doc2, file); + bool failed = false; + + error = deserializeJson(doc1, file1); if (error) { - Serial.printf("Error. Failed to deserialize json, error %s", error.c_str()); - file.close(); - SPIFFS.end(); - LittleFS.begin(); - return; + Serial.printf("Error. Failed to deserialize json, doc1, error %s", error.c_str()); + failed = true; + } + error = deserializeJson(doc2, file2); + if (error) { + Serial.printf("Error. Failed to deserialize json, doc2, error %s", error.c_str()); + failed = true; } - file.close(); - - // close SPIFFS and open LittleFS + file1.close(); + file2.close(); SPIFFS.end(); - LittleFS.begin(); + + if (failed) { + return false; // parse error + } #pragma GCC diagnostic pop + LittleFS.begin(); + EMSESP::esp8266React.begin(); // loads system settings (wifi, mqtt, etc) + EMSESP::emsespSettingsService.begin(); // load EMS-ESP specific settings + Serial.println(F("Migrating settings from EMS-ESP 1.9.x...")); // get the json objects - JsonObject network = doc["network"]; - JsonObject general = doc["general"]; - JsonObject mqtt = doc["mqtt"]; + JsonObject network = doc1["network"]; + JsonObject general = doc1["general"]; + JsonObject mqtt = doc1["mqtt"]; JsonObject custom_settings = doc2["settings"]; // from 2nd file EMSESP::esp8266React.getWiFiSettingsService()->update( @@ -717,8 +714,10 @@ void System::check_upgrade() { return StateUpdateResult::CHANGED; }, "local"); + + Serial.end(); + return true; #endif -*/ } } // namespace emsesp diff --git a/src/system.h b/src/system.h index 6ecb63ba7..024b79ad0 100644 --- a/src/system.h +++ b/src/system.h @@ -54,18 +54,12 @@ class System { static uint8_t free_mem(); static void upload_status(bool in_progress); static bool upload_status(); - - void syslog_init(); - - // heartbeat - void set_heartbeat(bool system_heartbeat); - void send_heartbeat(); - - static void show_mem(const char * note); - - static void set_led(); - - void check_upgrade(); + void syslog_init(); + void set_heartbeat(bool system_heartbeat); + void send_heartbeat(); + static void show_mem(const char * note); + static void set_led(); + bool check_upgrade(); private: static uuid::log::Logger logger_;