Better handling of out of memory situations in live data websocket (onBattery)

This commit is contained in:
helgeerbe 2024-01-06 22:42:34 +01:00
parent 210fce67ce
commit ec93004724
6 changed files with 52 additions and 28 deletions

View File

@ -3,7 +3,7 @@
#include "ArduinoJson.h"
#include <ESPAsyncWebServer.h>
//#include <HuaweiFrameHandler.h>
#include <mutex>
class WebApiWsHuaweiLiveClass {
public:
@ -21,4 +21,6 @@ private:
uint32_t _lastWsCleanup = 0;
uint32_t _lastUpdateCheck = 0;
std::mutex _mutex;
};

View File

@ -3,6 +3,7 @@
#include "ArduinoJson.h"
#include <ESPAsyncWebServer.h>
#include <mutex>
class WebApiWsBatteryLiveClass {
public:
@ -21,4 +22,6 @@ private:
uint32_t _lastWsCleanup = 0;
uint32_t _lastUpdateCheck = 0;
static constexpr uint16_t _responseSize = 1024 + 512;
std::mutex _mutex;
};

View File

@ -4,6 +4,7 @@
#include "ArduinoJson.h"
#include <ESPAsyncWebServer.h>
#include <VeDirectMpptController.h>
#include <mutex>
class WebApiWsVedirectLiveClass {
public:
@ -23,4 +24,6 @@ private:
uint32_t _lastWsCleanup = 0;
uint32_t _dataAgeMillis = 0;
static constexpr uint16_t _responseSize = 1024 + 128;
std::mutex _mutex;
};

View File

@ -7,6 +7,7 @@
#include "Configuration.h"
#include "Huawei_can.h"
#include "MessageOutput.h"
#include "Utils.h"
#include "WebApi.h"
#include "defaults.h"
@ -50,16 +51,15 @@ void WebApiWsHuaweiLiveClass::loop()
_lastUpdateCheck = millis();
try {
String buffer;
// free JsonDocument as soon as possible
{
DynamicJsonDocument root(1024);
std::lock_guard<std::mutex> lock(_mutex);
DynamicJsonDocument root(1024);
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
JsonVariant var = root;
generateJsonResponse(var);
serializeJson(root, buffer);
}
if (buffer) {
String buffer;
serializeJson(root, buffer);
if (Configuration.get().Security.AllowReadonly) {
_ws.setAuthentication("", "");
} else {
@ -69,7 +69,9 @@ void WebApiWsHuaweiLiveClass::loop()
_ws.textAll(buffer);
}
} catch (std::bad_alloc& bad_alloc) {
MessageOutput.printf("Calling /api/livedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
MessageOutput.printf("Calling /api/huaweilivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
} catch (const std::exception& exc) {
MessageOutput.printf("Unknown exception in /api/huaweilivedata/status. Reason: \"%s\".\r\n", exc.what());
}
}
@ -122,15 +124,19 @@ void WebApiWsHuaweiLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
return;
}
try {
std::lock_guard<std::mutex> lock(_mutex);
AsyncJsonResponse* response = new AsyncJsonResponse(false, 1024U);
auto& root = response->getRoot();
generateJsonResponse(root);
response->setLength();
request->send(response);
} catch (std::bad_alloc& bad_alloc) {
MessageOutput.printf("Calling /api/livedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
MessageOutput.printf("Calling /api/huaweilivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
WebApi.sendTooManyRequests(request);
} catch (const std::exception& exc) {
MessageOutput.printf("Unknown exception in /api/huaweilivedata/status. Reason: \"%s\".\r\n", exc.what());
WebApi.sendTooManyRequests(request);
}
}

View File

@ -9,6 +9,7 @@
#include "MessageOutput.h"
#include "WebApi.h"
#include "defaults.h"
#include "Utils.h"
WebApiWsBatteryLiveClass::WebApiWsBatteryLiveClass()
: _ws("/batterylivedata")
@ -48,16 +49,15 @@ void WebApiWsBatteryLiveClass::loop()
_lastUpdateCheck = millis();
try {
String buffer;
// free JsonDocument as soon as possible
{
DynamicJsonDocument root(_responseSize);
std::lock_guard<std::mutex> lock(_mutex);
DynamicJsonDocument root(_responseSize);
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
JsonVariant var = root;
generateJsonResponse(var);
serializeJson(root, buffer);
}
if (buffer) {
String buffer;
serializeJson(root, buffer);
if (Configuration.get().Security.AllowReadonly) {
_ws.setAuthentication("", "");
} else {
@ -68,6 +68,8 @@ void WebApiWsBatteryLiveClass::loop()
}
} catch (std::bad_alloc& bad_alloc) {
MessageOutput.printf("Calling /api/batterylivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
} catch (const std::exception& exc) {
MessageOutput.printf("Unknown exception in /api/batterylivedata/status. Reason: \"%s\".\r\n", exc.what());
}
}
@ -91,6 +93,7 @@ void WebApiWsBatteryLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
return;
}
try {
std::lock_guard<std::mutex> lock(_mutex);
AsyncJsonResponse* response = new AsyncJsonResponse(false, _responseSize);
auto& root = response->getRoot();
generateJsonResponse(root);
@ -99,7 +102,9 @@ void WebApiWsBatteryLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
request->send(response);
} catch (std::bad_alloc& bad_alloc) {
MessageOutput.printf("Calling /api/batterylivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
WebApi.sendTooManyRequests(request);
} catch (const std::exception& exc) {
MessageOutput.printf("Unknown exception in /api/batterylivedata/status. Reason: \"%s\".\r\n", exc.what());
WebApi.sendTooManyRequests(request);
}
}

View File

@ -6,6 +6,7 @@
#include "AsyncJson.h"
#include "Configuration.h"
#include "MessageOutput.h"
#include "Utils.h"
#include "WebApi.h"
#include "defaults.h"
#include "PowerLimiter.h"
@ -55,16 +56,15 @@ void WebApiWsVedirectLiveClass::loop()
if (millis() - _lastWsPublish > (10 * 1000) || lastDataAgeMillis > _dataAgeMillis) {
try {
String buffer;
// free JsonDocument as soon as possible
{
DynamicJsonDocument root(_responseSize);
std::lock_guard<std::mutex> lock(_mutex);
DynamicJsonDocument root(_responseSize);
if (Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
JsonVariant var = root;
generateJsonResponse(var);
String buffer;
serializeJson(root, buffer);
}
if (buffer) {
if (Configuration.get().Security.AllowReadonly) {
_ws.setAuthentication("", "");
} else {
@ -76,6 +76,8 @@ void WebApiWsVedirectLiveClass::loop()
} catch (std::bad_alloc& bad_alloc) {
MessageOutput.printf("Calling /api/vedirectlivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
} catch (const std::exception& exc) {
MessageOutput.printf("Unknown exception in /api/vedirectlivedata/status. Reason: \"%s\".\r\n", exc.what());
}
_lastWsPublish = millis();
@ -168,6 +170,7 @@ void WebApiWsVedirectLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
return;
}
try {
std::lock_guard<std::mutex> lock(_mutex);
AsyncJsonResponse* response = new AsyncJsonResponse(false, _responseSize);
auto& root = response->getRoot();
@ -177,8 +180,10 @@ void WebApiWsVedirectLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
request->send(response);
} catch (std::bad_alloc& bad_alloc) {
MessageOutput.printf("Calling /api/livedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
MessageOutput.printf("Calling /api/vedirectlivedata/status has temporarily run out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
WebApi.sendTooManyRequests(request);
} catch (const std::exception& exc) {
MessageOutput.printf("Unknown exception in /api/vedirectlivedata/status. Reason: \"%s\".\r\n", exc.what());
WebApi.sendTooManyRequests(request);
}
}