From cc066ebd44ba83857c5d381857b240017154ef46 Mon Sep 17 00:00:00 2001 From: jimmys01 Date: Tue, 10 Sep 2019 14:49:33 +0300 Subject: [PATCH 1/6] [IR] Sent decoded values back to the controller --- src/_P016_IR.ino | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index 01720fe67..1b688d58c 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -102,7 +102,7 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) { Device[++deviceCount].Number = PLUGIN_ID_016; Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = SENSOR_TYPE_LONG; + Device[deviceCount].VType = SENSOR_TYPE_STRING; Device[deviceCount].Ports = 0; Device[deviceCount].PullUpOption = true; Device[deviceCount].InverseLogicOption = true; @@ -138,7 +138,7 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) if (irReceiver == 0 && irPin != -1) { addLog(LOG_LEVEL_INFO, String(F("INIT: IR RX"))); - addLog(LOG_LEVEL_INFO, String(F("IR lib Version: "))+_IRREMOTEESP8266_VERSION_); + addLog(LOG_LEVEL_INFO, String(F("IR lib Version: ")) + _IRREMOTEESP8266_VERSION_); irReceiver = new IRrecv(irPin, kCaptureBufferSize, P016_TIMEOUT, true); irReceiver->setUnknownThreshold(kMinUnknownSize); // Ignore messages with less than minimum on or off pulses. irReceiver->enableIRIn(); // Start the receiver @@ -189,13 +189,16 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) // Display the basic output of what we found. if (results.decode_type != decode_type_t::UNKNOWN) { - addLog(LOG_LEVEL_INFO, String(F("IRSEND,")) + typeToString(results.decode_type, results.repeat) + ',' + resultToHexidecimal(&results) + ',' + uint64ToString(results.bits)); //Show the appropriate command to the user, so he can replay the message via P035 + String output = String(F("IRSEND,")) + typeToString(results.decode_type, results.repeat) + ',' + resultToHexidecimal(&results) + ',' + uint64ToString(results.bits); + addLog(LOG_LEVEL_INFO, output); //Show the appropriate command to the user, so he can replay the message via P035 + event->String2 = output; } //Check if a solution for RAW2 is found and if not give the user the option to access the timings info. - if (results.decode_type == decode_type_t::UNKNOWN && !displayRawToReadableB32Hex()) + if (results.decode_type == decode_type_t::UNKNOWN && !displayRawToReadableB32Hex(event->String2)) { addLog(LOG_LEVEL_INFO, F("IR: No replay solutions found! Press button again or try RAW encoding (timmings are in the serial output)")); serialPrint(String(F("IR: RAW TIMINGS: ")) + resultToSourceCode(&results)); + event->String2 = F("NaN"); yield(); // Feed the WDT as it can take a while to print. //addLog(LOG_LEVEL_DEBUG,(String(F("IR: RAW TIMINGS: ")) + resultToSourceCode(&results))); // Output the results as RAW source code //not showing up nicely in the web log } @@ -223,11 +226,11 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) state.beep = false; state.sleep = -1; state.clock = -1; - + String description = IRAcUtils::resultAcToString(&results); if (description != "") addLog(LOG_LEVEL_INFO, String(F("AC State: ")) + description); // If we got a human-readable description of the message, display it. - if (IRac::isProtocolSupported(results.decode_type)) //Check If there is a replayable AC state and show the JSON command that can be send + if (IRac::isProtocolSupported(results.decode_type)) //Check If there is a replayable AC state and show the JSON command that can be send { IRAcUtils::decodeToState(&results, &state); StaticJsonDocument<300> doc; @@ -266,6 +269,7 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) doc[F("clock")] = state.clock; //Nr. of mins past midnight to set the clock to. (< 0 means off.) String output = F("IRSENDAC,"); serializeJson(doc, output); + event->String2 = output; addLog(LOG_LEVEL_INFO, output); //Show the command that the user can put to replay the AC state with P035 } #endif // P016_P035_Extended_AC @@ -299,7 +303,7 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) // // Author: Gilad Raz (jazzgil) 23sep2018 -boolean displayRawToReadableB32Hex() +boolean displayRawToReadableB32Hex(String &outputStr) { String line; uint16_t div[2]; @@ -411,6 +415,7 @@ boolean displayRawToReadableB32Hex() out[iOut] = 0; line = String(F("IRSEND,RAW2,")) + String(out) + String(F(",38,")) + uint64ToString(div[0], 10) + ',' + uint64ToString(div[1], 10); addLog(LOG_LEVEL_INFO, line); + outputStr = line; return true; } From 11dd524e2165206bb269dc41d34eee72dc9f3d72 Mon Sep 17 00:00:00 2001 From: jimmys01 Date: Tue, 10 Sep 2019 15:12:56 +0300 Subject: [PATCH 2/6] Comment out interfering code --- src/_P016_IR.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index 1b688d58c..6ac946fb7 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -274,9 +274,9 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) } #endif // P016_P035_Extended_AC - unsigned long IRcode = results.value; - UserVar[event->BaseVarIndex] = (IRcode & 0xFFFF); - UserVar[event->BaseVarIndex + 1] = ((IRcode >> 16) & 0xFFFF); + //unsigned long IRcode = results.value; + //UserVar[event->BaseVarIndex] = (IRcode & 0xFFFF); + //UserVar[event->BaseVarIndex + 1] = ((IRcode >> 16) & 0xFFFF); sendData(event); } success = true; From d3beadc8e2fae6f2cfca0d3ec3b07db852127636 Mon Sep 17 00:00:00 2001 From: jimmys01 Date: Tue, 10 Sep 2019 21:00:06 +0300 Subject: [PATCH 3/6] Force rebuild --- src/_P016_IR.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index 6ac946fb7..9eecf95ae 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -31,7 +31,7 @@ #define PLUGIN_VALUENAME1_016 "IR" // A lot of the following code has been taken directly (with permission) from the IRrecvDumpV2.ino example code -// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266) +// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266) // ==================== start of TUNEABLE PARAMETERS ==================== // As this program is a special purpose capture/decoder, let us use a larger @@ -431,4 +431,4 @@ unsigned int storeB32Hex(char out[], unsigned int iOut, unsigned int val) return iOut; } -#endif // USES_P016 \ No newline at end of file +#endif // USES_P016 From 2603d2775ada819808010ab9108b4af6aa754d83 Mon Sep 17 00:00:00 2001 From: jimmys01 Date: Tue, 5 Nov 2019 15:12:48 +0200 Subject: [PATCH 4/6] Resolve code conflicts --- src/_P016_IR.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index 91fa91b00..9f4d6be71 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -194,7 +194,11 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) event->String2 = output; } //Check if a solution for RAW2 is found and if not give the user the option to access the timings info. + #ifdef P016_P035_USE_RAW_RAW2 if (results.decode_type == decode_type_t::UNKNOWN && !displayRawToReadableB32Hex(event->String2)) + #else + if (results.decode_type == decode_type_t::UNKNOWN) + #endif { addLog(LOG_LEVEL_INFO, F("IR: No replay solutions found! Press button again or try RAW encoding (timmings are in the serial output)")); serialPrint(String(F("IR: RAW TIMINGS: ")) + resultToSourceCode(&results)); @@ -286,6 +290,7 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) return success; } +#ifdef P016_P035_USE_RAW_RAW2 #define PCT_TOLERANCE 8u //Percent tolerance #define pct_tolerance(v) ((v) / (100u / PCT_TOLERANCE)) //Tolerance % is calculated as the delta between any original timing, and the result after encoding and decoding //#define MIN_TOLERANCE 10u From 38cd2196580e4cf35ec34eeda4071d2619e856ed Mon Sep 17 00:00:00 2001 From: jimmys01 Date: Wed, 13 Nov 2019 12:55:57 +0200 Subject: [PATCH 5/6] [IR RX] Add the extra ' needed for the parsing of the JSON command --- src/_P016_IR.ino | 9 +++++---- src/_P035_IRTX.ino | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index 71bf39862..27bb8844c 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -16,7 +16,7 @@ // // IF the IR code is an Air Condition protocol that the IR library can decode, then there will be a human-readable description of that IR message. // If the IR library can encode those kind of messages then a JSON formated command will be given, that can be replayed by P035 as well. -// That commands format is: IRSENDAC,{"protocol":"COOLIX","power":"on","mode":"dry","fanspeed":"auto","temp":22,"swingv":"max","swingh":"off"} +// That commands format is: IRSENDAC,'{"protocol":"COOLIX","power":"on","mode":"dry","fanspeed":"auto","temp":22,"swingv":"max","swingh":"off"}' #include #include #include @@ -190,8 +190,8 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) if (results.decode_type != decode_type_t::UNKNOWN) { String output = String(F("IRSEND,")) + typeToString(results.decode_type, results.repeat) + ',' + resultToHexidecimal(&results) + ',' + uint64ToString(results.bits); - //addLog(LOG_LEVEL_INFO, output); //Show the appropriate command to the user, so he can replay the message via P035 - addLog(LOG_LEVEL_INFO, String(F("IRSEND,{\"protocol\":\"")) + typeToString(results.decode_type, results.repeat) + String(F("\",\"data\":\"")) + resultToHexidecimal(&results) + String(F("\",\"bits\":")) + uint64ToString(results.bits)+ '}'); //JSON representation of the command + //addLog(LOG_LEVEL_INFO, output); //Show the appropriate command to the user, so he can replay the message via P035 // Old style command + addLog(LOG_LEVEL_INFO, String(F("IRSEND,\'{\"protocol\":\"")) + typeToString(results.decode_type, results.repeat) + String(F("\",\"data\":\"")) + resultToHexidecimal(&results) + String(F("\",\"bits\":")) + uint64ToString(results.bits)+ '}'+'\''); //JSON representation of the command event->String2 = output; } //Check if a solution for RAW2 is found and if not give the user the option to access the timings info. @@ -272,8 +272,9 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) doc[F("sleep")] = state.sleep; //Nr. of mins of sleep mode, or use sleep mode. (<= 0 means off.) if (state.clock >= 0) doc[F("clock")] = state.clock; //Nr. of mins past midnight to set the clock to. (< 0 means off.) - String output = F("IRSENDAC,"); + String output = F("IRSENDAC,'"); serializeJson(doc, output); + output += '\''; event->String2 = output; addLog(LOG_LEVEL_INFO, output); //Show the command that the user can put to replay the AC state with P035 } diff --git a/src/_P035_IRTX.ino b/src/_P035_IRTX.ino index 094ceb90e..e2b835c9c 100644 --- a/src/_P035_IRTX.ino +++ b/src/_P035_IRTX.ino @@ -10,10 +10,10 @@ // Commands can be send to this plug in and it will translate them to IR signals. // Possible commands are IRSEND and IRSENDAC //---IRSEND: That commands format is: IRSEND,,,, -// OR JSON formated: IRSEND,{"protocol":"","data":"","bits":,"repeats":} +// OR JSON formated: IRSEND,'{"protocol":"","data":"","bits":,"repeats":}' // bits and repeat default to 0 if not used and they are optional // For protocols RAW and RAW2 there is no bits and repeat part, they are supposed to be replayed as they are calculated by a Google docs sheet or by plugin P016 -//---IRSENDAC: That commands format is: IRSENDAC,{"protocol":"COOLIX","power":"on","mode":"dry","fanspeed":"auto","temp":22,"swingv":"max","swingh":"off"} +//---IRSENDAC: That commands format is: IRSENDAC,'{"protocol":"COOLIX","power":"on","mode":"dry","fanspeed":"auto","temp":22,"swingv":"max","swingh":"off"}' // The possible values // Protocols: Argo Coolix Daikin Fujitsu Haier Hitachi Kelvinator Midea Mitsubishi MitsubishiHeavy Panasonic Samsung Sharp Tcl Teco Toshiba Trotec Vestel Whirlpool //---opmodes: ---fanspeed: --swingv: --swingh: From ae14a55c05b6783fba909356f5583fc9212145ad Mon Sep 17 00:00:00 2001 From: jimmys01 Date: Wed, 13 Nov 2019 13:50:29 +0200 Subject: [PATCH 6/6] [IR RX] Option to Send IR events to MQTT broker Set a compile time option to send the String representation of the IR signal back to the conrroller. Defaults to the old behaviour so it does not brake anything. --- src/Custom-sample.h | 1 + src/_P016_IR.ino | 29 ++++++++++++++++++----------- src/define_plugin_sets.h | 2 ++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Custom-sample.h b/src/Custom-sample.h index 2cd1d4208..5a8621df4 100644 --- a/src/Custom-sample.h +++ b/src/Custom-sample.h @@ -252,6 +252,7 @@ // Special plugins needing IR library // #define USES_P016 // IR +// #define P016_SEND_IR_TO_CONTROLLER false //IF true then the JSON replay solution is transmited back to the condroller. // #define USES_P035 // IRTX // #define P016_P035_Extended_AC // The following define is needed for extended decoding of A/C Messages and or using standardised //common arguments for controlling all deeply supported A/C units diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index 27bb8844c..e6f2d873a 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -30,6 +30,10 @@ #define PLUGIN_NAME_016 "Communication - TSOP4838" #define PLUGIN_VALUENAME1_016 "IR" +#ifndef P016_SEND_IR_TO_CONTROLLER +#define P016_SEND_IR_TO_CONTROLLER false +#endif + // A lot of the following code has been taken directly (with permission) from the IRrecvDumpV2.ino example code // of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266) @@ -102,7 +106,8 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) { Device[++deviceCount].Number = PLUGIN_ID_016; Device[deviceCount].Type = DEVICE_TYPE_SINGLE; - Device[deviceCount].VType = SENSOR_TYPE_STRING; + if (P016_SEND_IR_TO_CONTROLLER) Device[deviceCount].VType = SENSOR_TYPE_STRING; + else Device[deviceCount].VType = SENSOR_TYPE_LONG; Device[deviceCount].Ports = 0; Device[deviceCount].PullUpOption = true; Device[deviceCount].InverseLogicOption = true; @@ -185,13 +190,14 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) success = false; break; //Do not continue and risk hanging the ESP } - + String output=""; // Display the basic output of what we found. if (results.decode_type != decode_type_t::UNKNOWN) { - String output = String(F("IRSEND,")) + typeToString(results.decode_type, results.repeat) + ',' + resultToHexidecimal(&results) + ',' + uint64ToString(results.bits); + //String output = String(F("IRSEND,")) + typeToString(results.decode_type, results.repeat) + ',' + resultToHexidecimal(&results) + ',' + uint64ToString(results.bits); //addLog(LOG_LEVEL_INFO, output); //Show the appropriate command to the user, so he can replay the message via P035 // Old style command - addLog(LOG_LEVEL_INFO, String(F("IRSEND,\'{\"protocol\":\"")) + typeToString(results.decode_type, results.repeat) + String(F("\",\"data\":\"")) + resultToHexidecimal(&results) + String(F("\",\"bits\":")) + uint64ToString(results.bits)+ '}'+'\''); //JSON representation of the command + output = String(F("{\"protocol\":\"")) + typeToString(results.decode_type, results.repeat) + String(F("\",\"data\":\"")) + resultToHexidecimal(&results) + String(F("\",\"bits\":")) + uint64ToString(results.bits)+ '}'; + addLog(LOG_LEVEL_INFO, String(F("IRSEND,\'"))+output+'\''); //JSON representation of the command event->String2 = output; } //Check if a solution for RAW2 is found and if not give the user the option to access the timings info. @@ -272,18 +278,19 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string) doc[F("sleep")] = state.sleep; //Nr. of mins of sleep mode, or use sleep mode. (<= 0 means off.) if (state.clock >= 0) doc[F("clock")] = state.clock; //Nr. of mins past midnight to set the clock to. (< 0 means off.) - String output = F("IRSENDAC,'"); + output=""; serializeJson(doc, output); - output += '\''; event->String2 = output; - addLog(LOG_LEVEL_INFO, output); //Show the command that the user can put to replay the AC state with P035 + addLog(LOG_LEVEL_INFO, String(F("IRSENDAC,'")) + output+ '\''); //Show the command that the user can put to replay the AC state with P035 } #endif // P016_P035_Extended_AC - - //unsigned long IRcode = results.value; - //UserVar[event->BaseVarIndex] = (IRcode & 0xFFFF); - //UserVar[event->BaseVarIndex + 1] = ((IRcode >> 16) & 0xFFFF); + if (P016_SEND_IR_TO_CONTROLLER) sendData(event); + else { + unsigned long IRcode = results.value; + UserVar[event->BaseVarIndex] = (IRcode & 0xFFFF); + UserVar[event->BaseVarIndex + 1] = ((IRcode >> 16) & 0xFFFF); sendData(event); + } } success = true; break; diff --git a/src/define_plugin_sets.h b/src/define_plugin_sets.h index d79ecca59..ec1d75b68 100644 --- a/src/define_plugin_sets.h +++ b/src/define_plugin_sets.h @@ -319,6 +319,7 @@ To create/register a plugin, you have to : #ifdef PLUGIN_BUILD_IR #define PLUGIN_DESCR "IR" #define USES_P016 // IR + #define P016_SEND_IR_TO_CONTROLLER false //IF true then the JSON replay solution is transmited back to the condroller. #define USES_P035 // IRTX #define P016_P035_USE_RAW_RAW2 //Use the RAW and RAW2 encodings, disabling it saves 3.7Kb #endif @@ -328,6 +329,7 @@ To create/register a plugin, you have to : #define PLUGIN_DESCR "IR Extended" #endif // PLUGIN_DESCR #define USES_P016 // IR + #define P016_SEND_IR_TO_CONTROLLER false //IF true then the JSON replay solution is transmited back to the condroller. #define USES_P035 // IRTX // The following define is needed for extended decoding of A/C Messages and or using standardised common arguments for controlling all deeply supported A/C units #define P016_P035_Extended_AC