mirror of
https://github.com/wled/WLED.git
synced 2025-07-15 23:06:36 +00:00
Remove oappend
Remove the large stack buffer as we're just going to copy it in to a heap buffer anyways. Later we can refine the length estimation or use a rope-style dynamic data structure like DynamicBufferList.
This commit is contained in:
parent
1346eb4f76
commit
32f9616b6e
@ -302,7 +302,7 @@ class Usermod {
|
|||||||
virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
|
virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
|
||||||
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
|
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
|
||||||
virtual void connected() {} // called when WiFi is (re)connected
|
virtual void connected() {} // called when WiFi is (re)connected
|
||||||
virtual void appendConfigData() {} // helper function called from usermod settings page to add metadata for entry fields
|
virtual void appendConfigData(Print&) {} // helper function called from usermod settings page to add metadata for entry fields
|
||||||
virtual void addToJsonState(JsonObject& obj) {} // add JSON objects for WLED state
|
virtual void addToJsonState(JsonObject& obj) {} // add JSON objects for WLED state
|
||||||
virtual void addToJsonInfo(JsonObject& obj) {} // add JSON objects for UI Info page
|
virtual void addToJsonInfo(JsonObject& obj) {} // add JSON objects for UI Info page
|
||||||
virtual void readFromJsonState(JsonObject& obj) {} // process JSON messages received from web server
|
virtual void readFromJsonState(JsonObject& obj) {} // process JSON messages received from web server
|
||||||
@ -328,7 +328,7 @@ class UsermodManager {
|
|||||||
bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods
|
bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods
|
||||||
void setup();
|
void setup();
|
||||||
void connected();
|
void connected();
|
||||||
void appendConfigData();
|
void appendConfigData(Print&);
|
||||||
void addToJsonState(JsonObject& obj);
|
void addToJsonState(JsonObject& obj);
|
||||||
void addToJsonInfo(JsonObject& obj);
|
void addToJsonInfo(JsonObject& obj);
|
||||||
void readFromJsonState(JsonObject& obj);
|
void readFromJsonState(JsonObject& obj);
|
||||||
@ -362,10 +362,8 @@ void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255);
|
|||||||
bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255);
|
bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255);
|
||||||
bool getBoolVal(JsonVariant elem, bool dflt);
|
bool getBoolVal(JsonVariant elem, bool dflt);
|
||||||
bool updateVal(const char* req, const char* key, byte* val, byte minv=0, byte maxv=255);
|
bool updateVal(const char* req, const char* key, byte* val, byte minv=0, byte maxv=255);
|
||||||
bool oappend(const char* txt); // append new c string to temp buffer efficiently
|
void sappend(Print& dest, char stype, const char* key, int val);
|
||||||
bool oappendi(int i); // append new number to temp buffer efficiently
|
void sappends(Print& dest, char stype, const char* key, char* val);
|
||||||
void sappend(char stype, const char* key, int val);
|
|
||||||
void sappends(char stype, const char* key, char* val);
|
|
||||||
void prepareHostname(char* hostname);
|
void prepareHostname(char* hostname);
|
||||||
bool isAsterisksOnly(const char* str, byte maxLen);
|
bool isAsterisksOnly(const char* str, byte maxLen);
|
||||||
bool requestJSONBufferLock(uint8_t module=255);
|
bool requestJSONBufferLock(uint8_t module=255);
|
||||||
@ -444,7 +442,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
void sendDataWs(AsyncWebSocketClient * client = nullptr);
|
void sendDataWs(AsyncWebSocketClient * client = nullptr);
|
||||||
|
|
||||||
//xml.cpp
|
//xml.cpp
|
||||||
void XML_response(AsyncWebServerRequest *request, char* dest = nullptr);
|
void XML_response(Print& dest);
|
||||||
void getSettingsJS(byte subPage, char* dest);
|
void getSettingsJS(byte subPage, Print& dest);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -124,6 +124,32 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp
|
|||||||
payloadStr = nullptr;
|
payloadStr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print adapter for flat buffers
|
||||||
|
namespace {
|
||||||
|
class bufferPrint : public Print {
|
||||||
|
char* _buf;
|
||||||
|
size_t _size, _offset;
|
||||||
|
public:
|
||||||
|
|
||||||
|
bufferPrint(char* buf, size_t size) : _buf(buf), _size(size), _offset(0) {};
|
||||||
|
|
||||||
|
size_t write(const uint8_t *buffer, size_t size) {
|
||||||
|
size = std::min(size, _size - _offset);
|
||||||
|
memcpy(_buf + _offset, buffer, size);
|
||||||
|
_offset += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write(uint8_t c) {
|
||||||
|
return this->write(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* data() const { return _buf; }
|
||||||
|
size_t size() const { return _offset; }
|
||||||
|
size_t capacity() const { return _size; }
|
||||||
|
};
|
||||||
|
}; // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
void publishMqtt()
|
void publishMqtt()
|
||||||
{
|
{
|
||||||
@ -148,11 +174,13 @@ void publishMqtt()
|
|||||||
strcat_P(subuf, PSTR("/status"));
|
strcat_P(subuf, PSTR("/status"));
|
||||||
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
|
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
|
||||||
|
|
||||||
char apires[1024]; // allocating 1024 bytes from stack can be risky
|
// TODO: use a DynamicBufferList. Requires a list-read-capable MQTT client API.
|
||||||
XML_response(nullptr, apires);
|
DynamicBuffer buf(1024);
|
||||||
|
bufferPrint pbuf(buf.data(), buf.size());
|
||||||
|
XML_response(pbuf);
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
strcat_P(subuf, PSTR("/v"));
|
strcat_P(subuf, PSTR("/v"));
|
||||||
mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263)
|
mqtt->publish(subuf, 0, retainMqttMsg, buf.data(), pbuf.size()); // optionally retain message (#2263)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1191,7 +1191,11 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
|
|
||||||
// internal call, does not send XML response
|
// internal call, does not send XML response
|
||||||
pos = req.indexOf(F("IN"));
|
pos = req.indexOf(F("IN"));
|
||||||
if (pos < 1) XML_response(request);
|
if (pos < 1) {
|
||||||
|
auto response = request->beginResponseStream("text/xml");
|
||||||
|
XML_response(*response);
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ void UsermodManager::setup() { for (unsigned i = 0; i < numMods; i++
|
|||||||
void UsermodManager::connected() { for (unsigned i = 0; i < numMods; i++) ums[i]->connected(); }
|
void UsermodManager::connected() { for (unsigned i = 0; i < numMods; i++) ums[i]->connected(); }
|
||||||
void UsermodManager::loop() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop(); }
|
void UsermodManager::loop() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop(); }
|
||||||
void UsermodManager::handleOverlayDraw() { for (unsigned i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); }
|
void UsermodManager::handleOverlayDraw() { for (unsigned i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); }
|
||||||
void UsermodManager::appendConfigData() { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(); }
|
void UsermodManager::appendConfigData(Print& dest) { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(dest); }
|
||||||
bool UsermodManager::handleButton(uint8_t b) {
|
bool UsermodManager::handleButton(uint8_t b) {
|
||||||
bool overrideIO = false;
|
bool overrideIO = false;
|
||||||
for (unsigned i = 0; i < numMods; i++) {
|
for (unsigned i = 0; i < numMods; i++) {
|
||||||
|
@ -89,88 +89,43 @@ bool updateVal(const char* req, const char* key, byte* val, byte minv, byte maxv
|
|||||||
|
|
||||||
|
|
||||||
//append a numeric setting to string buffer
|
//append a numeric setting to string buffer
|
||||||
void sappend(char stype, const char* key, int val)
|
void sappend(Print& dest, char stype, const char* key, int val)
|
||||||
{
|
{
|
||||||
char ds[] = "d.Sf.";
|
const __FlashStringHelper* type_str;
|
||||||
|
|
||||||
switch(stype)
|
switch(stype)
|
||||||
{
|
{
|
||||||
case 'c': //checkbox
|
case 'c': //checkbox
|
||||||
oappend(ds);
|
type_str = F(".checked=");
|
||||||
oappend(key);
|
|
||||||
oappend(".checked=");
|
|
||||||
oappendi(val);
|
|
||||||
oappend(";");
|
|
||||||
break;
|
break;
|
||||||
case 'v': //numeric
|
case 'v': //numeric
|
||||||
oappend(ds);
|
type_str = F(".value=");
|
||||||
oappend(key);
|
|
||||||
oappend(".value=");
|
|
||||||
oappendi(val);
|
|
||||||
oappend(";");
|
|
||||||
break;
|
break;
|
||||||
case 'i': //selectedIndex
|
case 'i': //selectedIndex
|
||||||
oappend(ds);
|
type_str = F(".selectedIndex=");
|
||||||
oappend(key);
|
|
||||||
oappend(SET_F(".selectedIndex="));
|
|
||||||
oappendi(val);
|
|
||||||
oappend(";");
|
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return; //???
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dest.printf_P(PSTR("d.Sf.%s%s%d;"), key, type_str, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//append a string setting to buffer
|
//append a string setting to buffer
|
||||||
void sappends(char stype, const char* key, char* val)
|
void sappends(Print& dest, char stype, const char* key, char* val)
|
||||||
{
|
{
|
||||||
switch(stype)
|
switch(stype)
|
||||||
{
|
{
|
||||||
case 's': {//string (we can interpret val as char*)
|
case 's': {//string (we can interpret val as char*)
|
||||||
String buf = val;
|
dest.printf_P(PSTR("d.Sf.%s.value=\"%s\";"),key,val);
|
||||||
//convert "%" to "%%" to make EspAsyncWebServer happy
|
|
||||||
//buf.replace("%","%%");
|
|
||||||
oappend("d.Sf.");
|
|
||||||
oappend(key);
|
|
||||||
oappend(".value=\"");
|
|
||||||
oappend(buf.c_str());
|
|
||||||
oappend("\";");
|
|
||||||
break;}
|
break;}
|
||||||
case 'm': //message
|
case 'm': //message
|
||||||
oappend(SET_F("d.getElementsByClassName"));
|
dest.printf_P(PSTR("d.getElementsByClassName%s.innerHTML=\"%s\";"), key, val);
|
||||||
oappend(key);
|
|
||||||
oappend(SET_F(".innerHTML=\""));
|
|
||||||
oappend(val);
|
|
||||||
oappend("\";");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool oappendi(int i)
|
|
||||||
{
|
|
||||||
char s[12]; // 32bit signed number can have 10 digits plus - sign
|
|
||||||
sprintf(s, "%d", i);
|
|
||||||
return oappend(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool oappend(const char* txt)
|
|
||||||
{
|
|
||||||
unsigned len = strlen(txt);
|
|
||||||
if ((obuf == nullptr) || (olen + len >= SETTINGS_STACK_BUF_SIZE)) { // sanity checks
|
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
DEBUG_PRINT(F("oappend() buffer overflow. Cannot append "));
|
|
||||||
DEBUG_PRINT(len); DEBUG_PRINT(F(" bytes \t\""));
|
|
||||||
DEBUG_PRINT(txt); DEBUG_PRINTLN(F("\""));
|
|
||||||
#endif
|
|
||||||
return false; // buffer full
|
|
||||||
}
|
|
||||||
strcpy(obuf + olen, txt);
|
|
||||||
olen += len;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void prepareHostname(char* hostname)
|
void prepareHostname(char* hostname)
|
||||||
{
|
{
|
||||||
sprintf_P(hostname, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
|
sprintf_P(hostname, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
|
||||||
|
@ -839,10 +839,6 @@ WLED_GLOBAL time_t sunrise _INIT(0);
|
|||||||
WLED_GLOBAL time_t sunset _INIT(0);
|
WLED_GLOBAL time_t sunset _INIT(0);
|
||||||
WLED_GLOBAL Toki toki _INIT(Toki());
|
WLED_GLOBAL Toki toki _INIT(Toki());
|
||||||
|
|
||||||
// Temp buffer
|
|
||||||
WLED_GLOBAL char* obuf;
|
|
||||||
WLED_GLOBAL uint16_t olen _INIT(0);
|
|
||||||
|
|
||||||
// General filesystem
|
// General filesystem
|
||||||
WLED_GLOBAL size_t fsBytesUsed _INIT(0);
|
WLED_GLOBAL size_t fsBytesUsed _INIT(0);
|
||||||
WLED_GLOBAL size_t fsBytesTotal _INIT(0);
|
WLED_GLOBAL size_t fsBytesTotal _INIT(0);
|
||||||
|
@ -520,27 +520,23 @@ void serveSettingsJS(AsyncWebServerRequest* request)
|
|||||||
handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length);
|
handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char buf[SETTINGS_STACK_BUF_SIZE+37];
|
|
||||||
buf[0] = 0;
|
|
||||||
byte subPage = request->arg(F("p")).toInt();
|
byte subPage = request->arg(F("p")).toInt();
|
||||||
if (subPage > 10) {
|
if (subPage > 10) {
|
||||||
strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
|
request->send_P(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), PSTR("alert('Settings for this request are not implemented.');"));
|
||||||
request->send(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
|
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
|
||||||
strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
|
request->send_P(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), PSTR("alert('PIN incorrect.');"));
|
||||||
request->send(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
strcat_P(buf,PSTR("function GetV(){var d=document;"));
|
|
||||||
getSettingsJS(subPage, buf+strlen(buf)); // this may overflow by 35bytes!!!
|
|
||||||
strcat_P(buf,PSTR("}"));
|
|
||||||
|
|
||||||
AsyncWebServerResponse *response;
|
AsyncResponseStream *response = request->beginResponseStream(FPSTR(CONTENT_TYPE_JAVASCRIPT));
|
||||||
response = request->beginResponse(200, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf);
|
|
||||||
response->addHeader(F("Cache-Control"), F("no-store"));
|
response->addHeader(F("Cache-Control"), F("no-store"));
|
||||||
response->addHeader(F("Expires"), F("0"));
|
response->addHeader(F("Expires"), F("0"));
|
||||||
|
|
||||||
|
response->print(F("function GetV(){var d=document;"));
|
||||||
|
getSettingsJS(subPage, *response);
|
||||||
|
response->print(F("}"));
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
772
wled00/xml.cpp
772
wled00/xml.cpp
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user