Merge pull request #3828 from willmmiles/0_15-asyncwebserver-2.2.0-features

ESPAsyncWebServer 2.2.0 + features
pull/3810/head^2
Blaž Kristan 2024-03-20 19:50:06 +01:00 zatwierdzone przez GitHub
commit f1987b9544
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
7 zmienionych plików z 69 dodań i 118 usunięć

Wyświetl plik

@ -144,7 +144,7 @@ lib_deps =
fastled/FastLED @ 3.6.0
IRremoteESP8266 @ 2.8.2
makuna/NeoPixelBus @ 2.7.5
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ^2.1.0
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ^2.2.0
# for I2C interface
;Wire
# ESP-NOW library

Wyświetl plik

@ -434,7 +434,6 @@ void handleSerial();
void updateBaudRate(uint32_t rate);
//wled_server.cpp
String getFileContentType(String &filename);
void createEditHandler(bool enable);
void initServer();
void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255);

Wyświetl plik

@ -375,6 +375,7 @@ void updateFSInfo() {
#endif
}
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
// caching presets in PSRAM may prevent occasional flashes seen when HomeAssitant polls WLED
// original idea by @akaricchi (https://github.com/Akaricchi)
@ -420,26 +421,19 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){
DEBUG_PRINT(F("WS FileRead: ")); DEBUG_PRINTLN(path);
if(path.endsWith("/")) path += "index.htm";
if(path.indexOf(F("sec")) > -1) return false;
String contentType = getFileContentType(path);
if(request->hasArg(F("download"))) contentType = F("application/octet-stream");
/*String pathWithGz = path + ".gz";
if(WLED_FS.exists(pathWithGz)){
request->send(WLED_FS, pathWithGz, contentType);
return true;
}*/
#if defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
if (path.endsWith(FPSTR(getPresetsFileName()))) {
size_t psize;
const uint8_t *presets = getPresetCache(psize);
if (presets) {
AsyncWebServerResponse *response = request->beginResponse_P(200, contentType, presets, psize);
AsyncWebServerResponse *response = request->beginResponse_P(200, FPSTR(CONTENT_TYPE_JSON), presets, psize);
request->send(response);
return true;
}
}
#endif
if(WLED_FS.exists(path)) {
request->send(WLED_FS, path, contentType);
if(WLED_FS.exists(path) || WLED_FS.exists(path + ".gz")) {
request->send(WLED_FS, path, String(), request->hasArg(F("download")));
return true;
}
return false;

Wyświetl plik

@ -1063,7 +1063,7 @@ void serveJson(AsyncWebServerRequest* request)
}
#endif
else if (url.indexOf("pal") > 0) {
request->send_P(200, "application/json", JSON_palette_names); // contentType defined in AsyncJson-v6.h
request->send_P(200, FPSTR(CONTENT_TYPE_JSON), JSON_palette_names);
return;
}
else if (url.indexOf(F("cfg")) > 0 && handleFileRead(request, F("/cfg.json"))) {
@ -1150,10 +1150,10 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
}
#endif
char buffer[2048]; // shoud be enough for 256 LEDs [RRGGBB] + all other text (9+25)
strcpy_P(buffer, PSTR("{\"leds\":["));
obuf = buffer; // assign buffer for oappnd() functions
olen = 9;
DynamicBuffer buffer(9 + (9*(1+(used/n))) + 7 + 5 + 6 + 5 + 6 + 5 + 2);
char* buf = buffer.data(); // assign buffer for oappnd() functions
strncpy_P(buffer.data(), PSTR("{\"leds\":["), buffer.size());
buf += 9; // sizeof(PSTR()) from last line
for (size_t i = 0; i < used; i += n)
{
@ -1168,29 +1168,27 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
r = scale8(qadd8(w, r), strip.getBrightness()); //R, add white channel to RGB channels as a simple RGBW -> RGB map
g = scale8(qadd8(w, g), strip.getBrightness()); //G
b = scale8(qadd8(w, b), strip.getBrightness()); //B
olen += sprintf_P(obuf + olen, PSTR("\"%06X\","), RGBW32(r,g,b,0));
buf += sprintf_P(buf, PSTR("\"%06X\","), RGBW32(r,g,b,0));
}
olen -= 1;
oappend((const char*)F("],\"n\":"));
oappendi(n);
buf--; // remove last comma
buf += sprintf_P(buf, PSTR("],\"n\":%d"), n);
#ifndef WLED_DISABLE_2D
if (strip.isMatrix) {
oappend((const char*)F(",\"w\":"));
oappendi(Segment::maxWidth/n);
oappend((const char*)F(",\"h\":"));
oappendi(Segment::maxHeight/n);
buf += sprintf_P(buf, PSTR(",\"w\":%d"), Segment::maxWidth/n);
buf += sprintf_P(buf, PSTR(",\"h\":%d"), Segment::maxHeight/n);
}
#endif
oappend("}");
(*buf++) = '}';
(*buf++) = 0;
if (request) {
request->send(200, "application/json", buffer); // contentType defined in AsyncJson-v6.h
request->send(200, FPSTR(CONTENT_TYPE_JSON), toString(std::move(buffer)));
}
#ifdef WLED_ENABLE_WEBSOCKETS
else {
wsc->text(obuf, olen);
wsc->text(toString(std::move(buffer)));
}
#endif
obuf = nullptr;
#endif
return true;
}
#endif

Wyświetl plik

@ -21,8 +21,6 @@
#define DYNAMIC_JSON_DOCUMENT_SIZE 16384
#endif
constexpr const char* JSON_MIMETYPE = "application/json";
/*
* Json Response
* */
@ -66,7 +64,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
AsyncJsonResponse(JsonDocument *ref, bool isArray=false) : _jsonBuffer(1), _isValid{false} {
_code = 200;
_contentType = JSON_MIMETYPE;
_contentType = FPSTR(CONTENT_TYPE_JSON);
if(isArray)
_root = ref->to<JsonArray>();
else
@ -75,7 +73,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
_code = 200;
_contentType = JSON_MIMETYPE;
_contentType = FPSTR(CONTENT_TYPE_JSON);
if(isArray)
_root = _jsonBuffer.createNestedArray();
else

Wyświetl plik

@ -18,36 +18,6 @@ static const char s_unlock_ota [] PROGMEM = "Please unlock OTA in security setti
static const char s_unlock_cfg [] PROGMEM = "Please unlock settings using PIN code!";
static const char s_notimplemented[] PROGMEM = "Not implemented";
static const char s_accessdenied[] PROGMEM = "Access Denied";
static const char s_javascript[] PROGMEM = "application/javascript";
static const char s_json[] = "application/json"; // AsyncJson-v6.h
static const char s_html[] PROGMEM = "text/html";
static const char s_plain[] = "text/plain"; // Espalexa.h
static const char s_css[] PROGMEM = "text/css";
static const char s_png[] PROGMEM = "image/png";
static const char s_gif[] PROGMEM = "image/gif";
static const char s_jpg[] PROGMEM = "image/jpeg";
static const char s_ico[] PROGMEM = "image/x-icon";
//static const char s_xml[] PROGMEM = "text/xml";
//static const char s_pdf[] PROGMEM = "application/x-pdf";
//static const char s_zip[] PROGMEM = "application/x-zip";
//static const char s_gz[] PROGMEM = "application/x-gzip";
String getFileContentType(String &filename) {
if (filename.endsWith(F(".htm"))) return FPSTR(s_html);
else if (filename.endsWith(F(".html"))) return FPSTR(s_html);
else if (filename.endsWith(F(".css"))) return FPSTR(s_css);
else if (filename.endsWith(F(".js"))) return FPSTR(s_javascript);
else if (filename.endsWith(F(".json"))) return s_json;
else if (filename.endsWith(F(".png"))) return FPSTR(s_png);
else if (filename.endsWith(F(".gif"))) return FPSTR(s_gif);
else if (filename.endsWith(F(".jpg"))) return FPSTR(s_jpg);
else if (filename.endsWith(F(".ico"))) return FPSTR(s_ico);
// else if (filename.endsWith(F(".xml"))) return FPSTR(s_xml);
// else if (filename.endsWith(F(".pdf"))) return FPSTR(s_pdf);
// else if (filename.endsWith(F(".zip"))) return FPSTR(s_zip);
// else if (filename.endsWith(F(".gz"))) return FPSTR(s_gz);
return s_plain;
}
//Is this an IP?
static bool isIp(String str) {
@ -183,7 +153,7 @@ static String msgProcessor(const String& var)
static void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
if (!correctPIN) {
if (final) request->send(401, FPSTR(s_plain), FPSTR(s_unlock_cfg));
if (final) request->send(401, FPSTR(CONTENT_TYPE_PLAIN), FPSTR(s_unlock_cfg));
return;
}
if (!index) {
@ -204,10 +174,10 @@ static void handleUpload(AsyncWebServerRequest *request, const String& filename,
request->_tempFile.close();
if (filename.indexOf(F("cfg.json")) >= 0) { // check for filename with or without slash
doReboot = true;
request->send(200, FPSTR(s_plain), F("Configuration restore successful.\nRebooting..."));
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("Configuration restore successful.\nRebooting..."));
} else {
if (filename.indexOf(F("palette")) >= 0 && filename.indexOf(F(".json")) >= 0) strip.loadCustomPalettes();
request->send(200, FPSTR(s_plain), F("File Uploaded!"));
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("File Uploaded!"));
}
cacheInvalidate++;
}
@ -259,24 +229,24 @@ void initServer()
#ifdef WLED_ENABLE_WEBSOCKETS
#ifndef WLED_DISABLE_2D
server.on(SET_F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveviewws2D, PAGE_liveviewws2D_length);
server.on(F("/liveview2D"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveviewws2D, PAGE_liveviewws2D_length);
});
#endif
#endif
server.on(SET_F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_liveview, PAGE_liveview_length);
server.on(F("/liveview"), HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_liveview, PAGE_liveview_length);
});
//settings page
server.on(SET_F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
server.on(F("/settings"), HTTP_GET, [](AsyncWebServerRequest *request){
serveSettings(request);
});
// "/settings/settings.js&p=x" request also handled by serveSettings()
static const char _style_css[] PROGMEM = "/style.css";
server.on(_style_css, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_style_css), 200, FPSTR(s_css), PAGE_settingsCss, PAGE_settingsCss_length);
handleStaticContent(request, FPSTR(_style_css), 200, FPSTR(CONTENT_TYPE_CSS), PAGE_settingsCss, PAGE_settingsCss_length);
});
static const char _favicon_ico[] PROGMEM = "/favicon.ico";
@ -287,28 +257,29 @@ void initServer()
static const char _skin_css[] PROGMEM = "/skin.css";
server.on(_skin_css, HTTP_GET, [](AsyncWebServerRequest *request) {
if (handleFileRead(request, FPSTR(_skin_css))) return;
AsyncWebServerResponse *response = request->beginResponse(200, FPSTR(s_css));
AsyncWebServerResponse *response = request->beginResponse(200, FPSTR(CONTENT_TYPE_CSS));
request->send(response);
});
server.on(SET_F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *request){
server.on(F("/welcome"), HTTP_GET, [](AsyncWebServerRequest *request){
serveSettings(request);
});
server.on(SET_F("/reset"), HTTP_GET, [](AsyncWebServerRequest *request){
server.on(F("/reset"), HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 200,F("Rebooting now..."),F("Please wait ~10 seconds..."),129);
doReboot = true;
});
server.on(SET_F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){
server.on(F("/settings"), HTTP_POST, [](AsyncWebServerRequest *request){
serveSettings(request, true);
});
server.on(SET_F("/json"), HTTP_GET, [](AsyncWebServerRequest *request){
const static char _json[] PROGMEM = "/json";
server.on(FPSTR(_json), HTTP_GET, [](AsyncWebServerRequest *request){
serveJson(request);
});
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(F("/json"), [](AsyncWebServerRequest *request) {
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler(FPSTR(_json), [](AsyncWebServerRequest *request) {
bool verboseResponse = false;
bool isConfig = false;
@ -356,33 +327,33 @@ void initServer()
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
}
}
request->send(200, s_json, F("{\"success\":true}"));
request->send(200, CONTENT_TYPE_JSON, F("{\"success\":true}"));
}, JSON_BUFFER_SIZE);
server.addHandler(handler);
server.on(SET_F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)VERSION);
server.on(F("/version"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)VERSION);
});
server.on(SET_F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)millis());
server.on(F("/uptime"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)millis());
});
server.on(SET_F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(s_plain), (String)ESP.getFreeHeap());
server.on(F("/freeheap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), (String)ESP.getFreeHeap());
});
#ifdef WLED_ENABLE_USERMOD_PAGE
server.on("/u", HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, "", 200, FPSTR(s_html), PAGE_usermod, PAGE_usermod_length);
handleStaticContent(request, "", 200, FPSTR(CONTENT_TYPE_HTML), PAGE_usermod, PAGE_usermod_length);
});
#endif
server.on(SET_F("/teapot"), HTTP_GET, [](AsyncWebServerRequest *request){
server.on(F("/teapot"), HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254);
});
server.on(SET_F("/upload"), HTTP_POST, [](AsyncWebServerRequest *request) {},
server.on(F("/upload"), HTTP_POST, [](AsyncWebServerRequest *request) {},
[](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data,
size_t len, bool final) {handleUpload(request, filename, index, data, len, final);}
);
@ -453,7 +424,7 @@ void initServer()
#ifdef WLED_ENABLE_DMX
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, FPSTR(s_html), PAGE_dmxmap , dmxProcessor);
request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap , dmxProcessor);
});
#else
server.on(SET_F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
@ -464,7 +435,7 @@ void initServer()
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
if (captivePortal(request)) return;
if (!showWelcomePage || request->hasArg(F("sliders"))) {
handleStaticContent(request, F("/index.htm"), 200, FPSTR(s_html), PAGE_index, PAGE_index_L);
handleStaticContent(request, F("/index.htm"), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_index, PAGE_index_L);
} else {
serveSettings(request);
}
@ -473,20 +444,20 @@ void initServer()
#ifdef WLED_ENABLE_PIXART
static const char _pixart_htm[] PROGMEM = "/pixart.htm";
server.on(_pixart_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(s_html), PAGE_pixart, PAGE_pixart_L);
handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pixart, PAGE_pixart_L);
});
#endif
#ifndef WLED_DISABLE_PXMAGIC
static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm";
server.on(_pxmagic_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(s_html), PAGE_pxmagic, PAGE_pxmagic_L);
handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pxmagic, PAGE_pxmagic_L);
});
#endif
static const char _cpal_htm[] PROGMEM = "/cpal.htm";
server.on(_cpal_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(s_html), PAGE_cpal, PAGE_cpal_L);
handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_cpal, PAGE_cpal_L);
});
#ifdef WLED_ENABLE_WEBSOCKETS
@ -511,7 +482,7 @@ void initServer()
#ifndef WLED_DISABLE_ALEXA
if(espalexa.handleAlexaApiCall(request)) return;
#endif
handleStaticContent(request, request->url(), 404, FPSTR(s_html), PAGE_404, PAGE_404_length);
handleStaticContent(request, request->url(), 404, FPSTR(CONTENT_TYPE_HTML), PAGE_404, PAGE_404_length);
});
}
@ -522,7 +493,7 @@ void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& h
messageSub = subl;
optionType = optionT;
request->send_P(code, FPSTR(s_html), PAGE_msg, msgProcessor);
request->send_P(code, FPSTR(CONTENT_TYPE_HTML), PAGE_msg, msgProcessor);
}
@ -530,7 +501,7 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro
{
AsyncJsonResponse *response = new AsyncJsonResponse(64);
if (error < ERR_NOT_IMPL) response->addHeader(F("Retry-After"), F("1"));
response->setContentType(s_json);
response->setContentType(CONTENT_TYPE_JSON);
response->setCode(code);
JsonObject obj = response->getRoot();
obj[F("error")] = error;
@ -546,12 +517,12 @@ void serveSettingsJS(AsyncWebServerRequest* request)
byte subPage = request->arg(F("p")).toInt();
if (subPage > 10) {
strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
request->send(501, FPSTR(s_javascript), buf);
request->send(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
return;
}
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
request->send(401, FPSTR(s_javascript), buf);
request->send(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
return;
}
strcat_P(buf,PSTR("function GetV(){var d=document;"));
@ -559,7 +530,7 @@ void serveSettingsJS(AsyncWebServerRequest* request)
strcat_P(buf,PSTR("}"));
AsyncWebServerResponse *response;
response = request->beginResponse(200, FPSTR(s_javascript), buf);
response = request->beginResponse(200, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
response->addHeader(F("Cache-Control"), F("no-store"));
response->addHeader(F("Expires"), F("0"));
request->send(response);
@ -640,7 +611,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
}
int code = 200;
String contentType = FPSTR(s_html);
String contentType = FPSTR(CONTENT_TYPE_HTML);
const uint8_t* content;
size_t len;
@ -666,7 +637,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) {
return;
}
case SUBPAGE_PINREQ : content = PAGE_settings_pin; len = PAGE_settings_pin_length; code = 401; break;
case SUBPAGE_CSS : content = PAGE_settingsCss; len = PAGE_settingsCss_length; contentType = FPSTR(s_css); break;
case SUBPAGE_CSS : content = PAGE_settingsCss; len = PAGE_settingsCss_length; contentType = FPSTR(CONTENT_TYPE_CSS); break;
case SUBPAGE_JS : serveSettingsJS(request); return;
case SUBPAGE_WELCOME : content = PAGE_welcome; len = PAGE_welcome_length; break;
default: content = PAGE_settings; len = PAGE_settings_length; break;

Wyświetl plik

@ -102,7 +102,6 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
void sendDataWs(AsyncWebSocketClient * client)
{
if (!ws.count()) return;
AsyncWebSocketMessageBuffer * buffer;
if (!requestJSONBufferLock(12)) {
if (client) {
@ -129,7 +128,7 @@ void sendDataWs(AsyncWebSocketClient * client)
return;
}
#endif
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes on ESP8266
AsyncWebSocketBuffer buffer(len);
#ifdef ESP8266
size_t heap2 = ESP.getFreeHeap();
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
@ -141,23 +140,18 @@ void sendDataWs(AsyncWebSocketClient * client)
DEBUG_PRINTLN(F("WS buffer allocation failed."));
ws.closeAll(1013); //code 1013 = temporary overload, try again later
ws.cleanupClients(0); //disconnect all clients to release memory
ws._cleanBuffers();
return; //out of memory
}
buffer->lock();
serializeJson(*pDoc, (char *)buffer->get(), len);
serializeJson(*pDoc, (char *)buffer.data(), len);
DEBUG_PRINT(F("Sending WS data "));
if (client) {
client->text(buffer);
client->text(std::move(buffer));
DEBUG_PRINTLN(F("to a single client."));
} else {
ws.textAll(buffer);
ws.textAll(std::move(buffer));
DEBUG_PRINTLN(F("to multiple clients."));
}
buffer->unlock();
ws._cleanBuffers();
releaseJSONBufferLock();
}
@ -187,11 +181,10 @@ bool sendLiveLedsWs(uint32_t wsClient)
#endif
size_t bufSize = pos + (used/n)*3;
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
AsyncWebSocketBuffer wsBuf(bufSize);
if (!wsBuf) return false; //out of memory
uint8_t* buffer = wsBuf->get();
uint8_t* buffer = reinterpret_cast<uint8_t*>(wsBuf.data());
if (!buffer) return false; //out of memory
wsBuf->lock(); // protect buffer from being cleaned by another WS instance
buffer[0] = 'L';
buffer[1] = 1; //version
@ -218,9 +211,7 @@ bool sendLiveLedsWs(uint32_t wsClient)
buffer[pos++] = scale8(qadd8(w, b), strip.getBrightness()); //B
}
wsc->binary(wsBuf);
wsBuf->unlock(); // un-protect buffer
ws._cleanBuffers();
wsc->binary(std::move(wsBuf));
return true;
}