mirror of https://github.com/arendst/Tasmota.git
Add wildcard patter for JSON marching in rules using ``?`` pattern
This commit is contained in:
parent
054850ef0b
commit
f5f1bdefdb
|
@ -6,6 +6,7 @@
|
||||||
- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]``
|
- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]``
|
||||||
- Add Three Phase Export Active Energy to SDM630 driver
|
- Add Three Phase Export Active Energy to SDM630 driver
|
||||||
- Add commands ``LedPwmOn 0..255``, ``LedPwmOff 0..255`` and ``LedPwmMode1 0/1`` to control led brightness by George (#8491)
|
- Add commands ``LedPwmOn 0..255``, ``LedPwmOff 0..255`` and ``LedPwmMode1 0/1`` to control led brightness by George (#8491)
|
||||||
|
- Add wildcard patter for JSON marching in rules using ``?`` pattern
|
||||||
|
|
||||||
### 8.3.1.1 20200518
|
### 8.3.1.1 20200518
|
||||||
|
|
||||||
|
|
|
@ -1874,65 +1874,6 @@ void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32
|
||||||
AddLog(loglevel);
|
AddLog(loglevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* JSON parsing
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
// does the character needs to be escaped, and if so with which character
|
|
||||||
char escapeJSONChar(char c) {
|
|
||||||
if ((c == '\"') || (c == '\\')) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
if (c == '\n') { return 'n'; }
|
|
||||||
if (c == '\t') { return 't'; }
|
|
||||||
if (c == '\r') { return 'r'; }
|
|
||||||
if (c == '\f') { return 'f'; }
|
|
||||||
if (c == '\b') { return 'b'; }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
String escapeJSONString(const char *str) {
|
|
||||||
String r("");
|
|
||||||
if (nullptr == str) { return r; }
|
|
||||||
|
|
||||||
bool needs_escape = false;
|
|
||||||
size_t len_out = 1;
|
|
||||||
const char * c = str;
|
|
||||||
|
|
||||||
while (*c) {
|
|
||||||
if (escapeJSONChar(*c)) {
|
|
||||||
len_out++;
|
|
||||||
needs_escape = true;
|
|
||||||
}
|
|
||||||
c++;
|
|
||||||
len_out++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needs_escape) {
|
|
||||||
// we need to escape some chars
|
|
||||||
// allocate target buffer
|
|
||||||
r.reserve(len_out);
|
|
||||||
c = str;
|
|
||||||
char *d = r.begin();
|
|
||||||
while (*c) {
|
|
||||||
char c2 = escapeJSONChar(*c);
|
|
||||||
if (c2) {
|
|
||||||
c++;
|
|
||||||
*d++ = '\\';
|
|
||||||
*d++ = c2;
|
|
||||||
} else {
|
|
||||||
*d++ = *c++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*d = 0; // add NULL terminator
|
|
||||||
r = (char*) r.begin(); // assign the buffer to the string
|
|
||||||
} else {
|
|
||||||
r = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Uncompress static PROGMEM strings
|
* Uncompress static PROGMEM strings
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
support_json.ino - Static binary buffer for Zigbee on Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2020 Theo Arends and Stephan Hadinger
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* JSON parsing
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
// does the character needs to be escaped, and if so with which character
|
||||||
|
char EscapeJSONChar(char c) {
|
||||||
|
if ((c == '\"') || (c == '\\')) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
if (c == '\n') { return 'n'; }
|
||||||
|
if (c == '\t') { return 't'; }
|
||||||
|
if (c == '\r') { return 'r'; }
|
||||||
|
if (c == '\f') { return 'f'; }
|
||||||
|
if (c == '\b') { return 'b'; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String EscapeJSONString(const char *str) {
|
||||||
|
String r("");
|
||||||
|
if (nullptr == str) { return r; }
|
||||||
|
|
||||||
|
bool needs_escape = false;
|
||||||
|
size_t len_out = 1;
|
||||||
|
const char * c = str;
|
||||||
|
|
||||||
|
while (*c) {
|
||||||
|
if (EscapeJSONChar(*c)) {
|
||||||
|
len_out++;
|
||||||
|
needs_escape = true;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
len_out++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needs_escape) {
|
||||||
|
// we need to escape some chars
|
||||||
|
// allocate target buffer
|
||||||
|
r.reserve(len_out);
|
||||||
|
c = str;
|
||||||
|
char *d = r.begin();
|
||||||
|
while (*c) {
|
||||||
|
char c2 = EscapeJSONChar(*c);
|
||||||
|
if (c2) {
|
||||||
|
c++;
|
||||||
|
*d++ = '\\';
|
||||||
|
*d++ = c2;
|
||||||
|
} else {
|
||||||
|
*d++ = *c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*d = 0; // add NULL terminator
|
||||||
|
r = (char*) r.begin(); // assign the buffer to the string
|
||||||
|
} else {
|
||||||
|
r = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Find key - case insensitive
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
// Given a JsonObject, finds the value as JsonVariant for the key needle.
|
||||||
|
// The search is case-insensitive, and will find the first match in the order of keys in JSON
|
||||||
|
//
|
||||||
|
// If the key is not found, returns a nullptr
|
||||||
|
// Input: needle cannot be NULL but may be PROGMEM
|
||||||
|
const JsonVariant &GetCaseInsensitive(const JsonObject &json, const char *needle) {
|
||||||
|
// key can be in PROGMEM
|
||||||
|
// if needle == "?" then we return the first valid key
|
||||||
|
bool wildcard = strcmp_P("?", needle) == 0;
|
||||||
|
if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) {
|
||||||
|
return *(JsonVariant*)nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JsonObject::const_iterator it=json.begin(); it!=json.end(); ++it) {
|
||||||
|
const char *key = it->key;
|
||||||
|
const JsonVariant &value = it->value;
|
||||||
|
|
||||||
|
if (wildcard || (0 == strcasecmp_P(key, needle))) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if not found
|
||||||
|
return *(JsonVariant*)nullptr;
|
||||||
|
}
|
|
@ -441,25 +441,20 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%TIME%%"));
|
if (rule_param.startsWith(F("%TIME%"))) {
|
||||||
if (rule_param.startsWith(stemp)) {
|
|
||||||
rule_param = String(MinutesPastMidnight());
|
rule_param = String(MinutesPastMidnight());
|
||||||
}
|
}
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%UPTIME%%"));
|
if (rule_param.startsWith(F("%UPTIME%"))) {
|
||||||
if (rule_param.startsWith(stemp)) {
|
|
||||||
rule_param = String(MinutesUptime());
|
rule_param = String(MinutesUptime());
|
||||||
}
|
}
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%TIMESTAMP%%"));
|
if (rule_param.startsWith(F("%TIMESTAMP%"))) {
|
||||||
if (rule_param.startsWith(stemp)) {
|
|
||||||
rule_param = GetDateAndTime(DT_LOCAL).c_str();
|
rule_param = GetDateAndTime(DT_LOCAL).c_str();
|
||||||
}
|
}
|
||||||
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
|
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNRISE%%"));
|
if (rule_param.startsWith(F("%SUNRISE%"))) {
|
||||||
if (rule_param.startsWith(stemp)) {
|
|
||||||
rule_param = String(SunMinutes(0));
|
rule_param = String(SunMinutes(0));
|
||||||
}
|
}
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNSET%%"));
|
if (rule_param.startsWith(F("%SUNSET%"))) {
|
||||||
if (rule_param.startsWith(stemp)) {
|
|
||||||
rule_param = String(SunMinutes(1));
|
rule_param = String(SunMinutes(1));
|
||||||
}
|
}
|
||||||
#endif // USE_TIMERS and USE_SUNRISE
|
#endif // USE_TIMERS and USE_SUNRISE
|
||||||
|
@ -493,13 +488,17 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while ((pos = rule_name.indexOf("#")) > 0) { // "SUBTYPE1#SUBTYPE2#CURRENT"
|
while ((pos = rule_name.indexOf("#")) > 0) { // "SUBTYPE1#SUBTYPE2#CURRENT"
|
||||||
subtype = rule_name.substring(0, pos);
|
subtype = rule_name.substring(0, pos);
|
||||||
if (!(*obj)[subtype].success()) { return false; } // No subtype in JSON data
|
const JsonVariant & val = GetCaseInsensitive(*obj, subtype.c_str());
|
||||||
JsonObject &obj2 = (*obj)[subtype];
|
if (nullptr == &val) { return false; } // not found
|
||||||
obj = &obj2;
|
obj = &(val.as<JsonObject>());
|
||||||
|
if (!obj->success()) { return false; } // not a JsonObject
|
||||||
|
|
||||||
rule_name = rule_name.substring(pos +1);
|
rule_name = rule_name.substring(pos +1);
|
||||||
if (i++ > 10) { return false; } // Abandon possible loop
|
if (i++ > 10) { return false; } // Abandon possible loop
|
||||||
}
|
}
|
||||||
if (!(*obj)[rule_name].success()) { return false; } // No name in JSON data
|
|
||||||
|
const JsonVariant & val = GetCaseInsensitive(*obj, rule_name.c_str());
|
||||||
|
if (nullptr == &val) { return false; } // last level not found
|
||||||
const char* str_value;
|
const char* str_value;
|
||||||
if (rule_name_idx) {
|
if (rule_name_idx) {
|
||||||
str_value = (*obj)[rule_name][rule_name_idx -1]; // "CURRENT[1]"
|
str_value = (*obj)[rule_name][rule_name_idx -1]; // "CURRENT[1]"
|
||||||
|
@ -2036,7 +2035,7 @@ void CmndRule(void)
|
||||||
XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)),
|
XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)),
|
||||||
GetStateText(bitRead(Settings.rule_stop, index -1)),
|
GetStateText(bitRead(Settings.rule_stop, index -1)),
|
||||||
rule_len, MAX_RULE_SIZE - GetRuleLenStorage(index - 1),
|
rule_len, MAX_RULE_SIZE - GetRuleLenStorage(index - 1),
|
||||||
escapeJSONString(rule.c_str()).c_str());
|
EscapeJSONString(rule.c_str()).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -437,8 +437,8 @@ void HueLightStatus2(uint8_t device, String *response)
|
||||||
fname[fname_len] = 0x00;
|
fname[fname_len] = 0x00;
|
||||||
}
|
}
|
||||||
snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2,
|
snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2,
|
||||||
escapeJSONString(fname).c_str(),
|
EscapeJSONString(fname).c_str(),
|
||||||
escapeJSONString(Settings.user_template_name).c_str(),
|
EscapeJSONString(Settings.user_template_name).c_str(),
|
||||||
PSTR("Tasmota"),
|
PSTR("Tasmota"),
|
||||||
GetHueDeviceId(device).c_str());
|
GetHueDeviceId(device).c_str());
|
||||||
*response += buf;
|
*response += buf;
|
||||||
|
|
|
@ -23,29 +23,9 @@
|
||||||
|
|
||||||
void ZigbeeZCLSend_Raw(uint16_t dtsAddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId);
|
void ZigbeeZCLSend_Raw(uint16_t dtsAddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId);
|
||||||
|
|
||||||
|
|
||||||
// Get an JSON attribute, with case insensitive key search
|
|
||||||
const JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) {
|
|
||||||
// key can be in PROGMEM
|
|
||||||
if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) {
|
|
||||||
return *(JsonVariant*)nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JsonObject::const_iterator it=json.begin(); it!=json.end(); ++it) {
|
|
||||||
const char *key = it->key;
|
|
||||||
const JsonVariant &value = it->value;
|
|
||||||
|
|
||||||
if (0 == strcasecmp_P(key, needle)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if not found
|
|
||||||
return *(JsonVariant*)nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the result as a string (const char*) and nullptr if there is no field or the string is empty
|
// get the result as a string (const char*) and nullptr if there is no field or the string is empty
|
||||||
const char * getCaseInsensitiveConstCharNull(const JsonObject &json, const char *needle) {
|
const char * getCaseInsensitiveConstCharNull(const JsonObject &json, const char *needle) {
|
||||||
const JsonVariant &val = getCaseInsensitive(json, needle);
|
const JsonVariant &val = GetCaseInsensitive(json, needle);
|
||||||
if (&val) {
|
if (&val) {
|
||||||
const char *val_cs = val.as<const char*>();
|
const char *val_cs = val.as<const char*>();
|
||||||
if (strlen(val_cs)) {
|
if (strlen(val_cs)) {
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ int32_t Z_Devices::deviceRestore(const JsonObject &json) {
|
||||||
size_t endpoints_len = 0;
|
size_t endpoints_len = 0;
|
||||||
|
|
||||||
// read mandatory "Device"
|
// read mandatory "Device"
|
||||||
const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device"));
|
const JsonVariant &val_device = GetCaseInsensitive(json, PSTR("Device"));
|
||||||
if (nullptr != &val_device) {
|
if (nullptr != &val_device) {
|
||||||
device = strToUInt(val_device);
|
device = strToUInt(val_device);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1083,7 +1083,7 @@ int32_t Z_Devices::deviceRestore(const JsonObject &json) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read "IEEEAddr" 64 bits in format "0x0000000000000000"
|
// read "IEEEAddr" 64 bits in format "0x0000000000000000"
|
||||||
const JsonVariant &val_ieeeaddr = getCaseInsensitive(json, PSTR("IEEEAddr"));
|
const JsonVariant &val_ieeeaddr = GetCaseInsensitive(json, PSTR("IEEEAddr"));
|
||||||
if (nullptr != &val_ieeeaddr) {
|
if (nullptr != &val_ieeeaddr) {
|
||||||
ieeeaddr = strtoull(val_ieeeaddr.as<const char*>(), nullptr, 0);
|
ieeeaddr = strtoull(val_ieeeaddr.as<const char*>(), nullptr, 0);
|
||||||
}
|
}
|
||||||
|
@ -1098,7 +1098,7 @@ int32_t Z_Devices::deviceRestore(const JsonObject &json) {
|
||||||
manufid = getCaseInsensitiveConstCharNull(json, PSTR("Manufacturer"));
|
manufid = getCaseInsensitiveConstCharNull(json, PSTR("Manufacturer"));
|
||||||
|
|
||||||
// read "Light"
|
// read "Light"
|
||||||
const JsonVariant &val_bulbtype = getCaseInsensitive(json, PSTR(D_JSON_ZIGBEE_LIGHT));
|
const JsonVariant &val_bulbtype = GetCaseInsensitive(json, PSTR(D_JSON_ZIGBEE_LIGHT));
|
||||||
if (nullptr != &val_bulbtype) { bulbtype = strToUInt(val_bulbtype);; }
|
if (nullptr != &val_bulbtype) { bulbtype = strToUInt(val_bulbtype);; }
|
||||||
|
|
||||||
// update internal device information
|
// update internal device information
|
||||||
|
@ -1109,7 +1109,7 @@ int32_t Z_Devices::deviceRestore(const JsonObject &json) {
|
||||||
if (&val_bulbtype) { setHueBulbtype(device, bulbtype); }
|
if (&val_bulbtype) { setHueBulbtype(device, bulbtype); }
|
||||||
|
|
||||||
// read "Endpoints"
|
// read "Endpoints"
|
||||||
const JsonVariant &val_endpoints = getCaseInsensitive(json, PSTR("Endpoints"));
|
const JsonVariant &val_endpoints = GetCaseInsensitive(json, PSTR("Endpoints"));
|
||||||
if ((nullptr != &val_endpoints) && (val_endpoints.is<JsonArray>())) {
|
if ((nullptr != &val_endpoints) && (val_endpoints.is<JsonArray>())) {
|
||||||
const JsonArray &arr_ep = val_endpoints.as<const JsonArray&>();
|
const JsonArray &arr_ep = val_endpoints.as<const JsonArray&>();
|
||||||
endpoints_len = arr_ep.size();
|
endpoints_len = arr_ep.size();
|
||||||
|
|
|
@ -85,9 +85,9 @@ void HueLightStatus2Zigbee(uint16_t shortaddr, String *response)
|
||||||
snprintf_P(shortaddrname, sizeof(shortaddrname), PSTR("0x%04X"), shortaddr);
|
snprintf_P(shortaddrname, sizeof(shortaddrname), PSTR("0x%04X"), shortaddr);
|
||||||
|
|
||||||
snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2,
|
snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2,
|
||||||
(friendlyName) ? escapeJSONString(friendlyName).c_str() : shortaddrname,
|
(friendlyName) ? EscapeJSONString(friendlyName).c_str() : shortaddrname,
|
||||||
(modelId) ? escapeJSONString(modelId).c_str() : PSTR("Unknown"),
|
(modelId) ? EscapeJSONString(modelId).c_str() : PSTR("Unknown"),
|
||||||
(manufacturerId) ? escapeJSONString(manufacturerId).c_str() : PSTR("Tasmota"),
|
(manufacturerId) ? EscapeJSONString(manufacturerId).c_str() : PSTR("Tasmota"),
|
||||||
GetHueDeviceId(shortaddr).c_str());
|
GetHueDeviceId(shortaddr).c_str());
|
||||||
|
|
||||||
*response += buf;
|
*response += buf;
|
||||||
|
|
|
@ -600,7 +600,7 @@ void Z_SendAFInfoRequest(uint16_t shortaddr) {
|
||||||
void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint8_t endpoint, const JsonObject &json) {
|
void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint8_t endpoint, const JsonObject &json) {
|
||||||
static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s
|
static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s
|
||||||
// Read OCCUPANCY value if any
|
// Read OCCUPANCY value if any
|
||||||
const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR(OCCUPANCY));
|
const JsonVariant &val_endpoint = GetCaseInsensitive(json, PSTR(OCCUPANCY));
|
||||||
if (nullptr != &val_endpoint) {
|
if (nullptr != &val_endpoint) {
|
||||||
uint32_t occupancy = strToUInt(val_endpoint);
|
uint32_t occupancy = strToUInt(val_endpoint);
|
||||||
|
|
||||||
|
|
|
@ -427,13 +427,13 @@ void CmndZbSend(void) {
|
||||||
bool clusterSpecific = true;
|
bool clusterSpecific = true;
|
||||||
|
|
||||||
// parse JSON
|
// parse JSON
|
||||||
const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device"));
|
const JsonVariant &val_device = GetCaseInsensitive(json, PSTR("Device"));
|
||||||
if (nullptr != &val_device) {
|
if (nullptr != &val_device) {
|
||||||
device = zigbee_devices.parseDeviceParam(val_device.as<char*>());
|
device = zigbee_devices.parseDeviceParam(val_device.as<char*>());
|
||||||
if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
||||||
}
|
}
|
||||||
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
|
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
|
||||||
const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group"));
|
const JsonVariant &val_group = GetCaseInsensitive(json, PSTR("Group"));
|
||||||
if (nullptr != &val_group) {
|
if (nullptr != &val_group) {
|
||||||
groupaddr = strToUInt(val_group);
|
groupaddr = strToUInt(val_group);
|
||||||
} else { // no device nor group
|
} else { // no device nor group
|
||||||
|
@ -442,11 +442,11 @@ void CmndZbSend(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint"));
|
const JsonVariant &val_endpoint = GetCaseInsensitive(json, PSTR("Endpoint"));
|
||||||
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
||||||
const JsonVariant &val_manuf = getCaseInsensitive(json, PSTR("Manuf"));
|
const JsonVariant &val_manuf = GetCaseInsensitive(json, PSTR("Manuf"));
|
||||||
if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); }
|
if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); }
|
||||||
const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send"));
|
const JsonVariant &val_cmd = GetCaseInsensitive(json, PSTR("Send"));
|
||||||
if (nullptr != &val_cmd) {
|
if (nullptr != &val_cmd) {
|
||||||
// probe the type of the argument
|
// probe the type of the argument
|
||||||
// If JSON object, it's high level commands
|
// If JSON object, it's high level commands
|
||||||
|
@ -582,7 +582,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||||
|
|
||||||
// Information about source device: "Device", "Endpoint", "Cluster"
|
// Information about source device: "Device", "Endpoint", "Cluster"
|
||||||
// - the source endpoint must have a known IEEE address
|
// - the source endpoint must have a known IEEE address
|
||||||
const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device"));
|
const JsonVariant &val_device = GetCaseInsensitive(json, PSTR("Device"));
|
||||||
if (nullptr != &val_device) {
|
if (nullptr != &val_device) {
|
||||||
srcDevice = zigbee_devices.parseDeviceParam(val_device.as<char*>());
|
srcDevice = zigbee_devices.parseDeviceParam(val_device.as<char*>());
|
||||||
}
|
}
|
||||||
|
@ -591,17 +591,17 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||||
uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(srcDevice);
|
uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(srcDevice);
|
||||||
if (0 == srcLongAddr) { ResponseCmndChar_P(PSTR("Unknown source IEEE address")); return; }
|
if (0 == srcLongAddr) { ResponseCmndChar_P(PSTR("Unknown source IEEE address")); return; }
|
||||||
// look for source endpoint
|
// look for source endpoint
|
||||||
const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint"));
|
const JsonVariant &val_endpoint = GetCaseInsensitive(json, PSTR("Endpoint"));
|
||||||
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
||||||
// look for source cluster
|
// look for source cluster
|
||||||
const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster"));
|
const JsonVariant &val_cluster = GetCaseInsensitive(json, PSTR("Cluster"));
|
||||||
if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); }
|
if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); }
|
||||||
|
|
||||||
// Either Device address
|
// Either Device address
|
||||||
// In this case the following parameters are mandatory
|
// In this case the following parameters are mandatory
|
||||||
// - "ToDevice" and the device must have a known IEEE address
|
// - "ToDevice" and the device must have a known IEEE address
|
||||||
// - "ToEndpoint"
|
// - "ToEndpoint"
|
||||||
const JsonVariant &dst_device = getCaseInsensitive(json, PSTR("ToDevice"));
|
const JsonVariant &dst_device = GetCaseInsensitive(json, PSTR("ToDevice"));
|
||||||
if (nullptr != &dst_device) {
|
if (nullptr != &dst_device) {
|
||||||
dstDevice = zigbee_devices.parseDeviceParam(dst_device.as<char*>());
|
dstDevice = zigbee_devices.parseDeviceParam(dst_device.as<char*>());
|
||||||
if (BAD_SHORTADDR == dstDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
if (BAD_SHORTADDR == dstDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
||||||
|
@ -612,12 +612,12 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||||
}
|
}
|
||||||
if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; }
|
if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; }
|
||||||
|
|
||||||
const JsonVariant &val_toendpoint = getCaseInsensitive(json, PSTR("ToEndpoint"));
|
const JsonVariant &val_toendpoint = GetCaseInsensitive(json, PSTR("ToEndpoint"));
|
||||||
if (nullptr != &val_toendpoint) { toendpoint = strToUInt(val_endpoint); } else { toendpoint = endpoint; }
|
if (nullptr != &val_toendpoint) { toendpoint = strToUInt(val_endpoint); } else { toendpoint = endpoint; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or Group Address - we don't need a dstEndpoint in this case
|
// Or Group Address - we don't need a dstEndpoint in this case
|
||||||
const JsonVariant &to_group = getCaseInsensitive(json, PSTR("ToGroup"));
|
const JsonVariant &to_group = GetCaseInsensitive(json, PSTR("ToGroup"));
|
||||||
if (nullptr != &to_group) { toGroup = strToUInt(to_group); }
|
if (nullptr != &to_group) { toGroup = strToUInt(to_group); }
|
||||||
|
|
||||||
// make sure we don't have conflicting parameters
|
// make sure we don't have conflicting parameters
|
||||||
|
@ -907,13 +907,13 @@ void CmndZbRead(void) {
|
||||||
size_t attrs_len = 0;
|
size_t attrs_len = 0;
|
||||||
uint8_t* attrs = nullptr; // empty string is valid
|
uint8_t* attrs = nullptr; // empty string is valid
|
||||||
|
|
||||||
const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device"));
|
const JsonVariant &val_device = GetCaseInsensitive(json, PSTR("Device"));
|
||||||
if (nullptr != &val_device) {
|
if (nullptr != &val_device) {
|
||||||
device = zigbee_devices.parseDeviceParam(val_device.as<char*>());
|
device = zigbee_devices.parseDeviceParam(val_device.as<char*>());
|
||||||
if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
||||||
}
|
}
|
||||||
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
|
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
|
||||||
const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group"));
|
const JsonVariant &val_group = GetCaseInsensitive(json, PSTR("Group"));
|
||||||
if (nullptr != &val_group) {
|
if (nullptr != &val_group) {
|
||||||
groupaddr = strToUInt(val_group);
|
groupaddr = strToUInt(val_group);
|
||||||
} else { // no device nor group
|
} else { // no device nor group
|
||||||
|
@ -922,14 +922,14 @@ void CmndZbRead(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster"));
|
const JsonVariant &val_cluster = GetCaseInsensitive(json, PSTR("Cluster"));
|
||||||
if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); }
|
if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); }
|
||||||
const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint"));
|
const JsonVariant &val_endpoint = GetCaseInsensitive(json, PSTR("Endpoint"));
|
||||||
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); }
|
||||||
const JsonVariant &val_manuf = getCaseInsensitive(json, PSTR("Manuf"));
|
const JsonVariant &val_manuf = GetCaseInsensitive(json, PSTR("Manuf"));
|
||||||
if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); }
|
if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); }
|
||||||
|
|
||||||
const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read"));
|
const JsonVariant &val_attr = GetCaseInsensitive(json, PSTR("Read"));
|
||||||
if (nullptr != &val_attr) {
|
if (nullptr != &val_attr) {
|
||||||
uint16_t val = strToUInt(val_attr);
|
uint16_t val = strToUInt(val_attr);
|
||||||
if (val_attr.is<JsonArray>()) {
|
if (val_attr.is<JsonArray>()) {
|
||||||
|
@ -1034,21 +1034,21 @@ void CmndZbConfig(void) {
|
||||||
if (!json.success()) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
|
if (!json.success()) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; }
|
||||||
|
|
||||||
// Channel
|
// Channel
|
||||||
const JsonVariant &val_channel = getCaseInsensitive(json, PSTR("Channel"));
|
const JsonVariant &val_channel = GetCaseInsensitive(json, PSTR("Channel"));
|
||||||
if (nullptr != &val_channel) { zb_channel = strToUInt(val_channel); }
|
if (nullptr != &val_channel) { zb_channel = strToUInt(val_channel); }
|
||||||
if (zb_channel < 11) { zb_channel = 11; }
|
if (zb_channel < 11) { zb_channel = 11; }
|
||||||
if (zb_channel > 26) { zb_channel = 26; }
|
if (zb_channel > 26) { zb_channel = 26; }
|
||||||
// PanID
|
// PanID
|
||||||
const JsonVariant &val_pan_id = getCaseInsensitive(json, PSTR("PanID"));
|
const JsonVariant &val_pan_id = GetCaseInsensitive(json, PSTR("PanID"));
|
||||||
if (nullptr != &val_pan_id) { zb_pan_id = strToUInt(val_pan_id); }
|
if (nullptr != &val_pan_id) { zb_pan_id = strToUInt(val_pan_id); }
|
||||||
// ExtPanID
|
// ExtPanID
|
||||||
const JsonVariant &val_ext_pan_id = getCaseInsensitive(json, PSTR("ExtPanID"));
|
const JsonVariant &val_ext_pan_id = GetCaseInsensitive(json, PSTR("ExtPanID"));
|
||||||
if (nullptr != &val_ext_pan_id) { zb_ext_panid = strtoull(val_ext_pan_id.as<const char*>(), nullptr, 0); }
|
if (nullptr != &val_ext_pan_id) { zb_ext_panid = strtoull(val_ext_pan_id.as<const char*>(), nullptr, 0); }
|
||||||
// KeyL
|
// KeyL
|
||||||
const JsonVariant &val_key_l = getCaseInsensitive(json, PSTR("KeyL"));
|
const JsonVariant &val_key_l = GetCaseInsensitive(json, PSTR("KeyL"));
|
||||||
if (nullptr != &val_key_l) { zb_precfgkey_l = strtoull(val_key_l.as<const char*>(), nullptr, 0); }
|
if (nullptr != &val_key_l) { zb_precfgkey_l = strtoull(val_key_l.as<const char*>(), nullptr, 0); }
|
||||||
// KeyH
|
// KeyH
|
||||||
const JsonVariant &val_key_h = getCaseInsensitive(json, PSTR("KeyH"));
|
const JsonVariant &val_key_h = GetCaseInsensitive(json, PSTR("KeyH"));
|
||||||
if (nullptr != &val_key_h) { zb_precfgkey_h = strtoull(val_key_h.as<const char*>(), nullptr, 0); }
|
if (nullptr != &val_key_h) { zb_precfgkey_h = strtoull(val_key_h.as<const char*>(), nullptr, 0); }
|
||||||
|
|
||||||
// Check if a parameter was changed after all
|
// Check if a parameter was changed after all
|
||||||
|
|
Loading…
Reference in New Issue