Skip to content

Commit

Permalink
Better handling of out of memory situations in live data websocket (o…
Browse files Browse the repository at this point in the history
…nBattery)
  • Loading branch information
helgeerbe committed Jan 6, 2024
1 parent 210fce6 commit ec93004
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 26 deletions.
4 changes: 3 additions & 1 deletion include/WebApi_ws_Huawei.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include "ArduinoJson.h"
#include <ESPAsyncWebServer.h>
//#include <HuaweiFrameHandler.h>
#include <mutex>

class WebApiWsHuaweiLiveClass {
public:
Expand All @@ -21,4 +21,6 @@ class WebApiWsHuaweiLiveClass {

uint32_t _lastWsCleanup = 0;
uint32_t _lastUpdateCheck = 0;

std::mutex _mutex;
};
3 changes: 3 additions & 0 deletions include/WebApi_ws_battery.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "ArduinoJson.h"
#include <ESPAsyncWebServer.h>
#include <mutex>

class WebApiWsBatteryLiveClass {
public:
Expand All @@ -21,4 +22,6 @@ class WebApiWsBatteryLiveClass {
uint32_t _lastWsCleanup = 0;
uint32_t _lastUpdateCheck = 0;
static constexpr uint16_t _responseSize = 1024 + 512;

std::mutex _mutex;
};
3 changes: 3 additions & 0 deletions include/WebApi_ws_vedirect_live.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "ArduinoJson.h"
#include <ESPAsyncWebServer.h>
#include <VeDirectMpptController.h>
#include <mutex>

class WebApiWsVedirectLiveClass {
public:
Expand All @@ -23,4 +24,6 @@ class WebApiWsVedirectLiveClass {
uint32_t _lastWsCleanup = 0;
uint32_t _dataAgeMillis = 0;
static constexpr uint16_t _responseSize = 1024 + 128;

std::mutex _mutex;
};
24 changes: 15 additions & 9 deletions src/WebApi_ws_Huawei.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Configuration.h"
#include "Huawei_can.h"
#include "MessageOutput.h"
#include "Utils.h"
#include "WebApi.h"
#include "defaults.h"

Expand Down Expand Up @@ -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);

String buffer;
serializeJson(root, buffer);
}

if (buffer) {
if (Configuration.get().Security.AllowReadonly) {
_ws.setAuthentication("", "");
} else {
Expand All @@ -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());
}
}

Expand Down Expand Up @@ -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);
}
}
19 changes: 12 additions & 7 deletions src/WebApi_ws_battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "MessageOutput.h"
#include "WebApi.h"
#include "defaults.h"
#include "Utils.h"

WebApiWsBatteryLiveClass::WebApiWsBatteryLiveClass()
: _ws("/batterylivedata")
Expand Down Expand Up @@ -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);

String buffer;
serializeJson(root, buffer);
}

if (buffer) {
if (Configuration.get().Security.AllowReadonly) {
_ws.setAuthentication("", "");
} else {
Expand All @@ -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());
}
}

Expand All @@ -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);
Expand All @@ -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);
}
}
23 changes: 14 additions & 9 deletions src/WebApi_ws_vedirect_live.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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();
Expand Down Expand Up @@ -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();

Expand All @@ -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);
}
}

0 comments on commit ec93004

Please sign in to comment.