diff --git a/lib_standalone/Arduino.cpp b/lib_standalone/Arduino.cpp index 4e25c2cc6..453a1539e 100644 --- a/lib_standalone/Arduino.cpp +++ b/lib_standalone/Arduino.cpp @@ -37,7 +37,6 @@ static bool __output_pins[256]; static int __output_level[256]; int main(int argc __attribute__((unused)), char * argv[] __attribute__((unused))) { - memset(__output_pins, 0, sizeof(__output_pins)); memset(__output_level, 0, sizeof(__output_level)); diff --git a/lib_standalone/AsyncJson.h b/lib_standalone/AsyncJson.h index e9a36ba76..c957646d5 100644 --- a/lib_standalone/AsyncJson.h +++ b/lib_standalone/AsyncJson.h @@ -3,16 +3,11 @@ #define ASYNC_JSON_H_ #include #include -// #include #define DYNAMIC_JSON_DOCUMENT_SIZE 1024 constexpr const char * JSON_MIMETYPE = "application/json"; -/* - * Json Response - * */ - class ChunkPrint : public Print { private: uint8_t * _destination; @@ -45,9 +40,8 @@ class ChunkPrint : public Print { } }; -class AsyncJsonResponse { +class AsyncJsonResponse { protected: - DynamicJsonDocument _jsonBuffer; JsonVariant _root; @@ -71,7 +65,7 @@ class AsyncJsonResponse { return _isValid; } size_t setLength() { -return 0; + return 0; } size_t getSize() { @@ -79,9 +73,6 @@ return 0; } size_t _fillBuffer(uint8_t * data, size_t len) { - // ChunkPrint dest(data, 0, len); - - // serializeJson(_root, dest); return len; } }; diff --git a/lib_standalone/AsyncMqttClient.h b/lib_standalone/AsyncMqttClient.h index 73a1058ea..65e40b2c8 100644 --- a/lib_standalone/AsyncMqttClient.h +++ b/lib_standalone/AsyncMqttClient.h @@ -24,7 +24,6 @@ struct AsyncMqttClientMessageProperties { bool retain; }; - namespace AsyncMqttClientInternals { typedef std::function OnConnectUserCallback; diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index 718a32b67..6621670c2 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -95,8 +95,6 @@ class EMSESPSettingsService { void begin(); private: - // HttpEndpoint _httpEndpoint; - // FSPersistence _fsPersistence; }; #endif diff --git a/lib_standalone/ESPAsyncWebServer.h b/lib_standalone/ESPAsyncWebServer.h index 35a848485..7b4a188e2 100644 --- a/lib_standalone/ESPAsyncWebServer.h +++ b/lib_standalone/ESPAsyncWebServer.h @@ -68,8 +68,8 @@ typedef std::function ArRequestFilterFunc class AsyncWebHandler { protected: - String _username; - String _password; + String _username; + String _password; public: AsyncWebHandler() @@ -131,7 +131,6 @@ class AsyncWebServer { } void on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest){}; - }; diff --git a/lib_standalone/FSPersistence.h b/lib_standalone/FSPersistence.h index 754a90cda..e6c43a69f 100644 --- a/lib_standalone/FSPersistence.h +++ b/lib_standalone/FSPersistence.h @@ -24,46 +24,13 @@ class FSPersistence { } void readFromFS() { - /* - File settingsFile = _fs->open(_filePath, "r"); - - if (settingsFile) { - DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); - DeserializationError error = deserializeJson(jsonDocument, settingsFile); - if (error == DeserializationError::Ok && jsonDocument.is()) { - JsonObject jsonObject = jsonDocument.as(); - _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater); - settingsFile.close(); - return; - } - settingsFile.close(); - } - */ - // If we reach here we have not been successful in loading the config, - // hard-coded emergency defaults are now applied. - applyDefaults(); } bool writeToFS() { - // create and populate a new json object DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); JsonObject jsonObject = jsonDocument.to(); _statefulService->read(jsonObject, _stateReader); - - // serialize it to filesystem - /* - File settingsFile = _fs->open(_filePath, "w"); - - // failed to open file, return false - if (!settingsFile) { - return false; - } - - // serialize the data to the file - serializeJson(jsonDocument, settingsFile); - settingsFile.close(); - */ return true; } @@ -90,8 +57,6 @@ class FSPersistence { update_handler_id_t _updateHandlerId; protected: - // We assume the updater supplies sensible defaults if an empty object - // is supplied, this virtual function allows that to be changed. virtual void applyDefaults() { DynamicJsonDocument jsonDocument = DynamicJsonDocument(_bufferSize); JsonObject jsonObject = jsonDocument.as(); diff --git a/lib_standalone/HttpEndpoint.h b/lib_standalone/HttpEndpoint.h index c5ce9fefe..ae3d7c89c 100644 --- a/lib_standalone/HttpEndpoint.h +++ b/lib_standalone/HttpEndpoint.h @@ -22,12 +22,6 @@ class HttpGetEndpoint { AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN, size_t bufferSize = DEFAULT_BUFFER_SIZE) : _stateReader(stateReader), _statefulService(statefulService), _bufferSize(bufferSize) { - /* - server->on(servicePath.c_str(), - HTTP_GET, - securityManager->wrapRequest(std::bind(&HttpGetEndpoint::fetchSettings, this, std::placeholders::_1), - authenticationPredicate)); - */ } HttpGetEndpoint(JsonStateReader stateReader, @@ -36,9 +30,6 @@ class HttpGetEndpoint { const String& servicePath, size_t bufferSize = DEFAULT_BUFFER_SIZE) : _stateReader(stateReader), _statefulService(statefulService), _bufferSize(bufferSize) { - /* - server->on(servicePath.c_str(), HTTP_GET, std::bind(&HttpGetEndpoint::fetchSettings, this, std::placeholders::_1)); - */ } protected: @@ -47,12 +38,6 @@ class HttpGetEndpoint { size_t _bufferSize; void fetchSettings(AsyncWebServerRequest* request) { - // AsyncJsonResponse* response = new AsyncJsonResponse(false, _bufferSize); - // JsonObject jsonObject = response->getRoot().to(); - // _statefulService->read(jsonObject, _stateReader); - - // response->setLength(); - // request->send(response); } }; @@ -70,17 +55,7 @@ class HttpPostEndpoint { _stateReader(stateReader), _stateUpdater(stateUpdater), _statefulService(statefulService), - /* - _updateHandler( - servicePath, - securityManager->wrapCallback( - std::bind(&HttpPostEndpoint::updateSettings, this, std::placeholders::_1, std::placeholders::_2), - authenticationPredicate), - bufferSize), - */ _bufferSize(bufferSize) { - //_updateHandler.setMethod(HTTP_POST); - // server->addHandler(&_updateHandler); } HttpPostEndpoint(JsonStateReader stateReader, @@ -92,42 +67,26 @@ class HttpPostEndpoint { _stateReader(stateReader), _stateUpdater(stateUpdater), _statefulService(statefulService), - /* - _updateHandler(servicePath, - std::bind(&HttpPostEndpoint::updateSettings, this, std::placeholders::_1, std::placeholders::_2), - bufferSize), - */ _bufferSize(bufferSize) { - // _updateHandler.setMethod(HTTP_POST); - // server->addHandler(&_updateHandler); } protected: JsonStateReader _stateReader; JsonStateUpdater _stateUpdater; StatefulService* _statefulService; - //AsyncCallbackJsonWebHandler _updateHandler; size_t _bufferSize; void updateSettings(AsyncWebServerRequest* request, JsonVariant& json) { if (!json.is()) { - // request->send(400); return; } JsonObject jsonObject = json.as(); StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater); if (outcome == StateUpdateResult::ERROR) { - // request->send(400); return; } if (outcome == StateUpdateResult::CHANGED) { - // request->onDisconnect([this]() { _statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID); }); } - // AsyncJsonResponse* response = new AsyncJsonResponse(false, _bufferSize); - // jsonObject = response->getRoot().to(); - // _statefulService->read(jsonObject, _stateReader); - // response->setLength(); - // request->send(response); } }; diff --git a/lib_standalone/SecurityManager.h b/lib_standalone/SecurityManager.h index 1f1258e09..327206351 100644 --- a/lib_standalone/SecurityManager.h +++ b/lib_standalone/SecurityManager.h @@ -4,7 +4,6 @@ #include #include #include -// #include #include #include @@ -21,82 +20,64 @@ #define MAX_JWT_SIZE 128 class User { - public: - String username; - String password; - bool admin; + public: + String username; + String password; + bool admin; - public: - User(String username, String password, bool admin) : username(username), password(password), admin(admin) { - } + public: + User(String username, String password, bool admin) + : username(username) + , password(password) + , admin(admin) { + } }; class Authentication { - public: - User* user; - boolean authenticated; + public: + User * user; + boolean authenticated; - public: - Authentication(User& user) : user(new User(user)), authenticated(true) { - } - Authentication() : user(nullptr), authenticated(false) { - } - ~Authentication() { - delete (user); - } + public: + Authentication(User & user) + : user(new User(user)) + , authenticated(true) { + } + Authentication() + : user(nullptr) + , authenticated(false) { + } + ~Authentication() { + delete (user); + } }; -typedef std::function AuthenticationPredicate; +typedef std::function AuthenticationPredicate; class AuthenticationPredicates { - public: - static bool NONE_REQUIRED(Authentication& authentication) { - return true; - }; - static bool IS_AUTHENTICATED(Authentication& authentication) { - return authentication.authenticated; - }; - static bool IS_ADMIN(Authentication& authentication) { - return authentication.authenticated && authentication.user->admin; - }; + public: + static bool NONE_REQUIRED(Authentication & authentication) { + return true; + }; + static bool IS_AUTHENTICATED(Authentication & authentication) { + return authentication.authenticated; + }; + static bool IS_ADMIN(Authentication & authentication) { + return authentication.authenticated && authentication.user->admin; + }; }; class SecurityManager { - public: + public: #if FT_ENABLED(FT_SECURITY) - /* - * Authenticate, returning the user if found - */ - virtual Authentication authenticate(const String& username, const String& password) = 0; - - /* - * Generate a JWT for the user provided - */ - virtual String generateJWT(User* user) = 0; - + virtual Authentication authenticate(const String & username, const String & password) = 0; + virtual String generateJWT(User * user) = 0; #endif - /* - * Check the request header for the Authorization token - */ - virtual Authentication authenticateRequest(AsyncWebServerRequest* request) = 0; - - /** - * Filter a request with the provided predicate, only returning true if the predicate matches. - */ - virtual ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate) = 0; - - /** - * Wrap the provided request to provide validation against an AuthenticationPredicate. - */ - virtual ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, - AuthenticationPredicate predicate) = 0; - - /** - * Wrap the provided json request callback to provide validation against an AuthenticationPredicate. - */ - virtual ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, - AuthenticationPredicate predicate) = 0; + virtual Authentication authenticateRequest(AsyncWebServerRequest * request) = 0; + virtual ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate) = 0; + virtual ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) = 0; + virtual ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) = 0; }; -#endif // end SecurityManager_h +#endif // end SecurityManager_h diff --git a/lib_standalone/SecuritySettingsService.h b/lib_standalone/SecuritySettingsService.h index 801e44a3e..0034d08a4 100644 --- a/lib_standalone/SecuritySettingsService.h +++ b/lib_standalone/SecuritySettingsService.h @@ -30,87 +30,79 @@ #if FT_ENABLED(FT_SECURITY) class SecuritySettings { - public: - String jwtSecret; - std::list users; + public: + String jwtSecret; + std::list users; - static void read(SecuritySettings& settings, JsonObject& root) { - // secret - root["jwt_secret"] = settings.jwtSecret; + static void read(SecuritySettings & settings, JsonObject & root) { + // secret + root["jwt_secret"] = settings.jwtSecret; - // users - JsonArray users = root.createNestedArray("users"); - for (User user : settings.users) { - JsonObject userRoot = users.createNestedObject(); - userRoot["username"] = user.username; - userRoot["password"] = user.password; - userRoot["admin"] = user.admin; + // users + JsonArray users = root.createNestedArray("users"); + for (User user : settings.users) { + JsonObject userRoot = users.createNestedObject(); + userRoot["username"] = user.username; + userRoot["password"] = user.password; + userRoot["admin"] = user.admin; + } } - } - static StateUpdateResult update(JsonObject& root, SecuritySettings& settings) { - // secret - settings.jwtSecret = root["jwt_secret"] | FACTORY_JWT_SECRET; + static StateUpdateResult update(JsonObject & root, SecuritySettings & settings) { + // secret + settings.jwtSecret = root["jwt_secret"] | FACTORY_JWT_SECRET; - // users - settings.users.clear(); - if (root["users"].is()) { - for (JsonVariant user : root["users"].as()) { - settings.users.push_back(User(user["username"], user["password"], user["admin"])); - } - } else { - settings.users.push_back(User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true)); - settings.users.push_back(User(FACTORY_GUEST_USERNAME, FACTORY_GUEST_PASSWORD, false)); + // users + settings.users.clear(); + if (root["users"].is()) { + for (JsonVariant user : root["users"].as()) { + settings.users.push_back(User(user["username"], user["password"], user["admin"])); + } + } else { + settings.users.push_back(User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true)); + settings.users.push_back(User(FACTORY_GUEST_USERNAME, FACTORY_GUEST_PASSWORD, false)); + } + return StateUpdateResult::CHANGED; } - return StateUpdateResult::CHANGED; - } }; class SecuritySettingsService : public StatefulService, public SecurityManager { - public: - SecuritySettingsService(AsyncWebServer* server, FS* fs); + public: + SecuritySettingsService(AsyncWebServer * server, FS * fs); - void begin(); + void begin(); - // Functions to implement SecurityManager - Authentication authenticate(const String& username, const String& password); - Authentication authenticateRequest(AsyncWebServerRequest* request); - String generateJWT(User* user); - ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate); - ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate); - ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction callback, AuthenticationPredicate predicate); + // Functions to implement SecurityManager + Authentication authenticate(const String & username, const String & password); + Authentication authenticateRequest(AsyncWebServerRequest * request); + String generateJWT(User * user); + ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate); + ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate); + ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction callback, AuthenticationPredicate predicate); - private: - HttpEndpoint _httpEndpoint; - FSPersistence _fsPersistence; - ArduinoJsonJWT _jwtHandler; + private: + HttpEndpoint _httpEndpoint; + FSPersistence _fsPersistence; + ArduinoJsonJWT _jwtHandler; - void configureJWTHandler(); - - /* - * Lookup the user by JWT - */ - Authentication authenticateJWT(String& jwt); - - /* - * Verify the payload is correct - */ - boolean validatePayload(JsonObject& parsedPayload, User* user); + void configureJWTHandler(); + Authentication authenticateJWT(String & jwt); + boolean validatePayload(JsonObject & parsedPayload, User * user); }; #else class SecuritySettingsService : public SecurityManager { - public: - SecuritySettingsService(AsyncWebServer* server, FS* fs); - ~SecuritySettingsService(); + public: + SecuritySettingsService(AsyncWebServer * server, FS * fs); + ~SecuritySettingsService(); - // minimal set of functions to support framework with security settings disabled - Authentication authenticateRequest(AsyncWebServerRequest* request); - ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate); - ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate); - ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate); + // minimal set of functions to support framework with security settings disabled + Authentication authenticateRequest(AsyncWebServerRequest * request); + ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate); + ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate); + ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate); }; -#endif // end FT_ENABLED(FT_SECURITY) -#endif // end SecuritySettingsService_h +#endif // end FT_ENABLED(FT_SECURITY) +#endif // end SecuritySettingsService_h diff --git a/lib_standalone/StatefulService.h b/lib_standalone/StatefulService.h index c6c38e988..41db7d3d5 100644 --- a/lib_standalone/StatefulService.h +++ b/lib_standalone/StatefulService.h @@ -12,133 +12,137 @@ #endif enum class StateUpdateResult { - CHANGED = 0, // The update changed the state and propagation should take place if required - UNCHANGED, // The state was unchanged, propagation should not take place - ERROR // There was a problem updating the state, propagation should not take place + CHANGED = 0, // The update changed the state and propagation should take place if required + UNCHANGED, // The state was unchanged, propagation should not take place + ERROR // There was a problem updating the state, propagation should not take place }; template -using JsonStateUpdater = std::function; +using JsonStateUpdater = std::function; template -using JsonStateReader = std::function; +using JsonStateReader = std::function; -typedef size_t update_handler_id_t; -typedef std::function StateUpdateCallback; +typedef size_t update_handler_id_t; +typedef std::function StateUpdateCallback; typedef struct StateUpdateHandlerInfo { - static update_handler_id_t currentUpdatedHandlerId; - update_handler_id_t _id; - StateUpdateCallback _cb; - bool _allowRemove; - StateUpdateHandlerInfo(StateUpdateCallback cb, bool allowRemove) : - _id(++currentUpdatedHandlerId), _cb(cb), _allowRemove(allowRemove){}; + static update_handler_id_t currentUpdatedHandlerId; + update_handler_id_t _id; + StateUpdateCallback _cb; + bool _allowRemove; + StateUpdateHandlerInfo(StateUpdateCallback cb, bool allowRemove) + : _id(++currentUpdatedHandlerId) + , _cb(cb) + , _allowRemove(allowRemove){}; } StateUpdateHandlerInfo_t; template class StatefulService { - public: - template + public: + template #ifdef ESP32 - StatefulService(Args&&... args) : - _state(std::forward(args)...), _accessMutex(xSemaphoreCreateRecursiveMutex()) { - } + StatefulService(Args &&... args) + : _state(std::forward(args)...) + , _accessMutex(xSemaphoreCreateRecursiveMutex()) { + } #else - StatefulService(Args&&... args) : _state(std::forward(args)...) { - } + StatefulService(Args &&... args) + : _state(std::forward(args)...) { + } #endif - update_handler_id_t addUpdateHandler(StateUpdateCallback cb, bool allowRemove = true) { - if (!cb) { - return 0; + update_handler_id_t addUpdateHandler(StateUpdateCallback cb, bool allowRemove = true) { + if (!cb) { + return 0; + } + StateUpdateHandlerInfo_t updateHandler(cb, allowRemove); + _updateHandlers.push_back(updateHandler); + return updateHandler._id; } - StateUpdateHandlerInfo_t updateHandler(cb, allowRemove); - _updateHandlers.push_back(updateHandler); - return updateHandler._id; - } - void removeUpdateHandler(update_handler_id_t id) { - for (auto i = _updateHandlers.begin(); i != _updateHandlers.end();) { - if ((*i)._allowRemove && (*i)._id == id) { - i = _updateHandlers.erase(i); - } else { - ++i; - } + void removeUpdateHandler(update_handler_id_t id) { + for (auto i = _updateHandlers.begin(); i != _updateHandlers.end();) { + if ((*i)._allowRemove && (*i)._id == id) { + i = _updateHandlers.erase(i); + } else { + ++i; + } + } } - } - StateUpdateResult update(std::function stateUpdater, const String& originId) { - beginTransaction(); - StateUpdateResult result = stateUpdater(_state); - endTransaction(); - if (result == StateUpdateResult::CHANGED) { - callUpdateHandlers(originId); + StateUpdateResult update(std::function stateUpdater, const String & originId) { + beginTransaction(); + StateUpdateResult result = stateUpdater(_state); + endTransaction(); + if (result == StateUpdateResult::CHANGED) { + callUpdateHandlers(originId); + } + return result; } - return result; - } - StateUpdateResult updateWithoutPropagation(std::function stateUpdater) { - beginTransaction(); - StateUpdateResult result = stateUpdater(_state); - endTransaction(); - return result; - } - - StateUpdateResult update(JsonObject& jsonObject, JsonStateUpdater stateUpdater, const String& originId) { - beginTransaction(); - StateUpdateResult result = stateUpdater(jsonObject, _state); - endTransaction(); - if (result == StateUpdateResult::CHANGED) { - callUpdateHandlers(originId); + StateUpdateResult updateWithoutPropagation(std::function stateUpdater) { + beginTransaction(); + StateUpdateResult result = stateUpdater(_state); + endTransaction(); + return result; } - return result; - } - StateUpdateResult updateWithoutPropagation(JsonObject& jsonObject, JsonStateUpdater stateUpdater) { - beginTransaction(); - StateUpdateResult result = stateUpdater(jsonObject, _state); - endTransaction(); - return result; - } - - void read(std::function stateReader) { - beginTransaction(); - stateReader(_state); - endTransaction(); - } - - void read(JsonObject& jsonObject, JsonStateReader stateReader) { - beginTransaction(); - stateReader(_state, jsonObject); - endTransaction(); - } - - void callUpdateHandlers(const String& originId) { - for (const StateUpdateHandlerInfo_t& updateHandler : _updateHandlers) { - updateHandler._cb(originId); + StateUpdateResult update(JsonObject & jsonObject, JsonStateUpdater stateUpdater, const String & originId) { + beginTransaction(); + StateUpdateResult result = stateUpdater(jsonObject, _state); + endTransaction(); + if (result == StateUpdateResult::CHANGED) { + callUpdateHandlers(originId); + } + return result; } - } - protected: - T _state; + StateUpdateResult updateWithoutPropagation(JsonObject & jsonObject, JsonStateUpdater stateUpdater) { + beginTransaction(); + StateUpdateResult result = stateUpdater(jsonObject, _state); + endTransaction(); + return result; + } - inline void beginTransaction() { + void read(std::function stateReader) { + beginTransaction(); + stateReader(_state); + endTransaction(); + } + + void read(JsonObject & jsonObject, JsonStateReader stateReader) { + beginTransaction(); + stateReader(_state, jsonObject); + endTransaction(); + } + + void callUpdateHandlers(const String & originId) { + for (const StateUpdateHandlerInfo_t & updateHandler : _updateHandlers) { + updateHandler._cb(originId); + } + } + + protected: + T _state; + + inline void beginTransaction() { #ifdef ESP32 - xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY); + xSemaphoreTakeRecursive(_accessMutex, portMAX_DELAY); #endif - } + } - inline void endTransaction() { + inline void endTransaction() { #ifdef ESP32 - xSemaphoreGiveRecursive(_accessMutex); + xSemaphoreGiveRecursive(_accessMutex); #endif - } + } - private: + private: #ifdef ESP32 - SemaphoreHandle_t _accessMutex; + SemaphoreHandle_t _accessMutex; #endif - std::list _updateHandlers; + std::list _updateHandlers; }; -#endif // end StatefulService_h +#endif // end StatefulService_h