Remove refrence to SPIFFS global from persistence code, factor out persistence code so it can be re-used.
This commit is contained in:
parent
4e200f3d08
commit
d03c03fd9d
98
src/SettingsPersistence.h
Normal file
98
src/SettingsPersistence.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#ifndef SettingsPersistence_h
|
||||||
|
#define SettingsPersistence_h
|
||||||
|
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <FS.h>
|
||||||
|
#include <AsyncJson.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <AsyncJsonRequestWebHandler.h>
|
||||||
|
#include <AsyncJsonCallbackResponse.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
@ -7,79 +7,24 @@
|
|||||||
#elif defined(ESP_PLATFORM)
|
#elif defined(ESP_PLATFORM)
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
#include <SPIFFS.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <SettingsPersistence.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <FS.h>
|
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJsonRequestWebHandler.h>
|
#include <AsyncJsonRequestWebHandler.h>
|
||||||
#include <AsyncJsonCallbackResponse.h>
|
#include <AsyncJsonCallbackResponse.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* 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:
|
private:
|
||||||
|
|
||||||
char const* _filePath;
|
|
||||||
|
|
||||||
AsyncJsonRequestWebHandler _updateHandler;
|
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){
|
void fetchConfig(AsyncWebServerRequest *request){
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse();
|
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||||
writeToJsonObject(response->getRoot());
|
writeToJsonObject(response->getRoot());
|
||||||
@ -91,7 +36,7 @@ private:
|
|||||||
if (json.is<JsonObject>()){
|
if (json.is<JsonObject>()){
|
||||||
JsonObject& newConfig = json.as<JsonObject>();
|
JsonObject& newConfig = json.as<JsonObject>();
|
||||||
readFromJsonObject(newConfig);
|
readFromJsonObject(newConfig);
|
||||||
writeToSPIFFS();
|
writeToFS();
|
||||||
|
|
||||||
// write settings back with a callback to reconfigure the wifi
|
// write settings back with a callback to reconfigure the wifi
|
||||||
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();});
|
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();});
|
||||||
@ -108,28 +53,13 @@ private:
|
|||||||
// will serve setting endpoints from here
|
// will serve setting endpoints from here
|
||||||
AsyncWebServer* _server;
|
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
|
// implement to perform action when config has been updated
|
||||||
virtual void onConfigUpdated(){}
|
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:
|
public:
|
||||||
|
|
||||||
SettingsService(AsyncWebServer* server, FS* fs, char const* servicePath, char const* filePath):
|
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
|
// configure fetch config handler
|
||||||
_server->on(servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1));
|
_server->on(servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1));
|
||||||
@ -145,7 +75,7 @@ private:
|
|||||||
virtual ~SettingsService() {}
|
virtual ~SettingsService() {}
|
||||||
|
|
||||||
virtual void begin() {
|
virtual void begin() {
|
||||||
readFromSPIFFS();
|
readFromFS();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user