From c062d35e6848e8bba21dd3aca7f75c3f45af3cab Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 12 Nov 2019 22:41:09 +0100 Subject: [PATCH] Change Kept only NEC/RC5/RC6/HASH IR protocols in standard Tasmota, all other protocols require Tasmota-IR, saving 4K --- .../src/IRremoteESP8266.h | 136 ++-- tasmota/_changelog.ino | 1 + tasmota/my_user_config.h | 19 - tasmota/tasmota_post.h | 1 - tasmota/xdrv_05_irremote.ino | 769 +----------------- 5 files changed, 74 insertions(+), 852 deletions(-) diff --git a/lib/IRremoteESP8266-2.7.0/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.7.0/src/IRremoteESP8266.h index 19e44d2fd..0bdd0a2dd 100644 --- a/lib/IRremoteESP8266-2.7.0/src/IRremoteESP8266.h +++ b/lib/IRremoteESP8266-2.7.0/src/IRremoteESP8266.h @@ -276,13 +276,13 @@ // Tasmota supported protocols (less protocols is less code size) #define DECODE_HASH true // Semi-unique code for unknown messages -#define SEND_RAW true +#define SEND_RAW false #define DECODE_NEC true #define SEND_NEC true #define DECODE_SHERWOOD false // Doesn't exist. Actually is DECODE_NEC -#define SEND_SHERWOOD true +#define SEND_SHERWOOD false #define DECODE_RC5 true #define SEND_RC5 true @@ -291,187 +291,187 @@ #define SEND_RC6 true #define DECODE_RCMM false -#define SEND_RCMM true +#define SEND_RCMM false -#define DECODE_SONY true -#define SEND_SONY true +#define DECODE_SONY false +#define SEND_SONY false -#define DECODE_PANASONIC true -#define SEND_PANASONIC true +#define DECODE_PANASONIC false +#define SEND_PANASONIC false -#define DECODE_JVC true -#define SEND_JVC true +#define DECODE_JVC false +#define SEND_JVC false -#define DECODE_SAMSUNG true -#define SEND_SAMSUNG true +#define DECODE_SAMSUNG false +#define SEND_SAMSUNG false #define DECODE_SAMSUNG36 false -#define SEND_SAMSUNG36 true +#define SEND_SAMSUNG36 false #define DECODE_SAMSUNG_AC false -#define SEND_SAMSUNG_AC true +#define SEND_SAMSUNG_AC false #define DECODE_WHYNTER false -#define SEND_WHYNTER true +#define SEND_WHYNTER false #define DECODE_AIWA_RC_T501 false -#define SEND_AIWA_RC_T501 true +#define SEND_AIWA_RC_T501 false -#define DECODE_LG true -#define SEND_LG true +#define DECODE_LG false +#define SEND_LG false #define DECODE_SANYO false -#define SEND_SANYO true +#define SEND_SANYO false #define DECODE_MITSUBISHI false -#define SEND_MITSUBISHI true +#define SEND_MITSUBISHI false #define DECODE_MITSUBISHI2 false -#define SEND_MITSUBISHI2 true +#define SEND_MITSUBISHI2 false #define DECODE_DISH false -#define SEND_DISH true +#define SEND_DISH false #define DECODE_SHARP false -#define SEND_SHARP true +#define SEND_SHARP false #define DECODE_SHARP_AC false -#define SEND_SHARP_AC true +#define SEND_SHARP_AC false #define DECODE_DENON false -#define SEND_DENON true +#define SEND_DENON false #define DECODE_KELVINATOR false -#define SEND_KELVINATOR true +#define SEND_KELVINATOR false #define DECODE_MITSUBISHI_AC false // Beta. -#define SEND_MITSUBISHI_AC true +#define SEND_MITSUBISHI_AC false #define DECODE_FUJITSU_AC false -#define SEND_FUJITSU_AC true +#define SEND_FUJITSU_AC false #define DECODE_INAX false -#define SEND_INAX true +#define SEND_INAX false #define DECODE_DAIKIN false -#define SEND_DAIKIN true +#define SEND_DAIKIN false #define DECODE_COOLIX false -#define SEND_COOLIX true +#define SEND_COOLIX false #define DECODE_GLOBALCACHE false // Not written. -#define SEND_GLOBALCACHE true +#define SEND_GLOBALCACHE false #define DECODE_GOODWEATHER false -#define SEND_GOODWEATHER true +#define SEND_GOODWEATHER false #define DECODE_GREE false -#define SEND_GREE true +#define SEND_GREE false #define DECODE_PRONTO false // Not written. -#define SEND_PRONTO true +#define SEND_PRONTO false #define DECODE_ARGO false // Experimental -#define SEND_ARGO true +#define SEND_ARGO false #define DECODE_TROTEC false -#define SEND_TROTEC true +#define SEND_TROTEC false #define DECODE_NIKAI false -#define SEND_NIKAI true +#define SEND_NIKAI false #define DECODE_TOSHIBA_AC false -#define SEND_TOSHIBA_AC true +#define SEND_TOSHIBA_AC false #define DECODE_MAGIQUEST false -#define SEND_MAGIQUEST true +#define SEND_MAGIQUEST false #define DECODE_MIDEA false -#define SEND_MIDEA true +#define SEND_MIDEA false #define DECODE_LASERTAG false -#define SEND_LASERTAG true +#define SEND_LASERTAG false #define DECODE_CARRIER_AC false -#define SEND_CARRIER_AC true +#define SEND_CARRIER_AC false #define DECODE_HAIER_AC false -#define SEND_HAIER_AC true +#define SEND_HAIER_AC false #define DECODE_HITACHI_AC false -#define SEND_HITACHI_AC true +#define SEND_HITACHI_AC false #define DECODE_HITACHI_AC1 false -#define SEND_HITACHI_AC1 true +#define SEND_HITACHI_AC1 false #define DECODE_HITACHI_AC2 false -#define SEND_HITACHI_AC2 true +#define SEND_HITACHI_AC2 false #define DECODE_GICABLE false -#define SEND_GICABLE true +#define SEND_GICABLE false #define DECODE_HAIER_AC_YRW02 false -#define SEND_HAIER_AC_YRW02 true +#define SEND_HAIER_AC_YRW02 false #define DECODE_WHIRLPOOL_AC false -#define SEND_WHIRLPOOL_AC true +#define SEND_WHIRLPOOL_AC false #define DECODE_LUTRON false -#define SEND_LUTRON true +#define SEND_LUTRON false #define DECODE_ELECTRA_AC false -#define SEND_ELECTRA_AC true +#define SEND_ELECTRA_AC false #define DECODE_PANASONIC_AC false -#define SEND_PANASONIC_AC true +#define SEND_PANASONIC_AC false #define DECODE_MWM false -#define SEND_MWM true +#define SEND_MWM false #define DECODE_PIONEER false -#define SEND_PIONEER true +#define SEND_PIONEER false #define DECODE_DAIKIN2 false -#define SEND_DAIKIN2 true +#define SEND_DAIKIN2 false #define DECODE_VESTEL_AC false -#define SEND_VESTEL_AC true +#define SEND_VESTEL_AC false #define DECODE_TECO false -#define SEND_TECO true +#define SEND_TECO false #define DECODE_TCL112AC false -#define SEND_TCL112AC true +#define SEND_TCL112AC false #define DECODE_LEGOPF false -#define SEND_LEGOPF true +#define SEND_LEGOPF false #define DECODE_MITSUBISHIHEAVY false -#define SEND_MITSUBISHIHEAVY true +#define SEND_MITSUBISHIHEAVY false #define DECODE_DAIKIN216 false -#define SEND_DAIKIN216 true +#define SEND_DAIKIN216 false #define DECODE_DAIKIN160 false -#define SEND_DAIKIN160 true +#define SEND_DAIKIN160 false #define DECODE_NEOCLIMA false -#define SEND_NEOCLIMA true +#define SEND_NEOCLIMA false #define DECODE_DAIKIN176 false -#define SEND_DAIKIN176 true +#define SEND_DAIKIN176 false #define DECODE_DAIKIN128 false -#define SEND_DAIKIN128 true +#define SEND_DAIKIN128 false #define DECODE_AMCOR false -#define SEND_AMCOR true +#define SEND_AMCOR false #define DECODE_DAIKIN152 false -#define SEND_DAIKIN152 true +#define SEND_DAIKIN152 false #define DECODE_HITACHI_AC424 false -#define SEND_HITACHI_AC424 true +#define SEND_HITACHI_AC424 false #endif // defined(FIRMWARE_IR) || defined(FIRMWARE_IR_CUSTOM) // full IR protocols diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 150a1ca96..f096c38b1 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -6,6 +6,7 @@ * Change supported MCP230xx I2C address range to 0x20 - 0x26 allowing other I2C devices with address 0x27 to be used at the same time * Add Keep last channels values when Color command end with '=' (#6799) * Add support for I2C sensor TLS2591 Light Intensity sensor (#6873) + * Change Kept only NEC/RC5/RC6/HASH IR protocols in standard Tasmota, all other protocols require Tasmota-IR, saving 4K * * 7.0.0.3 20191103 * Add command I2cDriver for I2C driver runtime control using document I2CDEVICES.md diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 447a84855..aa98f3e82 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -509,28 +509,9 @@ // -- IR Remote features - subset of IR protocols -------------------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) -// #define USE_IR_SEND_AIWA // Support IRsend Aiwa protocol - #define USE_IR_SEND_DISH // Support IRsend Dish protocol - #define USE_IR_SEND_JVC // Support IRsend JVC protocol -// #define USE_IR_SEND_LG // Support IRsend LG protocol -// #define USE_IR_SEND_MITSUBISHI // Support IRsend Mitsubishi protocol #define USE_IR_SEND_NEC // Support IRsend NEC protocol - #define USE_IR_SEND_PANASONIC // Support IRsend Panasonic protocol - #define USE_IR_SEND_PIONEER // Support IRsend Pioneer protocol #define USE_IR_SEND_RC5 // Support IRsend Philips RC5 protocol #define USE_IR_SEND_RC6 // Support IRsend Philips RC6 protocol - #define USE_IR_SEND_SAMSUNG // Support IRsend Samsung protocol -// #define USE_IR_SEND_SANYO // Support IRsend Sanyo protocol -// #define USE_IR_SEND_SHARP // Support IRsend Sharp protocol - #define USE_IR_SEND_SONY // Support IRsend Sony protocol -// #define USE_IR_SEND_WHYNTER // Support IRsend Whynter protocol - -// #define USE_IR_HVAC // Support for HVAC systems using IR (+3k5 code) - #define USE_IR_HVAC_TOSHIBA // Support IRhvac Toshiba protocol - #define USE_IR_HVAC_MITSUBISHI // Support IRhvac Mitsubischi protocol - #define USE_IR_HVAC_LG // Support IRhvac LG protocol - #define USE_IR_HVAC_FUJITSU // Support IRhvac Fujitsu protocol -// #define USE_IR_HVAC_MIDEA // Support IRhvac Midea/Komeco protocol #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) #define IR_RCV_BUFFER_SIZE 100 // Max number of packets allowed in capture buffer (default 100 (*2 bytes ram)) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index becd3f5c9..a68e044a6 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -194,7 +194,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI //#define USE_MAX31865 // Add support for MAX31865 RTD sensors using softSPI #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) - #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) //#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP diff --git a/tasmota/xdrv_05_irremote.ino b/tasmota/xdrv_05_irremote.ino index 1fd65ca43..7ac3d0ca8 100644 --- a/tasmota/xdrv_05_irremote.ino +++ b/tasmota/xdrv_05_irremote.ino @@ -28,32 +28,14 @@ enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC }; -const char kIrRemoteCommands[] PROGMEM = "|" // No prefix -#ifdef USE_IR_HVAC - D_CMND_IRHVAC "|" -#endif - D_CMND_IRSEND ; +const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; -void (* const IrRemoteCommand[])(void) PROGMEM = { -#ifdef USE_IR_HVAC - &CmndIrHvac, -#endif - &CmndIrSend }; +void (* const IrRemoteCommand[])(void) PROGMEM = { &CmndIrSend }; // Based on IRremoteESP8266.h enum decode_type_t static const uint8_t MAX_STANDARD_IR = SHARP; // this is the last code mapped to decode_type_t -enum IrVendors { IR_BASE = MAX_STANDARD_IR, -#ifdef USE_IR_SEND_PIONEER - IR_PIONEER, -#endif // USE_IR_SEND_PIONEER -}; -const char kIrRemoteProtocols[] PROGMEM = - "UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP" - // now allow for other codes beyond the first series; -#ifdef USE_IR_SEND_PIONEER - "|PIONEER" -#endif // USE_IR_SEND_PIONEER - ; +enum IrVendors { IR_BASE = MAX_STANDARD_IR }; +const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; /*********************************************************************************************\ * IR Send @@ -188,698 +170,10 @@ void IrReceiveCheck(void) } #endif // USE_IR_RECEIVE - -#ifdef USE_IR_HVAC -/*********************************************************************************************\ - * IR Heating, Ventilation and Air Conditioning -\*********************************************************************************************/ - -enum IrHvacVendors { VNDR_TOSHIBA, VNDR_MITSUBISHI, VNDR_LG, VNDR_FUJITSU, VNDR_MIDEA }; -const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu|Midea" ; - -const char kFanSpeedOptions[] = "A12345S"; -const char kHvacModeOptions[] = "HDCA"; - -#ifdef USE_IR_HVAC_TOSHIBA -/*-------------------------------------------------------------------------------------------*\ - * Toshiba -\*-------------------------------------------------------------------------------------------*/ - -const uint16_t HVAC_TOSHIBA_HDR_MARK = 4400; -const uint16_t HVAC_TOSHIBA_HDR_SPACE = 4300; -const uint16_t HVAC_TOSHIBA_BIT_MARK = 543; -const uint16_t HVAC_TOSHIBA_ONE_SPACE = 1623; -const uint16_t HVAC_MISTUBISHI_ZERO_SPACE = 472; -const uint16_t HVAC_TOSHIBA_RPT_MARK = 440; -const uint16_t HVAC_TOSHIBA_RPT_SPACE = 7048; // Above original iremote limit -const uint8_t HVAC_TOSHIBA_DATALEN = 9; - -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]; - uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; - - char *p; - uint8_t mode; - - if (HVAC_Mode == nullptr) { - p = (char *)kHvacModeOptions; // default HVAC_HOT - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - data[6] = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 - - if (!HVAC_Power) { - data[6] = (uint8_t)0x07; // Turn OFF HVAC - } - - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = p - kFanSpeedOptions + 1; - if ((1 == mode) || (7 == mode)) { - mode = 0; - } - mode = mode << 5; // AUTO = 0x00, SPEED = 0x40, 0x60, 0x80, 0xA0, 0xC0, SILENT = 0x00 - data[6] = data[6] | mode; - - uint8_t Temp; - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 17) { - Temp = 17; - } - else { - Temp = HVAC_Temp; - } - data[5] = (uint8_t)(Temp - 17) << 4; - - data[HVAC_TOSHIBA_DATALEN - 1] = 0; - for (uint32_t x = 0; x < HVAC_TOSHIBA_DATALEN - 1; x++) { - data[HVAC_TOSHIBA_DATALEN - 1] = (uint8_t)data[x] ^ data[HVAC_TOSHIBA_DATALEN - 1]; // CRC is a simple bits addition - } - - int i = 0; - uint8_t mask = 1; - - //header - rawdata[i++] = HVAC_TOSHIBA_HDR_MARK; - rawdata[i++] = HVAC_TOSHIBA_HDR_SPACE; - - //data - for (uint32_t b = 0; b < HVAC_TOSHIBA_DATALEN; b++) { - for (mask = B10000000; mask > 0; mask >>= 1) { //iterate through bit mask - if (data[b] & mask) { // Bit ONE - rawdata[i++] = HVAC_TOSHIBA_BIT_MARK; - rawdata[i++] = HVAC_TOSHIBA_ONE_SPACE; - } - else { // Bit ZERO - rawdata[i++] = HVAC_TOSHIBA_BIT_MARK; - rawdata[i++] = HVAC_MISTUBISHI_ZERO_SPACE; - } - } - } - - //trailer - rawdata[i++] = HVAC_TOSHIBA_RPT_MARK; - rawdata[i++] = HVAC_TOSHIBA_RPT_SPACE; - -// noInterrupts(); - irsend->sendRaw(rawdata, i, 38); - irsend->sendRaw(rawdata, i, 38); -// interrupts(); - - return IE_NO_ERROR; -} -#endif // USE_IR_HVAC_TOSHIBA - -#ifdef USE_IR_HVAC_MIDEA -/*-------------------------------------------------------------------------------------------*\ - * Midea / Komeco -\*-------------------------------------------------------------------------------------------*/ - -// http://veillard.com/embedded/midea.html -// https://github.com/sheinz/esp-midea-ir/blob/master/midea-ir.c - -const uint16_t HVAC_MIDEA_HDR_MARK = 4420; // 8T high -const uint16_t HVAC_MIDEA_HDR_SPACE = 4420; // 8T low -const uint16_t HVAC_MIDEA_BIT_MARK = 553; // 1T -const uint16_t HVAC_MIDEA_ONE_SPACE = 1660; // 3T low -const uint16_t HVAC_MIDEA_ZERO_SPACE = 553; // 1T high -const uint16_t HVAC_MIDEA_RPT_MARK = 553; // 1T -const uint16_t HVAC_MIDEA_RPT_SPACE = 5530; // 10T -const uint8_t HVAC_MIDEA_DATALEN = 3; - -uint8_t IrHvacMidea(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - uint16_t rawdata[2 + 2 * 2 * 8 * HVAC_MIDEA_DATALEN + 2]; // START + 2* (2 * 3 BYTES) + STOP - uint8_t data[HVAC_MIDEA_DATALEN] = {0xB2, 0x00, 0x00}; - - char *p; - uint8_t mode; - - if (!HVAC_Power) { // Turn OFF HVAC - data[1] = 0x7B; - data[2] = 0xE0; - } else { - // FAN - if (HVAC_FanMode == nullptr) { - p = (char*)kFanSpeedOptions; // default auto - } - else { - p = (char*)HVAC_FanMode; - } - - switch(p[0]) { - case '1': data[1] = 0xBF; break; // off - case '2': data[1] = 0x9F; break; // low - case '3': data[1] = 0x5F; break; // med - case '4': data[1] = 0x3F; break; // high - case '5': data[1] = 0x1F; break; // auto - case 'A': data[1] = 0x1F; break; // auto - default: return IE_SYNTAX_IRHVAC; - } - - // TEMPERATURE - uint8_t Temp; - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 17) { - Temp = 17; - } - else { - Temp = HVAC_Temp-17; - } - if (10 == Temp) { // Temp is encoded as gray code; except 27 and 28. Go figure... - data[2] = 0x90; - } else if (11 == Temp) { - data[2] = 0x80; - } else { - Temp = (Temp >> 1) ^Temp; - data[2] = (Temp << 4); - } - - // MODE - if (HVAC_Mode == nullptr) { - p = (char*)kHvacModeOptions + 3; // default to auto - } - else { - p = (char*)HVAC_Mode; - } - switch(toupper(p[0])) { - case 'D': data[2] = 0xE4; break; // for fan Temp must be 0XE - case 'C': data[2] = 0x0 | data[2]; break; - case 'A': data[2] = 0x8 | data[2]; data[1] = 0x1F; break; // for auto Fan must be 0x1 - case 'H': data[2] = 0xC | data[2]; break; - default: return IE_SYNTAX_IRHVAC; - } - } - - int i = 0; - uint8_t mask = 1; - - //header - rawdata[i++] = HVAC_MIDEA_HDR_MARK; - rawdata[i++] = HVAC_MIDEA_HDR_SPACE; - - //data - for (int b = 0; b < HVAC_MIDEA_DATALEN; b++) { // Send value - for (mask = B10000000; mask > 0; mask >>= 1) { - if (data[b] & mask) { // Bit ONE - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ONE_SPACE; - } - else { // Bit ZERO - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ZERO_SPACE; - } - } - for (mask = B10000000; mask > 0; mask >>= 1) { // Send complement - if (data[b] & mask) { // Bit ONE - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ZERO_SPACE; - } - else { // Bit ZERO - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ONE_SPACE; - } - } - - } - - //trailer - rawdata[i++] = HVAC_MIDEA_RPT_MARK; - rawdata[i++] = HVAC_MIDEA_RPT_SPACE; - - // this takes ~180 ms : - irsend->sendRaw(rawdata, i, 38); - irsend->sendRaw(rawdata, i, 38); - - return IE_NO_ERROR; -} -#endif // USE_IR_HVAC_MIDEA - -#ifdef USE_IR_HVAC_MITSUBISHI -/*-------------------------------------------------------------------------------------------*\ - * Mitsubishi -\*-------------------------------------------------------------------------------------------*/ - -#include - -uint8_t IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - char *p; - uint8_t mode; - - IRMitsubishiAC mitsubir(pin[GPIO_IRSEND]); - - mitsubir.stateReset(); - - if (HVAC_Mode == nullptr) { - p = (char *)kHvacModeOptions; // default HVAC_HOT - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = (p - kHvacModeOptions + 1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20 - mitsubir.setMode(mode); - - mitsubir.setPower(HVAC_Power); - - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = p - kFanSpeedOptions; // AUTO = 0, SPEED = 1 .. 5, SILENT = 6 - mitsubir.setFan(mode); - - mitsubir.setTemp(HVAC_Temp); - mitsubir.setVane(MITSUBISHI_AC_VANE_AUTO); - mitsubir.send(); - -// 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()); - - return IE_NO_ERROR; -} -#endif // USE_IR_HVAC_MITSUBISHI - -#ifdef USE_IR_HVAC_LG -/*-------------------------------------------------------------------------------------------*\ - * LG -\*-------------------------------------------------------------------------------------------*/ - -const uint8_t HVAC_LG_DATALEN = 7; - -uint8_t IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - uint32_t LG_Code; - uint8_t data[HVAC_LG_DATALEN]; - static bool hvacOn = false; - char *p; - uint8_t mode; - uint8_t Temp; - - // Constant data - data[0] = 0x08; - data[1] = 0x08; - data[2] = 0x00; - - if (!HVAC_Power) { - data[2] = (uint8_t)0x0C; // Turn OFF HVAC, code 0x88C0051 - data[3] = (uint8_t)0x00; - data[4] = (uint8_t)0x00; - data[5] = (uint8_t)0x05; - data[6] = (uint8_t)0x01; - hvacOn = false; - } - - else { - - // Set code for HVAC Mode - data[3] - if (HVAC_Mode == nullptr) { - p = (char *)kHvacModeOptions; // default HVAC_HOT - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 - switch (mode) { - case 0: // AUTO - data[3] = 11; - break; - case 1: // COOL - data[3] = 8; - break; - case 2: // DRY - data[3] = 9; - break; - case 3: // HOT - data[3] = 12; - break; - } - if (!hvacOn) { - data[3] = data[3] & 7; // reset bit3 - hvacOn = true; - } - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); - - // Set code for HVAC temperature - data[4] - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 18) { - Temp = 18; - } - else { - Temp = HVAC_Temp; - } - data[4] = (uint8_t)(Temp - 15); - - // Set code for HVAC fan mode - data[5] - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = p - kFanSpeedOptions; - if ((mode == 0) || (mode > 3)) { - data[5] = 5; // Auto = 0x05 - } - else { - data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 - } - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); - - // Set CRC code - data[6] - data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC - - } - // Build LG IR code - LG_Code = data[0] << 4; - for (uint32_t i = 1; i < 6; i++) { - LG_Code = (LG_Code + data[i]) << 4; - } - LG_Code = LG_Code + data[6]; - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: LG_Code %d"), LG_Code); - - // Send LG IR Code - irsend->sendLG(LG_Code, 28); - - return IE_NO_ERROR; -} -#endif // USE_IR_HVAC_LG - -#ifdef USE_IR_HVAC_FUJITSU -/*-------------------------------------------------------------------------------------------*\ - * Fujitsu -\*-------------------------------------------------------------------------------------------*/ - -#include - -uint8_t IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - const char kFujitsuHvacModeOptions[] = "HDCAF"; - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - - IRFujitsuAC ac(pin[GPIO_IRSEND]); - - if (0 == HVAC_Power) { - ac.off(); - ac.send(); - 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 fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; - ac.setCmd(FUJITSU_AC_CMD_TURN_ON); - ac.setSwing(FUJITSU_AC_SWING_VERT); - - char *p; - if (nullptr == HVAC_Mode) { - p = (char *)kFujitsuHvacModeOptions; - } - else { - p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - ac.setMode(modes[p - kFujitsuHvacModeOptions]); - - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); - - ac.setTemp(HVAC_Temp); - ac.send(); - - return IE_NO_ERROR; -} -#endif // USE_IR_HVAC_FUJITSU - -/*-------------------------------------------------------------------------------------------*/ - -uint32_t IrRemoteCmndIrHvacJson(void) -{ - // IrHvac { "Vendor": "", "Power": <0|1>, "Mode": "", "FanSpeed": "<1|2|3|4|5|Auto|Silence>", "Temp": <17..30> } - const char *HVAC_Mode; - const char *HVAC_FanMode; - const char *HVAC_Vendor; - char parm_uc[12]; - int HVAC_Temp = 21; - bool HVAC_Power = true; - - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { - return IE_INVALID_JSON; - } - - StaticJsonBuffer<164> jsonBufer; - JsonObject &root = jsonBufer.parseObject(dataBufUc); - if (!root.success()) { - return IE_INVALID_JSON; - } - - HVAC_Vendor = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR))]; - HVAC_Power = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER))]; - HVAC_Mode = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE))]; - HVAC_FanMode = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED))]; - HVAC_Temp = root[UpperCase_P(parm_uc, PSTR(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); - - char vendor[20]; - int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); - irsend_active = true; - switch (vendor_code) { -#ifdef USE_IR_HVAC_TOSHIBA - case VNDR_TOSHIBA: - return IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_MITSUBISHI - case VNDR_MITSUBISHI: - return IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_LG - case VNDR_LG: - return IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_FUJITSU - case VNDR_FUJITSU: - return IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_MIDEA - case VNDR_MIDEA: - return IrHvacMidea(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif - default: - irsend_active = false; - } - - return IE_SYNTAX_IRHVAC; -} - -void CmndIrHvac(void) -{ - uint8_t error = IE_SYNTAX_IRHVAC; - - if (XdrvMailbox.data_len) { - error = IrRemoteCmndIrHvacJson(); - } - IrRemoteCmndResponse(error); -} - -#endif // USE_IR_HVAC - /*********************************************************************************************\ * Commands \*********************************************************************************************/ -uint32_t IrRemoteCmndIrSendRaw(void) -{ - // IRsend ,, ... - // or - // IRsend raw,,, (one space = zero space *2) - // IRsend raw,,,, - // IRsend raw,,,, - // IRsend raw,,
,
,,,, - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - if (p == nullptr) { - return IE_INVALID_RAWDATA; - } - - // repeat - uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; - - uint16_t freq = atoi(str); - if (!freq && (*str != '0')) { // First parameter is any string - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (count < 2) { - return IE_INVALID_RAWDATA; - } // Parameters must be at least 3 - - uint16_t parm[count]; - for (uint32_t i = 0; i < count; i++) { - parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - if (!parm[i]) { - if (!i) { - parm[0] = 38000; // Frequency default to 38kHz - } else { - return IE_INVALID_RAWDATA; // Other parameters may not be 0 - } - } - } - - uint16_t i = 0; - if (count < 4) { - // IRsend raw,0,889,000000100110000001001 - uint16_t mark = parm[1] *2; // Protocol where 0 = t, 1 = 2t (RC5) - if (3 == count) { - if (parm[2] < parm[1]) { - // IRsend raw,0,889,2,000000100110000001001 - mark = parm[1] * parm[2]; // Protocol where 0 = t1, 1 = t1*t2 (Could be RC5) - } else { - // IRsend raw,0,889,1778,000000100110000001001 - mark = parm[2]; // Protocol where 0 = t1, 1 = t2 (Could be RC5) - } - } - uint16_t raw_array[strlen(p)]; // Bits - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[1]; // Space - } - else if (*p == '1') { - raw_array[i++] = mark; // Mark - } - } - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { // if it's not the last message - irsend->space(40000); // since we don't know the inter-message gap, place an arbitrary 40ms gap - } - } - } - else if (6 == count) { // NEC Protocol - // IRsend raw,0,8620,4260,544,411,1496,010101101000111011001110000000001100110000000001100000000000000010001100 - uint16_t raw_array[strlen(p)*2+3]; // Header + bits + end - raw_array[i++] = parm[1]; // Header mark - raw_array[i++] = parm[2]; // Header space - uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; // compute an inter-message gap (32 bits) - uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; // avoid 16 bits overflow - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[3]; // Bit mark - raw_array[i++] = parm[4]; // Zero space - } - else if (*p == '1') { - raw_array[i++] = parm[3]; // Bit mark - raw_array[i++] = parm[5]; // One space - } - } - raw_array[i++] = parm[3]; // Trailing mark - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { // if it's not the last message - irsend->space(inter_message); // since we don't know the inter-message gap, place an arbitrary 40ms gap - } - } - } - else { - return IE_INVALID_RAWDATA; // Invalid number of parameters - } - } else { - if (!freq) { freq = 38000; } // Default to 38kHz - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (0 == count) { - return IE_INVALID_RAWDATA; - } - - // IRsend 0,896,876,900,888,894,876,1790,874,872,1810,1736,948,872,880,872,936,872,1792,900,888,1734 - count++; - if (count < 200) { - uint16_t raw_array[count]; // It's safe to use stack for up to 200 packets (limited by mqtt_data length) - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); // Allow decimal (20496) and hexadecimal (0x5010) input - } - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: stack count %d"), count); - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - } else { - uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); - if (raw_array == nullptr) { - return IE_INVALID_RAWDATA; - } - - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); // Allow decimal (20496) and hexadecimal (0x5010) input - } - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: heap count %d"), count); - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - free(raw_array); - } - } - - return IE_NO_ERROR; -} - uint32_t IrRemoteCmndIrSendJson(void) { // ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(3) + 40 = 96 @@ -936,54 +230,6 @@ uint32_t IrRemoteCmndIrSendJson(void) case NEC: irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits, repeat); break; #endif -#ifdef USE_IR_SEND_SONY - case SONY: - irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, repeat > kSonyMinRepeat ? repeat : kSonyMinRepeat); break; -#endif -#ifdef USE_IR_SEND_PANASONIC - case PANASONIC: - irsend->sendPanasonic64(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_JVC - case JVC: - irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, repeat > 1 ? repeat : 1); break; -#endif -#ifdef USE_IR_SEND_SAMSUNG - case SAMSUNG: - irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits, repeat); break; -#endif -#ifdef USE_IR_SEND_WHYNTER - case WHYNTER: - irsend->sendWhynter(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_AIWA - case AIWA_RC_T501: - irsend->sendAiwaRCT501(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_LG - case LG: - irsend->sendLG(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_SANYO - case SANYO: - irsend->sendSanyoLC7461(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_MITSUBISHI - case MITSUBISHI: - irsend->sendMitsubishi(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_DISH - case DISH: - irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits, repeat > kDishMinRepeat ? repeat : kDishMinRepeat); break; -#endif -#ifdef USE_IR_SEND_SHARP - case SHARP: - irsend->sendSharpRaw(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_PIONEER - case IR_PIONEER: - irsend->sendPioneer(data, bits, repeat); break; -#endif // USE_IR_SEND_PIONEER default: irsend_active = false; ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); @@ -999,7 +245,7 @@ void CmndIrSend(void) if (XdrvMailbox.data_len) { // error = (strstr(XdrvMailbox.data, "{") == nullptr) ? IrRemoteCmndIrSendRaw() : IrRemoteCmndIrSendJson(); if (strstr(XdrvMailbox.data, "{") == nullptr) { - error = IrRemoteCmndIrSendRaw(); + error = IE_INVALID_JSON; } else { error = IrRemoteCmndIrSendJson(); } @@ -1019,11 +265,6 @@ void IrRemoteCmndResponse(uint32_t error) 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 default: // IE_NO_ERROR ResponseCmndDone(); }