#ifndef FSPersistence_h #define FSPersistence_h #include #include 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(); } 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); 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; } // 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(); }); } } 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