From d03c03fd9dbd779bf5b6bfd095e1238aee410b20 Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Mon, 10 Dec 2018 22:35:12 +0000 Subject: [PATCH] Remove refrence to SPIFFS global from persistence code, factor out persistence code so it can be re-used. --- src/SettingsPersistence.h | 98 +++++++++++++++++++++++++++++++++++++++ src/SettingsService.h | 82 +++----------------------------- 2 files changed, 104 insertions(+), 76 deletions(-) create mode 100644 src/SettingsPersistence.h diff --git a/src/SettingsPersistence.h b/src/SettingsPersistence.h new file mode 100644 index 0000000..0dd1604 --- /dev/null +++ b/src/SettingsPersistence.h @@ -0,0 +1,98 @@ +#ifndef SettingsPersistence_h +#define SettingsPersistence_h + +#include +#include +#include +#include +#include +#include + +/** +* At the moment, not expecting settings service to have to deal with large JSON +* files this could be made configurable fairly simply, it's exposed on +* AsyncJsonRequestWebHandler with a setter. +*/ +#define MAX_SETTINGS_SIZE 1024 + +/* +* Mixin for classes which need to save settings to/from a file on the the file system as JSON. +*/ +class SettingsPersistence { + +protected: + + // will store and retrieve config from the file system + FS* _fs; + + // the file path our settings will be saved to + char const* _filePath; + + bool writeToFS() { + // create and populate a new json object + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + writeToJsonObject(root); + + // serialize it to filesystem + File configFile = _fs->open(_filePath, "w"); + + // failed to open file, return false + if (!configFile) { + return false; + } + + root.printTo(configFile); + configFile.close(); + + return true; + } + + void readFromFS(){ + File configFile = _fs->open(_filePath, "r"); + + // use defaults if no config found + if (configFile) { + // Protect against bad data uploaded to file system + // We never expect the config file to get very large, so cap it. + size_t size = configFile.size(); + if (size <= MAX_SETTINGS_SIZE) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(configFile); + if (root.success()) { + readFromJsonObject(root); + configFile.close(); + return; + } + } + configFile.close(); + } + + // If we reach here we have not been successful in loading the config, + // hard-coded emergency defaults are now applied. + applyDefaultConfig(); + } + + + // serialization routene, from local config to JsonObject + virtual void readFromJsonObject(JsonObject& root){} + virtual void writeToJsonObject(JsonObject& root){} + + // We assume the readFromJsonObject supplies sensible defaults if an empty object + // is supplied, this virtual function allows that to be changed. + virtual void applyDefaultConfig(){ + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + readFromJsonObject(root); + } + + public: + + SettingsPersistence(FS* fs, char const* servicePath, char const* filePath): + _fs(fs), _filePath(filePath) {} + + virtual ~SettingsPersistence() {} + +}; + +#endif // end SettingsPersistence diff --git a/src/SettingsService.h b/src/SettingsService.h index 182082d..7c6e5a0 100644 --- a/src/SettingsService.h +++ b/src/SettingsService.h @@ -7,79 +7,24 @@ #elif defined(ESP_PLATFORM) #include #include - #include #endif +#include #include -#include #include #include #include #include -/** -* At the moment, not expecting settings service to have to deal with large JSON -* files this could be made configurable fairly simply, it's exposed on -* AsyncJsonRequestWebHandler with a setter. -*/ -#define MAX_SETTINGS_SIZE 1024 - /* -* Abstraction of a service which stores it's settings as JSON in SPIFFS. +* Abstraction of a service which stores it's settings as JSON in a file system. */ -class SettingsService { +class SettingsService : public SettingsPersistence { private: - char const* _filePath; - AsyncJsonRequestWebHandler _updateHandler; - bool writeToSPIFFS() { - // create and populate a new json object - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - writeToJsonObject(root); - - // serialize it to SPIFFS - File configFile = SPIFFS.open(_filePath, "w"); - - // failed to open file, return false - if (!configFile) { - return false; - } - - root.printTo(configFile); - configFile.close(); - - return true; - } - - void readFromSPIFFS(){ - File configFile = SPIFFS.open(_filePath, "r"); - - // use defaults if no config found - if (configFile) { - // Protect against bad data uploaded to SPIFFS - // We never expect the config file to get very large, so cap it. - size_t size = configFile.size(); - if (size <= MAX_SETTINGS_SIZE) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(configFile); - if (root.success()) { - readFromJsonObject(root); - configFile.close(); - return; - } - } - configFile.close(); - } - - // If we reach here we have not been successful in loading the config, - // hard-coded emergency defaults are now applied. - applyDefaultConfig(); - } - void fetchConfig(AsyncWebServerRequest *request){ AsyncJsonResponse * response = new AsyncJsonResponse(); writeToJsonObject(response->getRoot()); @@ -91,7 +36,7 @@ private: if (json.is()){ JsonObject& newConfig = json.as(); readFromJsonObject(newConfig); - writeToSPIFFS(); + writeToFS(); // write settings back with a callback to reconfigure the wifi AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();}); @@ -108,28 +53,13 @@ private: // will serve setting endpoints from here AsyncWebServer* _server; - // will store and retrieve config from the file system - FS* _fs; - - // reads the local config from the - virtual void readFromJsonObject(JsonObject& root){} - virtual void writeToJsonObject(JsonObject& root){} - // implement to perform action when config has been updated virtual void onConfigUpdated(){} - // We assume the readFromJsonObject supplies sensible defaults if an empty object - // is supplied, this virtual function allows that to be changed. - virtual void applyDefaultConfig(){ - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - readFromJsonObject(root); - } - public: SettingsService(AsyncWebServer* server, FS* fs, char const* servicePath, char const* filePath): - _filePath(filePath), _server(server), _fs(fs){ + SettingsPersistence(fs, servicePath, filePath), _server(server) { // configure fetch config handler _server->on(servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1)); @@ -145,7 +75,7 @@ private: virtual ~SettingsService() {} virtual void begin() { - readFromSPIFFS(); + readFromFS(); } };