Fix parameter exceptions (#5555)

Fix parameter exceptions (#5555)
This commit is contained in:
Theo Arends 2019-03-31 13:06:42 +02:00
parent f7c30250c1
commit b9a0581280

View File

@ -26,6 +26,8 @@
#include <IRremoteESP8266.h> #include <IRremoteESP8266.h>
enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC };
enum IrRemoteCommands { CMND_IRSEND, CMND_IRHVAC }; enum IrRemoteCommands { CMND_IRSEND, CMND_IRHVAC };
const char kIrRemoteCommands[] PROGMEM = D_CMND_IRSEND "|" D_CMND_IRHVAC ; const char kIrRemoteCommands[] PROGMEM = D_CMND_IRSEND "|" D_CMND_IRHVAC ;
@ -180,7 +182,7 @@ void IrReceiveCheck(void)
TOSHIBA TOSHIBA
********************/ ********************/
bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) uint8_t IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp)
{ {
uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2];
uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00};
@ -195,7 +197,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po
p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
data[6] = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 data[6] = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00
@ -210,7 +212,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po
p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
mode = p - kFanSpeedOptions + 1; mode = p - kFanSpeedOptions + 1;
if ((1 == mode) || (7 == mode)) { if ((1 == mode) || (7 == mode)) {
@ -267,7 +269,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po
irsend->sendRaw(rawdata, i, 38); irsend->sendRaw(rawdata, i, 38);
// interrupts(); // interrupts();
return false; return IE_NO_ERROR;
} }
@ -275,7 +277,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po
MITSUBISHI MITSUBISHI
********************/ ********************/
bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) uint8_t IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp)
{ {
char *p; char *p;
uint8_t mode; uint8_t mode;
@ -289,7 +291,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC
p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
mode = (p - kHvacModeOptions + 1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20 mode = (p - kHvacModeOptions + 1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20
mitsubir->setMode(mode); mitsubir->setMode(mode);
@ -303,7 +305,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC
p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
mode = p - kFanSpeedOptions; // AUTO = 0, SPEED = 1 .. 5, SILENT = 6 mode = p - kFanSpeedOptions; // AUTO = 0, SPEED = 1 .. 5, SILENT = 6
mitsubir->setFan(mode); mitsubir->setFan(mode);
@ -315,7 +317,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Mitsubishi Power %d, Mode %d, FanSpeed %d, Temp %d, VaneMode %d"), // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Mitsubishi Power %d, Mode %d, FanSpeed %d, Temp %d, VaneMode %d"),
// mitsubir->getPower(), mitsubir->getMode(), mitsubir->getFan(), mitsubir->getTemp(), mitsubir->getVane()); // mitsubir->getPower(), mitsubir->getMode(), mitsubir->getFan(), mitsubir->getTemp(), mitsubir->getVane());
return false; return IE_NO_ERROR;
} }
@ -323,7 +325,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC
LG LG
********************/ ********************/
bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) uint8_t IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp)
{ {
uint32_t LG_Code; uint32_t LG_Code;
uint8_t data[HVAC_LG_DATALEN]; uint8_t data[HVAC_LG_DATALEN];
@ -356,7 +358,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power,
p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00
switch (mode) { switch (mode) {
@ -400,7 +402,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power,
p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
mode = p - kFanSpeedOptions; mode = p - kFanSpeedOptions;
if ((mode == 0) || (mode > 3)) { if ((mode == 0) || (mode > 3)) {
@ -431,7 +433,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power,
irsend->sendLG(LG_Code, 28); irsend->sendLG(LG_Code, 28);
// interrupts(); // interrupts();
return false; return IE_NO_ERROR;
} }
@ -439,7 +441,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power,
Fujitsu Fujitsu
********************/ ********************/
bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) uint8_t IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp)
{ {
const char kFujitsuHvacModeOptions[] = "HDCAF"; const char kFujitsuHvacModeOptions[] = "HDCAF";
@ -452,7 +454,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po
if (0 == HVAC_Power) { if (0 == HVAC_Power) {
ac.off(); ac.off();
ac.send(); ac.send();
return false; return IE_NO_ERROR;
} }
uint8_t modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; uint8_t modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN};
@ -468,7 +470,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po
p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
ac.setMode(modes[p - kFujitsuHvacModeOptions]); ac.setMode(modes[p - kFujitsuHvacModeOptions]);
@ -479,14 +481,14 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po
p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0]));
} }
if (!p) { if (!p) {
return true; return IE_SYNTAX_IRHVAC;
} }
ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); ac.setFanSpeed(fanModes[p - kFanSpeedOptions]);
ac.setTemp(HVAC_Temp); ac.setTemp(HVAC_Temp);
ac.send(); ac.send();
return false; return IE_NO_ERROR;
} }
#endif // USE_IR_HVAC #endif // USE_IR_HVAC
@ -507,7 +509,7 @@ bool IrSendCommand(void)
{ {
char command [CMDSZ]; char command [CMDSZ];
bool serviced = true; bool serviced = true;
bool error = false; uint8_t error = IE_NO_ERROR;
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kIrRemoteCommands); int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kIrRemoteCommands);
if (-1 == command_code) { if (-1 == command_code) {
@ -521,86 +523,87 @@ bool IrSendCommand(void)
// IRSend frequency, rawdata, rawdata ... // IRSend frequency, rawdata, rawdata ...
char *p; char *p;
char *str = strtok_r(XdrvMailbox.data, ", ", &p); char *str = strtok_r(XdrvMailbox.data, ", ", &p);
uint16_t freq = atoi(str); if (p == nullptr) {
if (!freq) { freq = 38000; } // Default to 38kHz error = IE_INVALID_RAWDATA;
uint16_t count = 0; } else {
char *q = p; uint16_t freq = atoi(str);
for (; *q; count += (*q++ == ',')); if (!freq) { freq = 38000; } // Default to 38kHz
if (count) { // At least two raw data values uint16_t count = 0;
count++; char *q = p;
uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) for (; *q; count += (*q++ == ','));
uint8_t i = 0; if (0 == count) {
for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { error = IE_INVALID_RAWDATA;
raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input } else { // At least two raw data values
} count++;
uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length)
uint8_t i = 0;
for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) {
raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input
}
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]);
irsend_active = true;
irsend->sendRaw(raw_array, count, freq);
if (!count) {
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED);
}
}
else {
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA);
}
}
else {
char dataBufUc[XdrvMailbox.data_len];
UpperCase(dataBufUc, XdrvMailbox.data);
StaticJsonBuffer<128> jsonBuf;
JsonObject &root = jsonBuf.parseObject(dataBufUc);
if (!root.success()) {
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON);
}
else {
// IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 }
char parm_uc[10];
const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))];
uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))];
uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0);
if (protocol && bits) {
char protocol_text[20];
int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"),
protocol_text, protocol, bits, data, data, protocol_code);
irsend_active = true; irsend_active = true;
switch (protocol_code) { irsend->sendRaw(raw_array, count, freq);
case NEC: if (!count) {
irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break; Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED);
case SONY:
irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break;
case RC5:
irsend->sendRC5(data, bits); break;
case RC6:
irsend->sendRC6(data, bits); break;
case DISH:
irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break;
case JVC:
irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break;
case SAMSUNG:
irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break;
case PANASONIC:
irsend->sendPanasonic(bits, data); break;
default:
irsend_active = false;
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED);
} }
} }
else { }
error = true; } else {
char dataBufUc[XdrvMailbox.data_len];
UpperCase(dataBufUc, XdrvMailbox.data);
RemoveSpace(dataBufUc);
if (strlen(dataBufUc) < 8) {
error = IE_INVALID_JSON;
} else {
StaticJsonBuffer<128> jsonBuf;
JsonObject &root = jsonBuf.parseObject(dataBufUc);
if (!root.success()) {
error = IE_INVALID_JSON;
} else {
// IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 }
char parm_uc[10];
const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))];
uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))];
uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0);
if (protocol && bits) {
char protocol_text[20];
int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"),
protocol_text, protocol, bits, data, data, protocol_code);
irsend_active = true;
switch (protocol_code) {
case NEC:
irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break;
case SONY:
irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break;
case RC5:
irsend->sendRC5(data, bits); break;
case RC6:
irsend->sendRC6(data, bits); break;
case DISH:
irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break;
case JVC:
irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break;
case SAMSUNG:
irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break;
case PANASONIC:
irsend->sendPanasonic(bits, data); break;
default:
irsend_active = false;
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED);
}
} else {
error = IE_SYNTAX_IRSEND;
}
} }
} }
} }
} } else {
else { error = IE_SYNTAX_IRSEND;
error = true;
}
if (error) {
Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}"));
} }
} }
#ifdef USE_IR_HVAC #ifdef USE_IR_HVAC
@ -614,47 +617,65 @@ bool IrSendCommand(void)
if (XdrvMailbox.data_len) { if (XdrvMailbox.data_len) {
char dataBufUc[XdrvMailbox.data_len]; char dataBufUc[XdrvMailbox.data_len];
UpperCase(dataBufUc, XdrvMailbox.data); UpperCase(dataBufUc, XdrvMailbox.data);
StaticJsonBuffer<164> jsonBufer; RemoveSpace(dataBufUc);
JsonObject &root = jsonBufer.parseObject(dataBufUc); if (strlen(dataBufUc) < 8) {
if (!root.success()) { error = IE_INVALID_JSON;
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); } else {
} StaticJsonBuffer<164> jsonBufer;
else { JsonObject &root = jsonBufer.parseObject(dataBufUc);
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); if (!root.success()) {
HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; error = IE_INVALID_JSON;
HVAC_Power = root[D_JSON_IRHVAC_POWER]; } else {
HVAC_Mode = root[D_JSON_IRHVAC_MODE]; Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED]; HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR];
HVAC_Temp = root[D_JSON_IRHVAC_TEMP]; HVAC_Power = root[D_JSON_IRHVAC_POWER];
HVAC_Mode = root[D_JSON_IRHVAC_MODE];
HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED];
HVAC_Temp = root[D_JSON_IRHVAC_TEMP];
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp);
char vendor[20]; char vendor[20];
int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors);
switch (vendor_code) { switch (vendor_code) {
case VNDR_TOSHIBA: case VNDR_TOSHIBA:
error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
case VNDR_MITSUBISHI: case VNDR_MITSUBISHI:
error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
case VNDR_LG: case VNDR_LG:
error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
case VNDR_FUJITSU: case VNDR_FUJITSU:
error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
default: default:
error = true; error = IE_SYNTAX_IRHVAC;
}
} }
} }
} }
else { else {
error = true; error = IE_SYNTAX_IRHVAC;
}
if (error) {
Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}"));
} }
} }
#endif // USE_IR_HVAC #endif // USE_IR_HVAC
else serviced = false; // Unknown command else serviced = false; // Unknown command
switch (error) {
case IE_INVALID_RAWDATA:
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA);
break;
case IE_INVALID_JSON:
Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON);
break;
case IE_SYNTAX_IRSEND:
Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}"));
break;
#ifdef USE_IR_HVAC
case IE_SYNTAX_IRHVAC:
Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}"));
break;
#endif // USE_IR_HVAC
}
return serviced; return serviced;
} }