Move IrSend rawdata to stack

Move IrSend rawdata from heap to stack
This commit is contained in:
Theo Arends 2018-11-22 17:58:07 +01:00
parent 9ec57e0203
commit 8c1b966004
1 changed files with 90 additions and 83 deletions

View File

@ -26,6 +26,9 @@
#include <IRremoteESP8266.h> #include <IRremoteESP8266.h>
enum IrRemoteCommands { CMND_IRSEND, CMND_IRHVAC };
const char kIrRemoteCommands[] PROGMEM = D_CMND_IRSEND "|" D_CMND_IRHVAC ;
// Based on IRremoteESP8266.h enum decode_type_t // Based on IRremoteESP8266.h enum decode_type_t
const char kIrRemoteProtocols[] PROGMEM = const char kIrRemoteProtocols[] PROGMEM =
"UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP"; "UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP";
@ -35,6 +38,9 @@ const char kIrRemoteProtocols[] PROGMEM =
#include <ir_Mitsubishi.h> #include <ir_Mitsubishi.h>
#include <ir_Fujitsu.h> #include <ir_Fujitsu.h>
enum IrHvacVendors { VNDR_TOSHIBA, VNDR_MITSUBISHI, VNDR_LG, VNDR_FUJITSU };
const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu" ;
// HVAC TOSHIBA_ // HVAC TOSHIBA_
#define HVAC_TOSHIBA_HDR_MARK 4400 #define HVAC_TOSHIBA_HDR_MARK 4400
#define HVAC_TOSHIBA_HDR_SPACE 4300 #define HVAC_TOSHIBA_HDR_SPACE 4300
@ -501,22 +507,19 @@ boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H
boolean IrSendCommand(void) boolean IrSendCommand(void)
{ {
char command [CMDSZ];
boolean serviced = true; boolean serviced = true;
boolean error = false; boolean error = false;
char protocol_text[20];
const char *protocol;
uint32_t bits = 0;
uint32_t data = 0;
char dataBufUc[XdrvMailbox.data_len]; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kIrRemoteCommands);
UpperCase(dataBufUc, XdrvMailbox.data); if (-1 == command_code) {
if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_IRSEND))) { serviced = false; // Unknown command
}
else if (CMND_IRSEND == command_code) {
if (XdrvMailbox.data_len) { if (XdrvMailbox.data_len) {
StaticJsonBuffer<128> jsonBuf; snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
JsonObject &root = jsonBuf.parseObject(dataBufUc);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_DONE "\"}")); if (!strstr(XdrvMailbox.data, "{")) { // If no JSON it must be rawdata
if (!root.success()) {
// 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);
@ -527,69 +530,72 @@ boolean IrSendCommand(void)
for (; *q; count += (*q++ == ',')); for (; *q; count += (*q++ == ','));
if (count) { // At least two raw data values if (count) { // At least two raw data values
count++; count++;
uint16_t* raw_array = NULL; uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length)
raw_array = reinterpret_cast<uint16_t*>(malloc(count * sizeof(uint16_t))); byte i = 0;
if (raw_array != NULL) { for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) {
byte i = 0; raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input
for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) {
raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input
}
// snprintf_P(log_data, sizeof(log_data), PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"),
// count, freq, raw_array[0], raw_array[count -1]);
// AddLog(LOG_LEVEL_DEBUG);
irsend->sendRaw(raw_array, count, freq);
free(raw_array);
if (!count) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_FAILED "\"}")); // JSON decode failed and invalid RawData
}
} }
else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO_BUFFER_SPACE "\"}")); // JSON decode failed and invalid RawData // DebugFreeMem();
// snprintf_P(log_data, sizeof(log_data), PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"),
// count, freq, raw_array[0], raw_array[count -1]);
// AddLog(LOG_LEVEL_DEBUG);
irsend->sendRaw(raw_array, count, freq);
if (!count) {
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED);
} }
} }
else { else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_INVALID_RAWDATA "\"}")); // JSON decode failed and invalid RawData snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA);
} }
} }
else { else {
// IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } char dataBufUc[XdrvMailbox.data_len];
char parm_uc[10]; UpperCase(dataBufUc, XdrvMailbox.data);
StaticJsonBuffer<128> jsonBuf;
protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; JsonObject &root = jsonBuf.parseObject(dataBufUc);
bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; if (!root.success()) {
data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON);
if (protocol && bits) {
int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols);
snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"),
protocol_text, protocol, bits, data, data, protocol_code);
AddLog(LOG_LEVEL_DEBUG);
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:
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_PROTOCOL_NOT_SUPPORTED "\"}"));
}
} }
else { else {
error = true; // 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))], NULL, 0);
if (protocol && bits) {
char protocol_text[20];
int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols);
snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"),
protocol_text, protocol, bits, data, data, protocol_code);
AddLog(LOG_LEVEL_DEBUG);
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:
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED);
}
}
else {
error = true;
}
} }
} }
} }
@ -601,7 +607,7 @@ boolean IrSendCommand(void)
} }
} }
#ifdef USE_IR_HVAC #ifdef USE_IR_HVAC
else if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_IRHVAC))) { else if (CMND_IRHVAC == command_code) {
const char *HVAC_Mode; const char *HVAC_Mode;
const char *HVAC_FanMode; const char *HVAC_FanMode;
const char *HVAC_Vendor; const char *HVAC_Vendor;
@ -609,13 +615,15 @@ boolean IrSendCommand(void)
boolean HVAC_Power = true; boolean HVAC_Power = true;
if (XdrvMailbox.data_len) { if (XdrvMailbox.data_len) {
char dataBufUc[XdrvMailbox.data_len];
UpperCase(dataBufUc, XdrvMailbox.data);
StaticJsonBuffer<164> jsonBufer; StaticJsonBuffer<164> jsonBufer;
JsonObject &root = jsonBufer.parseObject(dataBufUc); JsonObject &root = jsonBufer.parseObject(dataBufUc);
if (!root.success()) { if (!root.success()) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_INVALID_JSON "\"}")); // JSON decode failed snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON);
} }
else { else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_DONE "\"}")); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR];
HVAC_Power = root[D_JSON_IRHVAC_POWER]; HVAC_Power = root[D_JSON_IRHVAC_POWER];
HVAC_Mode = root[D_JSON_IRHVAC_MODE]; HVAC_Mode = root[D_JSON_IRHVAC_MODE];
@ -626,20 +634,19 @@ boolean IrSendCommand(void)
// HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); // HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp);
// AddLog(LOG_LEVEL_DEBUG); // AddLog(LOG_LEVEL_DEBUG);
if (HVAC_Vendor == NULL || !strcasecmp_P(HVAC_Vendor, PSTR("TOSHIBA"))) { char vendor[20];
error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors);
} switch (vendor_code) {
else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { case VNDR_TOSHIBA:
error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
} case VNDR_MITSUBISHI:
else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); case VNDR_LG:
} error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
else if (!strcasecmp_P(HVAC_Vendor, PSTR("FUJITSU"))) { case VNDR_FUJITSU:
error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break;
} default:
else { error = true;
error = true;
} }
} }
} }
@ -651,7 +658,7 @@ boolean IrSendCommand(void)
} }
} }
#endif // USE_IR_HVAC #endif // USE_IR_HVAC
else serviced = false; // Unknown command else serviced = false; // Unknown command
return serviced; return serviced;
} }