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.

137 lines
3.4 KiB

  1. #ifndef StatefulService_h
  2. #define StatefulService_h
  3. #include <Arduino.h>
  4. #include <JsonDeserializer.h>
  5. #include <JsonSerializer.h>
  6. #include <list>
  7. #include <functional>
  8. #ifdef ESP32
  9. #include <freertos/FreeRTOS.h>
  10. #include <freertos/semphr.h>
  11. #endif
  12. typedef size_t update_handler_id_t;
  13. typedef std::function<void(const String& originId)> StateUpdateCallback;
  14. typedef struct StateUpdateHandlerInfo {
  15. static update_handler_id_t currentUpdatedHandlerId;
  16. update_handler_id_t _id;
  17. StateUpdateCallback _cb;
  18. bool _allowRemove;
  19. StateUpdateHandlerInfo(StateUpdateCallback cb, bool allowRemove) :
  20. _id(++currentUpdatedHandlerId), _cb(cb), _allowRemove(allowRemove){};
  21. } StateUpdateHandlerInfo_t;
  22. template <class T>
  23. class StatefulService {
  24. public:
  25. template <typename... Args>
  26. #ifdef ESP32
  27. StatefulService(Args&&... args) :
  28. _state(std::forward<Args>(args)...), _accessMutex(xSemaphoreCreateRecursiveMutex()) {
  29. }
  30. #else
  31. StatefulService(Args&&... args) : _state(std::forward<Args>(args)...) {
  32. }
  33. #endif
  34. update_handler_id_t addUpdateHandler(StateUpdateCallback cb, bool allowRemove = true) {
  35. if (!cb) {
  36. return 0;
  37. }
  38. StateUpdateHandlerInfo_t updateHandler(cb, allowRemove);
  39. _updateHandlers.push_back(updateHandler);
  40. return updateHandler._id;
  41. }
  42. void removeUpdateHandler(update_handler_id_t id) {
  43. for (auto i = _updateHandlers.begin(); i != _updateHandlers.end();) {
  44. if ((*i)._allowRemove && (*i)._id == id) {
  45. i = _updateHandlers.erase(i);
  46. } else {
  47. ++i;
  48. }
  49. }
  50. }
  51. void updateWithoutPropagation(std::function<void(T&)> callback) {
  52. #ifdef ESP32
  53. xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
  54. #endif
  55. callback(_state);
  56. #ifdef ESP32
  57. xSemaphoreGiveRecursive(_accessMutex);
  58. #endif
  59. }
  60. void updateWithoutPropagation(JsonObject& jsonObject, JsonDeserializer<T> deserializer) {
  61. #ifdef ESP32
  62. xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
  63. #endif
  64. deserializer(jsonObject, _state);
  65. #ifdef ESP32
  66. xSemaphoreGiveRecursive(_accessMutex);
  67. #endif
  68. }
  69. void update(std::function<void(T&)> callback, const String& originId) {
  70. #ifdef ESP32
  71. xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
  72. #endif
  73. callback(_state);
  74. callUpdateHandlers(originId);
  75. #ifdef ESP32
  76. xSemaphoreGiveRecursive(_accessMutex);
  77. #endif
  78. }
  79. void update(JsonObject& jsonObject, JsonDeserializer<T> deserializer, const String& originId) {
  80. #ifdef ESP32
  81. xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
  82. #endif
  83. deserializer(jsonObject, _state);
  84. callUpdateHandlers(originId);
  85. #ifdef ESP32
  86. xSemaphoreGiveRecursive(_accessMutex);
  87. #endif
  88. }
  89. void read(std::function<void(T&)> callback) {
  90. #ifdef ESP32
  91. xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
  92. #endif
  93. callback(_state);
  94. #ifdef ESP32
  95. xSemaphoreGiveRecursive(_accessMutex);
  96. #endif
  97. }
  98. void read(JsonObject& jsonObject, JsonSerializer<T> serializer) {
  99. #ifdef ESP32
  100. xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY);
  101. #endif
  102. serializer(_state, jsonObject);
  103. #ifdef ESP32
  104. xSemaphoreGiveRecursive(_accessMutex);
  105. #endif
  106. }
  107. void callUpdateHandlers(const String& originId) {
  108. for (const StateUpdateHandlerInfo_t& updateHandler : _updateHandlers) {
  109. updateHandler._cb(originId);
  110. }
  111. }
  112. protected:
  113. T _state;
  114. private:
  115. #ifdef ESP32
  116. SemaphoreHandle_t _accessMutex;
  117. #endif
  118. std::list<StateUpdateHandlerInfo_t> _updateHandlers;
  119. };
  120. #endif // end StatefulService_h