From 36d49d082dd70b10896184ebefc9f9f694ded49e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 1 Oct 2020 23:10:17 +0200 Subject: [PATCH] Extend IR Raw compat to regular IR code --- tasmota/xdrv_05_irremote.ino | 114 ++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 15 deletions(-) diff --git a/tasmota/xdrv_05_irremote.ino b/tasmota/xdrv_05_irremote.ino index 690dc0c61..da60ed813 100644 --- a/tasmota/xdrv_05_irremote.ino +++ b/tasmota/xdrv_05_irremote.ino @@ -17,6 +17,41 @@ along with this program. If not, see . */ +/* +Below is the Pyhton3 code to decompress IR comact format. + +====================================================================== +import re + +def ir_expand(ir_compact): + count = ir_compact.count(',') # number of occurence of comma + + if count > 1: + return "Unsupported format" + + if count == 1: + ir_compact = input.split(',')[1] # if 1 comma, skip the frequency + + arr = re.findall("(\d+|[A-Za-z])", ir_compact) + + comp_table = [] # compression history table + arr2 = [] # output + + for elt in arr: + if len(elt) == 1: + c = ord(elt.upper()) - ord('A') + if c >= len(arr): return "Error index undefined" + arr2.append(comp_table[c]) + else: + comp_table.append(elt) + arr2.append(elt) + + out = ",".join(arr2) + + return out +====================================================================== + */ + #if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) /*********************************************************************************************\ * IR Remote send and receive using IRremoteESP8266 library @@ -25,6 +60,7 @@ #define XDRV_05 5 #include +#include enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; @@ -34,6 +70,44 @@ const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; void (* const IrRemoteCommand[])(void) PROGMEM = { &CmndIrSend }; +/*********************************************************************************************\ + * Class used to make a compact IR Raw format. + * + * We round timings to the closest 10ms value, + * and store up to last 26 values with seen. + * A value already seen is encoded with a letter indicating the position in the table. +\*********************************************************************************************/ + +class IRRawTable { +public: + IRRawTable() : timings() {} // zero initialize the array + + int32_t getTimingForLetter(uint8_t l) const { + l = toupper(l); + if ((l < 'A') || (l > 'Z')) { return -1; } + return timings[l - 'A']; + } + uint8_t findOrAdd(uint16_t t) { + if (0 == t) { return 0; } + + for (uint32_t i=0; i<26; i++) { + if (timings[i] == t) { return i + 'A'; } + if (timings[i] == 0) { timings[i] = t; break; } // add new value + } + return 0; // not found + } + void add(uint16_t t) { + if (0 == t) { return; } + + for (uint32_t i=0; i<26; i++) { + if (timings[i] == 0) { timings[i] = t; break; } // add new value + } + } + +protected: + uint16_t timings[26]; +}; + // Based on IRremoteESP8266.h enum decode_type_t static const uint8_t MAX_STANDARD_IR = NEC; // this is the last code mapped to decode_type_t const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; @@ -133,25 +207,35 @@ void IrReceiveCheck(void) ResponseAppend_P(PSTR(",\"" D_JSON_IR_HASH "\":%s"), svalue); } + IRRawTable raw_table; + bool prev_number = false; // was the previous value a number, meaning we may need a comma prefix + bool ir_high = true; // alternate high/low + // Add raw data in a compact format if (Settings.flag3.receive_raw) { // SetOption58 - Add IR Raw data to JSON message - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); - uint16_t i; - for (i = 1; i < results.rawlen; i++) { - if (i > 1) { ResponseAppend_P(PSTR(",")); } - uint32_t usecs; - for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\"")); + size_t rawlen = results.rawlen; + uint32_t i; + + for (i = 1; i < rawlen; i++) { + // round to closest 10ms + uint32_t raw_val_millis = results.rawbuf[i] * kRawTick; + uint16_t raw_dms = (raw_val_millis*2 + 5) / 10; // in 5 micro sec steps + // look if the data is already seen + uint8_t letter = raw_table.findOrAdd(raw_dms); + if (letter) { + if (!ir_high) { letter = tolower(letter); } + ResponseAppend_P(PSTR("%c"), letter); + prev_number = false; + } else { + // number + ResponseAppend_P(PSTR("%c%d"), ir_high ? '+' : '-', (uint32_t)raw_dms * 5); + prev_number = true; } - ResponseAppend_P(PSTR("%d"), usecs); + ir_high = !ir_high; if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } // Quit if char string becomes too long } - uint16_t extended_length = results.rawlen - 1; - for (uint32_t j = 0; j < results.rawlen - 1; j++) { - uint32_t usecs = results.rawbuf[j] * kRawTick; - // Add two extra entries for multiple larger than UINT16_MAX it is. - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + uint16_t extended_length = getCorrectedRawLength(&results); + ResponseAppend_P(PSTR("\",\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); } ResponseJsonEndEnd();