Fork of the excellent esp8266-react - https://github.com/rjwats/esp8266-react
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
2.9 KiB

  1. #ifndef FSPersistence_h
  2. #define FSPersistence_h
  3. #include <StatefulService.h>
  4. #include <FS.h>
  5. template <class T>
  6. class FSPersistence {
  7. public:
  8. FSPersistence(JsonStateReader<T> stateReader,
  9. JsonStateUpdater<T> stateUpdater,
  10. StatefulService<T>* statefulService,
  11. FS* fs,
  12. char const* filePath,
  13. size_t bufferSize = DEFAULT_BUFFER_SIZE) :
  14. _stateReader(stateReader),
  15. _stateUpdater(stateUpdater),
  16. _statefulService(statefulService),
  17. _fs(fs),
  18. _filePath(filePath),
  19. _bufferSize(bufferSize),
  20. _updateHandlerId(0) {
  21. enableUpdateHandler();
  22. }
  23. void readFromFS() {
  24. File settingsFile = _fs->open(_filePath, "r");
  25. if (settingsFile) {
  26. DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
  27. DeserializationError error = deserializeJson(jsonDocument, settingsFile);
  28. if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
  29. JsonObject jsonObject = jsonDocument.as<JsonObject>();
  30. _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
  31. settingsFile.close();
  32. return;
  33. }
  34. settingsFile.close();
  35. }
  36. // If we reach here we have not been successful in loading the config,
  37. // hard-coded emergency defaults are now applied.
  38. applyDefaults();
  39. }
  40. bool writeToFS() {
  41. // create and populate a new json object
  42. DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
  43. JsonObject jsonObject = jsonDocument.to<JsonObject>();
  44. _statefulService->read(jsonObject, _stateReader);
  45. // serialize it to filesystem
  46. File settingsFile = _fs->open(_filePath, "w");
  47. // failed to open file, return false
  48. if (!settingsFile) {
  49. return false;
  50. }
  51. // serialize the data to the file
  52. serializeJson(jsonDocument, settingsFile);
  53. settingsFile.close();
  54. return true;
  55. }
  56. void disableUpdateHandler() {
  57. if (_updateHandlerId) {
  58. _statefulService->removeUpdateHandler(_updateHandlerId);
  59. _updateHandlerId = 0;
  60. }
  61. }
  62. void enableUpdateHandler() {
  63. if (!_updateHandlerId) {
  64. _updateHandlerId = _statefulService->addUpdateHandler([&](const String& originId) { writeToFS(); });
  65. }
  66. }
  67. private:
  68. JsonStateReader<T> _stateReader;
  69. JsonStateUpdater<T> _stateUpdater;
  70. StatefulService<T>* _statefulService;
  71. FS* _fs;
  72. char const* _filePath;
  73. size_t _bufferSize;
  74. update_handler_id_t _updateHandlerId;
  75. protected:
  76. // We assume the updater supplies sensible defaults if an empty object
  77. // is supplied, this virtual function allows that to be changed.
  78. virtual void applyDefaults() {
  79. DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize);
  80. JsonObject jsonObject = jsonDocument.as<JsonObject>();
  81. _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
  82. }
  83. };
  84. #endif // end FSPersistence