Skip to content

Commit d03c03f

Browse files
committed
Remove refrence to SPIFFS global from persistence code, factor out persistence code so it can be re-used.
1 parent 4e200f3 commit d03c03f

File tree

2 files changed

+104
-76
lines changed

2 files changed

+104
-76
lines changed

src/SettingsPersistence.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#ifndef SettingsPersistence_h
2+
#define SettingsPersistence_h
3+
4+
#include <ESPAsyncWebServer.h>
5+
#include <FS.h>
6+
#include <AsyncJson.h>
7+
#include <ArduinoJson.h>
8+
#include <AsyncJsonRequestWebHandler.h>
9+
#include <AsyncJsonCallbackResponse.h>
10+
11+
/**
12+
* At the moment, not expecting settings service to have to deal with large JSON
13+
* files this could be made configurable fairly simply, it's exposed on
14+
* AsyncJsonRequestWebHandler with a setter.
15+
*/
16+
#define MAX_SETTINGS_SIZE 1024
17+
18+
/*
19+
* Mixin for classes which need to save settings to/from a file on the the file system as JSON.
20+
*/
21+
class SettingsPersistence {
22+
23+
protected:
24+
25+
// will store and retrieve config from the file system
26+
FS* _fs;
27+
28+
// the file path our settings will be saved to
29+
char const* _filePath;
30+
31+
bool writeToFS() {
32+
// create and populate a new json object
33+
DynamicJsonBuffer jsonBuffer;
34+
JsonObject& root = jsonBuffer.createObject();
35+
writeToJsonObject(root);
36+
37+
// serialize it to filesystem
38+
File configFile = _fs->open(_filePath, "w");
39+
40+
// failed to open file, return false
41+
if (!configFile) {
42+
return false;
43+
}
44+
45+
root.printTo(configFile);
46+
configFile.close();
47+
48+
return true;
49+
}
50+
51+
void readFromFS(){
52+
File configFile = _fs->open(_filePath, "r");
53+
54+
// use defaults if no config found
55+
if (configFile) {
56+
// Protect against bad data uploaded to file system
57+
// We never expect the config file to get very large, so cap it.
58+
size_t size = configFile.size();
59+
if (size <= MAX_SETTINGS_SIZE) {
60+
DynamicJsonBuffer jsonBuffer;
61+
JsonObject& root = jsonBuffer.parseObject(configFile);
62+
if (root.success()) {
63+
readFromJsonObject(root);
64+
configFile.close();
65+
return;
66+
}
67+
}
68+
configFile.close();
69+
}
70+
71+
// If we reach here we have not been successful in loading the config,
72+
// hard-coded emergency defaults are now applied.
73+
applyDefaultConfig();
74+
}
75+
76+
77+
// serialization routene, from local config to JsonObject
78+
virtual void readFromJsonObject(JsonObject& root){}
79+
virtual void writeToJsonObject(JsonObject& root){}
80+
81+
// We assume the readFromJsonObject supplies sensible defaults if an empty object
82+
// is supplied, this virtual function allows that to be changed.
83+
virtual void applyDefaultConfig(){
84+
DynamicJsonBuffer jsonBuffer;
85+
JsonObject& root = jsonBuffer.createObject();
86+
readFromJsonObject(root);
87+
}
88+
89+
public:
90+
91+
SettingsPersistence(FS* fs, char const* servicePath, char const* filePath):
92+
_fs(fs), _filePath(filePath) {}
93+
94+
virtual ~SettingsPersistence() {}
95+
96+
};
97+
98+
#endif // end SettingsPersistence

src/SettingsService.h

Lines changed: 6 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -7,79 +7,24 @@
77
#elif defined(ESP_PLATFORM)
88
#include <WiFi.h>
99
#include <AsyncTCP.h>
10-
#include <SPIFFS.h>
1110
#endif
1211

12+
#include <SettingsPersistence.h>
1313
#include <ESPAsyncWebServer.h>
14-
#include <FS.h>
1514
#include <AsyncJson.h>
1615
#include <ArduinoJson.h>
1716
#include <AsyncJsonRequestWebHandler.h>
1817
#include <AsyncJsonCallbackResponse.h>
1918

20-
/**
21-
* At the moment, not expecting settings service to have to deal with large JSON
22-
* files this could be made configurable fairly simply, it's exposed on
23-
* AsyncJsonRequestWebHandler with a setter.
24-
*/
25-
#define MAX_SETTINGS_SIZE 1024
26-
2719
/*
28-
* Abstraction of a service which stores it's settings as JSON in SPIFFS.
20+
* Abstraction of a service which stores it's settings as JSON in a file system.
2921
*/
30-
class SettingsService {
22+
class SettingsService : public SettingsPersistence {
3123

3224
private:
3325

34-
char const* _filePath;
35-
3626
AsyncJsonRequestWebHandler _updateHandler;
3727

38-
bool writeToSPIFFS() {
39-
// create and populate a new json object
40-
DynamicJsonBuffer jsonBuffer;
41-
JsonObject& root = jsonBuffer.createObject();
42-
writeToJsonObject(root);
43-
44-
// serialize it to SPIFFS
45-
File configFile = SPIFFS.open(_filePath, "w");
46-
47-
// failed to open file, return false
48-
if (!configFile) {
49-
return false;
50-
}
51-
52-
root.printTo(configFile);
53-
configFile.close();
54-
55-
return true;
56-
}
57-
58-
void readFromSPIFFS(){
59-
File configFile = SPIFFS.open(_filePath, "r");
60-
61-
// use defaults if no config found
62-
if (configFile) {
63-
// Protect against bad data uploaded to SPIFFS
64-
// We never expect the config file to get very large, so cap it.
65-
size_t size = configFile.size();
66-
if (size <= MAX_SETTINGS_SIZE) {
67-
DynamicJsonBuffer jsonBuffer;
68-
JsonObject& root = jsonBuffer.parseObject(configFile);
69-
if (root.success()) {
70-
readFromJsonObject(root);
71-
configFile.close();
72-
return;
73-
}
74-
}
75-
configFile.close();
76-
}
77-
78-
// If we reach here we have not been successful in loading the config,
79-
// hard-coded emergency defaults are now applied.
80-
applyDefaultConfig();
81-
}
82-
8328
void fetchConfig(AsyncWebServerRequest *request){
8429
AsyncJsonResponse * response = new AsyncJsonResponse();
8530
writeToJsonObject(response->getRoot());
@@ -91,7 +36,7 @@ class SettingsService {
9136
if (json.is<JsonObject>()){
9237
JsonObject& newConfig = json.as<JsonObject>();
9338
readFromJsonObject(newConfig);
94-
writeToSPIFFS();
39+
writeToFS();
9540

9641
// write settings back with a callback to reconfigure the wifi
9742
AsyncJsonCallbackResponse * response = new AsyncJsonCallbackResponse([this] () {onConfigUpdated();});
@@ -108,28 +53,13 @@ class SettingsService {
10853
// will serve setting endpoints from here
10954
AsyncWebServer* _server;
11055

111-
// will store and retrieve config from the file system
112-
FS* _fs;
113-
114-
// reads the local config from the
115-
virtual void readFromJsonObject(JsonObject& root){}
116-
virtual void writeToJsonObject(JsonObject& root){}
117-
11856
// implement to perform action when config has been updated
11957
virtual void onConfigUpdated(){}
12058

121-
// We assume the readFromJsonObject supplies sensible defaults if an empty object
122-
// is supplied, this virtual function allows that to be changed.
123-
virtual void applyDefaultConfig(){
124-
DynamicJsonBuffer jsonBuffer;
125-
JsonObject& root = jsonBuffer.createObject();
126-
readFromJsonObject(root);
127-
}
128-
12959
public:
13060

13161
SettingsService(AsyncWebServer* server, FS* fs, char const* servicePath, char const* filePath):
132-
_filePath(filePath), _server(server), _fs(fs){
62+
SettingsPersistence(fs, servicePath, filePath), _server(server) {
13363

13464
// configure fetch config handler
13565
_server->on(servicePath, HTTP_GET, std::bind(&SettingsService::fetchConfig, this, std::placeholders::_1));
@@ -145,7 +75,7 @@ class SettingsService {
14575
virtual ~SettingsService() {}
14676

14777
virtual void begin() {
148-
readFromSPIFFS();
78+
readFromFS();
14979
}
15080

15181
};

0 commit comments

Comments
 (0)