diff --git a/interface/package.json b/interface/package.json index 3c9391ce4..362e03882 100644 --- a/interface/package.json +++ b/interface/package.json @@ -32,7 +32,7 @@ "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", "@types/node": "^20.11.16", - "@types/react": "^18.2.52", + "@types/react": "^18.2.53", "@types/react-dom": "^18.2.18", "@types/react-router-dom": "^5.3.3", "alova": "^2.17.0", diff --git a/interface/yarn.lock b/interface/yarn.lock index c4aa445c8..0f649fefe 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1670,14 +1670,14 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18.2.52": - version: 18.2.52 - resolution: "@types/react@npm:18.2.52" +"@types/react@npm:^18.2.53": + version: 18.2.53 + resolution: "@types/react@npm:18.2.53" dependencies: "@types/prop-types": "npm:*" "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/0ab90a37fd82028c3559f18ce50790d01b262589a2ea49d014d8888291f47d9c91e65cb7db031a3e5d58818cb5376577afb4b593068473abfd0c695fa7e6b7c4 + checksum: 10/9a518aef07c6bb743aa18a2aea7f618d4e7c9e44e14d25119d2e255c48e68ecd901ede8b4eaf22ffe4f52c1ff85e11634ec75e73dcfc0719cc52269629f13d69 languageName: node linkType: hard @@ -1859,7 +1859,7 @@ __metadata: "@types/imagemin": "npm:^8.0.5" "@types/lodash-es": "npm:^4.17.12" "@types/node": "npm:^20.11.16" - "@types/react": "npm:^18.2.52" + "@types/react": "npm:^18.2.53" "@types/react-dom": "npm:^18.2.18" "@types/react-router-dom": "npm:^5.3.3" "@typescript-eslint/eslint-plugin": "npm:^6.20.0" diff --git a/lib/AsyncTCP/library.json b/lib/AsyncTCP/library.json deleted file mode 100644 index e6befd42b..000000000 --- a/lib/AsyncTCP/library.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "AsyncTCP-esphome", - "description": "Asynchronous TCP Library for ESP32", - "keywords": "async,tcp", - "authors": { - "name": "Hristo Gochkov", - "maintainer": true - }, - "repository": { - "type": "git", - "url": "https://github.com/esphome/AsyncTCP.git" - }, - "version": "2.1.1", - "license": "LGPL-3.0", - "frameworks": "arduino", - "platforms": [ - "espressif32", - "libretiny" - ], - "build": { - "libCompatMode": 2 - } -} diff --git a/lib/ESPAsyncWebServer/library.json b/lib/ESPAsyncWebServer/library.json deleted file mode 100644 index 94271bdd4..000000000 --- a/lib/ESPAsyncWebServer/library.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "ESP Async WebServer", - "version": "2.6.1", - "description": "Asynchronous HTTP and WebSocket Server Library for ESP32. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.", - "keywords": "http,async,websocket,webserver", - "homepage": "https://github.com/mathieucarbou/ESPAsyncWebServer", - "repository": { - "type": "git", - "url": "https://github.com/mathieucarbou/ESPAsyncWebServer.git" - }, - "authors": [ - { - "name": "Hristo Gochkov" - }, - { - "name": "Mathieu Carbou", - "maintainer": true - } - ], - "license": "LGPL-3.0", - "frameworks": "arduino", - "platforms": [ - "espressif32" - ], - "dependencies": [ - { - "owner": "esphome", - "name": "AsyncTCP-esphome", - "version": "^2.1.1", - "platforms": "espressif32" - } - ], - "export": { - "include": [ - "examples", - "src", - "library.json", - "library.properties", - "LICENSE", - "README.md" - ] - } -} \ No newline at end of file diff --git a/lib/ESPAsyncWebServer/src/AsyncJson.h b/lib/ESPAsyncWebServer/src/AsyncJson.h index 7c8e278e4..48f5b7867 100644 --- a/lib/ESPAsyncWebServer/src/AsyncJson.h +++ b/lib/ESPAsyncWebServer/src/AsyncJson.h @@ -38,18 +38,8 @@ #include #include -#if ARDUINOJSON_VERSION_MAJOR == 6 -#ifndef DYNAMIC_JSON_DOCUMENT_SIZE -#define DYNAMIC_JSON_DOCUMENT_SIZE 1024 -#endif -#endif - constexpr const char * JSON_MIMETYPE = "application/json"; -/* - * Json Response - * */ - class ChunkPrint : public Print { private: uint8_t * _destination; @@ -129,40 +119,11 @@ class MsgpackAsyncJsonResponse : public AsyncAbstractResponse { class AsyncJsonResponse : public AsyncAbstractResponse { protected: -#if ARDUINOJSON_VERSION_MAJOR == 5 - DynamicJsonBuffer _jsonBuffer; -#elif ARDUINOJSON_VERSION_MAJOR == 6 - DynamicJsonDocument _jsonBuffer; -#else JsonDocument _jsonBuffer; -#endif - - JsonVariant _root; - bool _isValid; + JsonVariant _root; + bool _isValid; public: -#if ARDUINOJSON_VERSION_MAJOR == 5 - AsyncJsonResponse(bool isArray = false) - : _isValid{false} { - _code = 200; - _contentType = JSON_MIMETYPE; - if (isArray) - _root = _jsonBuffer.createArray(); - else - _root = _jsonBuffer.createObject(); - } -#elif ARDUINOJSON_VERSION_MAJOR == 6 - AsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) - : _jsonBuffer(maxJsonBufferSize) - , _isValid{false} { - _code = 200; - _contentType = JSON_MIMETYPE; - if (isArray) - _root = _jsonBuffer.createNestedArray(); - else - _root = _jsonBuffer.createNestedObject(); - } -#else AsyncJsonResponse(bool isArray = false) : _isValid{false} { _code = 200; @@ -172,7 +133,6 @@ class AsyncJsonResponse : public AsyncAbstractResponse { else _root = _jsonBuffer.add(); } -#endif ~AsyncJsonResponse() { } @@ -183,11 +143,7 @@ class AsyncJsonResponse : public AsyncAbstractResponse { return _isValid; } size_t setLength() { -#if ARDUINOJSON_VERSION_MAJOR == 5 - _contentLength = _root.measureLength(); -#else _contentLength = measureJson(_root); -#endif if (_contentLength) { _isValid = true; @@ -201,33 +157,18 @@ class AsyncJsonResponse : public AsyncAbstractResponse { size_t _fillBuffer(uint8_t * data, size_t len) { ChunkPrint dest(data, _sentLength, len); - -#if ARDUINOJSON_VERSION_MAJOR == 5 - _root.printTo(dest); -#else serializeJson(_root, dest); -#endif return len; } }; class PrettyAsyncJsonResponse : public AsyncJsonResponse { public: -#if ARDUINOJSON_VERSION_MAJOR == 6 - PrettyAsyncJsonResponse(bool isArray = false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) - : AsyncJsonResponse{isArray, maxJsonBufferSize} { - } -#else PrettyAsyncJsonResponse(bool isArray = false) : AsyncJsonResponse{isArray} { } -#endif size_t setLength() { -#if ARDUINOJSON_VERSION_MAJOR == 5 - _contentLength = _root.measurePrettyLength(); -#else _contentLength = measureJsonPretty(_root); -#endif if (_contentLength) { _isValid = true; } @@ -235,11 +176,7 @@ class PrettyAsyncJsonResponse : public AsyncJsonResponse { } size_t _fillBuffer(uint8_t * data, size_t len) { ChunkPrint dest(data, _sentLength, len); -#if ARDUINOJSON_VERSION_MAJOR == 5 - _root.prettyPrintTo(dest); -#else serializeJsonPretty(_root, dest); -#endif return len; } }; @@ -253,28 +190,15 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler { WebRequestMethodComposite _method; ArJsonRequestHandlerFunction _onRequest; size_t _contentLength; -#if ARDUINOJSON_VERSION_MAJOR == 6 - const size_t maxJsonBufferSize; -#endif - size_t _maxContentLength; + size_t _maxContentLength; public: -#if ARDUINOJSON_VERSION_MAJOR == 6 - AsyncCallbackJsonWebHandler(const String & uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) - : _uri(uri) - , _method(HTTP_POST | HTTP_PUT | HTTP_PATCH) - , _onRequest(onRequest) - , maxJsonBufferSize(maxJsonBufferSize) - , _maxContentLength(16384) { - } -#else AsyncCallbackJsonWebHandler(const String & uri, ArJsonRequestHandlerFunction onRequest) : _uri(uri) - , _method(HTTP_POST | HTTP_PUT | HTTP_PATCH) + , _method(HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_PATCH) , _onRequest(onRequest) , _maxContentLength(16384) { } -#endif void setMethod(WebRequestMethodComposite method) { _method = method; @@ -286,6 +210,7 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler { _onRequest = fn; } + virtual bool canHandle(AsyncWebServerRequest * request) override final { if (!_onRequest) return false; @@ -305,28 +230,17 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler { virtual void handleRequest(AsyncWebServerRequest * request) override final { if (_onRequest) { + JsonVariant json; // empty variant if (request->_tempObject != NULL) { -#if ARDUINOJSON_VERSION_MAJOR == 5 - DynamicJsonBuffer jsonBuffer; - JsonVariant json = jsonBuffer.parse((uint8_t *)(request->_tempObject)); - if (json.success()) { -#elif ARDUINOJSON_VERSION_MAJOR == 6 - DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize); - DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject)); - if (!error) { - JsonVariant json = jsonBuffer.as(); -#else JsonDocument jsonBuffer; DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject)); if (!error) { - JsonVariant json = jsonBuffer.as(); -#endif - + json = jsonBuffer.as(); _onRequest(request, json); return; } } - request->send(_contentLength > _maxContentLength ? 413 : 400); + _onRequest(request, json); } else { request->send(500); } diff --git a/lib/framework/HttpEndpoint.h b/lib/framework/HttpEndpoint.h index 3c1902583..00cf6e20f 100644 --- a/lib/framework/HttpEndpoint.h +++ b/lib/framework/HttpEndpoint.h @@ -34,21 +34,19 @@ class HttpEndpoint { , _stateUpdater(stateUpdater) , _statefulService(statefulService) { // Create the GET and POST endpoints - // We can't use HTTP_ANY and process one a single endpoint due to the way the ESPAsyncWebServer library works - // Could also use server->on() but this is more efficient - - // create the GET - GEThandler = new AsyncCallbackWebHandler(); - GEThandler->setUri(servicePath); - GEThandler->setMethod(HTTP_GET); - GEThandler->onRequest(securityManager->wrapRequest(std::bind(&HttpEndpoint::fetchSettings, this, _1), authenticationPredicate)); - server->addHandler(GEThandler); - - // create the POST - POSThandler = - new AsyncCallbackJsonWebHandler(servicePath, - securityManager->wrapCallback(std::bind(&HttpEndpoint::updateSettings, this, _1, _2), authenticationPredicate)); - POSThandler->setMethod(HTTP_POST); + POSThandler = new AsyncCallbackJsonWebHandler(servicePath, + securityManager->wrapCallback( + [this](AsyncWebServerRequest * request, JsonVariant json) { + // + if (request->method() == HTTP_GET) { + fetchSettings(request); + } else if (request->method() == HTTP_POST) { + updateSettings(request, json); + } else { + request->send(405, "application/json", "{\"message\":\"Method Not Allowed\"}"); + } + }, + authenticationPredicate)); server->addHandler(POSThandler); } @@ -59,20 +57,25 @@ class HttpEndpoint { request->send(400); return; } + JsonObject jsonObject = json.as(); StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater); + if (outcome == StateUpdateResult::ERROR) { request->send(400); return; } else if ((outcome == StateUpdateResult::CHANGED) || (outcome == StateUpdateResult::CHANGED_RESTART)) { request->onDisconnect([this]() { _statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID); }); } + AsyncJsonResponse * response = new AsyncJsonResponse(false); jsonObject = response->getRoot().to(); _statefulService->read(jsonObject, _stateReader); + if (outcome == StateUpdateResult::CHANGED_RESTART) { response->setCode(205); // reboot required } + response->setLength(); request->send(response); } diff --git a/pio_local.ini_example b/pio_local.ini_example index 77c68f171..9e25f8543 100644 --- a/pio_local.ini_example +++ b/pio_local.ini_example @@ -71,7 +71,7 @@ build_flags = -D EMSESP_TEST -D EMSESP_DEBUG -D CONFIG_ETH_ENABLED - -D TASMOTA_SDK + -D CONFIG_ASYNC_TCP_STACK_SIZE=8192 '-DEMSESP_DEFAULT_BOARD_PROFILE="Test"' [env:lolin_s3]