diff --git a/lib/framework/APSettingsService.cpp b/lib/framework/APSettingsService.cpp index 658570880..cff6d3818 100644 --- a/lib/framework/APSettingsService.cpp +++ b/lib/framework/APSettingsService.cpp @@ -1,4 +1,4 @@ -#include +#include "APSettingsService.h" #include "../../src/emsesp_stub.hpp" @@ -9,8 +9,8 @@ APSettingsService::APSettingsService(AsyncWebServer * server, FS * fs, SecurityM , _lastManaged(0) , _reconfigureAp(false) , _connected(0) { - addUpdateHandler([&](const String & originId) { reconfigureAP(); }, false); - WiFi.onEvent(std::bind(&APSettingsService::WiFiEvent, this, _1)); + addUpdateHandler([this] { reconfigureAP(); }, false); + WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event); }); } void APSettingsService::begin() { @@ -53,7 +53,7 @@ void APSettingsService::reconfigureAP() { void APSettingsService::loop() { unsigned long currentMillis = uuid::get_uptime(); - unsigned long manageElapsed = (uint32_t)(currentMillis - _lastManaged); + unsigned long manageElapsed = static_cast(currentMillis - _lastManaged); if (manageElapsed >= MANAGE_NETWORK_DELAY) { _lastManaged = currentMillis; manageAP(); @@ -76,7 +76,7 @@ void APSettingsService::manageAP() { void APSettingsService::startAP() { WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask); - esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_AP, WIFI_BW_HT20); + esp_wifi_set_bandwidth(static_cast(ESP_IF_WIFI_AP), WIFI_BW_HT20); WiFi.softAP(_state.ssid.c_str(), _state.password.c_str(), _state.channel, _state.ssidHidden, _state.maxClients); #if CONFIG_IDF_TARGET_ESP32C3 WiFi.setTxPower(WIFI_POWER_8_5dBm); // https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi @@ -108,14 +108,16 @@ void APSettingsService::handleDNS() { APNetworkStatus APSettingsService::getAPNetworkStatus() { WiFiMode_t currentWiFiMode = WiFi.getMode(); bool apActive = currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA; + if (apActive && _state.provisionMode != AP_MODE_ALWAYS && WiFi.status() == WL_CONNECTED) { return APNetworkStatus::LINGERING; } + return apActive ? APNetworkStatus::ACTIVE : APNetworkStatus::INACTIVE; } -void APSettings::read(APSettings & settings, JsonObject root) { +void APSettings::read(const APSettings & settings, JsonObject root) { root["provision_mode"] = settings.provisionMode; root["ssid"] = settings.ssid; root["password"] = settings.password; @@ -129,7 +131,8 @@ void APSettings::read(APSettings & settings, JsonObject root) { StateUpdateResult APSettings::update(JsonObject root, APSettings & settings) { APSettings newSettings = {}; - newSettings.provisionMode = root["provision_mode"] | FACTORY_AP_PROVISION_MODE; + newSettings.provisionMode = static_cast(root["provision_mode"] | FACTORY_AP_PROVISION_MODE); + switch (settings.provisionMode) { case AP_MODE_ALWAYS: case AP_MODE_DISCONNECTED: @@ -138,11 +141,12 @@ StateUpdateResult APSettings::update(JsonObject root, APSettings & settings) { default: newSettings.provisionMode = AP_MODE_ALWAYS; } + newSettings.ssid = root["ssid"] | FACTORY_AP_SSID; newSettings.password = root["password"] | FACTORY_AP_PASSWORD; - newSettings.channel = root["channel"] | FACTORY_AP_CHANNEL; + newSettings.channel = static_cast(root["channel"] | FACTORY_AP_CHANNEL); newSettings.ssidHidden = root["ssid_hidden"] | FACTORY_AP_SSID_HIDDEN; - newSettings.maxClients = root["max_clients"] | FACTORY_AP_MAX_CLIENTS; + newSettings.maxClients = static_cast(root["max_clients"] | FACTORY_AP_MAX_CLIENTS); JsonUtils::readIP(root, "local_ip", newSettings.localIP, FACTORY_AP_LOCAL_IP); JsonUtils::readIP(root, "gateway_ip", newSettings.gatewayIP, FACTORY_AP_GATEWAY_IP); @@ -151,6 +155,7 @@ StateUpdateResult APSettings::update(JsonObject root, APSettings & settings) { if (newSettings == settings) { return StateUpdateResult::UNCHANGED; } + settings = newSettings; return StateUpdateResult::CHANGED; } diff --git a/lib/framework/APSettingsService.h b/lib/framework/APSettingsService.h index 8857c4f99..3c76feeb5 100644 --- a/lib/framework/APSettingsService.h +++ b/lib/framework/APSettingsService.h @@ -1,9 +1,9 @@ #ifndef APSettingsConfig_h #define APSettingsConfig_h -#include -#include -#include +#include "HttpEndpoint.h" +#include "FSPersistence.h" +#include "JsonUtils.h" #include #include @@ -75,7 +75,7 @@ class APSettings { && subnetMask == settings.subnetMask; } - static void read(APSettings & settings, JsonObject root); + static void read(const APSettings & settings, JsonObject root); static StateUpdateResult update(JsonObject root, APSettings & settings); }; diff --git a/lib/framework/APStatus.cpp b/lib/framework/APStatus.cpp index d4595fefe..47ec3c8fa 100644 --- a/lib/framework/APStatus.cpp +++ b/lib/framework/APStatus.cpp @@ -1,17 +1,15 @@ -#include - -using namespace std::placeholders; // for `_1` etc +#include "APStatus.h" APStatus::APStatus(AsyncWebServer * server, SecurityManager * securityManager, APSettingsService * apSettingsService) : _apSettingsService(apSettingsService) { server->on(AP_STATUS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&APStatus::apStatus, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { apStatus(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); } void APStatus::apStatus(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); root["status"] = _apSettingsService->getAPNetworkStatus(); root["ip_address"] = WiFi.softAPIP().toString(); diff --git a/lib/framework/APStatus.h b/lib/framework/APStatus.h index addda2a25..23ee79305 100644 --- a/lib/framework/APStatus.h +++ b/lib/framework/APStatus.h @@ -7,8 +7,9 @@ #include #include #include -#include -#include + +#include "SecurityManager.h" +#include "APSettingsService.h" #define AP_STATUS_SERVICE_PATH "/rest/apStatus" diff --git a/lib/framework/ArduinoJsonJWT.cpp b/lib/framework/ArduinoJsonJWT.cpp index 595166ec5..eb8dce2d0 100644 --- a/lib/framework/ArduinoJsonJWT.cpp +++ b/lib/framework/ArduinoJsonJWT.cpp @@ -1,47 +1,27 @@ #include "ArduinoJsonJWT.h" +#include + ArduinoJsonJWT::ArduinoJsonJWT(String secret) - : _secret(secret) { + : _secret(std::move(secret)) { } void ArduinoJsonJWT::setSecret(String secret) { - _secret = secret; + _secret = std::move(secret); } String ArduinoJsonJWT::getSecret() { return _secret; } -/* - * ESP32 uses mbedtls, ESP2866 uses bearssl. - * - * Both come with decent HMAC implementations supporting sha256, as well as others. - * - * No need to pull in additional crypto libraries - lets use what we already have. - */ -String ArduinoJsonJWT::sign(String & payload) { - unsigned char hmacResult[32]; - { - mbedtls_md_context_t ctx; - mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256; - mbedtls_md_init(&ctx); - mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1); - mbedtls_md_hmac_starts(&ctx, (unsigned char *)_secret.c_str(), _secret.length()); - mbedtls_md_hmac_update(&ctx, (unsigned char *)payload.c_str(), payload.length()); - mbedtls_md_hmac_finish(&ctx, hmacResult); - mbedtls_md_free(&ctx); - } - return encode((char *)hmacResult, 32); -} - String ArduinoJsonJWT::buildJWT(JsonObject payload) { // serialize, then encode payload String jwt; serializeJson(payload, jwt); - jwt = encode(jwt.c_str(), jwt.length()); + jwt = encode(jwt.c_str(), static_cast(jwt.length())); // add the header to payload - jwt = JWT_HEADER + '.' + jwt; + jwt = getJWTHeader() + '.' + jwt; // add signature jwt += '.' + sign(jwt); @@ -53,65 +33,88 @@ void ArduinoJsonJWT::parseJWT(String jwt, JsonDocument & jsonDocument) { // clear json document before we begin, jsonDocument wil be null on failure jsonDocument.clear(); + const String & jwt_header = getJWTHeader(); + const unsigned int jwt_header_size = jwt_header.length(); + // must have the correct header and delimiter - if (!jwt.startsWith(JWT_HEADER) || jwt.indexOf('.') != JWT_HEADER_SIZE) { + if (!jwt.startsWith(jwt_header) || jwt.indexOf('.') != static_cast(jwt_header_size)) { return; } // check there is a signature delimieter - int signatureDelimiterIndex = jwt.lastIndexOf('.'); - if (signatureDelimiterIndex == JWT_HEADER_SIZE) { + const int signatureDelimiterIndex = jwt.lastIndexOf('.'); + if (signatureDelimiterIndex == static_cast(jwt_header_size)) { return; } // check the signature is valid - String signature = jwt.substring(signatureDelimiterIndex + 1); - jwt = jwt.substring(0, signatureDelimiterIndex); + const String signature = jwt.substring(static_cast(signatureDelimiterIndex) + 1); + jwt = jwt.substring(0, static_cast(signatureDelimiterIndex)); if (sign(jwt) != signature) { return; } // decode payload - jwt = jwt.substring(JWT_HEADER_SIZE + 1); + jwt = jwt.substring(jwt_header_size + 1); jwt = decode(jwt); // parse payload, clearing json document after failure - DeserializationError error = deserializeJson(jsonDocument, jwt); + const DeserializationError error = deserializeJson(jsonDocument, jwt); if (error != DeserializationError::Ok || !jsonDocument.is()) { jsonDocument.clear(); } } +/* + * ESP32 uses mbedtls, ESP2866 uses bearssl. + * + * Both come with decent HMAC implementations supporting sha256, as well as others. + * + * No need to pull in additional crypto libraries - lets use what we already have. + */ +String ArduinoJsonJWT::sign(String & payload) { + std::array hmacResult{}; + { + mbedtls_md_context_t ctx; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256; + mbedtls_md_init(&ctx); + mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1); + mbedtls_md_hmac_starts(&ctx, reinterpret_cast(_secret.c_str()), _secret.length()); + mbedtls_md_hmac_update(&ctx, reinterpret_cast(payload.c_str()), payload.length()); + mbedtls_md_hmac_finish(&ctx, hmacResult.data()); + mbedtls_md_free(&ctx); + } + return encode(reinterpret_cast(hmacResult.data()), hmacResult.size()); +} + String ArduinoJsonJWT::encode(const char * cstr, int inputLen) { // prepare encoder base64_encodestate _state; base64_init_encodestate(&_state); - size_t encodedLength = base64_encode_expected_len(inputLen) + 1; - // prepare buffer of correct length, returning an empty string on failure - char * buffer = (char *)malloc(encodedLength * sizeof(char)); - if (buffer == nullptr) { - return ""; - } + + // prepare buffer of correct length + const auto bufferLength = static_cast(base64_encode_expected_len(inputLen)) + 1; + auto * buffer = new char[bufferLength]; // encode to buffer int len = base64_encode_block(cstr, inputLen, &buffer[0], &_state); len += base64_encode_blockend(&buffer[len], &_state); - buffer[len] = 0; + buffer[len] = '\0'; // convert to arduino string, freeing buffer - String value = String(buffer); - free(buffer); + auto result = String(buffer); + delete[] buffer; buffer = nullptr; // remove padding and convert to URL safe form - while (value.length() > 0 && value.charAt(value.length() - 1) == '=') { - value.remove(value.length() - 1); + while (result.length() > 0 && result.charAt(result.length() - 1) == '=') { + result.remove(result.length() - 1); } - value.replace('+', '-'); - value.replace('/', '_'); + result.replace('+', '-'); + result.replace('/', '_'); // return as string - return value; + return result; } String ArduinoJsonJWT::decode(String value) { @@ -120,12 +123,18 @@ String ArduinoJsonJWT::decode(String value) { value.replace('_', '/'); // prepare buffer of correct length - char buffer[base64_decode_expected_len(value.length()) + 1]; + const auto bufferLength = static_cast(base64_decode_expected_len(value.length()) + 1); + auto * buffer = new char[bufferLength]; // decode - int len = base64_decode_chars(value.c_str(), value.length(), &buffer[0]); - buffer[len] = 0; + const int len = base64_decode_chars(value.c_str(), static_cast(value.length()), &buffer[0]); + buffer[len] = '\0'; + + // convert to arduino string, freeing buffer + auto result = String(buffer); + delete[] buffer; + buffer = nullptr; // return as string - return String(buffer); -} + return result; +} \ No newline at end of file diff --git a/lib/framework/ArduinoJsonJWT.h b/lib/framework/ArduinoJsonJWT.h index cd13d5fa4..dc9a28da6 100644 --- a/lib/framework/ArduinoJsonJWT.h +++ b/lib/framework/ArduinoJsonJWT.h @@ -3,30 +3,33 @@ #include #include + #include #include #include class ArduinoJsonJWT { - private: - String _secret; - - const String JWT_HEADER = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"; - const int JWT_HEADER_SIZE = JWT_HEADER.length(); - - String sign(String & value); - - static String encode(const char * cstr, int len); - static String decode(String value); - public: - ArduinoJsonJWT(String secret); + explicit ArduinoJsonJWT(String secret); void setSecret(String secret); String getSecret(); String buildJWT(JsonObject payload); void parseJWT(String jwt, JsonDocument & jsonDocument); + + private: + String _secret; + + String sign(String & value); + + static String encode(const char * cstr, int len); + static String decode(String value); + + static const String & getJWTHeader() { + static const String JWT_HEADER = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"; + return JWT_HEADER; + } }; -#endif +#endif \ No newline at end of file diff --git a/lib/framework/AuthenticationService.cpp b/lib/framework/AuthenticationService.cpp index f0fc92dbb..241e912c9 100644 --- a/lib/framework/AuthenticationService.cpp +++ b/lib/framework/AuthenticationService.cpp @@ -1,11 +1,9 @@ -#include - -using namespace std::placeholders; // for `_1` etc +#include "AuthenticationService.h" AuthenticationService::AuthenticationService(AsyncWebServer * server, SecurityManager * securityManager) : _securityManager(securityManager) - , _signInHandler(SIGN_IN_PATH, std::bind(&AuthenticationService::signIn, this, _1, _2)) { - server->on(VERIFY_AUTHORIZATION_PATH, HTTP_GET, std::bind(&AuthenticationService::verifyAuthorization, this, _1)); + , _signInHandler(SIGN_IN_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { signIn(request, json); }) { + server->on(VERIFY_AUTHORIZATION_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { verifyAuthorization(request); }); _signInHandler.setMethod(HTTP_POST); _signInHandler.setMaxContentLength(MAX_AUTHENTICATION_SIZE); server->addHandler(&_signInHandler); @@ -29,10 +27,10 @@ void AuthenticationService::signIn(AsyncWebServerRequest * request, JsonVariant String password = json["password"]; Authentication authentication = _securityManager->authenticate(username, password); if (authentication.authenticated) { - User * user = authentication.user; - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject jsonObject = response->getRoot(); - jsonObject["access_token"] = _securityManager->generateJWT(user); + User * user = authentication.user; + auto * response = new AsyncJsonResponse(false); + JsonObject jsonObject = response->getRoot(); + jsonObject["access_token"] = _securityManager->generateJWT(user); response->setLength(); request->send(response); return; diff --git a/lib/framework/AuthenticationService.h b/lib/framework/AuthenticationService.h index c7ca70646..b4b7eac23 100644 --- a/lib/framework/AuthenticationService.h +++ b/lib/framework/AuthenticationService.h @@ -1,9 +1,10 @@ #ifndef AuthenticationService_H_ #define AuthenticationService_H_ -#include +#include "Features.h" +#include "SecurityManager.h" + #include -#include #define VERIFY_AUTHORIZATION_PATH "/rest/verifyAuthorization" #define SIGN_IN_PATH "/rest/signIn" diff --git a/lib/framework/ESP8266React.cpp b/lib/framework/ESP8266React.cpp index 20e936a0c..d81fe7b83 100644 --- a/lib/framework/ESP8266React.cpp +++ b/lib/framework/ESP8266React.cpp @@ -1,6 +1,6 @@ -#include +#include "ESP8266React.h" -#include +#include "WWWData.h" ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs) : _securitySettingsService(server, fs) @@ -27,7 +27,7 @@ ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs) static char last_modified[50]; sprintf(last_modified, "%s %s CET", __DATE__, __TIME__); - WWWData::registerRoutes([server, this](const String & uri, const String & contentType, const uint8_t * content, size_t len, const String & hash) { + WWWData::registerRoutes([server](const String & uri, const String & contentType, const uint8_t * content, size_t len, const String & hash) { ArRequestHandlerFunction requestHandler = [contentType, content, len, hash](AsyncWebServerRequest * request) { // Check if the client already has the same version and respond with a 304 (Not modified) if (request->header("If-Modified-Since").indexOf(last_modified) > 0) { @@ -66,12 +66,13 @@ ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs) void ESP8266React::begin() { _networkSettingsService.begin(); _networkSettingsService.read([&](NetworkSettings & networkSettings) { + DefaultHeaders & defaultHeaders = DefaultHeaders::Instance(); if (networkSettings.enableCORS) { - DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", networkSettings.CORSOrigin); - DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization"); - DefaultHeaders::Instance().addHeader("Access-Control-Allow-Credentials", "true"); + defaultHeaders.addHeader("Access-Control-Allow-Origin", networkSettings.CORSOrigin); + defaultHeaders.addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization"); + defaultHeaders.addHeader("Access-Control-Allow-Credentials", "true"); } - DefaultHeaders::Instance().addHeader("Server", networkSettings.hostname); + defaultHeaders.addHeader("Server", networkSettings.hostname); }); _apSettingsService.begin(); _ntpSettingsService.begin(); diff --git a/lib/framework/ESP8266React.h b/lib/framework/ESP8266React.h index 2a86019e1..589369f33 100644 --- a/lib/framework/ESP8266React.h +++ b/lib/framework/ESP8266React.h @@ -1,28 +1,27 @@ #ifndef ESP8266React_h #define ESP8266React_h -#include +#include "APSettingsService.h" +#include "APStatus.h" +#include "AuthenticationService.h" +#include "FactoryResetService.h" +#include "MqttSettingsService.h" +#include "MqttStatus.h" +#include "NTPSettingsService.h" +#include "NTPStatus.h" +#include "OTASettingsService.h" +#include "UploadFileService.h" +#include "RestartService.h" +#include "SecuritySettingsService.h" +#include "SystemStatus.h" +#include "WiFiScanner.h" +#include "NetworkSettingsService.h" +#include "NetworkStatus.h" +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - class ESP8266React { public: ESP8266React(AsyncWebServer * server, FS * fs); diff --git a/lib/framework/ESPUtils.h b/lib/framework/ESPUtils.h index 0c5861628..490514f45 100644 --- a/lib/framework/ESPUtils.h +++ b/lib/framework/ESPUtils.h @@ -5,8 +5,8 @@ class ESPUtils { public: - static String defaultDeviceValue(String prefix = "") { - return prefix + String((uint32_t)ESP.getEfuseMac(), HEX); + static String defaultDeviceValue(const String & prefix = "") { + return prefix + String(static_cast(ESP.getEfuseMac()), HEX); } }; diff --git a/lib/framework/FSPersistence.h b/lib/framework/FSPersistence.h index 5a7639c13..ff2205aeb 100644 --- a/lib/framework/FSPersistence.h +++ b/lib/framework/FSPersistence.h @@ -1,8 +1,8 @@ #ifndef FSPersistence_h #define FSPersistence_h -#include -#include +#include "StatefulService.h" +#include "FS.h" template class FSPersistence { @@ -47,8 +47,8 @@ class FSPersistence { // make directories if required, for new IDF4.2 & LittleFS String path(_filePath); int index = 0; - while ((index = path.indexOf('/', index + 1)) != -1) { - String segment = path.substring(0, index); + while ((index = path.indexOf('/', static_cast(index) + 1)) != -1) { + String segment = path.substring(0, static_cast(index)); if (!_fs->exists(segment)) { _fs->mkdir(segment); } @@ -80,7 +80,7 @@ class FSPersistence { void enableUpdateHandler() { if (!_updateHandlerId) { - _updateHandlerId = _statefulService->addUpdateHandler([&] { writeToFS(); }); + _updateHandlerId = _statefulService->addUpdateHandler([this] { writeToFS(); }); } } diff --git a/lib/framework/FactoryResetService.cpp b/lib/framework/FactoryResetService.cpp index 6bb631b02..c7f4ee0d1 100644 --- a/lib/framework/FactoryResetService.cpp +++ b/lib/framework/FactoryResetService.cpp @@ -1,16 +1,14 @@ -#include - -using namespace std::placeholders; +#include "FactoryResetService.h" FactoryResetService::FactoryResetService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : fs(fs) { server->on(FACTORY_RESET_SERVICE_PATH, HTTP_POST, - securityManager->wrapRequest(std::bind(&FactoryResetService::handleRequest, this, _1), AuthenticationPredicates::IS_ADMIN)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { handleRequest(request); }, AuthenticationPredicates::IS_ADMIN)); } void FactoryResetService::handleRequest(AsyncWebServerRequest * request) { - request->onDisconnect(std::bind(&FactoryResetService::factoryReset, this)); + request->onDisconnect([this]() { factoryReset(); }); request->send(200); } @@ -21,7 +19,7 @@ void FactoryResetService::factoryReset() { // TODO To replaced with fs.rmdir(FS_CONFIG_DIRECTORY) now we're using IDF 4.2 File root = fs->open(FS_CONFIG_DIRECTORY); File file; - while (file = root.openNextFile()) { + while ((file = root.openNextFile())) { String path = file.path(); file.close(); fs->remove(path); diff --git a/lib/framework/FactoryResetService.h b/lib/framework/FactoryResetService.h index a6a4bee12..2a53c3122 100644 --- a/lib/framework/FactoryResetService.h +++ b/lib/framework/FactoryResetService.h @@ -3,22 +3,22 @@ #include #include -#include -#include #include +#include "SecurityManager.h" +#include "RestartService.h" + #define FS_CONFIG_DIRECTORY "/config" #define FACTORY_RESET_SERVICE_PATH "/rest/factoryReset" class FactoryResetService { - FS * fs; - public: FactoryResetService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager); void factoryReset(); private: + FS * fs; void handleRequest(AsyncWebServerRequest * request); }; diff --git a/lib/framework/HttpEndpoint.h b/lib/framework/HttpEndpoint.h index a8dac9119..db33394b0 100644 --- a/lib/framework/HttpEndpoint.h +++ b/lib/framework/HttpEndpoint.h @@ -2,15 +2,13 @@ #define HttpEndpoint_h #include - #include -#include -#include +#include "SecurityManager.h" +#include "StatefulService.h" #define HTTP_ENDPOINT_ORIGIN_ID "http" - -using namespace std::placeholders; // for `_1` etc +#define HTTPS_ENDPOINT_ORIGIN_ID "https" template class HttpEndpoint { @@ -19,8 +17,7 @@ class HttpEndpoint { JsonStateUpdater _stateUpdater; StatefulService * _statefulService; - AsyncCallbackWebHandler * GEThandler; - AsyncCallbackJsonWebHandler * POSThandler; + AsyncCallbackJsonWebHandler * handler; public: HttpEndpoint(JsonStateReader stateReader, @@ -33,12 +30,12 @@ class HttpEndpoint { : _stateReader(stateReader) , _stateUpdater(stateUpdater) , _statefulService(statefulService) { - // Create the GET and POST endpoints - POSThandler = new AsyncCallbackJsonWebHandler(servicePath, - securityManager->wrapCallback([this](AsyncWebServerRequest * request, - JsonVariant json) { handleRequest(request, json); }, - authenticationPredicate)); - server->addHandler(POSThandler); + // Create hander for both GET and POST endpoints + handler = new AsyncCallbackJsonWebHandler(servicePath, + securityManager->wrapCallback([this](AsyncWebServerRequest * request, + JsonVariant json) { handleRequest(request, json); }, + authenticationPredicate)); + server->addHandler(handler); } protected: @@ -66,8 +63,8 @@ class HttpEndpoint { } } - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject jsonObject = response->getRoot().to(); + auto * response = new AsyncJsonResponse(false); + JsonObject jsonObject = response->getRoot().to(); _statefulService->read(jsonObject, _stateReader); response->setLength(); request->send(response); diff --git a/lib/framework/IPUtils.h b/lib/framework/IPUtils.h index 5c211d6c0..528c36494 100644 --- a/lib/framework/IPUtils.h +++ b/lib/framework/IPUtils.h @@ -3,16 +3,20 @@ #include -const IPAddress IP_NOT_SET = IPAddress(INADDR_NONE); - class IPUtils { public: static bool isSet(const IPAddress & ip) { - return ip != IP_NOT_SET; + return ip != getNotSetIP(); } static bool isNotSet(const IPAddress & ip) { - return ip == IP_NOT_SET; + return ip == getNotSetIP(); + } + + private: + static const IPAddress & getNotSetIP() { + static const IPAddress IP_NOT_SET = IPAddress(INADDR_NONE); + return IP_NOT_SET; } }; -#endif +#endif \ No newline at end of file diff --git a/lib/framework/JsonUtils.h b/lib/framework/JsonUtils.h index 29a72bd6a..0d2ff9fa5 100644 --- a/lib/framework/JsonUtils.h +++ b/lib/framework/JsonUtils.h @@ -2,9 +2,10 @@ #define JsonUtils_h #include -#include -#include #include +#include + +#include "IPUtils.h" class JsonUtils { public: diff --git a/lib/framework/MqttSettingsService.cpp b/lib/framework/MqttSettingsService.cpp index 3e69c1b92..d8f98d9b3 100644 --- a/lib/framework/MqttSettingsService.cpp +++ b/lib/framework/MqttSettingsService.cpp @@ -1,22 +1,23 @@ -#include - +#include "MqttSettingsService.h" #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - /** * Retains a copy of the cstr provided in the pointer provided using dynamic allocation. * * Frees the pointer before allocation and leaves it as nullptr if cstr == nullptr. */ static char * retainCstr(const char * cstr, char ** ptr) { + if (ptr == nullptr || *ptr == nullptr) { + return nullptr; + } + // free up previously retained value if exists - free(*ptr); + delete[] *ptr; *ptr = nullptr; // dynamically allocate and copy cstr (if non null) if (cstr != nullptr) { - *ptr = (char *)malloc(strlen(cstr) + 1); + *ptr = new char[strlen(cstr) + 1]; strcpy(*ptr, cstr); } @@ -31,15 +32,22 @@ MqttSettingsService::MqttSettingsService(AsyncWebServer * server, FS * fs, Secur , _retainedClientId(nullptr) , _retainedUsername(nullptr) , _retainedPassword(nullptr) + , _retainedRootCA(nullptr) , _reconfigureMqtt(false) , _disconnectedAt(0) , _disconnectReason(espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED) , _mqttClient(nullptr) { - WiFi.onEvent(std::bind(&MqttSettingsService::WiFiEvent, this, _1, _2)); - addUpdateHandler([&] { onConfigUpdated(); }, false); + WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event); }); + addUpdateHandler([this]() { onConfigUpdated(); }, false); } MqttSettingsService::~MqttSettingsService() { + delete _mqttClient; + retainCstr(nullptr, &_retainedHost); + retainCstr(nullptr, &_retainedClientId); + retainCstr(nullptr, &_retainedUsername); + retainCstr(nullptr, &_retainedPassword); + retainCstr(nullptr, &_retainedRootCA); } void MqttSettingsService::begin() { @@ -55,32 +63,41 @@ void MqttSettingsService::startClient() { return; } delete _mqttClient; + _mqttClient = nullptr; } #if CONFIG_IDF_TARGET_ESP32S3 if (_state.enableTLS) { isSecure = true; - _mqttClient = static_cast(new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO)); + _mqttClient = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO); if (_state.rootCA == "insecure") { static_cast(_mqttClient)->setInsecure(); } else { String certificate = "-----BEGIN CERTIFICATE-----\n" + _state.rootCA + "\n-----END CERTIFICATE-----\n"; static_cast(_mqttClient)->setCACert(retainCstr(certificate.c_str(), &_retainedRootCA)); } - static_cast(_mqttClient)->onConnect(std::bind(&MqttSettingsService::onMqttConnect, this, _1)); - static_cast(_mqttClient)->onDisconnect(std::bind(&MqttSettingsService::onMqttDisconnect, this, _1)); - static_cast(_mqttClient)->onMessage(std::bind(&MqttSettingsService::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + static_cast(_mqttClient)->onConnect([this](bool sessionPresent) { onMqttConnect(sessionPresent); }); + static_cast(_mqttClient)->onDisconnect([this](espMqttClientTypes::DisconnectReason reason) { onMqttDisconnect(reason); }); + static_cast(_mqttClient) + ->onMessage( + [this](const espMqttClientTypes::MessageProperties & properties, const char * topic, const uint8_t * payload, size_t len, size_t index, size_t total) { + onMqttMessage(properties, topic, payload, len, index, total); + }); return; } #endif isSecure = false; - _mqttClient = static_cast(new espMqttClient(espMqttClientTypes::UseInternalTask::NO)); - static_cast(_mqttClient)->onConnect(std::bind(&MqttSettingsService::onMqttConnect, this, _1)); - static_cast(_mqttClient)->onDisconnect(std::bind(&MqttSettingsService::onMqttDisconnect, this, _1)); - static_cast(_mqttClient)->onMessage(std::bind(&MqttSettingsService::onMqttMessage, this, _1, _2, _3, _4, _5, _6)); + _mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO); + static_cast(_mqttClient)->onConnect([this](bool sessionPresent) { onMqttConnect(sessionPresent); }); + static_cast(_mqttClient)->onDisconnect([this](espMqttClientTypes::DisconnectReason reason) { onMqttDisconnect(reason); }); + static_cast(_mqttClient) + ->onMessage( + [this](const espMqttClientTypes::MessageProperties & properties, const char * topic, const uint8_t * payload, size_t len, size_t index, size_t total) { + onMqttMessage(properties, topic, payload, len, index, total); + }); } void MqttSettingsService::loop() { - if (_reconfigureMqtt || (_disconnectedAt && (uint32_t)(uuid::get_uptime() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) { + if (_reconfigureMqtt || (_disconnectedAt && static_cast(uuid::get_uptime() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) { // reconfigure MQTT client _disconnectedAt = configureMqtt() ? 0 : uuid::get_uptime(); _reconfigureMqtt = false; @@ -116,6 +133,9 @@ void MqttSettingsService::onMqttMessage(const espMqttClientTypes::MessagePropert size_t len, size_t index, size_t total) { + (void)properties; + (void)index; + (void)total; emsesp::EMSESP::mqtt_.on_message(topic, payload, len); } @@ -128,6 +148,7 @@ MqttClient * MqttSettingsService::getMqttClient() { } void MqttSettingsService::onMqttConnect(bool sessionPresent) { + (void)sessionPresent; // _disconnectedAt = 0; emsesp::EMSESP::mqtt_.on_connect(); // emsesp::EMSESP::logger().info("Connected to MQTT, %s", (sessionPresent) ? ("with persistent session") : ("without persistent session")); @@ -149,7 +170,7 @@ void MqttSettingsService::onConfigUpdated() { emsesp::EMSESP::mqtt_.start(); // reload EMS-ESP MQTT settings } -void MqttSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) { +void MqttSettingsService::WiFiEvent(WiFiEvent_t event) { switch (event) { case ARDUINO_EVENT_WIFI_STA_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP: @@ -264,32 +285,32 @@ StateUpdateResult MqttSettings::update(JsonObject root, MqttSettings & settings) #endif newSettings.enabled = root["enabled"] | FACTORY_MQTT_ENABLED; newSettings.host = root["host"] | FACTORY_MQTT_HOST; - newSettings.port = root["port"] | FACTORY_MQTT_PORT; + newSettings.port = static_cast(root["port"] | FACTORY_MQTT_PORT); newSettings.base = root["base"] | FACTORY_MQTT_BASE; newSettings.username = root["username"] | FACTORY_MQTT_USERNAME; newSettings.password = root["password"] | FACTORY_MQTT_PASSWORD; newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID; - newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE; + newSettings.keepAlive = static_cast(root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE); newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION; - newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; + newSettings.mqtt_qos = static_cast(root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS); newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; - newSettings.publish_time_boiler = root["publish_time_boiler"] | EMSESP_DEFAULT_PUBLISH_TIME; - newSettings.publish_time_thermostat = root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME; - newSettings.publish_time_solar = root["publish_time_solar"] | EMSESP_DEFAULT_PUBLISH_TIME; - newSettings.publish_time_mixer = root["publish_time_mixer"] | EMSESP_DEFAULT_PUBLISH_TIME; - newSettings.publish_time_other = root["publish_time_other"] | EMSESP_DEFAULT_PUBLISH_TIME; - newSettings.publish_time_sensor = root["publish_time_sensor"] | EMSESP_DEFAULT_PUBLISH_TIME; - newSettings.publish_time_heartbeat = root["publish_time_heartbeat"] | EMSESP_DEFAULT_PUBLISH_HEARTBEAT; + newSettings.publish_time_boiler = static_cast(root["publish_time_boiler"] | EMSESP_DEFAULT_PUBLISH_TIME); + newSettings.publish_time_thermostat = static_cast(root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME); + newSettings.publish_time_solar = static_cast(root["publish_time_solar"] | EMSESP_DEFAULT_PUBLISH_TIME); + newSettings.publish_time_mixer = static_cast(root["publish_time_mixer"] | EMSESP_DEFAULT_PUBLISH_TIME); + newSettings.publish_time_other = static_cast(root["publish_time_other"] | EMSESP_DEFAULT_PUBLISH_TIME); + newSettings.publish_time_sensor = static_cast(root["publish_time_sensor"] | EMSESP_DEFAULT_PUBLISH_TIME); + newSettings.publish_time_heartbeat = static_cast(root["publish_time_heartbeat"] | EMSESP_DEFAULT_PUBLISH_HEARTBEAT); newSettings.ha_enabled = root["ha_enabled"] | EMSESP_DEFAULT_HA_ENABLED; - newSettings.nested_format = root["nested_format"] | EMSESP_DEFAULT_NESTED_FORMAT; + newSettings.nested_format = static_cast(root["nested_format"] | EMSESP_DEFAULT_NESTED_FORMAT); newSettings.discovery_prefix = root["discovery_prefix"] | EMSESP_DEFAULT_DISCOVERY_PREFIX; - newSettings.discovery_type = root["discovery_type"] | EMSESP_DEFAULT_DISCOVERY_TYPE; + newSettings.discovery_type = static_cast(root["discovery_type"] | EMSESP_DEFAULT_DISCOVERY_TYPE); newSettings.publish_single = root["publish_single"] | EMSESP_DEFAULT_PUBLISH_SINGLE; newSettings.publish_single2cmd = root["publish_single2cmd"] | EMSESP_DEFAULT_PUBLISH_SINGLE2CMD; newSettings.send_response = root["send_response"] | EMSESP_DEFAULT_SEND_RESPONSE; - newSettings.entity_format = root["entity_format"] | EMSESP_DEFAULT_ENTITY_FORMAT; + newSettings.entity_format = static_cast(root["entity_format"] | EMSESP_DEFAULT_ENTITY_FORMAT); if (newSettings.enabled != settings.enabled) { changed = true; diff --git a/lib/framework/MqttSettingsService.h b/lib/framework/MqttSettingsService.h index 93bd0d163..335070780 100644 --- a/lib/framework/MqttSettingsService.h +++ b/lib/framework/MqttSettingsService.h @@ -1,11 +1,12 @@ #ifndef MqttSettingsService_h #define MqttSettingsService_h -#include -#include -#include +#include "StatefulService.h" +#include "HttpEndpoint.h" +#include "FSPersistence.h" +#include "ESPUtils.h" + #include -#include #include @@ -141,11 +142,12 @@ class MqttSettingsService : public StatefulService { // the MQTT client instance MqttClient * _mqttClient; - void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info); + void WiFiEvent(WiFiEvent_t event); void onMqttConnect(bool sessionPresent); void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason); void onMqttMessage(const espMqttClientTypes::MessageProperties & properties, const char * topic, const uint8_t * payload, size_t len, size_t index, size_t total); + bool configureMqtt(); }; diff --git a/lib/framework/MqttStatus.cpp b/lib/framework/MqttStatus.cpp index c62ba99e1..c1c66d5ab 100644 --- a/lib/framework/MqttStatus.cpp +++ b/lib/framework/MqttStatus.cpp @@ -1,19 +1,17 @@ -#include +#include "MqttStatus.h" #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - MqttStatus::MqttStatus(AsyncWebServer * server, MqttSettingsService * mqttSettingsService, SecurityManager * securityManager) : _mqttSettingsService(mqttSettingsService) { server->on(MQTT_STATUS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&MqttStatus::mqttStatus, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { mqttStatus(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); } void MqttStatus::mqttStatus(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); root["enabled"] = _mqttSettingsService->isEnabled(); root["connected"] = _mqttSettingsService->isConnected(); diff --git a/lib/framework/MqttStatus.h b/lib/framework/MqttStatus.h index eb7ba980b..87fa18616 100644 --- a/lib/framework/MqttStatus.h +++ b/lib/framework/MqttStatus.h @@ -2,10 +2,11 @@ #define MqttStatus_h #include -#include #include #include -#include + +#include "MqttSettingsService.h" +#include "SecurityManager.h" #define MQTT_STATUS_SERVICE_PATH "/rest/mqttStatus" diff --git a/lib/framework/NTPSettingsService.cpp b/lib/framework/NTPSettingsService.cpp index 212d9d3ae..6c7e75e2b 100644 --- a/lib/framework/NTPSettingsService.cpp +++ b/lib/framework/NTPSettingsService.cpp @@ -1,20 +1,20 @@ -#include +#include "NTPSettingsService.h" #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - NTPSettingsService::NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(NTPSettings::read, NTPSettings::update, this, server, NTP_SETTINGS_SERVICE_PATH, securityManager) , _fsPersistence(NTPSettings::read, NTPSettings::update, this, fs, NTP_SETTINGS_FILE) - , _timeHandler(TIME_PATH, securityManager->wrapCallback(std::bind(&NTPSettingsService::configureTime, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) { + , _timeHandler(TIME_PATH, + securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { configureTime(request, json); }, + AuthenticationPredicates::IS_ADMIN)) + , _connected(false) { _timeHandler.setMethod(HTTP_POST); _timeHandler.setMaxContentLength(MAX_TIME_SIZE); server->addHandler(&_timeHandler); - WiFi.onEvent(std::bind(&NTPSettingsService::WiFiEvent, this, _1)); - - addUpdateHandler([&] { configureNTP(); }, false); + WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event); }); + addUpdateHandler([this] { configureNTP(); }, false); } void NTPSettingsService::begin() { @@ -27,9 +27,9 @@ void NTPSettingsService::WiFiEvent(WiFiEvent_t event) { switch (event) { case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: case ARDUINO_EVENT_ETH_DISCONNECTED: - if (connected_) { + if (_connected) { emsesp::EMSESP::logger().info("WiFi connection dropped, stopping NTP"); - connected_ = false; + _connected = false; configureNTP(); } break; @@ -37,7 +37,7 @@ void NTPSettingsService::WiFiEvent(WiFiEvent_t event) { case ARDUINO_EVENT_WIFI_STA_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP: // emsesp::EMSESP::logger().info("Got IP address, starting NTP synchronization"); - connected_ = true; + _connected = true; configureNTP(); break; @@ -49,7 +49,7 @@ void NTPSettingsService::WiFiEvent(WiFiEvent_t event) { // https://werner.rothschopf.net/microcontroller/202103_arduino_esp32_ntp_en.htm void NTPSettingsService::configureNTP() { emsesp::EMSESP::system_.ntp_connected(false); - if (connected_ && _state.enabled) { + if (_connected && _state.enabled) { emsesp::EMSESP::logger().info("Starting NTP service"); esp_sntp_set_sync_interval(3600000); // one hour esp_sntp_set_time_sync_notification_cb(ntp_received); @@ -63,13 +63,13 @@ void NTPSettingsService::configureNTP() { void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVariant json) { if (json.is()) { - struct tm tm = {0}; + struct tm tm = {}; String timeLocal = json["local_time"]; char * s = strptime(timeLocal.c_str(), "%Y-%m-%dT%H:%M:%S", &tm); if (s != nullptr) { tm.tm_isdst = -1; // not set by strptime, tells mktime to determine daylightsaving time_t time = mktime(&tm); - struct timeval now = {.tv_sec = time}; + struct timeval now = {.tv_sec = time, .tv_usec = {}}; settimeofday(&now, nullptr); AsyncWebServerResponse * response = request->beginResponse(200); request->send(response); @@ -82,6 +82,7 @@ void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVari } void NTPSettingsService::ntp_received(struct timeval * tv) { + (void)tv; // emsesp::EMSESP::logger().info("NTP sync to %d sec", tv->tv_sec); emsesp::EMSESP::system_.ntp_connected(true); } @@ -99,4 +100,4 @@ StateUpdateResult NTPSettings::update(JsonObject root, NTPSettings & settings) { settings.tzLabel = root["tz_label"] | FACTORY_NTP_TIME_ZONE_LABEL; settings.tzFormat = root["tz_format"] | FACTORY_NTP_TIME_ZONE_FORMAT; return StateUpdateResult::CHANGED; -} +} \ No newline at end of file diff --git a/lib/framework/NTPSettingsService.h b/lib/framework/NTPSettingsService.h index 976d29d70..9e1c503ac 100644 --- a/lib/framework/NTPSettingsService.h +++ b/lib/framework/NTPSettingsService.h @@ -1,10 +1,10 @@ #ifndef NTPSettingsService_h #define NTPSettingsService_h -#include -#include +#include "HttpEndpoint.h" +#include "FSPersistence.h" -#include +#include #include #ifndef FACTORY_NTP_ENABLED @@ -51,8 +51,8 @@ class NTPSettingsService : public StatefulService { HttpEndpoint _httpEndpoint; FSPersistence _fsPersistence; AsyncCallbackJsonWebHandler _timeHandler; + bool _connected; - bool connected_ = false; void WiFiEvent(WiFiEvent_t event); void configureNTP(); void configureTime(AsyncWebServerRequest * request, JsonVariant json); diff --git a/lib/framework/NTPStatus.cpp b/lib/framework/NTPStatus.cpp index ddb6bbc2d..95b9c32a6 100644 --- a/lib/framework/NTPStatus.cpp +++ b/lib/framework/NTPStatus.cpp @@ -1,12 +1,13 @@ -#include +#include "NTPStatus.h" + #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc +#include NTPStatus::NTPStatus(AsyncWebServer * server, SecurityManager * securityManager) { server->on(NTP_STATUS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&NTPStatus::ntpStatus, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { ntpStatus(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); } /* @@ -15,9 +16,9 @@ NTPStatus::NTPStatus(AsyncWebServer * server, SecurityManager * securityManager) * Uses a 25 byte buffer, large enough to fit an ISO time string with offset. */ String formatTime(tm * time, const char * format) { - char time_string[25]; - strftime(time_string, 25, format, time); - return String(time_string); + std::array time_string{}; + strftime(time_string.data(), time_string.size(), format, time); + return {time_string.data()}; } String toUTCTimeString(tm * time) { @@ -29,14 +30,23 @@ String toLocalTimeString(tm * time) { } void NTPStatus::ntpStatus(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); // grab the current instant in unix seconds time_t now = time(nullptr); // only provide enabled/disabled status for now - root["status"] = esp_sntp_enabled() ? emsesp::EMSESP::system_.ntp_connected() ? 2 : 1 : 0; + root["status"] = []() { + if (esp_sntp_enabled()) { + if (emsesp::EMSESP::system_.ntp_connected()) { + return 2; + } else { + return 1; + } + } + return 0; + }(); // the current time in UTC root["utc_time"] = toUTCTimeString(gmtime(&now)); @@ -49,4 +59,4 @@ void NTPStatus::ntpStatus(AsyncWebServerRequest * request) { response->setLength(); request->send(response); -} +} \ No newline at end of file diff --git a/lib/framework/NTPStatus.h b/lib/framework/NTPStatus.h index 2dec0a9f4..e9aa7d766 100644 --- a/lib/framework/NTPStatus.h +++ b/lib/framework/NTPStatus.h @@ -1,14 +1,14 @@ #ifndef NTPStatus_h #define NTPStatus_h -#include - +#include #include #include - #include #include -#include + +#include "SecurityManager.h" + #include #define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus" diff --git a/lib/framework/NetworkSettingsService.cpp b/lib/framework/NetworkSettingsService.cpp index 1bb03be27..83cd8b0c2 100644 --- a/lib/framework/NetworkSettingsService.cpp +++ b/lib/framework/NetworkSettingsService.cpp @@ -1,16 +1,25 @@ -#include +#include "NetworkSettingsService.h" #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - NetworkSettingsService::NetworkSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(NetworkSettings::read, NetworkSettings::update, this, server, NETWORK_SETTINGS_SERVICE_PATH, securityManager) , _fsPersistence(NetworkSettings::read, NetworkSettings::update, this, fs, NETWORK_SETTINGS_FILE) - , _lastConnectionAttempt(0) { - addUpdateHandler([&] { reconfigureWiFiConnection(); }, false); - // wifi event callbacks - WiFi.onEvent(std::bind(&NetworkSettingsService::WiFiEvent, this, _1, _2)); + , _lastConnectionAttempt(0) + , _stopping(false) { + addUpdateHandler([this]() { reconfigureWiFiConnection(); }, false); + WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event, info); }); +} + +static bool formatBssid(const String & bssid, uint8_t (&mac)[6]) { + uint tmp[6]; + if (bssid.isEmpty() || sscanf(bssid.c_str(), "%X:%X:%X:%X:%X:%X", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]) != 6) { + return false; + } + for (uint8_t i = 0; i < 6; i++) { + mac[i] = static_cast(tmp[i]); + } + return true; } void NetworkSettingsService::begin() { @@ -47,7 +56,7 @@ void NetworkSettingsService::reconfigureWiFiConnection() { void NetworkSettingsService::loop() { unsigned long currentMillis = millis(); - if (!_lastConnectionAttempt || (uint32_t)(currentMillis - _lastConnectionAttempt) >= WIFI_RECONNECTION_DELAY) { + if (!_lastConnectionAttempt || static_cast(currentMillis - _lastConnectionAttempt) >= WIFI_RECONNECTION_DELAY) { _lastConnectionAttempt = currentMillis; manageSTA(); } @@ -68,22 +77,18 @@ void NetworkSettingsService::manageSTA() { // www.esp32.com/viewtopic.php?t=12055 if (_state.bandwidth20) { - esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_STA, WIFI_BW_HT20); + esp_wifi_set_bandwidth(static_cast(ESP_IF_WIFI_STA), WIFI_BW_HT20); } else { - esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_STA, WIFI_BW_HT40); + esp_wifi_set_bandwidth(static_cast(ESP_IF_WIFI_STA), WIFI_BW_HT40); } if (_state.nosleep) { WiFi.setSleep(false); // turn off sleep - WIFI_PS_NONE } // attempt to connect to the network - uint mac[6]; - if (!_state.bssid.isEmpty() && sscanf(_state.bssid.c_str(), "%X:%X:%X:%X:%X:%X", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6) { - uint8_t mac1[6]; - for (uint8_t i = 0; i < 6; i++) { - mac1[i] = (uint8_t)mac[i]; - } - WiFi.begin(_state.ssid.c_str(), _state.password.c_str(), 0, mac1); + uint8_t bssid[6]; + if (formatBssid(_state.bssid, bssid)) { + WiFi.begin(_state.ssid.c_str(), _state.password.c_str(), 0, bssid); } else { WiFi.begin(_state.ssid.c_str(), _state.password.c_str()); } @@ -96,7 +101,7 @@ void NetworkSettingsService::manageSTA() { #else if (_state.tx_power != 0) { // if not set to Auto (0) set the Tx power now - if (!WiFi.setTxPower((wifi_power_t)_state.tx_power)) { + if (!WiFi.setTxPower(static_cast(_state.tx_power))) { emsesp::EMSESP::logger().warning("Failed to set WiFi Tx Power"); } } @@ -173,7 +178,7 @@ void NetworkSettingsService::setWiFiPowerOnRSSI() { emsesp::EMSESP::logger().debug("Recommended set WiFi Tx Power (set_power %d, new power %d, rssi %d, threshold %d", set_power, p, rssi, threshold); #else char result[10]; - emsesp::EMSESP::logger().info("Setting WiFi Tx Power to %s dBm", emsesp::Helpers::render_value(result, (double)(p / 4), 1)); + emsesp::EMSESP::logger().info("Setting WiFi Tx Power to %s dBm", emsesp::Helpers::render_value(result, ((double)(p) / 4), 1)); #endif if (!WiFi.setTxPower(p)) { @@ -310,7 +315,7 @@ void NetworkSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) emsesp::EMSESP::logger().info("WiFi connected with IP=%s, hostname=%s, TxPower=%s dBm", WiFi.localIP().toString().c_str(), WiFi.getHostname(), - emsesp::Helpers::render_value(result, (double)(WiFi.getTxPower() / 4), 1)); + emsesp::Helpers::render_value(result, ((double)(WiFi.getTxPower()) / 4), 1)); mDNS_start(); break; @@ -389,7 +394,6 @@ void NetworkSettings::read(NetworkSettings & settings, JsonObject root) { root["static_ip_config"] = settings.staticIPConfig; root["enableIPv6"] = settings.enableIPv6; root["bandwidth20"] = settings.bandwidth20; - root["tx_power"] = settings.tx_power; root["nosleep"] = settings.nosleep; root["enableMDNS"] = settings.enableMDNS; root["enableCORS"] = settings.enableCORS; @@ -417,7 +421,7 @@ StateUpdateResult NetworkSettings::update(JsonObject root, NetworkSettings & set settings.staticIPConfig = root["static_ip_config"] | false; settings.enableIPv6 = root["enableIPv6"] | false; settings.bandwidth20 = root["bandwidth20"] | false; - settings.tx_power = root["tx_power"] | 0; + settings.tx_power = static_cast(root["tx_power"] | 0); settings.nosleep = root["nosleep"] | false; settings.enableMDNS = root["enableMDNS"] | true; settings.enableCORS = root["enableCORS"] | false; @@ -445,7 +449,7 @@ StateUpdateResult NetworkSettings::update(JsonObject root, NetworkSettings & set // see if we need to inform the user of a restart if (tx_power != settings.tx_power || enableCORS != settings.enableCORS || CORSOrigin != settings.CORSOrigin - || (ssid != settings.ssid && settings.ssid == "")) { + || (ssid != settings.ssid && settings.ssid.isEmpty())) { return StateUpdateResult::CHANGED_RESTART; // tell WebUI that a restart is needed } diff --git a/lib/framework/NetworkSettingsService.h b/lib/framework/NetworkSettingsService.h index 6b5551802..e27af0e01 100644 --- a/lib/framework/NetworkSettingsService.h +++ b/lib/framework/NetworkSettingsService.h @@ -1,10 +1,10 @@ #ifndef NetworkSettingsService_h #define NetworkSettingsService_h -#include -#include -#include -#include +#include "StatefulService.h" +#include "FSPersistence.h" +#include "HttpEndpoint.h" +#include "JsonUtils.h" #ifndef EMSESP_STANDALONE #include @@ -16,7 +16,7 @@ #define NETWORK_SETTINGS_FILE "/config/networkSettings.json" #define NETWORK_SETTINGS_SERVICE_PATH "/rest/networkSettings" -#define WIFI_RECONNECTION_DELAY 1000 * 3 +#define WIFI_RECONNECTION_DELAY (1000 * 3) #ifndef FACTORY_WIFI_SSID #define FACTORY_WIFI_SSID "" diff --git a/lib/framework/NetworkStatus.cpp b/lib/framework/NetworkStatus.cpp index 64e0cd604..27c37cee7 100644 --- a/lib/framework/NetworkStatus.cpp +++ b/lib/framework/NetworkStatus.cpp @@ -1,18 +1,16 @@ -#include +#include "NetworkStatus.h" #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - NetworkStatus::NetworkStatus(AsyncWebServer * server, SecurityManager * securityManager) { server->on(NETWORK_STATUS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&NetworkStatus::networkStatus, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { networkStatus(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); } void NetworkStatus::networkStatus(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); bool ethernet_connected = emsesp::EMSESP::system_.ethernet_connected(); wl_status_t wifi_status = WiFi.status(); @@ -22,7 +20,7 @@ void NetworkStatus::networkStatus(AsyncWebServerRequest * request) { root["status"] = 10; // custom code #10 - ETHERNET_STATUS_CONNECTED root["hostname"] = ETH.getHostname(); } else { - root["status"] = (uint8_t)wifi_status; + root["status"] = static_cast(wifi_status); root["hostname"] = WiFi.getHostname(); } diff --git a/lib/framework/NetworkStatus.h b/lib/framework/NetworkStatus.h index f31630e25..6c5524169 100644 --- a/lib/framework/NetworkStatus.h +++ b/lib/framework/NetworkStatus.h @@ -4,9 +4,9 @@ #include #include #include -#include -#include +#include "IPUtils.h" +#include "SecurityManager.h" #define MAX_NETWORK_STATUS_SIZE 1024 #define NETWORK_STATUS_SERVICE_PATH "/rest/networkStatus" diff --git a/lib/framework/OTASettingsService.cpp b/lib/framework/OTASettingsService.cpp index ecf18a1da..61673092c 100644 --- a/lib/framework/OTASettingsService.cpp +++ b/lib/framework/OTASettingsService.cpp @@ -1,15 +1,13 @@ -#include +#include "OTASettingsService.h" #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - OTASettingsService::OTASettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(OTASettings::read, OTASettings::update, this, server, OTA_SETTINGS_SERVICE_PATH, securityManager) , _fsPersistence(OTASettings::read, OTASettings::update, this, fs, OTA_SETTINGS_FILE) , _arduinoOTA(nullptr) { - WiFi.onEvent(std::bind(&OTASettingsService::WiFiEvent, this, _1, _2)); - addUpdateHandler([&] { configureArduinoOTA(); }, false); + WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event); }); + addUpdateHandler([this] { configureArduinoOTA(); }, false); } void OTASettingsService::begin() { @@ -32,7 +30,7 @@ void OTASettingsService::configureArduinoOTA() { if (_state.enabled) { _arduinoOTA = new ArduinoOTAClass; - _arduinoOTA->setPort(_state.port); + _arduinoOTA->setPort(static_cast(_state.port)); _arduinoOTA->setPassword(_state.password.c_str()); _arduinoOTA->onStart([] { emsesp::EMSESP::system_.upload_status(true); }); @@ -64,7 +62,7 @@ void OTASettingsService::configureArduinoOTA() { } } -void OTASettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) { +void OTASettingsService::WiFiEvent(WiFiEvent_t event) { switch (event) { case ARDUINO_EVENT_WIFI_STA_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP: diff --git a/lib/framework/OTASettingsService.h b/lib/framework/OTASettingsService.h index 72ed4581a..41183dac6 100644 --- a/lib/framework/OTASettingsService.h +++ b/lib/framework/OTASettingsService.h @@ -1,8 +1,8 @@ #ifndef OTASettingsService_h #define OTASettingsService_h -#include -#include +#include "HttpEndpoint.h" +#include "FSPersistence.h" #include #include @@ -45,7 +45,7 @@ class OTASettingsService : public StatefulService { ArduinoOTAClass * _arduinoOTA; void configureArduinoOTA(); - void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info); + void WiFiEvent(WiFiEvent_t event); }; #endif diff --git a/lib/framework/RestartService.cpp b/lib/framework/RestartService.cpp index b767b9cf0..b56232408 100644 --- a/lib/framework/RestartService.cpp +++ b/lib/framework/RestartService.cpp @@ -1,15 +1,22 @@ -#include +#include "RestartService.h" + #include #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - RestartService::RestartService(AsyncWebServer * server, SecurityManager * securityManager) { - server->on(RESTART_SERVICE_PATH, HTTP_POST, securityManager->wrapRequest(std::bind(&RestartService::restart, this, _1), AuthenticationPredicates::IS_ADMIN)); + server->on(RESTART_SERVICE_PATH, + HTTP_POST, + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { restart(request); }, AuthenticationPredicates::IS_ADMIN)); server->on(PARTITION_SERVICE_PATH, HTTP_POST, - securityManager->wrapRequest(std::bind(&RestartService::partition, this, _1), AuthenticationPredicates::IS_ADMIN)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { partition(request); }, AuthenticationPredicates::IS_ADMIN)); +} + +void RestartService::restartNow() { + WiFi.disconnect(true); + delay(500); + ESP.restart(); } void RestartService::restart(AsyncWebServerRequest * request) { @@ -19,7 +26,7 @@ void RestartService::restart(AsyncWebServerRequest * request) { } void RestartService::partition(AsyncWebServerRequest * request) { - const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr); if (factory_partition) { esp_ota_set_boot_partition(factory_partition); emsesp::EMSESP::system_.store_nvs_values(); @@ -27,7 +34,7 @@ void RestartService::partition(AsyncWebServerRequest * request) { request->send(200); return; } - const esp_partition_t * ota_partition = esp_ota_get_next_update_partition(NULL); + const esp_partition_t * ota_partition = esp_ota_get_next_update_partition(nullptr); if (!ota_partition) { request->send(400); // bad request return; diff --git a/lib/framework/RestartService.h b/lib/framework/RestartService.h index 8a010716f..55c0b25d1 100644 --- a/lib/framework/RestartService.h +++ b/lib/framework/RestartService.h @@ -3,9 +3,9 @@ #include #include - #include -#include + +#include "SecurityManager.h" #define RESTART_SERVICE_PATH "/rest/restart" #define PARTITION_SERVICE_PATH "/rest/partition" @@ -14,11 +14,7 @@ class RestartService { public: RestartService(AsyncWebServer * server, SecurityManager * securityManager); - static void restartNow() { - WiFi.disconnect(true); - delay(500); - ESP.restart(); - } + static void restartNow(); private: void restart(AsyncWebServerRequest * request); diff --git a/lib/framework/SecurityManager.h b/lib/framework/SecurityManager.h index 2f1610588..1e9bec21b 100644 --- a/lib/framework/SecurityManager.h +++ b/lib/framework/SecurityManager.h @@ -1,10 +1,11 @@ #ifndef SecurityManager_h #define SecurityManager_h -#include -#include +#include "Features.h" +#include "ArduinoJsonJWT.h" +#include "ESPUtils.h" + #include -#include #include #include @@ -26,28 +27,27 @@ class User { public: User(String username, String password, bool admin) - : username(username) - , password(password) + : username(std::move(username)) + , password(std::move(password)) , admin(admin) { } }; class Authentication { public: - User * user; - boolean authenticated; + User * user = nullptr; + boolean authenticated = false; public: - Authentication(User & user) + explicit Authentication(const User & user) : user(new User(user)) , authenticated(true) { } - Authentication() - : user(nullptr) - , authenticated(false) { - } + + Authentication() = default; + ~Authentication() { - delete (user); + delete user; } }; @@ -55,13 +55,14 @@ typedef std::function AuthenticationPr class AuthenticationPredicates { public: - static bool NONE_REQUIRED(Authentication & authentication) { + static bool NONE_REQUIRED(const Authentication & authentication) { + (void)authentication; return true; }; - static bool IS_AUTHENTICATED(Authentication & authentication) { + static bool IS_AUTHENTICATED(const Authentication & authentication) { return authentication.authenticated; }; - static bool IS_ADMIN(Authentication & authentication) { + static bool IS_ADMIN(const Authentication & authentication) { return authentication.authenticated && authentication.user->admin; }; }; @@ -76,7 +77,7 @@ class SecurityManager { /* * Generate a JWT for the user provided */ - virtual String generateJWT(User * user) = 0; + virtual String generateJWT(const User * user) = 0; /* * Check the request header for the Authorization token diff --git a/lib/framework/SecuritySettingsService.cpp b/lib/framework/SecuritySettingsService.cpp index 2b4d13636..195be6a1a 100644 --- a/lib/framework/SecuritySettingsService.cpp +++ b/lib/framework/SecuritySettingsService.cpp @@ -1,15 +1,13 @@ -#include - -#include "../../src/emsesp_stub.hpp" +#include "SecuritySettingsService.h" SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * fs) : _httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this) , _fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE) , _jwtHandler(FACTORY_JWT_SECRET) { - addUpdateHandler([&] { configureJWTHandler(); }, false); + addUpdateHandler([this] { configureJWTHandler(); }, false); server->on(GENERATE_TOKEN_PATH, HTTP_GET, - wrapRequest(std::bind(&SecuritySettingsService::generateToken, this, std::placeholders::_1), AuthenticationPredicates::IS_ADMIN)); + SecuritySettingsService::wrapRequest([this](AsyncWebServerRequest * request) { generateToken(request); }, AuthenticationPredicates::IS_ADMIN)); } void SecuritySettingsService::begin() { @@ -30,7 +28,7 @@ Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerReques String value = tokenParamater->value(); return authenticateJWT(value); } - return Authentication(); + return {}; } void SecuritySettingsService::configureJWTHandler() { @@ -43,37 +41,37 @@ Authentication SecuritySettingsService::authenticateJWT(String & jwt) { if (payloadDocument.is()) { JsonObject parsedPayload = payloadDocument.as(); String username = parsedPayload["username"]; - for (User _user : _state.users) { + for (const User & _user : _state.users) { if (_user.username == username && validatePayload(parsedPayload, &_user)) { return Authentication(_user); } } } - return Authentication(); + return {}; } Authentication SecuritySettingsService::authenticate(const String & username, const String & password) { - for (User _user : _state.users) { + for (const User & _user : _state.users) { if (_user.username == username && _user.password == password) { return Authentication(_user); } } - return Authentication(); + return {}; } -inline void populateJWTPayload(JsonObject payload, User * user) { +inline void populateJWTPayload(JsonObject payload, const User * user) { payload["username"] = user->username; payload["admin"] = user->admin; } -boolean SecuritySettingsService::validatePayload(JsonObject parsedPayload, User * user) { +boolean SecuritySettingsService::validatePayload(JsonObject parsedPayload, const User * user) { JsonDocument jsonDocument; JsonObject payload = jsonDocument.to(); populateJWTPayload(payload, user); return payload == parsedPayload; } -String SecuritySettingsService::generateJWT(User * user) { +String SecuritySettingsService::generateJWT(const User * user) { JsonDocument jsonDocument; JsonObject payload = jsonDocument.to(); populateJWTPayload(payload, user); @@ -111,11 +109,11 @@ ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequest void SecuritySettingsService::generateToken(AsyncWebServerRequest * request) { AsyncWebParameter * usernameParam = request->getParam("username"); - for (User _user : _state.users) { + for (const User & _user : _state.users) { if (_user.username == usernameParam->value()) { - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); - root["token"] = generateJWT(&_user); + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); + root["token"] = generateJWT(&_user); response->setLength(); request->send(response); return; @@ -123,34 +121,3 @@ void SecuritySettingsService::generateToken(AsyncWebServerRequest * request) { } request->send(401); } - -void SecuritySettings::read(SecuritySettings & settings, JsonObject root) { - // secret - root["jwt_secret"] = settings.jwtSecret; - - // users - JsonArray users = root["users"].to(); - for (User user : settings.users) { - JsonObject userRoot = users.add(); - userRoot["username"] = user.username; - userRoot["password"] = user.password; - userRoot["admin"] = user.admin; - } -} - -StateUpdateResult SecuritySettings::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)); - } - return StateUpdateResult::CHANGED; -} diff --git a/lib/framework/SecuritySettingsService.h b/lib/framework/SecuritySettingsService.h index 82aedf6ef..91f3f4b3b 100644 --- a/lib/framework/SecuritySettingsService.h +++ b/lib/framework/SecuritySettingsService.h @@ -1,10 +1,10 @@ #ifndef SecuritySettingsService_h #define SecuritySettingsService_h -#include -#include -#include -#include +#include "Features.h" +#include "SecurityManager.h" +#include "HttpEndpoint.h" +#include "FSPersistence.h" #ifndef FACTORY_ADMIN_USERNAME #define FACTORY_ADMIN_USERNAME "admin" @@ -33,23 +33,51 @@ class SecuritySettings { String jwtSecret; std::vector users; - static void read(SecuritySettings & settings, JsonObject root); - static StateUpdateResult update(JsonObject root, SecuritySettings & settings); + static void read(SecuritySettings & settings, JsonObject root) { + // secret + root["jwt_secret"] = settings.jwtSecret; + + // users + JsonArray users = root["users"].to(); + for (const User & user : settings.users) { + JsonObject userRoot = users.add(); + 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; + + // users + settings.users.clear(); + if (root["users"].is()) { + for (JsonVariant user : root["users"].as()) { + settings.users.emplace_back(user["username"], user["password"], user["admin"]); + } + } else { + settings.users.emplace_back(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true); + settings.users.emplace_back(FACTORY_GUEST_USERNAME, FACTORY_GUEST_PASSWORD, false); + } + return StateUpdateResult::CHANGED; + } }; -class SecuritySettingsService : public StatefulService, public SecurityManager { +class SecuritySettingsService final : public StatefulService, public SecurityManager { public: SecuritySettingsService(AsyncWebServer * server, FS * fs); 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); + Authentication authenticate(const String & username, const String & password) override; + Authentication authenticateRequest(AsyncWebServerRequest * request) override; + String generateJWT(const User * user) override; + ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate) override; + ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) override; + ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction callback, AuthenticationPredicate predicate) override; private: HttpEndpoint _httpEndpoint; @@ -68,7 +96,7 @@ class SecuritySettingsService : public StatefulService, public /* * Verify the payload is correct */ - boolean validatePayload(JsonObject parsedPayload, User * user); + boolean validatePayload(JsonObject parsedPayload, const User * user); }; #endif \ No newline at end of file diff --git a/lib/framework/StatefulService.cpp b/lib/framework/StatefulService.cpp index ece6b1fb3..d5f847aba 100644 --- a/lib/framework/StatefulService.cpp +++ b/lib/framework/StatefulService.cpp @@ -1,3 +1,3 @@ -#include +#include "StatefulService.h" update_handler_id_t StateUpdateHandlerInfo::currentUpdatedHandlerId = 0; diff --git a/lib/framework/SystemStatus.cpp b/lib/framework/SystemStatus.cpp index d82cb8326..b90ef7c38 100644 --- a/lib/framework/SystemStatus.cpp +++ b/lib/framework/SystemStatus.cpp @@ -1,21 +1,20 @@ -#include +#include "SystemStatus.h" + #include #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc - SystemStatus::SystemStatus(AsyncWebServer * server, SecurityManager * securityManager) { server->on(SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&SystemStatus::systemStatus, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { systemStatus(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); } void SystemStatus::systemStatus(AsyncWebServerRequest * request) { emsesp::EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); #ifdef EMSESP_DEBUG root["emsesp_version"] = std::string(EMSESP_APP_VERSION) + " (DEBUG)"; @@ -49,11 +48,11 @@ void SystemStatus::systemStatus(AsyncWebServerRequest * request) { root["psram_size"] = emsesp::EMSESP::system_.PSram(); root["free_psram"] = ESP.getFreePsram() / 1024; } - const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr); if (partition != NULL) { // factory partition found root["has_loader"] = true; } else { // check for not empty, smaller OTA partition - partition = esp_ota_get_next_update_partition(NULL); + partition = esp_ota_get_next_update_partition(nullptr); if (partition) { uint64_t buffer; esp_partition_read(partition, 0, &buffer, 8); diff --git a/lib/framework/SystemStatus.h b/lib/framework/SystemStatus.h index 4970e81b9..bd2d7ebf6 100644 --- a/lib/framework/SystemStatus.h +++ b/lib/framework/SystemStatus.h @@ -5,10 +5,10 @@ #include #include #include - #include #include -#include + +#include "SecurityManager.h" #define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus" diff --git a/lib/framework/UploadFileService.cpp b/lib/framework/UploadFileService.cpp index 58bedf83f..ee818b4d6 100644 --- a/lib/framework/UploadFileService.cpp +++ b/lib/framework/UploadFileService.cpp @@ -1,20 +1,27 @@ -#include -#include -#include - +#include "UploadFileService.h" #include "../../src/emsesp_stub.hpp" -using namespace std::placeholders; // for `_1` etc +#include -static bool is_firmware = false; -static char md5[33] = "\0"; +static String getFilenameExtension(const String & filename) { + const auto pos = filename.lastIndexOf('.'); + if (pos != -1) { + return filename.substring(static_cast(pos) + 1); + } + return {}; +} UploadFileService::UploadFileService(AsyncWebServer * server, SecurityManager * securityManager) - : _securityManager(securityManager) { - server->on(UPLOAD_FILE_PATH, - HTTP_POST, - std::bind(&UploadFileService::uploadComplete, this, _1), - std::bind(&UploadFileService::handleUpload, this, _1, _2, _3, _4, _5, _6)); + : _securityManager(securityManager) + , _is_firmware(false) + , _md5() { + server->on( + UPLOAD_FILE_PATH, + HTTP_POST, + [this](AsyncWebServerRequest * request) { uploadComplete(request); }, + [this](AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final) { + handleUpload(request, filename, index, data, len, final); + }); } void UploadFileService::handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final) { @@ -28,29 +35,27 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri // at init if (!index) { // check details of the file, to see if its a valid bin or json file - std::string fname(filename.c_str()); - auto position = fname.find_last_of("."); - std::string extension = fname.substr(position + 1); - size_t fsize = request->contentLength(); + const String extension = getFilenameExtension(filename); + const std::size_t filesize = request->contentLength(); - is_firmware = false; - if ((extension == "bin") && (fsize > 1000000)) { - is_firmware = true; + _is_firmware = false; + if ((extension == "bin") && (filesize > 1000000)) { + _is_firmware = true; } else if (extension == "json") { - md5[0] = '\0'; // clear md5 + _md5[0] = '\0'; // clear md5 } else if (extension == "md5") { - if (len == 32) { - memcpy(md5, data, 32); - md5[32] = '\0'; + if (len == _md5.size() - 1) { + std::memcpy(_md5.data(), data, _md5.size() - 1); + _md5.back() = '\0'; } return; } else { - md5[0] = '\0'; + _md5.front() = '\0'; handleError(request, 406); // Not Acceptable - unsupported file type return; } - if (is_firmware) { + if (_is_firmware) { // Check firmware header, 0xE9 magic offset 0 indicates esp bin, chip offset 12: esp32:0, S2:2, C3:5 #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 if (len > 12 && (data[0] != 0xE9 || data[12] != 0)) { @@ -74,12 +79,12 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri } #endif // it's firmware - initialize the ArduinoOTA updater - if (Update.begin(fsize - sizeof(esp_image_header_t))) { - if (strlen(md5) == 32) { - Update.setMD5(md5); - md5[0] = '\0'; + if (Update.begin(filesize - sizeof(esp_image_header_t))) { + if (strlen(_md5.data()) == _md5.size() - 1) { + Update.setMD5(_md5.data()); + _md5.front() = '\0'; } - request->onDisconnect(UploadFileService::handleEarlyDisconnect); // success, let's make sure we end the update if the client hangs up + request->onDisconnect([this]() { handleEarlyDisconnect(); }); // success, let's make sure we end the update if the client hangs up } else { handleError(request, 507); // failed to begin, send an error response Insufficient Storage return; @@ -90,23 +95,17 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri } } - if (!is_firmware) { - if (len) { - if (len != request->_tempFile.write(data, len)) { // stream the incoming chunk to the opened file - handleError(request, 507); // 507-Insufficient Storage - } + if (!_is_firmware) { + if (len && len != request->_tempFile.write(data, len)) { // stream the incoming chunk to the opened file + handleError(request, 507); // 507-Insufficient Storage } - } else { - // if we haven't delt with an error, continue with the firmware update - if (!request->_tempObject) { - if (Update.write(data, len) != len) { - handleError(request, 500); - } - if (final) { - if (!Update.end(true)) { - handleError(request, 500); - } - } + } else if (!request->_tempObject) { // if we haven't delt with an error, continue with the firmware update + if (Update.write(data, len) != len) { + handleError(request, 500); + return; + } + if (final && !Update.end(true)) { + handleError(request, 500); } } } @@ -124,7 +123,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) { // check if it was a firmware upgrade // if no error, send the success response as a JSON - if (is_firmware && !request->_tempObject) { + if (_is_firmware && !request->_tempObject) { emsesp::EMSESP::system_.store_nvs_values(); request->onDisconnect(RestartService::restartNow); AsyncWebServerResponse * response = request->beginResponse(200); @@ -132,10 +131,10 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) { return; } - if (strlen(md5) == 32) { + if (strlen(_md5.data()) == _md5.size() - 1) { auto * response = new AsyncJsonResponse(false); JsonObject root = response->getRoot(); - root["md5"] = md5; + root["md5"] = _md5.data(); response->setLength(); request->send(response); return; @@ -163,6 +162,6 @@ void UploadFileService::handleError(AsyncWebServerRequest * request, int code) { } void UploadFileService::handleEarlyDisconnect() { - is_firmware = false; + _is_firmware = false; Update.abort(); -} +} \ No newline at end of file diff --git a/lib/framework/UploadFileService.h b/lib/framework/UploadFileService.h index 4abcdf7ce..0885805fa 100644 --- a/lib/framework/UploadFileService.h +++ b/lib/framework/UploadFileService.h @@ -1,16 +1,16 @@ #ifndef UploadFileService_h #define UploadFileService_h -#include +#include "RestartService.h" +#include "SecurityManager.h" +#include +#include +#include #include #include -#include - -#include -#include -#include +#include #define UPLOAD_FILE_PATH "/rest/uploadFile" #define TEMP_FILENAME_PATH "/tmp_upload" @@ -20,11 +20,14 @@ class UploadFileService { UploadFileService(AsyncWebServer * server, SecurityManager * securityManager); private: - SecurityManager * _securityManager; - void handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final); - void uploadComplete(AsyncWebServerRequest * request); - void handleError(AsyncWebServerRequest * request, int code); - static void handleEarlyDisconnect(); + SecurityManager * _securityManager; + bool _is_firmware; + std::array _md5; + + void handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final); + void uploadComplete(AsyncWebServerRequest * request); + void handleError(AsyncWebServerRequest * request, int code); + void handleEarlyDisconnect(); }; -#endif +#endif \ No newline at end of file diff --git a/lib/framework/WiFiScanner.cpp b/lib/framework/WiFiScanner.cpp index 51fd74bc1..c4e698361 100644 --- a/lib/framework/WiFiScanner.cpp +++ b/lib/framework/WiFiScanner.cpp @@ -1,14 +1,12 @@ -#include - -using namespace std::placeholders; // for `_1` etc +#include "WiFiScanner.h" WiFiScanner::WiFiScanner(AsyncWebServer * server, SecurityManager * securityManager) { server->on(SCAN_NETWORKS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WiFiScanner::scanNetworks, this, _1), AuthenticationPredicates::IS_ADMIN)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { scanNetworks(request); }, AuthenticationPredicates::IS_ADMIN)); server->on(LIST_NETWORKS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WiFiScanner::listNetworks, this, _1), AuthenticationPredicates::IS_ADMIN)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { listNetworks(request); }, AuthenticationPredicates::IS_ADMIN)); }; void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) { @@ -21,18 +19,18 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) { } void WiFiScanner::listNetworks(AsyncWebServerRequest * request) { - int numNetworks = WiFi.scanComplete(); + const int numNetworks = WiFi.scanComplete(); if (numNetworks > -1) { - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); - JsonArray networks = root["networks"].to(); - for (int i = 0; i < numNetworks; i++) { + auto * response = new AsyncJsonResponse(false); + JsonObject root = response->getRoot(); + JsonArray networks = root["networks"].to(); + for (uint8_t i = 0; i < numNetworks; i++) { JsonObject network = networks.add(); network["rssi"] = WiFi.RSSI(i); network["ssid"] = WiFi.SSID(i); network["bssid"] = WiFi.BSSIDstr(i); network["channel"] = WiFi.channel(i); - network["encryption_type"] = (uint8_t)WiFi.encryptionType(i); + network["encryption_type"] = static_cast(WiFi.encryptionType(i)); } response->setLength(); request->send(response); diff --git a/lib/framework/WiFiScanner.h b/lib/framework/WiFiScanner.h index e73a2e669..7c76bdb15 100644 --- a/lib/framework/WiFiScanner.h +++ b/lib/framework/WiFiScanner.h @@ -3,10 +3,10 @@ #include #include - #include #include -#include + +#include "SecurityManager.h" #define SCAN_NETWORKS_SERVICE_PATH "/rest/scanNetworks" #define LIST_NETWORKS_SERVICE_PATH "/rest/listNetworks" diff --git a/lib_standalone/StatefulService.h b/lib_standalone/StatefulService.h index 0210bc1b3..ceb2ae965 100644 --- a/lib_standalone/StatefulService.h +++ b/lib_standalone/StatefulService.h @@ -68,7 +68,7 @@ class StatefulService { } } - StateUpdateResult update(std::function stateUpdater, ) { + StateUpdateResult update(std::function stateUpdater) { beginTransaction(); StateUpdateResult result = stateUpdater(_state); endTransaction(); @@ -85,7 +85,7 @@ class StatefulService { return result; } - StateUpdateResult update(JsonObject jsonObject, JsonStateUpdater stateUpdater, ) { + StateUpdateResult update(JsonObject jsonObject, JsonStateUpdater stateUpdater) { beginTransaction(); StateUpdateResult result = stateUpdater(jsonObject, _state); endTransaction(); diff --git a/src/emsesp.h b/src/emsesp.h index 324ed9ad5..427476e41 100644 --- a/src/emsesp.h +++ b/src/emsesp.h @@ -38,8 +38,7 @@ #endif #include -#include - +#include "ESP8266React.h" #include "web/WebStatusService.h" #include "web/WebDataService.h" #include "web/WebSettingsService.h" diff --git a/src/emsesp_stub.hpp b/src/emsesp_stub.hpp index 2f8eb0535..d028b30ec 100644 --- a/src/emsesp_stub.hpp +++ b/src/emsesp_stub.hpp @@ -24,8 +24,7 @@ #include "version.h" #include "default_settings.h" #include "helpers.h" - -#include +#include "ESP8266React.h" #include diff --git a/src/telegram.h b/src/telegram.h index fb047823d..aba93af64 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -21,16 +21,15 @@ #include #include +#include // UART drivers #if defined(ESP32) #include "uart/emsuart_esp32.h" #elif defined(EMSESP_STANDALONE) -#include +#include "emsuart_standalone.h" #endif -#include - #include "helpers.h" #define MAX_RX_TELEGRAMS 10 // size of Rx queue diff --git a/src/version.h b/src/version.h index 259e9ea01..2caf6b5af 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.5-dev.13" +#define EMSESP_APP_VERSION "3.6.5-dev.14" diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index f997cd5f8..be53e9f4c 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -18,8 +18,6 @@ #include "emsesp.h" -using namespace std::placeholders; // for `_1` etc - namespace emsesp { uint32_t WebAPIService::api_count_ = 0; @@ -27,17 +25,26 @@ uint16_t WebAPIService::api_fails_ = 0; WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * securityManager) : _securityManager(securityManager) - , _apiHandler("/api", std::bind(&WebAPIService::webAPIService_post, this, _1, _2)) { // for POSTS, must use 'Content-Type: application/json' in header - server->on("/api", HTTP_GET, std::bind(&WebAPIService::webAPIService_get, this, _1)); // for GETS + , _apiHandler(EMSESP_API_SERVICE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { webAPIService_post(request, json); }) { // for POSTs + server->on(EMSESP_API_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { webAPIService_get(request); }); // for GETs server->addHandler(&_apiHandler); // for settings - server->on(GET_SETTINGS_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebAPIService::getSettings, this, _1), AuthenticationPredicates::IS_ADMIN)); + server->on(GET_SETTINGS_PATH, + HTTP_GET, + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getSettings(request); }, AuthenticationPredicates::IS_ADMIN)); + server->on(GET_CUSTOMIZATIONS_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebAPIService::getCustomizations, this, _1), AuthenticationPredicates::IS_ADMIN)); - server->on(GET_SCHEDULE_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebAPIService::getSchedule, this, _1), AuthenticationPredicates::IS_ADMIN)); - server->on(GET_ENTITIES_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebAPIService::getEntities, this, _1), AuthenticationPredicates::IS_ADMIN)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getCustomizations(request); }, AuthenticationPredicates::IS_ADMIN)); + + server->on(GET_SCHEDULE_PATH, + HTTP_GET, + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getSchedule(request); }, AuthenticationPredicates::IS_ADMIN)); + + server->on(GET_ENTITIES_PATH, + HTTP_GET, + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getEntities(request); }, AuthenticationPredicates::IS_ADMIN)); } // HTTP GET diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index 998faa611..7cbc1b7a0 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -20,8 +20,6 @@ namespace emsesp { -using namespace std::placeholders; // for `_1` etc - WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(WebCustomEntity::read, WebCustomEntity::update, diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 62b8839bf..1181190e4 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -20,27 +20,24 @@ namespace emsesp { -using namespace std::placeholders; // for `_1` etc - bool WebCustomization::_start = true; WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) , _masked_entities_handler(CUSTOMIZATION_ENTITIES_PATH, - securityManager->wrapCallback(std::bind(&WebCustomizationService::customization_entities, this, _1, _2), + securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { customization_entities(request, json); }, AuthenticationPredicates::IS_AUTHENTICATED)) { server->on(DEVICE_ENTITIES_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebCustomizationService::device_entities, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); - + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_entities(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); server->on(DEVICES_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebCustomizationService::devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { devices(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); server->on(RESET_CUSTOMIZATION_SERVICE_PATH, HTTP_POST, - securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { reset_customization(request); }, AuthenticationPredicates::IS_ADMIN)); _masked_entities_handler.setMethod(HTTP_POST); _masked_entities_handler.setMaxContentLength(2048); diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 4fba68a1f..2fb7f624b 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -20,33 +20,36 @@ namespace emsesp { -using namespace std::placeholders; // for `_1` etc - WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securityManager) : _write_value_handler(WRITE_DEVICE_VALUE_SERVICE_PATH, - securityManager->wrapCallback(std::bind(&WebDataService::write_device_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) + securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { write_device_value(request, json); }, + AuthenticationPredicates::IS_ADMIN)) , _write_temperature_handler(WRITE_TEMPERATURE_SENSOR_SERVICE_PATH, - securityManager->wrapCallback(std::bind(&WebDataService::write_temperature_sensor, this, _1, _2), + securityManager->wrapCallback([this](AsyncWebServerRequest * request, + JsonVariant json) { write_temperature_sensor(request, json); }, AuthenticationPredicates::IS_ADMIN)) , _write_analog_handler(WRITE_ANALOG_SENSOR_SERVICE_PATH, - securityManager->wrapCallback(std::bind(&WebDataService::write_analog_sensor, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) { + securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { write_analog_sensor(request, json); }, + AuthenticationPredicates::IS_ADMIN)) { // GET's server->on(DEVICE_DATA_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebDataService::device_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_data(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); + server->on(CORE_DATA_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { core_data(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); server->on(SENSOR_DATA_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebDataService::sensor_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { sensor_data(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); // POST's server->on(SCAN_DEVICES_SERVICE_PATH, HTTP_POST, - securityManager->wrapRequest(std::bind(&WebDataService::scan_devices, this, _1), AuthenticationPredicates::IS_ADMIN)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { scan_devices(request); }, AuthenticationPredicates::IS_ADMIN)); + _write_value_handler.setMethod(HTTP_POST); _write_value_handler.setMaxContentLength(256); diff --git a/src/web/WebLogService.cpp b/src/web/WebLogService.cpp index 0558f1a26..634c728b5 100644 --- a/src/web/WebLogService.cpp +++ b/src/web/WebLogService.cpp @@ -18,19 +18,18 @@ #include "emsesp.h" -using namespace std::placeholders; - namespace emsesp { WebLogService::WebLogService(AsyncWebServer * server, SecurityManager * securityManager) : events_(EVENT_SOURCE_LOG_PATH) - , setValues_(LOG_SETTINGS_PATH, std::bind(&WebLogService::setValues, this, _1, _2)) { + , setValues_(LOG_SETTINGS_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { setValues(request, json); }) { events_.setFilter(securityManager->filterRequest(AuthenticationPredicates::IS_ADMIN)); - server->on(LOG_SETTINGS_PATH, HTTP_GET, std::bind(&WebLogService::getValues, this, _1)); // get settings + // get settings + server->on(LOG_SETTINGS_PATH, HTTP_POST, [this](AsyncWebServerRequest * request) { getValues(request); }); // for bring back the whole log - is a command, hence a POST - server->on(FETCH_LOG_PATH, HTTP_POST, std::bind(&WebLogService::fetchLog, this, _1)); + server->on(FETCH_LOG_PATH, HTTP_POST, [this](AsyncWebServerRequest * request) { fetchLog(request); }); server->addHandler(&setValues_); server->addHandler(&events_); diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index a5d3e527b..52665811a 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -21,8 +21,6 @@ namespace emsesp { -using namespace std::placeholders; // for `_1` etc - WebSchedulerService::WebSchedulerService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(WebScheduler::read, WebScheduler::update, this, server, EMSESP_SCHEDULER_SERVICE_PATH, securityManager, AuthenticationPredicates::IS_AUTHENTICATED) , _fsPersistence(WebScheduler::read, WebScheduler::update, this, fs, EMSESP_SCHEDULER_FILE) { diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 04ce8f8eb..16f1015ea 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -22,17 +22,13 @@ namespace emsesp { uint8_t WebSettings::flags_ = 0; -using namespace std::placeholders; // for `_1` etc - WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager) , _fsPersistence(WebSettings::read, WebSettings::update, this, fs, EMSESP_SETTINGS_FILE) { - // GET server->on(EMSESP_BOARD_PROFILE_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebSettingsService::board_profile, this, _1), AuthenticationPredicates::IS_ADMIN)); - - addUpdateHandler([&] { onUpdate(); }, false); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { board_profile(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); + addUpdateHandler([this] { onUpdate(); }, false); } void WebSettings::read(WebSettings & settings, JsonObject root) { diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 773d73927..9fab268c9 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -18,14 +18,12 @@ #include "emsesp.h" -using namespace std::placeholders; // for `_1` etc - namespace emsesp { WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) { server->on(EMSESP_STATUS_SERVICE_PATH, HTTP_GET, - securityManager->wrapRequest(std::bind(&WebStatusService::webStatusService, this, _1), AuthenticationPredicates::IS_AUTHENTICATED)); + securityManager->wrapRequest([this](AsyncWebServerRequest * request) { webStatusService(request); }, AuthenticationPredicates::IS_AUTHENTICATED)); } void WebStatusService::webStatusService(AsyncWebServerRequest * request) {