mirror of https://github.com/arendst/Tasmota.git
Fix memory corruption
This commit is contained in:
parent
c1fd24efc6
commit
f3591b8419
|
@ -1,9 +1,15 @@
|
|||
# JSMN lightweight JSON parser for Tasmota
|
||||
|
||||
Intro:
|
||||
Intro: this library uses the JSMN in-place JSON parser.
|
||||
See https://github.com/zserge/jsmn and https://zserge.com/jsmn/
|
||||
|
||||
It is proposed as a replacement for ArduinoJson. It has less features, does only parsing but does it in a very efficient way.
|
||||
|
||||
## Benefits
|
||||
|
||||
First, the memory impact is very low: 4 bytes per token and no need to add an extra buffer for values.
|
||||
Second, the code is much smaller than ArduinoJson by 5-7KB.
|
||||
|
||||
## How to use
|
||||
|
||||
`{"Device":"0x1234","Power":true,"Temperature":25.5}`
|
||||
|
@ -24,7 +30,8 @@ If what you need is to parse a JSON Object for values with default values:
|
|||
#include "JsonParser.h"
|
||||
|
||||
char json_buffer[] = "{\"Device\":\"0x1234\",\"Power\":true,\"Temperature\":25.6}";
|
||||
JsonParserObject root = JsonParser(json_buffer).getRootObject();
|
||||
JsonParser parser(json_buffer);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { ResponseCmndChar_P(PSTR("Invalid JSON")); return; }
|
||||
|
||||
uint16_t d = root.getUInt(PSTR("DEVICE"), 0xFFFF); // case insensitive
|
||||
|
@ -37,7 +44,8 @@ Alternative pattern, if you want to test the existence of the attribute first:
|
|||
#include "JsonParser.h"
|
||||
|
||||
char json_buffer[] = "{\"Device\":\"0x1234\",\"Power\":true,\"Temperature\":25.6}";
|
||||
JsonParserObject root = JsonParser(json_buffer).getRootObject();
|
||||
JsonParser parser(json_buffer);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { ResponseCmndChar_P(PSTR("Invalid JSON")); return; }
|
||||
|
||||
JsonParserToken val = root[PSTR("DEVICE")];
|
||||
|
@ -54,6 +62,12 @@ if (val) {
|
|||
}
|
||||
```
|
||||
|
||||
WARNING: never use the following form:
|
||||
```
|
||||
JsonParserObject root = JsonParser(json_buffer).getRootObject();
|
||||
```
|
||||
In this case, the `JsonParser` object is temporary and destroyed at the end of the expression. Setting the JsonParser to a local variable ensures that the lifetime of the object is extended to the end of the scope.
|
||||
|
||||
## Types and conversion
|
||||
|
||||
JSMN relies on the concept of JSON Tokens `JsonParserToken`. Tokens do not hold any data, but point to token boundaries in JSON string instead. Every jsmn token has a type, which indicates the type of corresponding JSON token. JSMN for Tasmota extends the type from JSMN to ease further parsing.
|
||||
|
|
|
@ -15,7 +15,7 @@ int main(int argc, char* argv[]) {
|
|||
// char * json_str = test_complex;
|
||||
char * json_str = test_simple;
|
||||
|
||||
JsonParser parser(64); // size for 64 tokens
|
||||
// JsonParser parser(64); // size for 64 tokens
|
||||
|
||||
int r = parser.parse(json_str);
|
||||
|
||||
|
|
|
@ -1473,7 +1473,8 @@ bool JsonTemplate(char* dataBuf)
|
|||
|
||||
if (strlen(dataBuf) < 9) { return false; } // Workaround exception if empty JSON like {} - Needs checks
|
||||
|
||||
JsonParserObject root = JsonParser((char*) dataBuf).getRootObject();
|
||||
JsonParser parser((char*) dataBuf);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { return false; }
|
||||
|
||||
// All parameters are optional allowing for partial changes
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
#define XDRV_01 1
|
||||
|
||||
#include "JsonParser.h"
|
||||
|
||||
#ifndef WIFI_SOFT_AP_CHANNEL
|
||||
#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by WifiManager web GUI
|
||||
#endif
|
||||
|
@ -3366,7 +3364,8 @@ bool JsonWebColor(const char* dataBuf)
|
|||
}
|
||||
}
|
||||
#else
|
||||
JsonParserObject root = JsonParser((char*) dataBuf).getRootObject();
|
||||
JsonParser parser((char*) dataBuf);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
JsonParserArray arr = root[PSTR(D_CMND_WEBCOLOR)].getArray();
|
||||
if (arr) { // if arr is valid, i.e. json is valid, the key D_CMND_WEBCOLOR was found and the token is an arra
|
||||
uint32_t i = 0;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#define XDRV_05 5
|
||||
|
||||
#include <IRremoteESP8266.h>
|
||||
#include "JsonParser.h"
|
||||
|
||||
enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND };
|
||||
|
||||
|
@ -204,7 +203,8 @@ uint32_t IrRemoteCmndIrSendJson(void)
|
|||
uint16_t repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT))];
|
||||
#else
|
||||
RemoveSpace(XdrvMailbox.data); // TODO is this really needed?
|
||||
JsonParserObject root = JsonParser((char*) XdrvMailbox.data).getRootObject();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { return IE_INVALID_JSON; }
|
||||
|
||||
// IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 }
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <IRrecv.h>
|
||||
#include <IRutils.h>
|
||||
#include <IRac.h>
|
||||
#include "JsonParser.h"
|
||||
|
||||
enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC,
|
||||
IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL };
|
||||
|
@ -288,7 +287,8 @@ uint32_t IrRemoteCmndIrHvacJson(void)
|
|||
stdAc::state_t state, prev;
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received %s"), XdrvMailbox.data);
|
||||
JsonParserObject root = JsonParser((char*) XdrvMailbox.data).getRootObject();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { return IE_INVALID_JSON; }
|
||||
|
||||
// from: https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/CommonAcControl/CommonAcControl.ino
|
||||
|
|
|
@ -425,7 +425,8 @@ void CmndTimer(void)
|
|||
#if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0
|
||||
if (devices_present) {
|
||||
#endif
|
||||
JsonParserObject root = JsonParser(XdrvMailbox.data).getRootObject();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) {
|
||||
Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); // JSON decode failed
|
||||
error = 1;
|
||||
|
|
|
@ -532,7 +532,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
|
|||
#else
|
||||
|
||||
String buf = event; // copy the string into a new buffer that will be modified
|
||||
JsonParser parser = JsonParser((char*)buf.c_str());
|
||||
JsonParser parser((char*)buf.c_str());
|
||||
JsonParserObject obj = parser.getRootObject();
|
||||
if (!obj) {
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Event too long (%d)"), event.length());
|
||||
|
@ -1069,7 +1069,8 @@ bool RulesMqttData(void)
|
|||
if (event_item.Key.length() == 0) { //If did not specify Key
|
||||
value = sData;
|
||||
} else { //If specified Key, need to parse Key/Value from JSON data
|
||||
JsonParserObject jsonData = JsonParser((char*)sData.c_str()).getRootObject();
|
||||
JsonParser parser((char*)sData.c_str());
|
||||
JsonParserObject jsonData = parser.getRootObject();
|
||||
|
||||
String key1 = event_item.Key;
|
||||
String key2;
|
||||
|
|
|
@ -104,7 +104,8 @@ void CmndRfSend(void)
|
|||
int repeat = 10;
|
||||
int pulse = 350;
|
||||
|
||||
JsonParserObject root = JsonParser(XdrvMailbox.data).getRootObject();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (root) {
|
||||
// RFsend {"data":0x501014,"bits":24,"protocol":1,"repeat":10,"pulse":350}
|
||||
char parm_uc[10];
|
||||
|
|
|
@ -569,7 +569,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) {
|
|||
if (Webserver->args()) {
|
||||
response = "[";
|
||||
|
||||
JsonParser parser = JsonParser((char*) Webserver->arg((Webserver->args())-1).c_str());
|
||||
JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str());
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
|
||||
JsonParserToken hue_on = root[PSTR("on")];
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
#ifdef USE_ZIGBEE
|
||||
|
||||
#include "JsonParser.h"
|
||||
|
||||
#ifndef ZIGBEE_SAVE_DELAY_SECONDS
|
||||
#define ZIGBEE_SAVE_DELAY_SECONDS 2 // wait for 2s before saving Zigbee info
|
||||
#endif
|
||||
|
|
|
@ -218,7 +218,7 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) {
|
|||
if (Webserver->args()) {
|
||||
response = "[";
|
||||
|
||||
JsonParser parser = JsonParser((char*) Webserver->arg((Webserver->args())-1).c_str());
|
||||
JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str());
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
|
||||
JsonParserToken hue_on = root[PSTR("on")];
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
#define XDRV_23 23
|
||||
|
||||
#include "JsonParser.h"
|
||||
|
||||
const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEEZNPRECEIVE "|"
|
||||
|
@ -626,7 +624,8 @@ void CmndZbSend(void) {
|
|||
// ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Color":"1,2"} }
|
||||
// ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Color":"0x1122,0xFFEE"} }
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
JsonParserObject root = JsonParser(XdrvMailbox.data).getRootObject();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
|
||||
|
||||
// params
|
||||
|
@ -748,7 +747,8 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
|||
|
||||
// local endpoint is always 1, IEEE addresses are calculated
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
JsonParserObject root = JsonParser(XdrvMailbox.data).getRootObject();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
|
||||
|
||||
// params
|
||||
|
@ -1064,8 +1064,8 @@ void CmndZbSave(void) {
|
|||
// ZbRestore {"Device":"0x5ADF","Name":"Petite_Lampe","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]}
|
||||
void CmndZbRestore(void) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
JsonParser p(XdrvMailbox.data);
|
||||
JsonParserToken root = p.getRoot();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserToken root = parser.getRoot();
|
||||
|
||||
if (!p || !(root.isObject() || root.isArray())) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
|
||||
|
||||
|
@ -1219,7 +1219,8 @@ void CmndZbConfig(void) {
|
|||
// if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
RemoveAllSpaces(XdrvMailbox.data);
|
||||
if (strlen(XdrvMailbox.data) > 0) {
|
||||
JsonParserObject root = JsonParser(XdrvMailbox.data).getRootObject();
|
||||
JsonParser parser(XdrvMailbox.data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
|
||||
// Channel
|
||||
|
||||
|
|
|
@ -1328,7 +1328,8 @@ void ThermostatDebug(uint8_t ctr_output)
|
|||
#endif // DEBUG_THERMOSTAT
|
||||
|
||||
void ThermostatGetLocalSensor(uint8_t ctr_output) {
|
||||
JsonParserObject root = JsonParser(mqtt_data).getRootObject();
|
||||
JsonParser parser(mqtt_data);
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (root) {
|
||||
JsonParserToken value_token = root[PSTR(THERMOSTAT_SENSOR_NAME)].getObject()[PSTR("Temperature")];
|
||||
if (value_token.isNum()) {
|
||||
|
|
|
@ -226,7 +226,8 @@ void TelegramAnalizeMessage(void) {
|
|||
Telegram.message[i][5] = "";
|
||||
|
||||
String buf = Telegram.message[i][0]; // we need to keep a copy of the buffer
|
||||
JsonParserObject root = JsonParser((char*)buf.c_str()).getRootObject();
|
||||
JsonParser parser((char*)buf.c_str());
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (root) {
|
||||
Telegram.message[i][0] = root["update_id"].getStr();
|
||||
Telegram.message[i][1] = root["message"].getObject()["from"].getObject()["id"].getStr();
|
||||
|
|
Loading…
Reference in New Issue