mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
memory optimizations
This commit is contained in:
@@ -32,7 +32,7 @@
|
|||||||
"@types/imagemin": "^8.0.5",
|
"@types/imagemin": "^8.0.5",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.11.16",
|
"@types/node": "^20.11.16",
|
||||||
"@types/react": "^18.2.52",
|
"@types/react": "^18.2.53",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"alova": "^2.17.0",
|
"alova": "^2.17.0",
|
||||||
|
|||||||
@@ -1670,14 +1670,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/react@npm:^18.2.52":
|
"@types/react@npm:^18.2.53":
|
||||||
version: 18.2.52
|
version: 18.2.53
|
||||||
resolution: "@types/react@npm:18.2.52"
|
resolution: "@types/react@npm:18.2.53"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/prop-types": "npm:*"
|
"@types/prop-types": "npm:*"
|
||||||
"@types/scheduler": "npm:*"
|
"@types/scheduler": "npm:*"
|
||||||
csstype: "npm:^3.0.2"
|
csstype: "npm:^3.0.2"
|
||||||
checksum: 10/0ab90a37fd82028c3559f18ce50790d01b262589a2ea49d014d8888291f47d9c91e65cb7db031a3e5d58818cb5376577afb4b593068473abfd0c695fa7e6b7c4
|
checksum: 10/9a518aef07c6bb743aa18a2aea7f618d4e7c9e44e14d25119d2e255c48e68ecd901ede8b4eaf22ffe4f52c1ff85e11634ec75e73dcfc0719cc52269629f13d69
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1859,7 +1859,7 @@ __metadata:
|
|||||||
"@types/imagemin": "npm:^8.0.5"
|
"@types/imagemin": "npm:^8.0.5"
|
||||||
"@types/lodash-es": "npm:^4.17.12"
|
"@types/lodash-es": "npm:^4.17.12"
|
||||||
"@types/node": "npm:^20.11.16"
|
"@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-dom": "npm:^18.2.18"
|
||||||
"@types/react-router-dom": "npm:^5.3.3"
|
"@types/react-router-dom": "npm:^5.3.3"
|
||||||
"@typescript-eslint/eslint-plugin": "npm:^6.20.0"
|
"@typescript-eslint/eslint-plugin": "npm:^6.20.0"
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -38,18 +38,8 @@
|
|||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <Print.h>
|
#include <Print.h>
|
||||||
|
|
||||||
#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";
|
constexpr const char * JSON_MIMETYPE = "application/json";
|
||||||
|
|
||||||
/*
|
|
||||||
* Json Response
|
|
||||||
* */
|
|
||||||
|
|
||||||
class ChunkPrint : public Print {
|
class ChunkPrint : public Print {
|
||||||
private:
|
private:
|
||||||
uint8_t * _destination;
|
uint8_t * _destination;
|
||||||
@@ -129,40 +119,11 @@ class MsgpackAsyncJsonResponse : public AsyncAbstractResponse {
|
|||||||
|
|
||||||
class AsyncJsonResponse : public AsyncAbstractResponse {
|
class AsyncJsonResponse : public AsyncAbstractResponse {
|
||||||
protected:
|
protected:
|
||||||
#if ARDUINOJSON_VERSION_MAJOR == 5
|
|
||||||
DynamicJsonBuffer _jsonBuffer;
|
|
||||||
#elif ARDUINOJSON_VERSION_MAJOR == 6
|
|
||||||
DynamicJsonDocument _jsonBuffer;
|
|
||||||
#else
|
|
||||||
JsonDocument _jsonBuffer;
|
JsonDocument _jsonBuffer;
|
||||||
#endif
|
JsonVariant _root;
|
||||||
|
bool _isValid;
|
||||||
JsonVariant _root;
|
|
||||||
bool _isValid;
|
|
||||||
|
|
||||||
public:
|
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)
|
AsyncJsonResponse(bool isArray = false)
|
||||||
: _isValid{false} {
|
: _isValid{false} {
|
||||||
_code = 200;
|
_code = 200;
|
||||||
@@ -172,7 +133,6 @@ class AsyncJsonResponse : public AsyncAbstractResponse {
|
|||||||
else
|
else
|
||||||
_root = _jsonBuffer.add<JsonObject>();
|
_root = _jsonBuffer.add<JsonObject>();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
~AsyncJsonResponse() {
|
~AsyncJsonResponse() {
|
||||||
}
|
}
|
||||||
@@ -183,11 +143,7 @@ class AsyncJsonResponse : public AsyncAbstractResponse {
|
|||||||
return _isValid;
|
return _isValid;
|
||||||
}
|
}
|
||||||
size_t setLength() {
|
size_t setLength() {
|
||||||
#if ARDUINOJSON_VERSION_MAJOR == 5
|
|
||||||
_contentLength = _root.measureLength();
|
|
||||||
#else
|
|
||||||
_contentLength = measureJson(_root);
|
_contentLength = measureJson(_root);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (_contentLength) {
|
if (_contentLength) {
|
||||||
_isValid = true;
|
_isValid = true;
|
||||||
@@ -201,33 +157,18 @@ class AsyncJsonResponse : public AsyncAbstractResponse {
|
|||||||
|
|
||||||
size_t _fillBuffer(uint8_t * data, size_t len) {
|
size_t _fillBuffer(uint8_t * data, size_t len) {
|
||||||
ChunkPrint dest(data, _sentLength, len);
|
ChunkPrint dest(data, _sentLength, len);
|
||||||
|
|
||||||
#if ARDUINOJSON_VERSION_MAJOR == 5
|
|
||||||
_root.printTo(dest);
|
|
||||||
#else
|
|
||||||
serializeJson(_root, dest);
|
serializeJson(_root, dest);
|
||||||
#endif
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrettyAsyncJsonResponse : public AsyncJsonResponse {
|
class PrettyAsyncJsonResponse : public AsyncJsonResponse {
|
||||||
public:
|
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)
|
PrettyAsyncJsonResponse(bool isArray = false)
|
||||||
: AsyncJsonResponse{isArray} {
|
: AsyncJsonResponse{isArray} {
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
size_t setLength() {
|
size_t setLength() {
|
||||||
#if ARDUINOJSON_VERSION_MAJOR == 5
|
|
||||||
_contentLength = _root.measurePrettyLength();
|
|
||||||
#else
|
|
||||||
_contentLength = measureJsonPretty(_root);
|
_contentLength = measureJsonPretty(_root);
|
||||||
#endif
|
|
||||||
if (_contentLength) {
|
if (_contentLength) {
|
||||||
_isValid = true;
|
_isValid = true;
|
||||||
}
|
}
|
||||||
@@ -235,11 +176,7 @@ class PrettyAsyncJsonResponse : public AsyncJsonResponse {
|
|||||||
}
|
}
|
||||||
size_t _fillBuffer(uint8_t * data, size_t len) {
|
size_t _fillBuffer(uint8_t * data, size_t len) {
|
||||||
ChunkPrint dest(data, _sentLength, len);
|
ChunkPrint dest(data, _sentLength, len);
|
||||||
#if ARDUINOJSON_VERSION_MAJOR == 5
|
|
||||||
_root.prettyPrintTo(dest);
|
|
||||||
#else
|
|
||||||
serializeJsonPretty(_root, dest);
|
serializeJsonPretty(_root, dest);
|
||||||
#endif
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -253,28 +190,15 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
WebRequestMethodComposite _method;
|
WebRequestMethodComposite _method;
|
||||||
ArJsonRequestHandlerFunction _onRequest;
|
ArJsonRequestHandlerFunction _onRequest;
|
||||||
size_t _contentLength;
|
size_t _contentLength;
|
||||||
#if ARDUINOJSON_VERSION_MAJOR == 6
|
size_t _maxContentLength;
|
||||||
const size_t maxJsonBufferSize;
|
|
||||||
#endif
|
|
||||||
size_t _maxContentLength;
|
|
||||||
|
|
||||||
public:
|
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)
|
AsyncCallbackJsonWebHandler(const String & uri, ArJsonRequestHandlerFunction onRequest)
|
||||||
: _uri(uri)
|
: _uri(uri)
|
||||||
, _method(HTTP_POST | HTTP_PUT | HTTP_PATCH)
|
, _method(HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_PATCH)
|
||||||
, _onRequest(onRequest)
|
, _onRequest(onRequest)
|
||||||
, _maxContentLength(16384) {
|
, _maxContentLength(16384) {
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void setMethod(WebRequestMethodComposite method) {
|
void setMethod(WebRequestMethodComposite method) {
|
||||||
_method = method;
|
_method = method;
|
||||||
@@ -286,6 +210,7 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
_onRequest = fn;
|
_onRequest = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual bool canHandle(AsyncWebServerRequest * request) override final {
|
virtual bool canHandle(AsyncWebServerRequest * request) override final {
|
||||||
if (!_onRequest)
|
if (!_onRequest)
|
||||||
return false;
|
return false;
|
||||||
@@ -305,28 +230,17 @@ class AsyncCallbackJsonWebHandler : public AsyncWebHandler {
|
|||||||
|
|
||||||
virtual void handleRequest(AsyncWebServerRequest * request) override final {
|
virtual void handleRequest(AsyncWebServerRequest * request) override final {
|
||||||
if (_onRequest) {
|
if (_onRequest) {
|
||||||
|
JsonVariant json; // empty variant
|
||||||
if (request->_tempObject != NULL) {
|
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<JsonVariant>();
|
|
||||||
#else
|
|
||||||
JsonDocument jsonBuffer;
|
JsonDocument jsonBuffer;
|
||||||
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject));
|
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t *)(request->_tempObject));
|
||||||
if (!error) {
|
if (!error) {
|
||||||
JsonVariant json = jsonBuffer.as<JsonVariant>();
|
json = jsonBuffer.as<JsonVariant>();
|
||||||
#endif
|
|
||||||
|
|
||||||
_onRequest(request, json);
|
_onRequest(request, json);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request->send(_contentLength > _maxContentLength ? 413 : 400);
|
_onRequest(request, json);
|
||||||
} else {
|
} else {
|
||||||
request->send(500);
|
request->send(500);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,21 +34,19 @@ class HttpEndpoint {
|
|||||||
, _stateUpdater(stateUpdater)
|
, _stateUpdater(stateUpdater)
|
||||||
, _statefulService(statefulService) {
|
, _statefulService(statefulService) {
|
||||||
// Create the GET and POST endpoints
|
// 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
|
POSThandler = new AsyncCallbackJsonWebHandler(servicePath,
|
||||||
// Could also use server->on() but this is more efficient
|
securityManager->wrapCallback(
|
||||||
|
[this](AsyncWebServerRequest * request, JsonVariant json) {
|
||||||
// create the GET
|
//
|
||||||
GEThandler = new AsyncCallbackWebHandler();
|
if (request->method() == HTTP_GET) {
|
||||||
GEThandler->setUri(servicePath);
|
fetchSettings(request);
|
||||||
GEThandler->setMethod(HTTP_GET);
|
} else if (request->method() == HTTP_POST) {
|
||||||
GEThandler->onRequest(securityManager->wrapRequest(std::bind(&HttpEndpoint::fetchSettings, this, _1), authenticationPredicate));
|
updateSettings(request, json);
|
||||||
server->addHandler(GEThandler);
|
} else {
|
||||||
|
request->send(405, "application/json", "{\"message\":\"Method Not Allowed\"}");
|
||||||
// create the POST
|
}
|
||||||
POSThandler =
|
},
|
||||||
new AsyncCallbackJsonWebHandler(servicePath,
|
authenticationPredicate));
|
||||||
securityManager->wrapCallback(std::bind(&HttpEndpoint::updateSettings, this, _1, _2), authenticationPredicate));
|
|
||||||
POSThandler->setMethod(HTTP_POST);
|
|
||||||
server->addHandler(POSThandler);
|
server->addHandler(POSThandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,20 +57,25 @@ class HttpEndpoint {
|
|||||||
request->send(400);
|
request->send(400);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject jsonObject = json.as<JsonObject>();
|
JsonObject jsonObject = json.as<JsonObject>();
|
||||||
StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
StateUpdateResult outcome = _statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
||||||
|
|
||||||
if (outcome == StateUpdateResult::ERROR) {
|
if (outcome == StateUpdateResult::ERROR) {
|
||||||
request->send(400);
|
request->send(400);
|
||||||
return;
|
return;
|
||||||
} else if ((outcome == StateUpdateResult::CHANGED) || (outcome == StateUpdateResult::CHANGED_RESTART)) {
|
} else if ((outcome == StateUpdateResult::CHANGED) || (outcome == StateUpdateResult::CHANGED_RESTART)) {
|
||||||
request->onDisconnect([this]() { _statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID); });
|
request->onDisconnect([this]() { _statefulService->callUpdateHandlers(HTTP_ENDPOINT_ORIGIN_ID); });
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
AsyncJsonResponse * response = new AsyncJsonResponse(false);
|
||||||
jsonObject = response->getRoot().to<JsonObject>();
|
jsonObject = response->getRoot().to<JsonObject>();
|
||||||
_statefulService->read(jsonObject, _stateReader);
|
_statefulService->read(jsonObject, _stateReader);
|
||||||
|
|
||||||
if (outcome == StateUpdateResult::CHANGED_RESTART) {
|
if (outcome == StateUpdateResult::CHANGED_RESTART) {
|
||||||
response->setCode(205); // reboot required
|
response->setCode(205); // reboot required
|
||||||
}
|
}
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ build_flags =
|
|||||||
-D EMSESP_TEST
|
-D EMSESP_TEST
|
||||||
-D EMSESP_DEBUG
|
-D EMSESP_DEBUG
|
||||||
-D CONFIG_ETH_ENABLED
|
-D CONFIG_ETH_ENABLED
|
||||||
-D TASMOTA_SDK
|
-D CONFIG_ASYNC_TCP_STACK_SIZE=8192
|
||||||
'-DEMSESP_DEFAULT_BOARD_PROFILE="Test"'
|
'-DEMSESP_DEFAULT_BOARD_PROFILE="Test"'
|
||||||
|
|
||||||
[env:lolin_s3]
|
[env:lolin_s3]
|
||||||
|
|||||||
Reference in New Issue
Block a user