update irremote ESP8266 to 2.5.6

This commit is contained in:
Florian committed 2019-03-16 13:16:54 +01:00
1 parent 1abd939125
commit 7a39bba272
36 files changed
+3023 -530

No files matched your search

+23 -2
View File
@@ -759,8 +759,29 @@ boolean sendIdentifiedProtocol(const char * protocol_name, unsigned long data, u
#endif
#ifdef IR_VESTEL_AC
if (strstr(protocol_name, "IR_VESTEL_AC") != NULL){
if (valueBITS == 0) valueBITS = kVestelACBits;
irsend.sendVestelAC(data, valueBITS, valueRPT);
if (valueBITS == 0) valueBITS = kVestelAcBits;
irsend.sendVestelAc(data, valueBITS, valueRPT);
return true;
}
#endif
#ifdef IR_SAMSUNG36
if (strstr(protocol_name, "IR_SAMSUNG36") != NULL){
if (valueBITS == 0) valueBITS = kSamsung36Bits;
irsend.sendSamsung36(data, valueBITS, valueRPT);
return true;
}
#endif
#ifdef IR_TCL112AC
if (strstr(protocol_name, "IR_TCL112AC") != NULL){
if (valueBITS == 0) valueBITS = kTcl112AcStateLength;
irsend.sendTcl112Ac(datastring, valueBITS, valueRPT);
return true;
}
#endif
#ifdef IR_TECO
if (strstr(protocol_name, "IR_TECO") != NULL){
if (valueBITS == 0) valueBITS = kTecoBits;
irsend.sendTeco(data, valueBITS, valueRPT);
return true;
}
#endif
+3
View File
@@ -95,6 +95,9 @@
#define IR_MWM
#define IR_DAIKIN2
#define IR_VESTEL_AC
#define IR_SAMSUNG36
#define IR_TCL112AC
#define IR_TECO
#elif ESP32
#define IR_Raw
#define IR_COOLIX
+2 -1
View File
@@ -12,7 +12,8 @@
- [Jorge Cisneros](https://github.com/jorgecis/)
- [Denes Varga](https://github.com/denxhun/)
- [Brett T. Warden](https://github.com/bwarden/)
- [Fabien Valthier](https://github.com/hcoohb)
All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors).
All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors).
### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md)
+2 -2
View File
@@ -8,8 +8,8 @@
This library enables you to **send _and_ receive** infra-red signals on an [ESP8266 using the Arduino framework](https://github.com/esp8266/Arduino) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* etc.
## v2.5.5 Now Available
Version 2.5.5 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
## v2.5.6 Now Available
Version 2.5.6 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes.
#### Upgrading from pre-v2.0
Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page.
+19
View File
@@ -1,5 +1,24 @@
# Release Notes
## _v2.5.6 (20190316)_
**[Bug Fixes]**
- Fix Coolix A/C Class to handle special states better. (#633, #624)
**[Features]**
- Fix case style for recent A/C protocols. (#631)
- Update `IRsend::send()` to include all simple protocols. (#629, #628)
- Experimental basic support for 112 bit TCL AC messages (#627, #619)
- Add support for TECO AC (#622)
- Experimental support for Samsung 36 bit protocol (#625, #621)
**[Misc]**
- Set Coolix to default to 1 repeat. (#637, #636, #624, #439)
- Set Daikin2 modulation to 36.7kHz. (#635)
- Refactor IRVestelAC class to use portable code. (#617)
- Adjust Daikin2 timings and tolerance. (#616, #582)
## _v2.5.5 (20190207)_
**[Bug Fixes]**
@@ -261,7 +261,7 @@ const uint16_t kMinUnknownSize = 2 * 10;
// ----------------- End of User Configuration Section -------------------------
// Globals
#define _MY_VERSION_ "v0.8.3"
#define _MY_VERSION_ "v0.8.4"
// HTML arguments we will parse for IR code information.
#define argType "type"
#define argData "code"
@@ -467,12 +467,14 @@ void handleRoot() {
"<option value='2'>RC-6</option>"
"<option value='21'>RC-MM</option>"
"<option value='7'>Samsung</option>"
"<option value='56'>Samsung36</option>"
"<option value='11'>Sanyo</option>"
"<option value='22'>Sanyo LC7461</option>"
"<option value='14'>Sharp</option>"
"<option value='19'>Sherwood</option>"
"<option value='4'>Sony</option>"
"<option value='54'>Vestel AC</option>"
"<option value='55'>Teco AC</option>"
"<option value='8'>Whynter</option>"
"</select>"
" Code: 0x<input type='text' name='code' min='0' value='0' size='16'"
@@ -558,6 +560,7 @@ void handleRoot() {
"<option value='20'>Mitsubishi</option>"
"<option value='52'>MWM</option>"
"<option value='46'>Samsung</option>"
"<option value='57'>TCL112</option>"
"<option value='32'>Toshiba</option>"
"<option value='28'>Trotec</option>"
"<option value='45'>Whirlpool</option>"
@@ -723,6 +726,9 @@ bool parseStringAndSendAirCon(const uint16_t irType, const String str) {
// Cap the maximum size.
stateSize = std::min(stateSize, kStateSizeMax);
break;
case TCL112AC:
stateSize = kTcl112AcStateLength;
break;
default: // Not a protocol we expected. Abort.
debug("Unexpected AirCon protocol detected. Ignoring.");
return false;
@@ -852,6 +858,11 @@ bool parseStringAndSendAirCon(const uint16_t irType, const String str) {
case MWM:
irsend.sendMWM(reinterpret_cast<uint8_t *>(state), stateSize);
break;
#endif
#if SEND_TCL112AC
case TCL112AC:
irsend.sendTcl112Ac(reinterpret_cast<uint8_t *>(state));
break;
#endif
default:
debug("Unexpected AirCon type in send request. Not sent.");
@@ -1413,6 +1424,13 @@ bool sendIRCode(int const ir_type, uint64_t const code, char const * code_str,
irsend.sendSAMSUNG(code, bits, repeat);
break;
#endif
#if SEND_SAMSUNG36
case SAMSUNG36: // 56
if (bits == 0)
bits = kSamsung36Bits;
irsend.sendSamsung36(code, bits, repeat);
break;
#endif
#if SEND_WHYNTER
case WHYNTER: // 8
if (bits == 0)
@@ -1612,8 +1630,15 @@ bool sendIRCode(int const ir_type, uint64_t const code, char const * code_str,
#if SEND_VESTEL_AC
case VESTEL_AC: // 54
if (bits == 0)
bits = kVestelACBits;
irsend.sendVestelAC(code, bits, repeat);
bits = kVestelAcBits;
irsend.sendVestelAc(code, bits, repeat);
break;
#endif
#if SEND_TECO
case TECO: // 55
if (bits == 0)
bits = kTecoBits;
irsend.sendTeco(code, bits, repeat);
break;
#endif
default:
@@ -37,6 +37,8 @@
#include <ir_Mitsubishi.h>
#include <ir_Panasonic.h>
#include <ir_Samsung.h>
#include <ir_Tcl.h>
#include <ir_Teco.h>
#include <ir_Toshiba.h>
#include <ir_Vestel.h>
#include <ir_Whirlpool.h>
@@ -225,11 +227,25 @@ void dumpACInfo(decode_results *results) {
#endif // DECODE_WHIRLPOOL_AC
#if DECODE_VESTEL_AC
if (results->decode_type == VESTEL_AC) {
IRVestelAC ac(0);
IRVestelAc ac(0);
ac.setRaw(results->value); // Like Coolix, use value instead of state.
description = ac.toString();
}
#endif // DECODE_VESTEL_AC
#if DECODE_TECO
if (results->decode_type == TECO) {
IRTecoAc ac(0);
ac.setRaw(results->value); // Like Coolix, use value instead of state.
description = ac.toString();
}
#endif // DECODE_TECO
#if DECODE_TCL112AC
if (results->decode_type == TCL112AC) {
IRTcl112Ac ac(0);
ac.setRaw(results->state);
description = ac.toString();
}
#endif // DECODE_TCL112AC
// If we got a human-readable description of the message, display it.
if (description != "") Serial.println("Mesg Desc.: " + description);
}
+124 -30
View File
@@ -34,9 +34,11 @@ IRMideaAC KEYWORD1
IRMitsubishiAC KEYWORD1
IRPanasonicAc KEYWORD1
IRSamsungAc KEYWORD1
IRTcl112Ac KEYWORD1
IRTecoAc KEYWORD1
IRToshibaAC KEYWORD1
IRTrotecESP KEYWORD1
IRVestelAC KEYWORD1
IRVestelAc KEYWORD1
IRWhirlpoolAc KEYWORD1
IRrecv KEYWORD1
IRsend KEYWORD1
@@ -111,13 +113,16 @@ decodeRC5 KEYWORD2
decodeRC6 KEYWORD2
decodeRCMM KEYWORD2
decodeSAMSUNG KEYWORD2
decodeSamsung36 KEYWORD2
decodeSamsungAC KEYWORD2
decodeSanyo KEYWORD2
decodeSanyoLC7461 KEYWORD2
decodeSharp KEYWORD2
decodeSony KEYWORD2
decodeTcl112Ac KEYWORD2
decodeTeco KEYWORD2
decodeToshibaAC KEYWORD2
decodeVestelAC KEYWORD2
decodeVestelAc KEYWORD2
decodeWhirlpoolAC KEYWORD2
decodeWhynter KEYWORD2
disableIRIn KEYWORD2
@@ -177,6 +182,7 @@ getMax KEYWORD2
getMode KEYWORD2
getMold KEYWORD2
getNight KEYWORD2
getNormalState KEYWORD2
getOffTime KEYWORD2
getOffTimer KEYWORD2
getOffTimerEnabled KEYWORD2
@@ -217,9 +223,13 @@ getZoneFollow KEYWORD2
getiFeel KEYWORD2
hasACState KEYWORD2
invertBits KEYWORD2
isOffTimerActive KEYWORD2
isOffTimerEnabled KEYWORD2
isOnTimerActive KEYWORD2
isOnTimerEnabled KEYWORD2
isSpecialState KEYWORD2
isTimeCommand KEYWORD2
isTimerActive KEYWORD2
isTimerEnabled KEYWORD2
ledOff KEYWORD2
ledOn KEYWORD2
@@ -233,6 +243,7 @@ off KEYWORD2
on KEYWORD2
printState KEYWORD2
readbits KEYWORD2
recoverSavedState KEYWORD2
renderTime KEYWORD2
reset KEYWORD2
resultToHexidecimal KEYWORD2
@@ -287,15 +298,18 @@ sendRC6 KEYWORD2
sendRCMM KEYWORD2
sendRaw KEYWORD2
sendSAMSUNG KEYWORD2
sendSamsung36 KEYWORD2
sendSamsungAC KEYWORD2
sendSanyoLC7461 KEYWORD2
sendSharp KEYWORD2
sendSharpRaw KEYWORD2
sendSherwood KEYWORD2
sendSony KEYWORD2
sendTcl112Ac KEYWORD2
sendTeco KEYWORD2
sendToshibaAC KEYWORD2
sendTrotec KEYWORD2
sendVestelAC KEYWORD2
sendVestelAc KEYWORD2
sendWhirlpoolAC KEYWORD2
sendWhynter KEYWORD2
serialPrintUint64 KEYWORD2
@@ -330,7 +344,9 @@ setModel KEYWORD2
setMold KEYWORD2
setNight KEYWORD2
setOffTimer KEYWORD2
setOffTimerActive KEYWORD2
setOnTimer KEYWORD2
setOnTimerActive KEYWORD2
setPower KEYWORD2
setPowerToggle KEYWORD2
setPowerful KEYWORD2
@@ -353,6 +369,7 @@ setTemp KEYWORD2
setTempRaw KEYWORD2
setTime KEYWORD2
setTimer KEYWORD2
setTimerActive KEYWORD2
setTurbo KEYWORD2
setUnknownThreshold KEYWORD2
setVane KEYWORD2
@@ -372,6 +389,7 @@ toggleRC5 KEYWORD2
toggleRC6 KEYWORD2
typeToString KEYWORD2
uint64ToString KEYWORD2
updateSavedState KEYWORD2
validChecksum KEYWORD2
xorBytes KEYWORD2
@@ -467,11 +485,14 @@ DECODE_RC5 LITERAL1
DECODE_RC6 LITERAL1
DECODE_RCMM LITERAL1
DECODE_SAMSUNG LITERAL1
DECODE_SAMSUNG36 LITERAL1
DECODE_SAMSUNG_AC LITERAL1
DECODE_SANYO LITERAL1
DECODE_SHARP LITERAL1
DECODE_SHERWOOD LITERAL1
DECODE_SONY LITERAL1
DECODE_TCL112AC LITERAL1
DECODE_TECO LITERAL1
DECODE_TOSHIBA_AC LITERAL1
DECODE_TROTEC LITERAL1
DECODE_VESTEL_AC LITERAL1
@@ -689,6 +710,7 @@ RC6_MODE0_BITS LITERAL1
RCMM LITERAL1
RCMM_BITS LITERAL1
SAMSUNG LITERAL1
SAMSUNG36 LITERAL1
SAMSUNG_AC LITERAL1
SAMSUNG_BITS LITERAL1
SANYO LITERAL1
@@ -735,11 +757,14 @@ SEND_RC5 LITERAL1
SEND_RC6 LITERAL1
SEND_RCMM LITERAL1
SEND_SAMSUNG LITERAL1
SEND_SAMSUNG36 LITERAL1
SEND_SAMSUNG_AC LITERAL1
SEND_SANYO LITERAL1
SEND_SHARP LITERAL1
SEND_SHERWOOD LITERAL1
SEND_SONY LITERAL1
SEND_TCL112AC LITERAL1
SEND_TECO LITERAL1
SEND_TOSHIBA_AC LITERAL1
SEND_TROTEC LITERAL1
SEND_VESTEL_AC LITERAL1
@@ -753,6 +778,8 @@ SONY LITERAL1
SONY_12_BITS LITERAL1
SONY_15_BITS LITERAL1
SONY_20_BITS LITERAL1
TCL112AC LITERAL1
TECO LITERAL1
TIMEOUT_MS LITERAL1
TOSHIBA_AC LITERAL1
TOSHIBA_AC_AUTO LITERAL1
@@ -887,6 +914,7 @@ kDaikin2BitPurify LITERAL1
kDaikin2BitSleepTimer LITERAL1
kDaikin2Bits LITERAL1
kDaikin2DefaultRepeat LITERAL1
kDaikin2Freq LITERAL1
kDaikin2Gap LITERAL1
kDaikin2HdrMark LITERAL1
kDaikin2HdrSpace LITERAL1
@@ -905,6 +933,7 @@ kDaikin2SwingVBreeze LITERAL1
kDaikin2SwingVCirculate LITERAL1
kDaikin2SwingVHigh LITERAL1
kDaikin2SwingVLow LITERAL1
kDaikin2Tolerance LITERAL1
kDaikin2ZeroSpace LITERAL1
kDaikinAuto LITERAL1
kDaikinBeepLoud LITERAL1
@@ -957,6 +986,7 @@ kDaikinStateLength LITERAL1
kDaikinTolerance LITERAL1
kDaikinUnusedTime LITERAL1
kDaikinZeroSpace LITERAL1
kDefaultMessageGap LITERAL1
kDenonBitMark LITERAL1
kDenonBitMarkTicks LITERAL1
kDenonBits LITERAL1
@@ -1554,6 +1584,7 @@ kRcmmRptLengthTicks LITERAL1
kRcmmTick LITERAL1
kRcmmTolerance LITERAL1
kRepeat LITERAL1
kSamsung36Bits LITERAL1
kSamsungACSectionLength LITERAL1
kSamsungAcAuto LITERAL1
kSamsungAcAutoTemp LITERAL1
@@ -1674,6 +1705,54 @@ kSpaceState LITERAL1
kStartOffset LITERAL1
kStateSizeMax LITERAL1
kStopState LITERAL1
kTcl112AcAuto LITERAL1
kTcl112AcBitMark LITERAL1
kTcl112AcBits LITERAL1
kTcl112AcCool LITERAL1
kTcl112AcDefaultRepeat LITERAL1
kTcl112AcDry LITERAL1
kTcl112AcFan LITERAL1
kTcl112AcGap LITERAL1
kTcl112AcHalfDegree LITERAL1
kTcl112AcHdrMark LITERAL1
kTcl112AcHdrSpace LITERAL1
kTcl112AcHeat LITERAL1
kTcl112AcOneSpace LITERAL1
kTcl112AcPowerMask LITERAL1
kTcl112AcStateLength LITERAL1
kTcl112AcTempMax LITERAL1
kTcl112AcTempMin LITERAL1
kTcl112AcZeroSpace LITERAL1
kTecoAuto LITERAL1
kTecoBitMark LITERAL1
kTecoBits LITERAL1
kTecoCool LITERAL1
kTecoDefaultRepeat LITERAL1
kTecoDry LITERAL1
kTecoFan LITERAL1
kTecoFanAuto LITERAL1
kTecoFanHigh LITERAL1
kTecoFanLow LITERAL1
kTecoFanMask LITERAL1
kTecoFanMed LITERAL1
kTecoGap LITERAL1
kTecoHdrMark LITERAL1
kTecoHdrSpace LITERAL1
kTecoHeat LITERAL1
kTecoMaxTemp LITERAL1
kTecoMinTemp LITERAL1
kTecoModeMask LITERAL1
kTecoOneSpace LITERAL1
kTecoPower LITERAL1
kTecoReset LITERAL1
kTecoSleep LITERAL1
kTecoSwing LITERAL1
kTecoTempMask LITERAL1
kTecoTimerHalfH LITERAL1
kTecoTimerOn LITERAL1
kTecoTimerTenHr LITERAL1
kTecoTimerUniHr LITERAL1
kTecoZeroSpace LITERAL1
kTimeoutMs LITERAL1
kTolerance LITERAL1
kToshibaACBits LITERAL1
@@ -1723,33 +1802,48 @@ kTrotecTimerOn LITERAL1
kTrotecZeroMark LITERAL1
kTrotecZeroSpace LITERAL1
kUnknownThreshold LITERAL1
kVestelACAuto LITERAL1
kVestelACBitMark LITERAL1
kVestelACBits LITERAL1
kVestelACCRCMask LITERAL1
kVestelACCool LITERAL1
kVestelACDry LITERAL1
kVestelACFan LITERAL1
kVestelACFanAuto LITERAL1
kVestelACFanAutoCool LITERAL1
kVestelACFanAutoHot LITERAL1
kVestelACFanHigh LITERAL1
kVestelACFanLow LITERAL1
kVestelACFanMed LITERAL1
kVestelACHdrMark LITERAL1
kVestelACHdrSpace LITERAL1
kVestelACHeat LITERAL1
kVestelACIon LITERAL1
kVestelACMaxTemp LITERAL1
kVestelACMinTempC LITERAL1
kVestelACMinTempH LITERAL1
kVestelACNormal LITERAL1
kVestelACOneSpace LITERAL1
kVestelACSleep LITERAL1
kVestelACSwing LITERAL1
kVestelACTolerance LITERAL1
kVestelACTurbo LITERAL1
kVestelACZeroSpace LITERAL1
kVestelAcAuto LITERAL1
kVestelAcBitMark LITERAL1
kVestelAcBits LITERAL1
kVestelAcCRCMask LITERAL1
kVestelAcChecksumOffset LITERAL1
kVestelAcCool LITERAL1
kVestelAcDry LITERAL1
kVestelAcFan LITERAL1
kVestelAcFanAuto LITERAL1
kVestelAcFanAutoCool LITERAL1
kVestelAcFanAutoHot LITERAL1
kVestelAcFanHigh LITERAL1
kVestelAcFanLow LITERAL1
kVestelAcFanMed LITERAL1
kVestelAcFanOffset LITERAL1
kVestelAcHdrMark LITERAL1
kVestelAcHdrSpace LITERAL1
kVestelAcHeat LITERAL1
kVestelAcHourOffset LITERAL1
kVestelAcIon LITERAL1
kVestelAcIonOffset LITERAL1
kVestelAcMaxTemp LITERAL1
kVestelAcMinTempC LITERAL1
kVestelAcMinTempH LITERAL1
kVestelAcMinuteOffset LITERAL1
kVestelAcModeOffset LITERAL1
kVestelAcNormal LITERAL1
kVestelAcOffTimeOffset LITERAL1
kVestelAcOffTimerFlagOffset LITERAL1
kVestelAcOnTimeOffset LITERAL1
kVestelAcOnTimerFlagOffset LITERAL1
kVestelAcOneSpace LITERAL1
kVestelAcPowerOffset LITERAL1
kVestelAcSleep LITERAL1
kVestelAcSwing LITERAL1
kVestelAcSwingOffset LITERAL1
kVestelAcTempOffset LITERAL1
kVestelAcTimerFlagOffset LITERAL1
kVestelAcTolerance LITERAL1
kVestelAcTurbo LITERAL1
kVestelAcTurboSleepOffset LITERAL1
kVestelAcZeroSpace LITERAL1
kWhirlpoolAcAltTempMask LITERAL1
kWhirlpoolAcAltTempPos LITERAL1
kWhirlpoolAcAuto LITERAL1
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "IRremoteESP8266",
"version": "2.5.5",
"version": "2.5.6",
"keywords": "infrared, ir, remote, esp8266",
"description": "Send and receive infrared signals with multiple protocols (ESP8266)",
"repository":
+1 -1
View File
@@ -1,5 +1,5 @@
name=IRremoteESP8266
version=2.5.5
version=2.5.6
author=Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran
maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto
sentence=Send and receive infrared signals with multiple protocols (ESP8266)
+13 -1
View File
@@ -364,6 +364,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
DPRINTLN("Attempting SAMSUNG decode");
if (decodeSAMSUNG(results)) return true;
#endif
#if DECODE_SAMSUNG36
DPRINTLN("Attempting Samsung36 decode");
if (decodeSamsung36(results)) return true;
#endif
#if DECODE_WHYNTER
DPRINTLN("Attempting Whynter decode");
if (decodeWhynter(results)) return true;
@@ -495,7 +499,15 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
#endif
#if DECODE_VESTEL_AC
DPRINTLN("Attempting Vestel AC decode");
if (decodeVestelAC(results)) return true;
if (decodeVestelAc(results)) return true;
#endif
#if DECODE_TCL112AC
DPRINTLN("Attempting TCL112AC decode");
if (decodeTcl112Ac(results)) return true;
#endif
#if DECODE_TECO
DPRINTLN("Attempting Teco decode");
if (decodeTeco(results)) return true;
#endif
#if DECODE_HASH
// decodeHash returns a hash on any input.
+15 -2
View File
@@ -216,6 +216,11 @@ class IRrecv {
bool decodeSAMSUNG(decode_results *results, uint16_t nbits = kSamsungBits,
bool strict = true);
#endif
#if DECODE_SAMSUNG
bool decodeSamsung36(decode_results *results,
const uint16_t nbits = kSamsung36Bits,
const bool strict = true);
#endif
#if DECODE_SAMSUNG_AC
bool decodeSamsungAC(decode_results *results, uint16_t nbits = kSamsungAcBits,
bool strict = true);
@@ -335,8 +340,16 @@ class IRrecv {
bool strict = true);
#endif
#if DECODE_VESTEL_AC
bool decodeVestelAC(decode_results *results, uint16_t nbits = kVestelACBits,
bool strict = true);
bool decodeVestelAc(decode_results *results, uint16_t nbits = kVestelAcBits,
bool strict = true);
#endif
#if DECODE_TCL112AC
bool decodeTcl112Ac(decode_results *results, uint16_t nbits = kTcl112AcBits,
bool strict = true);
#endif
#if DECODE_TECO
bool decodeTeco(decode_results *results, uint16_t nbits = kTecoBits,
bool strict = false);
#endif
};
+25 -5
View File
@@ -35,6 +35,7 @@
* Trotec AC code by stufisher
* Carrier & Haier AC code by crankyoldgit
* Vestel AC code by Erdem U. Altınyurt
* Teco AC code by Fabien Valthier (hcoohb)
*
* GPL license, all text above must be included in any redistribution
****************************************************/
@@ -49,7 +50,7 @@
#endif
// Library Version
#define _IRREMOTEESP8266_VERSION_ "2.5.5"
#define _IRREMOTEESP8266_VERSION_ "2.5.6"
// Supported IR protocols
// Each protocol you include costs memory and, during decode, costs time
// Disable (set to false) all the protocols you do not need/want!
@@ -86,6 +87,9 @@
#define DECODE_SAMSUNG true
#define SEND_SAMSUNG true
#define DECODE_SAMSUNG36 true
#define SEND_SAMSUNG36 true
#define DECODE_SAMSUNG_AC true
#define SEND_SAMSUNG_AC true
@@ -206,12 +210,19 @@
#define DECODE_VESTEL_AC true
#define SEND_VESTEL_AC true
#define DECODE_TECO true
#define SEND_TECO true
#define DECODE_TCL112AC true
#define SEND_TCL112AC true
#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2 || DECODE_HAIER_AC_YRW02 || \
DECODE_WHIRLPOOL_AC || DECODE_SAMSUNG_AC || DECODE_ELECTRA_AC || \
DECODE_PANASONIC_AC || DECODE_MWM || DECODE_DAIKIN2 || DECODE_VESTEL_AC )
DECODE_PANASONIC_AC || DECODE_MWM || DECODE_DAIKIN2 || \
DECODE_VESTEL_AC || DECODE_TCL112AC)
#define DECODE_AC true // We need some common infrastructure for decoding A/Cs.
#else
#define DECODE_AC false // We don't need that infrastructure.
@@ -280,11 +291,14 @@ enum decode_type_t {
LUTRON,
ELECTRA_AC,
PANASONIC_AC,
PIONEER, // 50
PIONEER, // (50)
LG2,
MWM,
DAIKIN2,
VESTEL_AC,
TECO, // (55)
SAMSUNG36,
TCL112AC,
};
// Message lengths & required repeat values
@@ -296,7 +310,7 @@ const uint16_t kAiwaRcT501MinRepeats = kSingleRepeat;
const uint16_t kArgoStateLength = 12;
const uint16_t kArgoDefaultRepeat = kNoRepeat;
const uint16_t kCoolixBits = 24;
const uint16_t kCoolixDefaultRepeat = kNoRepeat;
const uint16_t kCoolixDefaultRepeat = 1;
const uint16_t kCarrierAcBits = 32;
const uint16_t kCarrierAcMinRepeat = kNoRepeat;
// Daikin has a lot of static stuff that is discarded
@@ -373,6 +387,7 @@ const uint16_t kRC6Mode0Bits = 20; // Excludes the 'start' bit.
const uint16_t kRC6_36Bits = 36; // Excludes the 'start' bit.
const uint16_t kRCMMBits = 24;
const uint16_t kSamsungBits = 32;
const uint16_t kSamsung36Bits = 36;
const uint16_t kSamsungAcStateLength = 14;
const uint16_t kSamsungAcBits = kSamsungAcStateLength * 8;
const uint16_t kSamsungAcExtendedStateLength = 21;
@@ -393,6 +408,11 @@ const uint16_t kSony15Bits = 15;
const uint16_t kSony20Bits = 20;
const uint16_t kSonyMinBits = 12;
const uint16_t kSonyMinRepeat = 2;
const uint16_t kTcl112AcStateLength = 14;
const uint16_t kTcl112AcBits = kTcl112AcStateLength * 8;
const uint16_t kTcl112AcDefaultRepeat = kNoRepeat;
const uint16_t kTecoBits = 35;
const uint16_t kTecoDefaultRepeat = kNoRepeat;
const uint16_t kToshibaACStateLength = 9;
const uint16_t kToshibaACBits = kToshibaACStateLength * 8;
const uint16_t kToshibaACMinRepeat = kSingleRepeat;
@@ -402,7 +422,7 @@ const uint16_t kWhirlpoolAcStateLength = 21;
const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8;
const uint16_t kWhirlpoolAcDefaultRepeat = kNoRepeat;
const uint16_t kWhynterBits = 32;
const uint8_t kVestelACBits = 56;
const uint8_t kVestelAcBits = 56;
// Legacy defines. (Deprecated)
+132 -74
View File
@@ -1,6 +1,6 @@
// Copyright 2009 Ken Shirriff
// Copyright 2015 Mark Szabo
// Copyright 2017 David Conran
// Copyright 2017,2019 David Conran
#include "IRsend.h"
#ifndef UNIT_TEST
@@ -488,57 +488,24 @@ void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) {
}
#endif // SEND_RAW
#ifndef UNIT_TEST
void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) {
// Send a simple (up to 64 bits) IR message of a given type.
// An unknown/unsupported type will do nothing.
// Args:
// type: Protocol number/type of the message you want to send.
// data: The data you want to send (up to 64 bits).
// nbits: How many bits long the message is to be.
// Returns:
// bool: True if it is a type we can attempt to send, false if not.
bool IRsend::send(decode_type_t type, uint64_t data, uint16_t nbits) {
switch (type) {
#if SEND_NEC
case NEC:
sendNEC(data, nbits);
#if SEND_AIWA_RC_T501
case AIWA_RC_T501:
sendAiwaRCT501(data, nbits);
break;
#endif
#if SEND_SONY
case SONY:
sendSony(data, nbits);
break;
#endif
#if SEND_RC5
case RC5:
sendRC5(data, nbits);
break;
#endif
#if SEND_RC6
case RC6:
sendRC6(data, nbits);
break;
#endif
#if SEND_DISH
case DISH:
sendDISH(data, nbits);
break;
#endif
#if SEND_JVC
case JVC:
sendJVC(data, nbits);
break;
#endif
#if SEND_SAMSUNG
case SAMSUNG:
sendSAMSUNG(data, nbits);
break;
#endif
#if SEND_LG
case LG:
sendLG(data, nbits);
break;
#endif
#if SEND_LG
case LG2:
sendLG2(data, nbits);
break;
#endif
#if SEND_WHYNTER
case WHYNTER:
sendWhynter(data, nbits);
#if SEND_CARRIER_AC
case CARRIER_AC:
sendCarrierAC(data, nbits);
break;
#endif
#if SEND_COOLIX
@@ -551,14 +518,52 @@ void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) {
sendDenon(data, nbits);
break;
#endif
#if SEND_SHERWOOD
case SHERWOOD:
sendSherwood(data, nbits);
#if SEND_DISH
case DISH:
sendDISH(data, nbits);
break;
#endif
#if SEND_RCMM
case RCMM:
sendRCMM(data, nbits);
#if SEND_GICABLE
case GICABLE:
sendGICable(data, nbits);
break;
#endif
#if SEND_GREE
case GREE:
sendGree(data, nbits);
break;
#endif
#if SEND_JVC
case JVC:
sendJVC(data, nbits);
break;
#endif
#if SEND_LASERTAG
case LASERTAG:
sendLasertag(data, nbits);
break;
#endif
#if SEND_LG
case LG:
sendLG(data, nbits);
break;
case LG2:
sendLG2(data, nbits);
break;
#endif
#if SEND_LUTRON
case LUTRON:
sendLutron(data, nbits);
break;
#endif
#if SEND_MAGIQUEST
case MAGIQUEST:
sendMagiQuest(data, nbits);
break;
#endif
#if SEND_MIDEA
case MIDEA:
sendMidea(data, nbits);
break;
#endif
#if SEND_MITSUBISHI
@@ -571,24 +576,20 @@ void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) {
sendMitsubishi2(data, nbits);
break;
#endif
#if SEND_SHARP
case SHARP:
sendSharpRaw(data, nbits);
#if SEND_NIKAI
case NIKAI:
sendNikai(data, nbits);
break;
#endif
#if SEND_AIWA_RC_T501
case AIWA_RC_T501:
sendAiwaRCT501(data, nbits);
#if SEND_NEC
case NEC:
case NEC_LIKE:
sendNEC(data, nbits);
break;
#endif
#if SEND_MIDEA
case MIDEA:
sendMidea(data, nbits);
break;
#endif
#if SEND_GICABLE
case GICABLE:
sendGICable(data, nbits);
#if SEND_PANASONIC
case PANASONIC:
sendPanasonic64(data, nbits);
break;
#endif
#if SEND_PIONEER
@@ -596,11 +597,68 @@ void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) {
sendPioneer(data, nbits);
break;
#endif
#if SEND_VESTEL_AC
case VESTEL_AC:
sendVestelAC(data, nbits);
#if SEND_RC5
case RC5:
sendRC5(data, nbits);
break;
#endif
}
}
#if SEND_RC6
case RC6:
sendRC6(data, nbits);
break;
#endif
#if SEND_RCMM
case RCMM:
sendRCMM(data, nbits);
break;
#endif
#if SEND_SAMSUNG
case SAMSUNG:
sendSAMSUNG(data, nbits);
break;
#endif
#if SEND_SAMSUNG36
case SAMSUNG36:
sendSamsung36(data, nbits);
break;
#endif
#if SEND_SANYO
case SANYO_LC7461:
sendSanyoLC7461(data, nbits);
break;
#endif
#if SEND_SHARP
case SHARP:
sendSharpRaw(data, nbits);
break;
#endif
#if SEND_SHERWOOD
case SHERWOOD:
sendSherwood(data, nbits);
break;
#endif
#if SEND_SONY
case SONY:
sendSony(data, nbits);
break;
#endif
#if SEND_TECO
case TECO:
sendTeco(data, nbits);
break;
#endif
#if SEND_VESTEL_AC
case VESTEL_AC:
sendVestelAc(data, nbits);
break;
#endif
#if SEND_WHYNTER
case WHYNTER:
sendWhynter(data, nbits);
break;
#endif
default:
return false;
}
return true;
}
+18 -2
View File
@@ -28,6 +28,8 @@ const uint8_t kDutyMax = 100; // Percentage
// delayMicroseconds() is only accurate to 16383us.
// Ref: https://www.arduino.cc/en/Reference/delayMicroseconds
const uint16_t kMaxAccurateUsecDelay = 16383;
// Usecs to wait between messages we don't know the proper gap time.
const uint32_t kDefaultMessageGap = 1000000;
// Classes
class IRsend {
@@ -66,7 +68,7 @@ class IRsend {
const uint8_t *dataptr, const uint16_t nbytes,
const uint16_t frequency, const bool MSBfirst,
const uint16_t repeat, const uint8_t dutycycle);
void send(uint16_t type, uint64_t data, uint16_t nbits);
bool send(decode_type_t type, uint64_t data, uint16_t nbits);
#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO)
void sendNEC(uint64_t data, uint16_t nbits = kNECBits,
uint16_t repeat = kNoRepeat);
@@ -92,6 +94,10 @@ class IRsend {
uint16_t repeat = kNoRepeat);
uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command);
#endif
#if SEND_SAMSUNG36
void sendSamsung36(const uint64_t data, const uint16_t nbits = kSamsung36Bits,
const uint16_t repeat = kNoRepeat);
#endif
#if SEND_SAMSUNG_AC
void sendSamsungAC(unsigned char data[],
uint16_t nbytes = kSamsungAcStateLength,
@@ -309,9 +315,19 @@ class IRsend {
uint16_t repeat = kNoRepeat);
#endif
#if SEND_VESTEL_AC
void sendVestelAC(const uint64_t data, const uint16_t nbits = kVestelACBits,
void sendVestelAc(const uint64_t data, const uint16_t nbits = kVestelAcBits,
const uint16_t repeat = kNoRepeat);
#endif
#if SEND_TCL112AC
void sendTcl112Ac(const unsigned char data[],
const uint16_t nbytes = kTcl112AcStateLength,
const uint16_t repeat = kTcl112AcDefaultRepeat);
#endif
#if SEND_TECO
void sendTeco(uint64_t data, uint16_t nbits = kTecoBits,
uint16_t repeat = kNoRepeat);
#endif
protected:
#ifdef UNIT_TEST
+10
View File
@@ -231,6 +231,9 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case SAMSUNG:
result = "SAMSUNG";
break;
case SAMSUNG36:
result = "SAMSUNG36";
break;
case SAMSUNG_AC:
result = "SAMSUNG_AC";
break;
@@ -249,6 +252,12 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case SONY:
result = "SONY";
break;
case TCL112AC:
result = "TCL112AC";
break;
case TECO:
result = "TECO";
break;
case TOSHIBA_AC:
result = "TOSHIBA_AC";
break;
@@ -287,6 +296,7 @@ bool hasACState(const decode_type_t protocol) {
case MWM:
case PANASONIC_AC:
case SAMSUNG_AC:
case TCL112AC:
case TOSHIBA_AC:
case WHIRLPOOL_AC:
return true;
+109 -52
View File
@@ -93,7 +93,7 @@ void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) {
// https://github.com/markszabo/IRremoteESP8266/issues/484
IRCoolixAC::IRCoolixAC(uint16_t pin) : _irsend(pin) { stateReset(); }
void IRCoolixAC::stateReset() { remote_state = kCoolixDefaultState; }
void IRCoolixAC::stateReset() { setRaw(kCoolixDefaultState); }
void IRCoolixAC::begin() { _irsend.begin(); }
@@ -105,15 +105,50 @@ void IRCoolixAC::send(const uint16_t repeat) {
uint32_t IRCoolixAC::getRaw() { return remote_state; }
void IRCoolixAC::setRaw(const uint32_t new_code) { remote_state = new_code; }
void IRCoolixAC::setRaw(const uint32_t new_code) {
remote_state = new_code;
saved_state = new_code;
}
// Return true if the current state is a special state.
bool IRCoolixAC::isSpecialState(void) {
switch (remote_state) {
case kCoolixClean:
case kCoolixLed:
case kCoolixOff:
case kCoolixSwing:
case kCoolixSleep:
case kCoolixTurbo:
return true;
default:
return false;
}
}
void IRCoolixAC::updateSavedState(void) {
if (!isSpecialState()) saved_state = remote_state;
}
void IRCoolixAC::recoverSavedState(void) {
// If the current state is a special one, last known normal one.
if (isSpecialState()) remote_state = saved_state;
// If the saved_state was also a special state, reset as we expect a normal
// state out of all this.
if (isSpecialState()) stateReset();
}
uint32_t IRCoolixAC::getNormalState(void) {
return isSpecialState() ? saved_state : remote_state;
}
void IRCoolixAC::setTempRaw(const uint8_t code) {
recoverSavedState();
remote_state &= ~kCoolixTempMask; // Clear the old temp.
remote_state |= (code << 4);
}
uint8_t IRCoolixAC::getTempRaw() {
return (remote_state & kCoolixTempMask) >> 4;
return (getNormalState() & kCoolixTempMask) >> 4;
}
void IRCoolixAC::setTemp(const uint8_t desired) {
@@ -132,6 +167,7 @@ uint8_t IRCoolixAC::getTemp() {
}
void IRCoolixAC::setSensorTempRaw(const uint8_t code) {
recoverSavedState();
remote_state &= ~kCoolixSensorTempMask; // Clear previous sensor temp.
remote_state |= ((code & 0xF) << 8);
}
@@ -145,7 +181,8 @@ void IRCoolixAC::setSensorTemp(const uint8_t desired) {
}
uint8_t IRCoolixAC::getSensorTemp() {
return ((remote_state & kCoolixSensorTempMask) >> 8) + kCoolixSensorTempMin;
return ((getNormalState() & kCoolixSensorTempMask) >> 8) +
kCoolixSensorTempMin;
}
bool IRCoolixAC::getPower() {
@@ -154,25 +191,35 @@ bool IRCoolixAC::getPower() {
}
void IRCoolixAC::setPower(const bool power) {
if (!power) remote_state = kCoolixOff;
// There really is no distinct "on" setting, so do nothing.
if (power) {
// There really is no distinct "on" setting, just ensure it a normal state.
recoverSavedState();
} else {
updateSavedState();
remote_state = kCoolixOff;
}
}
bool IRCoolixAC::getSwing() { return remote_state == kCoolixSwing; }
void IRCoolixAC::setSwing() {
// Assumes that repeated sending "swing" toggles the action on the device.
updateSavedState();
remote_state = kCoolixSwing;
}
bool IRCoolixAC::getSleep() { return remote_state == kCoolixSleep; }
void IRCoolixAC::setSleep() { remote_state = kCoolixSleep; }
void IRCoolixAC::setSleep() {
updateSavedState();
remote_state = kCoolixSleep;
}
bool IRCoolixAC::getTurbo() { return remote_state == kCoolixTurbo; }
void IRCoolixAC::setTurbo() {
// Assumes that repeated sending "turbo" toggles the action on the device.
updateSavedState();
remote_state = kCoolixTurbo;
}
@@ -180,19 +227,24 @@ bool IRCoolixAC::getLed() { return remote_state == kCoolixLed; }
void IRCoolixAC::setLed() {
// Assumes that repeated sending "Led" toggles the action on the device.
updateSavedState();
remote_state = kCoolixLed;
}
bool IRCoolixAC::getClean() { return remote_state == kCoolixClean; }
void IRCoolixAC::setClean() { remote_state = kCoolixClean; }
void IRCoolixAC::setClean() {
updateSavedState();
remote_state = kCoolixClean;
}
bool IRCoolixAC::getZoneFollow() {
return remote_state & kCoolixZoneFollowMask;
return getNormalState() & kCoolixZoneFollowMask;
}
// Internal use only.
void IRCoolixAC::setZoneFollow(bool state) {
recoverSavedState();
if (state) {
remote_state |= kCoolixZoneFollowMask;
} else {
@@ -201,6 +253,7 @@ void IRCoolixAC::setZoneFollow(bool state) {
}
void IRCoolixAC::clearSensorTemp() {
recoverSavedState();
setZoneFollow(false);
setSensorTempRaw(kCoolixSensorTempIgnoreCode);
}
@@ -214,6 +267,7 @@ void IRCoolixAC::setMode(const uint8_t mode) {
case kCoolixAuto:
case kCoolixHeat:
case kCoolixDry:
recoverSavedState();
remote_state = (remote_state & ~kCoolixModeMask) | (actualmode << 2);
// Force the temp into a known-good state.
setTemp(getTemp());
@@ -222,15 +276,18 @@ void IRCoolixAC::setMode(const uint8_t mode) {
}
uint8_t IRCoolixAC::getMode() {
uint8_t mode = (remote_state & kCoolixModeMask) >> 2;
uint8_t mode = (getNormalState() & kCoolixModeMask) >> 2;
if (mode == kCoolixDry)
if (getTempRaw() == kCoolixFanTempCode) return kCoolixFan;
return mode;
}
uint8_t IRCoolixAC::getFan() { return (remote_state & kCoolixFanMask) >> 13; }
uint8_t IRCoolixAC::getFan() {
return (getNormalState() & kCoolixFanMask) >> 13;
}
void IRCoolixAC::setFan(const uint8_t speed) {
recoverSavedState();
uint8_t newspeed = speed;
switch (speed) {
case kCoolixFanMin:
@@ -263,6 +320,47 @@ std::string IRCoolixAC::toString() {
result += "Off";
return result; // If it's off, there is no other info.
}
// Special modes.
if (getSwing()) {
result += ", Swing: Toggle";
return result;
}
if (getSleep()) {
result += ", Sleep: Toggle";
return result;
}
if (getTurbo()) {
result += ", Turbo: Toggle";
return result;
}
if (getLed()) {
result += ", Led: Toggle";
return result;
}
if (getClean()) {
result += ", Clean: Toggle";
return result;
}
result += ", Mode: " + uint64ToString(getMode());
switch (getMode()) {
case kCoolixAuto:
result += " (AUTO)";
break;
case kCoolixCool:
result += " (COOL)";
break;
case kCoolixHeat:
result += " (HEAT)";
break;
case kCoolixDry:
result += " (DRY)";
break;
case kCoolixFan:
result += " (FAN)";
break;
default:
result += " (UNKNOWN)";
}
result += ", Fan: " + uint64ToString(getFan());
switch (getFan()) {
case kCoolixFanAuto:
@@ -289,47 +387,6 @@ std::string IRCoolixAC::toString() {
default:
result += " (UNKNOWN)";
}
// Special modes.
if (getSwing()) {
result += ", Swing: Toggle";
return result;
}
if (getSleep()) {
result += ", Sleep: Toggle";
return result;
}
if (getTurbo()) {
result += ", Turbo: Toggle";
return result;
}
if (getLed()) {
result += ", Led: Toggle";
return result;
}
if (getClean()) {
result += ", Mode: Self clean";
return result;
}
result += ", Mode: " + uint64ToString(getMode());
switch (getMode()) {
case kCoolixAuto:
result += " (AUTO)";
break;
case kCoolixCool:
result += " (COOL)";
break;
case kCoolixHeat:
result += " (HEAT)";
break;
case kCoolixDry:
result += " (DRY)";
break;
case kCoolixFan:
result += " (FAN)";
break;
default:
result += " (UNKNOWN)";
}
if (getMode() != kCoolixFan) // Fan mode doesn't have a temperature.
result += ", Temp: " + uint64ToString(getTemp()) + "C";
result += ", Zone Follow: ";
+6 -2
View File
@@ -128,13 +128,17 @@ class IRCoolixAC {
#endif
private:
// The state of the IR remote in IR code form.
uint32_t remote_state;
uint32_t remote_state; // The state of the IR remote in IR code form.
uint32_t saved_state; // Copy of the state if we required a special mode.
IRsend _irsend;
void setTempRaw(const uint8_t code);
uint8_t getTempRaw();
void setSensorTempRaw(const uint8_t code);
void setZoneFollow(const bool state);
bool isSpecialState(void);
void updateSavedState(void);
void recoverSavedState(void);
uint32_t getNormalState(void);
};
#endif // IR_COOLIX_H_
+18 -12
View File
@@ -755,18 +755,18 @@ void IRsend::sendDaikin2(unsigned char data[], uint16_t nbytes,
// Leader
sendGeneric(kDaikin2LeaderMark, kDaikin2LeaderSpace,
0, 0, 0, 0, 0, 0, (uint64_t) 0, // No data payload.
0, 38000, false, 0, 50);
0, kDaikin2Freq, false, 0, 50);
// Section #1
sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark,
kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace,
kDaikin2BitMark, kDaikin2Gap, data, kDaikin2Section1Length,
38000, false, 0, 50);
kDaikin2Freq, false, 0, 50);
// Section #2
sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark,
kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace,
kDaikin2BitMark, kDaikin2Gap, data + kDaikin2Section1Length,
nbytes - kDaikin2Section1Length,
38000, false, 0, 50);
kDaikin2Freq, false, 0, 50);
}
}
#endif // SEND_DAIKIN2
@@ -1354,9 +1354,10 @@ bool IRrecv::decodeDaikin2(decode_results *results, uint16_t nbits,
kDaikin2Section2Length};
// Leader
if (!matchMark(results->rawbuf[offset++], kDaikin2LeaderMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kDaikin2LeaderSpace))
return false;
if (!matchMark(results->rawbuf[offset++], kDaikin2LeaderMark,
kDaikin2Tolerance)) return false;
if (!matchSpace(results->rawbuf[offset++], kDaikin2LeaderSpace,
kDaikin2Tolerance)) return false;
// Sections
// Keep reading bytes until we either run out of section or state to fill.
@@ -1365,8 +1366,10 @@ bool IRrecv::decodeDaikin2(decode_results *results, uint16_t nbits,
pos += sectionSize[section];
// Section Header
if (!matchMark(results->rawbuf[offset++], kDaikin2HdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kDaikin2HdrSpace)) return false;
if (!matchMark(results->rawbuf[offset++], kDaikin2HdrMark,
kDaikin2Tolerance)) return false;
if (!matchSpace(results->rawbuf[offset++], kDaikin2HdrSpace,
kDaikin2Tolerance)) return false;
// Section Data
for (; offset <= results->rawlen - 16 && i < pos;
@@ -1375,18 +1378,21 @@ bool IRrecv::decodeDaikin2(decode_results *results, uint16_t nbits,
data_result =
matchData(&(results->rawbuf[offset]), 8, kDaikin2BitMark,
kDaikin2OneSpace, kDaikin2BitMark,
kDaikin2ZeroSpace, kTolerance, kMarkExcess, false);
kDaikin2ZeroSpace, kDaikin2Tolerance, kMarkExcess, false);
if (data_result.success == false) break; // Fail
results->state[i] = (uint8_t)data_result.data;
}
// Section Footer
if (!matchMark(results->rawbuf[offset++], kDaikin2BitMark)) return false;
if (!matchMark(results->rawbuf[offset++], kDaikin2BitMark,
kDaikin2Tolerance)) return false;
if (section < kDaikin2Sections - 1) { // Inter-section gaps.
if (!matchSpace(results->rawbuf[offset++], kDaikin2Gap)) return false;
if (!matchSpace(results->rawbuf[offset++], kDaikin2Gap,
kDaikin2Tolerance)) return false;
} else { // Last section / End of message gap.
if (offset <= results->rawlen &&
!matchAtLeast(results->rawbuf[offset++], kDaikin2Gap)) return false;
!matchAtLeast(results->rawbuf[offset++], kDaikin2Gap,
kDaikin2Tolerance)) return false;
}
}
+5 -3
View File
@@ -128,17 +128,19 @@ const uint64_t kDaikinFirstHeader64 =
0b1101011100000000000000001100010100000000001001111101101000010001;
// Another variant of the protocol for the Daikin ARC477A1 remote.
const uint16_t kDaikin2Freq = 36700; // Modulation Frequency in Hz.
const uint16_t kDaikin2LeaderMark = 10024;
const uint16_t kDaikin2LeaderSpace = 25180;
const uint16_t kDaikin2Gap = kDaikin2LeaderMark + kDaikin2LeaderSpace;
const uint16_t kDaikin2HdrMark = 3500;
const uint16_t kDaikin2HdrSpace = 1728;
const uint16_t kDaikin2BitMark = 418;
const uint16_t kDaikin2OneSpace = 1315;
const uint16_t kDaikin2ZeroSpace = 451;
const uint16_t kDaikin2BitMark = 460;
const uint16_t kDaikin2OneSpace = 1270;
const uint16_t kDaikin2ZeroSpace = 420;
const uint16_t kDaikin2Sections = 2;
const uint16_t kDaikin2Section1Length = 20;
const uint16_t kDaikin2Section2Length = 19;
const uint8_t kDaikin2Tolerance = kTolerance + 5;
const uint8_t kDaikin2BitSleepTimer = 0b00100000;
const uint8_t kDaikin2BitPurify = 0b00010000;
+122 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017 David Conran
// Copyright 2017, 2018, 2019 David Conran
#include "ir_Samsung.h"
#include <algorithm>
@@ -168,6 +168,127 @@ bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits,
}
#endif
#if SEND_SAMSUNG36
// Send a Samsung 36-bit formatted message.
//
// Args:
// data: The message to be sent.
// nbits: The bit size of the message being sent. typically kSamsung36Bits.
// repeat: The number of times the message is to be repeated.
//
// Status: Alpha / Experimental.
//
// Note:
// Protocol is used by Samsung Bluray Remote: ak59-00167a
//
// Ref:
// https://github.com/markszabo/IRremoteESP8266/issues/621
void IRsend::sendSamsung36(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
if (nbits < 16) return; // To small to send.
for (uint16_t r = 0; r <= repeat; r++) {
// Block #1 (16 bits)
sendGeneric(kSamsungHdrMark, kSamsungHdrSpace,
kSamsungBitMark, kSamsungOneSpace,
kSamsungBitMark, kSamsungZeroSpace,
kSamsungBitMark, kSamsungHdrSpace,
data >> (nbits - 16), 16, 38, true, 0, kDutyDefault);
// Block #2 (The rest, typically 20 bits)
sendGeneric(0, 0, // No header
kSamsungBitMark, kSamsungOneSpace,
kSamsungBitMark, kSamsungZeroSpace,
kSamsungBitMark, kSamsungMinGap, // Gap is just a guess.
// Mask off the rest of the bits.
data & ((1ULL << (nbits - 16)) - 1),
nbits - 16, 38, true, 0, kDutyDefault);
}
}
#endif // SEND_SAMSUNG36
#if DECODE_SAMSUNG36
// Decode the supplied Samsung36 message.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: Nr. of bits to expect in the data portion.
// Typically kSamsung36Bits.
// strict: Flag to indicate if we strictly adhere to the specification.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: Alpha / Experimental
//
// Note:
// Protocol is used by Samsung Bluray Remote: ak59-00167a
//
// Ref:
// https://github.com/markszabo/IRremoteESP8266/issues/621
bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits,
const bool strict) {
if (results->rawlen < 2 * nbits + kHeader + kFooter * 2 - 1)
return false; // Can't possibly be a valid Samsung message.
// We need to be looking for > 16 bits to make sense.
if (nbits <= 16) return false;
if (strict && nbits != kSamsung36Bits)
return false; // We expect nbits to be 36 bits of message.
uint64_t data = 0;
uint16_t offset = kStartOffset;
// Header
if (!matchMark(results->rawbuf[offset], kSamsungHdrMark)) return false;
// Calculate how long the common tick time is based on the header mark.
uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kSamsungHdrMarkTicks;
if (!matchSpace(results->rawbuf[offset], kSamsungHdrSpace)) return false;
// Calculate how long the common tick time is based on the header space.
uint32_t s_tick =
results->rawbuf[offset++] * kRawTick / kSamsungHdrSpaceTicks;
// Data (Block #1)
match_result_t data_result =
matchData(&(results->rawbuf[offset]), 16,
kSamsungBitMarkTicks * m_tick, kSamsungOneSpaceTicks * s_tick,
kSamsungBitMarkTicks * m_tick, kSamsungZeroSpaceTicks * s_tick);
if (data_result.success == false) return false;
data = data_result.data;
offset += data_result.used;
uint16_t bitsSoFar = data_result.used / 2;
// Footer (Block #1)
if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick))
return false;
if (!matchSpace(results->rawbuf[offset++], kSamsungHdrSpaceTicks * s_tick))
return false;
// Data (Block #2)
data_result = matchData(&(results->rawbuf[offset]),
nbits - 16,
kSamsungBitMarkTicks * m_tick,
kSamsungOneSpaceTicks * s_tick,
kSamsungBitMarkTicks * m_tick,
kSamsungZeroSpaceTicks * s_tick);
if (data_result.success == false) return false;
data <<= (nbits - 16);
data += data_result.data;
offset += data_result.used;
bitsSoFar += data_result.used / 2;
// Footer (Block #2)
if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick))
return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset], kSamsungMinGapTicks * s_tick))
return false;
// Compliance
if (nbits != bitsSoFar) return false;
// Success
results->bits = bitsSoFar;
results->value = data;
results->decode_type = SAMSUNG36;
results->command = data & ((1ULL << (nbits - 16)) - 1);
results->address = data >> (nbits - 16);
return true;
}
#endif // DECODE_SAMSUNG36
#if SEND_SAMSUNG_AC
// Send a Samsung A/C message.
//
+253
View File
@@ -0,0 +1,253 @@
// Copyright 2019 David Conran
#include "ir_Tcl.h"
#include <algorithm>
#ifndef ARDUINO
#include <string>
#endif
#include "IRremoteESP8266.h"
#include "IRutils.h"
// Constants
#if SEND_TCL112AC
void IRsend::sendTcl112Ac(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
sendGeneric(kTcl112AcHdrMark, kTcl112AcHdrSpace,
kTcl112AcBitMark, kTcl112AcOneSpace,
kTcl112AcBitMark, kTcl112AcZeroSpace,
kTcl112AcBitMark, kTcl112AcGap,
data, nbytes, 38000, false, repeat, 50);
}
#endif // SEND_TCL112AC
IRTcl112Ac::IRTcl112Ac(uint16_t pin) : _irsend(pin) { stateReset(); }
void IRTcl112Ac::begin() { this->_irsend.begin(); }
#if SEND_TCL112AC
void IRTcl112Ac::send(const uint16_t repeat) {
this->checksum();
this->_irsend.sendTcl112Ac(remote_state, kTcl112AcStateLength, repeat);
}
#endif // SEND_TCL112AC
// Calculate the checksum for a given array.
// Args:
// state: The array to calculate the checksum over.
// length: The size of the array.
// Returns:
// The 8 bit checksum value.
uint8_t IRTcl112Ac::calcChecksum(uint8_t state[],
const uint16_t length) {
if (length)
return sumBytes(state, length - 1);
else
return 0;
}
// Calculate & set the checksum for the current internal state of the remote.
void IRTcl112Ac::checksum(const uint16_t length) {
// Stored the checksum value in the last byte.
if (length > 1)
remote_state[length - 1] = calcChecksum(remote_state, length);
}
// Verify the checksum is valid for a given state.
// Args:
// state: The array to verify the checksum of.
// length: The size of the state.
// Returns:
// A boolean.
bool IRTcl112Ac::validChecksum(uint8_t state[], const uint16_t length) {
return (length > 1 && state[length - 1] == calcChecksum(state, length));
}
void IRTcl112Ac::stateReset() {
for (uint8_t i = 0; i < kTcl112AcStateLength; i++)
remote_state[i] = 0x0;
// A known good state. (On, Cool, 24C)
remote_state[0] = 0x23;
remote_state[1] = 0xCB;
remote_state[2] = 0x26;
remote_state[3] = 0x01;
remote_state[5] = 0x24;
remote_state[6] = 0x03;
remote_state[7] = 0x07;
remote_state[8] = 0x40;
remote_state[13] = 0x03;
}
uint8_t* IRTcl112Ac::getRaw() {
this->checksum();
return remote_state;
}
void IRTcl112Ac::setRaw(const uint8_t new_code[], const uint16_t length) {
for (uint8_t i = 0; i < length && i < kTcl112AcStateLength; i++) {
remote_state[i] = new_code[i];
}
}
// Set the requested power state of the A/C to on.
void IRTcl112Ac::on(void) { this->setPower(true); }
// Set the requested power state of the A/C to off.
void IRTcl112Ac::off(void) { this->setPower(false); }
// Set the requested power state of the A/C.
void IRTcl112Ac::setPower(const bool on) {
if (on)
remote_state[5] |= kTcl112AcPowerMask;
else
remote_state[5] &= ~kTcl112AcPowerMask;
}
// Return the requested power state of the A/C.
bool IRTcl112Ac::getPower(void) {
return remote_state[5] & kTcl112AcPowerMask;
}
// Get the requested climate operation mode of the a/c unit.
// Returns:
// A uint8_t containing the A/C mode.
uint8_t IRTcl112Ac::getMode() {
return remote_state[6] & 0xF;
}
// Set the requested climate operation mode of the a/c unit.
void IRTcl112Ac::setMode(const uint8_t mode) {
// If we get an unexpected mode, default to AUTO.
switch (mode) {
case kTcl112AcAuto:
case kTcl112AcCool:
case kTcl112AcHeat:
case kTcl112AcDry:
case kTcl112AcFan:
remote_state[6] &= 0xF0;
remote_state[6] |= mode;
break;
default:
setMode(kTcl112AcAuto);
}
}
void IRTcl112Ac::setTemp(const float celsius) {
// Make sure we have desired temp in the correct range.
float safecelsius = std::max(celsius, kTcl112AcTempMin);
safecelsius = std::min(safecelsius, kTcl112AcTempMax);
// Convert to integer nr. of half degrees.
uint8_t nrHalfDegrees = safecelsius * 2;
if (nrHalfDegrees & 1) // Do we have a half degree celsius?
remote_state[12] |= kTcl112AcHalfDegree; // Add 0.5 degrees
else
remote_state[12] &= ~kTcl112AcHalfDegree; // Clear the half degree.
remote_state[7] &= 0xF0; // Clear temp bits.
remote_state[7] |= ((uint8_t)kTcl112AcTempMax - nrHalfDegrees / 2);
}
float IRTcl112Ac::getTemp() {
float result = kTcl112AcTempMax - (remote_state[7] & 0xF);
if (remote_state[12] & kTcl112AcHalfDegree) result += 0.5;
return result;
}
// Convert the internal state into a human readable string.
#ifdef ARDUINO
String IRTcl112Ac::toString() {
String result = "";
#else
std::string IRTcl112Ac::toString() {
std::string result = "";
#endif // ARDUINO
result += "Power: ";
result += (this->getPower() ? "On" : "Off");
result += ", Mode: " + uint64ToString(getMode());
switch (this->getMode()) {
case kTcl112AcAuto:
result += " (AUTO)";
break;
case kTcl112AcCool:
result += " (COOL)";
break;
case kTcl112AcHeat:
result += " (HEAT)";
break;
case kTcl112AcDry:
result += " (DRY)";
break;
case kTcl112AcFan:
result += " (FAN)";
break;
default:
result += " (UNKNOWN)";
}
uint16_t nrHalfDegrees = this->getTemp() * 2;
result += ", Temp: " + uint64ToString(nrHalfDegrees / 2);
if (nrHalfDegrees & 1) result += ".5";
result += "C";
return result;
}
#if DECODE_TCL112AC
// Decode the supplied TCL112AC message.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: The number of data bits to expect. Typically kTcl112AcBits.
// strict: Flag indicating if we should perform strict matching.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: BETA / Appears to mostly work.
//
// Ref:
// https://github.com/markszabo/IRremoteESP8266/issues/619
bool IRrecv::decodeTcl112Ac(decode_results *results, uint16_t nbits,
bool strict) {
if (results->rawlen < 2 * nbits + kHeader + kFooter - 1)
return false; // Can't possibly be a valid Samsung A/C message.
if (strict && nbits != kTcl112AcBits) return false;
uint16_t offset = kStartOffset;
uint16_t dataBitsSoFar = 0;
match_result_t data_result;
// Message Header
if (!matchMark(results->rawbuf[offset++], kTcl112AcHdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kTcl112AcHdrSpace)) return false;
// Data
// Keep reading bytes until we either run out of section or state to fill.
for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8;
i++, dataBitsSoFar += 8, offset += data_result.used) {
data_result = matchData(&(results->rawbuf[offset]), 8, kTcl112AcBitMark,
kTcl112AcOneSpace, kTcl112AcBitMark,
kTcl112AcZeroSpace, kTolerance, 0, false);
if (data_result.success == false) {
DPRINT("DEBUG: offset = ");
DPRINTLN(offset + data_result.used);
return false; // Fail
}
results->state[i] = data_result.data;
}
// Footer
if (!matchMark(results->rawbuf[offset++], kTcl112AcBitMark)) return false;
if (offset <= results->rawlen &&
!matchAtLeast(results->rawbuf[offset++], kTcl112AcGap)) return false;
// Compliance
// Re-check we got the correct size/length due to the way we read the data.
if (dataBitsSoFar != nbits) return false;
// Verify we got a valid checksum.
if (strict && !IRTcl112Ac::validChecksum(results->state)) return false;
// Success
results->decode_type = TCL112AC;
results->bits = dataBitsSoFar;
// No need to record the state as we stored it as we decoded it.
// As we use result->state, we don't record value, address, or command as it
// is a union data type.
return true;
}
#endif // DECODE_TCL112AC
+69
View File
@@ -0,0 +1,69 @@
// Copyright 2019 David Conran
#ifndef IR_TCL_H_
#define IR_TCL_H_
#ifndef UNIT_TEST
#include <Arduino.h>
#else
#include <string>
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
// Constants
const uint16_t kTcl112AcHdrMark = 3000;
const uint16_t kTcl112AcHdrSpace = 1650;
const uint16_t kTcl112AcBitMark = 500;
const uint16_t kTcl112AcOneSpace = 1050;
const uint16_t kTcl112AcZeroSpace = 325;
const uint32_t kTcl112AcGap = 100000; // Just a guess.
const uint8_t kTcl112AcHeat = 1;
const uint8_t kTcl112AcDry = 2;
const uint8_t kTcl112AcCool = 3;
const uint8_t kTcl112AcFan = 7;
const uint8_t kTcl112AcAuto = 8;
const uint8_t kTcl112AcHalfDegree = 0b00100000;
const float kTcl112AcTempMax = 31.0;
const float kTcl112AcTempMin = 16.0;
const uint8_t kTcl112AcPowerMask = 0x04;
class IRTcl112Ac {
public:
explicit IRTcl112Ac(uint16_t pin);
#if SEND_TCL112AC
void send(const uint16_t repeat = kTcl112AcDefaultRepeat);
#endif // SEND_TCL
void begin(void);
uint8_t* getRaw(void);
void setRaw(const uint8_t new_code[],
const uint16_t length = kTcl112AcStateLength);
void on(void);
void off(void);
void setPower(const bool on);
bool getPower(void);
void setTemp(const float celsius); // Celsius in 0.5 increments
float getTemp(void);
void setMode(const uint8_t mode);
uint8_t getMode(void);
static uint8_t calcChecksum(uint8_t state[],
const uint16_t length = kTcl112AcStateLength);
static bool validChecksum(uint8_t state[],
const uint16_t length = kTcl112AcStateLength);
#ifdef ARDUINO
String toString();
#else
std::string toString();
#endif
private:
uint8_t remote_state[kTcl112AcStateLength];
void stateReset();
void checksum(const uint16_t length = kTcl112AcStateLength);
IRsend _irsend;
};
#endif // IR_TCL_H_
+243
View File
@@ -0,0 +1,243 @@
// Copyright 2019 Fabien Valthier
/*
Node MCU/ESP8266 Sketch to emulate Teco
*/
#include "ir_Teco.h"
#include <algorithm>
#include "IRremoteESP8266.h"
#include "IRutils.h"
#ifndef ARDUINO
#include <string>
#endif
// Constants
// using SPACE modulation.
const uint16_t kTecoHdrMark = 9000;
const uint16_t kTecoHdrSpace = 4440;
const uint16_t kTecoBitMark = 620;
const uint16_t kTecoOneSpace = 1650;
const uint16_t kTecoZeroSpace = 580;
const uint32_t kTecoGap = kDefaultMessageGap; // Made-up value. Just a guess.
#if SEND_TECO
// Send a Teco A/C message.
//
// Args:
// data: Contents of the message to be sent.
// nbits: Nr. of bits of data to be sent. Typically kTecoBits.
// repeat: Nr. of additional times the message is to be sent.
void IRsend::sendTeco(uint64_t data, uint16_t nbits, uint16_t repeat) {
sendGeneric(kTecoHdrMark, kTecoHdrSpace, kTecoBitMark, kTecoOneSpace,
kTecoBitMark, kTecoZeroSpace, kTecoBitMark, kTecoGap,
data, nbits, 38000, false, repeat, kDutyDefault);
}
#endif // SEND_TECO
// Class for decoding and constructing Teco AC messages.
IRTecoAc::IRTecoAc(const uint16_t pin) : _irsend(pin) { stateReset(); }
void IRTecoAc::begin() { _irsend.begin(); }
#if SEND_TECO
void IRTecoAc::send(const uint16_t repeat) {
_irsend.sendTeco(remote_state, kTecoBits, repeat);
}
#endif // SEND_TECO
void IRTecoAc::stateReset(void) {
// Mode:auto, Power:Off, fan:auto, temp:16, swing:off, sleep:off
remote_state = kTecoReset;
}
uint64_t IRTecoAc::getRaw(void) { return remote_state; }
void IRTecoAc::setRaw(const uint64_t new_code) { remote_state = new_code; }
void IRTecoAc::on(void) { remote_state |= kTecoPower; }
void IRTecoAc::off(void) { remote_state &= ~kTecoPower; }
void IRTecoAc::setPower(const bool on) {
if (on)
this->on();
else
this->off();
}
bool IRTecoAc::getPower(void) {
return (remote_state & kTecoPower) == kTecoPower; }
void IRTecoAc::setTemp(const uint8_t temp) {
uint8_t newtemp = temp;
newtemp = std::min(newtemp, kTecoMaxTemp);
newtemp = std::max(newtemp, kTecoMinTemp);
newtemp -= kTecoMinTemp; // 16=0b000
remote_state &= ~kTecoTempMask; // reinit temp
remote_state |= (newtemp << 8);
}
uint8_t IRTecoAc::getTemp(void) {
return ((remote_state & kTecoTempMask) >> 8) + kTecoMinTemp;
}
// Set the speed of the fan
void IRTecoAc::setFan(const uint8_t speed) {
uint8_t newspeed = speed;
switch (speed) {
case kTecoFanAuto:
case kTecoFanHigh:
case kTecoFanMed:
case kTecoFanLow:
break;
default:
newspeed = kTecoFanAuto;
}
remote_state &= ~kTecoFanMask; // reinit fan
remote_state |= (newspeed << 4);
}
uint8_t IRTecoAc::getFan(void) { return (remote_state & kTecoFanMask) >> 4; }
void IRTecoAc::setMode(const uint8_t mode) {
uint8_t newmode = mode;
switch (mode) {
case kTecoAuto:
case kTecoCool:
case kTecoDry:
case kTecoFan:
case kTecoHeat:
break;
default:
newmode = kTecoAuto;
}
remote_state &= ~kTecoModeMask; // reinit mode
remote_state |= newmode;
}
uint8_t IRTecoAc::getMode(void) { return remote_state & kTecoModeMask; }
void IRTecoAc::setSwing(const bool on) {
if (on)
remote_state |= kTecoSwing;
else
remote_state &= ~kTecoSwing;
}
bool IRTecoAc::getSwing(void) { return remote_state & kTecoSwing; }
void IRTecoAc::setSleep(const bool on) {
if (on)
remote_state |= kTecoSleep;
else
remote_state &= ~kTecoSleep;
}
bool IRTecoAc::getSleep(void) { return remote_state & kTecoSleep; }
// Convert the internal state into a human readable string.
#ifdef ARDUINO
String IRTecoAc::toString(void) {
String result = "";
#else
std::string IRTecoAc::toString(void) {
std::string result = "";
#endif // ARDUINO
result += "Power: ";
result += (this->getPower() ? "On" : "Off");
result += ", Mode: " + uint64ToString(this->getMode());
switch (this->getMode()) {
case kTecoAuto:
result += " (AUTO)";
break;
case kTecoCool:
result += " (COOL)";
break;
case kTecoHeat:
result += " (HEAT)";
break;
case kTecoDry:
result += " (DRY)";
break;
case kTecoFan:
result += " (FAN)";
break;
default:
result += " (UNKNOWN)";
}
result += ", Temp: " + uint64ToString(this->getTemp()) + "C";
result += ", Fan: " + uint64ToString(this->getFan());
switch (this->getFan()) {
case kTecoFanAuto:
result += " (Auto)";
break;
case kTecoFanHigh:
result += " (High)";
break;
case kTecoFanLow:
result += " (Low)";
break;
case kTecoFanMed:
result += " (Med)";
break;
default:
result += " (UNKNOWN)";
}
result += ", Sleep: ";
result += (this->getSleep() ? "On" : "Off");
result += ", Swing: ";
result += (this->getSwing() ? "On" : "Off");
return result;
}
#if DECODE_TECO
// Decode the supplied Teco message.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: The number of data bits to expect. Typically kTecoBits.
// strict: Flag indicating if we should perform strict matching.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: STABLE / Tested.
bool IRrecv::decodeTeco(decode_results* results, uint16_t nbits, bool strict) {
// Check if can possibly be a valid Teco message.
if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false;
if (strict && nbits != kTecoBits) return false; // Not what is expected
uint64_t data = 0;
uint16_t offset = kStartOffset;
match_result_t data_result;
// Header
if (!matchMark(results->rawbuf[offset++], kTecoHdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kTecoHdrSpace)) return false;
// Data (35 bits)
data_result =
matchData(&(results->rawbuf[offset]), 35, kTecoBitMark, kTecoOneSpace,
kTecoBitMark, kTecoZeroSpace, kTolerance, kMarkExcess, false);
if (data_result.success == false) return false;
data = data_result.data;
offset += data_result.used;
uint16_t actualBits = data_result.used / 2;
// Footer.
if (!matchMark(results->rawbuf[offset++], kTecoBitMark)) return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset], kTecoGap)) return false;
// Compliance
if (actualBits < nbits) return false;
if (strict && actualBits != nbits) return false; // Not as we expected.
// Success
results->decode_type = TECO;
results->bits = actualBits;
results->value = data;
results->address = 0;
results->command = 0;
return true;
}
#endif // DECODE_TECO
+135
View File
@@ -0,0 +1,135 @@
// Copyright 2019 Fabien Valthier
#ifndef IR_TECO_H_
#define IR_TECO_H_
#ifndef UNIT_TEST
#include <Arduino.h>
#else
#include <string>
#endif
#include "IRremoteESP8266.h"
#include "IRsend.h"
// Constants. Using LSB to be able to send only 35bits.
const uint8_t kTecoAuto = 0; // 0b000
const uint8_t kTecoCool = 1; // 0b001
const uint8_t kTecoDry = 2; // 0b010
const uint8_t kTecoFan = 3; // 0b110
const uint8_t kTecoHeat = 4; // 0b001
const uint8_t kTecoFanAuto = 0; // 0b00
const uint8_t kTecoFanHigh = 3; // 0b11
const uint8_t kTecoFanMed = 2; // 0b10
const uint8_t kTecoFanLow = 1; // 0b01
const uint8_t kTecoMinTemp = 16; // 16C
const uint8_t kTecoMaxTemp = 30; // 30C
const uint64_t kTecoModeMask = 0b00000000000000000000000000000000111;
const uint64_t kTecoPower = 0b00000000000000000000000000000001000;
const uint64_t kTecoFanMask = 0b00000000000000000000000000000110000;
const uint64_t kTecoSwing = 0b00000000000000000000000000001000000;
const uint64_t kTecoSleep = 0b00000000000000000000000000010000000;
const uint64_t kTecoTempMask = 0b00000000000000000000000111100000000;
const uint64_t kTecoTimerHalfH = 0b00000000000000000000001000000000000;
const uint64_t kTecoTimerTenHr = 0b00000000000000000000110000000000000;
const uint64_t kTecoTimerOn = 0b00000000000000000001000000000000000;
const uint64_t kTecoTimerUniHr = 0b00000000000000011110000000000000000;
const uint64_t kTecoReset = 0b01001010000000000000010000000000000;
/*
(header mark and space)
Teco AC map read and to be sent in LSB with number of bits
byte 0 = Cst 0x02
byte 1 = Cst 0x50
byte 2:
b0-3 = 0b0000
b4-7 = Timer hours (unit, not thenth)
hours:
0000 (0) = +0 hour
0001 (1) = +1 hour
...
1001 (9) = +9 hours
byte 3: = timer and Temperature
b0 = Timer (1 = On, 0 = Off)
b1-2 = Timer - number of 10hours
10Hours:
00 = 0 * 10hours of timer
01 = 1 * 10 hours of timer
10 = 2 * 10hours of timer
b3 = Timer - half hour (1=half hour on, 0 = round hour)
b4-7: Degrees C.
0000 (0) = 16C
0001 (1) = 17C
0010 (2) = 18C
...
1101 (13) = 29C
1110 (14) = 30C
byte 4: Basics
b0 = Sleep Mode (1 = On, 0 = Off)
b1 = Vent swing (1 = On, 0 = Off)
b2-3 = Fan
Fan:
00 = Auto
01 = Fan 1
10 = Fan 2
11 = Fan 3 or higher
b4 = Power Status (1 = On, 0 = Off)
b5-7 = Modes LSB first
Modes:
000 = Auto (temp = 25C)
001 = Cool
010 = Dry (temp = 25C, but not shown)
011 = Fan
100 = Heat
*/
// Classes
class IRTecoAc {
public:
explicit IRTecoAc(const uint16_t pin);
void stateReset(void);
#if SEND_TECO
void send(const uint16_t repeat = kTecoDefaultRepeat);
#endif // SEND_TECO
void begin(void);
void on(void);
void off(void);
void setPower(const bool on);
bool getPower(void);
void setTemp(const uint8_t temp);
uint8_t getTemp(void);
void setFan(const uint8_t fan);
uint8_t getFan(void);
void setMode(const uint8_t mode);
uint8_t getMode(void);
void setSwing(const bool state);
bool getSwing(void);
void setSleep(const bool state);
bool getSleep(void);
// void setTimer(uint8_t time); // To check unit
// uint8_t getTimer(uint8_t);
uint64_t getRaw(void);
void setRaw(const uint64_t new_code);
#ifdef ARDUINO
String toString(void);
#else
std::string toString(void);
#endif
private:
// The state of the IR remote in IR code form.
uint64_t remote_state;
IRsend _irsend;
};
#endif // IR_TECO_H_
+212 -153
View File
@@ -1,4 +1,5 @@
// Copyright 2018 Erdem U. Altinyurt
// Copyright 2019 David Conran
#include "ir_Vestel.h"
#include <algorithm>
@@ -37,14 +38,14 @@
//
// Status: STABLE / Working.
//
void IRsend::sendVestelAC(const uint64_t data, const uint16_t nbits,
void IRsend::sendVestelAc(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
if (nbits % 8 != 0) return; // nbits is required to be a multiple of 8.
sendGeneric(kVestelACHdrMark, kVestelACHdrSpace, // Header
kVestelACBitMark, kVestelACOneSpace, // Data
kVestelACBitMark, kVestelACZeroSpace, // Data
kVestelACBitMark, 100000, // Footer + repeat gap
sendGeneric(kVestelAcHdrMark, kVestelAcHdrSpace, // Header
kVestelAcBitMark, kVestelAcOneSpace, // Data
kVestelAcBitMark, kVestelAcZeroSpace, // Data
kVestelAcBitMark, 100000, // Footer + repeat gap
data, nbits, 38, false, repeat, 50);
}
#endif
@@ -52,133 +53,146 @@ void IRsend::sendVestelAC(const uint64_t data, const uint16_t nbits,
// Code to emulate Vestel A/C IR remote control unit.
// Initialise the object.
IRVestelAC::IRVestelAC(uint16_t pin) : _irsend(pin) { stateReset(); }
IRVestelAc::IRVestelAc(uint16_t pin) : _irsend(pin) { stateReset(); }
// Reset the state of the remote to a known good state/sequence.
void IRVestelAC::stateReset() {
void IRVestelAc::stateReset() {
// Power On, Mode Auto, Fan Auto, Temp = 25C/77F
remote_state.rawCode = 0x0F00D9001FEF201LL;
remote_time_state.rawCode = 0x00;
remote_state = 0x0F00D9001FEF201ULL;
remote_time_state = 0x201ULL;
use_time_state = false;
}
// Configure the pin for output.
void IRVestelAC::begin() {
void IRVestelAc::begin() {
_irsend.begin();
stateReset();
}
#if SEND_VESTEL_AC
// Send the current desired state to the IR LED.
void IRVestelAC::send() {
void IRVestelAc::send() {
checksum(); // Ensure correct checksum before sending.
uint64_t code_to_send;
if (use_time_state)
code_to_send = remote_time_state.rawCode;
code_to_send = remote_time_state;
else
code_to_send = remote_state.rawCode;
_irsend.sendVestelAC(code_to_send);
code_to_send = remote_state;
_irsend.sendVestelAc(code_to_send);
}
#endif // SEND_VESTEL_AC
// Return the internal state date of the remote.
uint64_t IRVestelAC::getRaw() {
uint64_t IRVestelAc::getRaw() {
checksum();
if (use_time_state) return remote_time_state.rawCode;
return remote_state.rawCode;
if (use_time_state) return remote_time_state;
return remote_state;
}
// Override the internal state with the new state.
void IRVestelAC::setRaw(uint8_t* newState) {
void IRVestelAc::setRaw(uint8_t* newState) {
uint64_t upState = 0;
for (int i = 0; i < 7; i++)
upState |= static_cast<uint64_t>(newState[i]) << (i * 8);
remote_state.rawCode = upState;
remote_time_state.rawCode = upState;
remote_state = upState;
remote_time_state = upState;
}
void IRVestelAC::setRaw(const uint64_t newState) {
remote_state.rawCode = newState;
remote_time_state.rawCode = newState;
void IRVestelAc::setRaw(const uint64_t newState) {
remote_state = newState;
remote_time_state = newState;
}
// Set the requested power state of the A/C to on.
void IRVestelAC::on() { setPower(true); }
void IRVestelAc::on() { setPower(true); }
// Set the requested power state of the A/C to off.
void IRVestelAC::off() { setPower(false); }
void IRVestelAc::off() { setPower(false); }
// Set the requested power state of the A/C.
void IRVestelAC::setPower(const bool state) {
void IRVestelAc::setPower(const bool state) {
remote_state &= ~((uint64_t)0xF << kVestelAcPowerOffset);
if (state)
remote_state.power = 0xF;
remote_state |= ((uint64_t)0xF << kVestelAcPowerOffset);
else
remote_state.power = 0xC;
remote_state |= ((uint64_t)0xC << kVestelAcPowerOffset);
use_time_state = false;
}
// Return the requested power state of the A/C.
bool IRVestelAC::getPower() { return (remote_state.power == 0xF); }
bool IRVestelAc::getPower() {
return (remote_state >> kVestelAcPowerOffset == 0xF);
}
// Set the temperature in Celsius degrees.
void IRVestelAC::setTemp(const uint8_t temp) {
void IRVestelAc::setTemp(const uint8_t temp) {
uint8_t new_temp = temp;
new_temp = std::max(kVestelACMinTempC, new_temp);
// new_temp = std::max(kVestelACMinTempH, new_temp); Check MODE
new_temp = std::min(kVestelACMaxTemp, new_temp);
remote_state.temp = new_temp - 16;
new_temp = std::max(kVestelAcMinTempC, new_temp);
// new_temp = std::max(kVestelAcMinTempH, new_temp); Check MODE
new_temp = std::min(kVestelAcMaxTemp, new_temp);
remote_state &= ~((uint64_t)0xF << kVestelAcTempOffset);
remote_state |= (uint64_t)(new_temp - 16) << kVestelAcTempOffset;
use_time_state = false;
}
// Return the set temperature.
uint8_t IRVestelAC::getTemp(void) { return remote_state.temp + 16; }
uint8_t IRVestelAc::getTemp(void) {
return ((remote_state >> kVestelAcTempOffset) & 0xF) + 16;
}
// Set the speed of the fan,
// 1-3 set the fan speed, 0 or anything else set it to auto.
void IRVestelAC::setFan(const uint8_t fan) {
void IRVestelAc::setFan(const uint8_t fan) {
switch (fan) {
case kVestelACFanLow:
case kVestelACFanMed:
case kVestelACFanHigh:
case kVestelACFanAutoCool:
case kVestelACFanAutoHot:
remote_state.fan = fan;
case kVestelAcFanLow:
case kVestelAcFanMed:
case kVestelAcFanHigh:
case kVestelAcFanAutoCool:
case kVestelAcFanAutoHot:
case kVestelAcFanAuto:
remote_state &= ~((uint64_t)0xF << kVestelAcFanOffset);
remote_state |= (uint64_t)fan << kVestelAcFanOffset;
break;
default:
remote_state.fan = kVestelACFanAuto;
setFan(kVestelAcFanAuto);
}
use_time_state = false;
}
// Return the requested state of the unit's fan.
uint8_t IRVestelAC::getFan() { return remote_state.fan; }
uint8_t IRVestelAc::getFan() {
return (remote_state >> kVestelAcFanOffset) & 0xF;
}
// Get the requested climate operation mode of the a/c unit.
// Returns:
// A uint8_t containing the A/C mode.
uint8_t IRVestelAC::getMode() { return remote_state.mode; }
uint8_t IRVestelAc::getMode() {
return (remote_state >> kVestelAcModeOffset) & 0xF;
}
// Set the requested climate operation mode of the a/c unit.
void IRVestelAC::setMode(const uint8_t mode) {
void IRVestelAc::setMode(const uint8_t mode) {
// If we get an unexpected mode, default to AUTO.
switch (mode) {
case kVestelACAuto:
case kVestelACCool:
case kVestelACHeat:
case kVestelACDry:
case kVestelACFan:
remote_state.mode = mode;
case kVestelAcAuto:
case kVestelAcCool:
case kVestelAcHeat:
case kVestelAcDry:
case kVestelAcFan:
remote_state &= ~((uint64_t)0xF << kVestelAcModeOffset);
remote_state |= (uint64_t)mode << kVestelAcModeOffset;
break;
default:
remote_state.mode = kVestelACAuto;
setMode(kVestelAcAuto);
}
use_time_state = false;
}
// Set Auto mode of AC.
void IRVestelAC::setAuto(const int8_t autoLevel) {
void IRVestelAc::setAuto(const int8_t autoLevel) {
if (autoLevel < -2 || autoLevel > 2) return;
setMode(kVestelACAuto);
setFan((autoLevel < 0 ? kVestelACFanAutoCool : kVestelACFanAutoHot));
setMode(kVestelAcAuto);
setFan((autoLevel < 0 ? kVestelAcFanAutoCool : kVestelAcFanAutoHot));
if (autoLevel == 2)
setTemp(30);
else if (autoLevel == 1)
@@ -191,124 +205,167 @@ void IRVestelAC::setAuto(const int8_t autoLevel) {
setTemp(17);
}
void IRVestelAc::setTimerActive(const bool on) {
if (on) // activation
remote_time_state |= ((uint64_t)1 << kVestelAcTimerFlagOffset);
else // deactivate
remote_time_state &= ~((uint64_t)1 << kVestelAcTimerFlagOffset);
use_time_state = true;
}
bool IRVestelAc::isTimerActive(void) {
return (remote_time_state >> kVestelAcTimerFlagOffset) & 1;
}
// Set Timer option of AC.
// Valid time arguments are 0, 0.5, 1, 2, 3 and 5 hours (in min). 0 disables the
// timer.
void IRVestelAC::setTimer(const uint16_t minutes) {
remote_time_state.t_turnOnMinute = 0;
remote_time_state.t_turnOnHour = 0;
remote_time_state.t_turnOffHour = minutes / 60;
remote_time_state.t_turnOffMinute = (minutes % 60) / 10;
remote_time_state.t_off_active = 0;
if (minutes) {
remote_time_state.t_timer_mode = 1;
// Yes. t_on_active instead of t_off_active.
remote_time_state.t_on_active = 1;
} else { // Turn off the timer.
remote_time_state.t_timer_mode = 0;
remote_time_state.t_on_active = 0;
}
void IRVestelAc::setTimer(const uint16_t minutes) {
// Clear both On & Off timers.
remote_time_state &= ~((uint64_t)0xFFFF << kVestelAcOffTimeOffset);
// Set the "Off" time with the nr of minutes before we turn off.
remote_time_state |= (uint64_t)(((minutes / 60) << 3) + (minutes % 60) / 10)
<< kVestelAcOffTimeOffset;
setOffTimerActive(false);
// Yes. On Timer instead of Off timer active.
setOnTimerActive(minutes != 0);
setTimerActive(minutes != 0);
use_time_state = true;
}
uint16_t IRVestelAC::getTimer(void) { return getOffTimer(); }
uint16_t IRVestelAc::getTimer(void) { return getOffTimer(); }
// Set the AC's internal clock
void IRVestelAC::setTime(const uint16_t minutes) {
remote_time_state.t_hour = minutes / 60;
remote_time_state.t_minute = minutes % 60;
void IRVestelAc::setTime(const uint16_t minutes) {
remote_time_state &= ~((uint64_t)0x1F << kVestelAcHourOffset);
remote_time_state |= (uint64_t)((minutes / 60) & 0x1F)
<< kVestelAcHourOffset;
remote_time_state &= ~((uint64_t)0xFF << kVestelAcMinuteOffset);
remote_time_state |= (uint64_t)((minutes % 60) & 0xFF)
<< kVestelAcMinuteOffset;
use_time_state = true;
}
uint16_t IRVestelAC::getTime(void) {
return remote_time_state.t_hour * 60 + remote_time_state.t_minute;
uint16_t IRVestelAc::getTime(void) {
return ((remote_time_state >> kVestelAcHourOffset) & 0x1F) * 60 +
((remote_time_state >> kVestelAcMinuteOffset) & 0xFF);
}
void IRVestelAc::setOnTimerActive(const bool on) {
if (on) // activation
remote_time_state |= ((uint64_t)1 << kVestelAcOnTimerFlagOffset);
else // deactivate
remote_time_state &= ~((uint64_t)1 << kVestelAcOnTimerFlagOffset);
use_time_state = true;
}
bool IRVestelAc::isOnTimerActive(void) {
return (remote_time_state >> kVestelAcOnTimerFlagOffset) & 1;
}
// Set AC's wake up time. Takes time in minute.
void IRVestelAC::setOnTimer(const uint16_t minutes) {
remote_time_state.t_turnOnHour = minutes / 60;
// Register is 3 bit and can only hold minute/10
remote_time_state.t_turnOnMinute = (minutes % 60) / 10;
if (minutes)
remote_time_state.t_on_active = 1; // activation
else
remote_time_state.t_on_active = 0; // deactivate
remote_time_state.t_timer_mode = 0;
void IRVestelAc::setOnTimer(const uint16_t minutes) {
remote_time_state &= ~((uint64_t)0xFF << kVestelAcOnTimeOffset);
remote_time_state |= (uint64_t)(((minutes / 60) << 3) + (minutes % 60) / 10)
<< kVestelAcOnTimeOffset;
setOnTimerActive(minutes != 0);
setTimerActive(false);
use_time_state = true;
}
uint16_t IRVestelAC::getOnTimer(void) {
return remote_time_state.t_turnOnHour * 60 +
remote_time_state.t_turnOnMinute * 10;
uint16_t IRVestelAc::getOnTimer(void) {
uint8_t ontime = (remote_time_state >> kVestelAcOnTimeOffset) & 0xFF;
return (ontime >> 3) * 60 + (ontime & 0x7) * 10;
}
void IRVestelAc::setOffTimerActive(const bool on) {
if (on) // activation
remote_time_state |= ((uint64_t)1 << kVestelAcOffTimerFlagOffset);
else // deactivate
remote_time_state &= ~((uint64_t)1 << kVestelAcOffTimerFlagOffset);
use_time_state = true;
}
bool IRVestelAc::isOffTimerActive(void) {
return (remote_time_state >> kVestelAcOffTimerFlagOffset) & 1;
}
// Set AC's turn off time. Takes time in minute.
void IRVestelAC::setOffTimer(const uint16_t minutes) {
remote_time_state.t_turnOffHour = minutes / 60;
// Register is 3 bit and can only hold minute/10
remote_time_state.t_turnOffMinute = (minutes % 60) / 10;
if (minutes)
remote_time_state.t_off_active = 1; // activation
else
remote_time_state.t_off_active = 0; // deactivate
remote_time_state.t_timer_mode = 0;
void IRVestelAc::setOffTimer(const uint16_t minutes) {
remote_time_state &= ~((uint64_t)0xFF << kVestelAcOffTimeOffset);
remote_time_state |=
(uint64_t)((((minutes / 60) << 3) + (minutes % 60) / 10) & 0xFF)
<< kVestelAcOffTimeOffset;
setOffTimerActive(minutes != 0);
setTimerActive(false);
use_time_state = true;
}
uint16_t IRVestelAC::getOffTimer(void) {
return remote_time_state.t_turnOffHour * 60 +
remote_time_state.t_turnOffMinute * 10;
uint16_t IRVestelAc::getOffTimer(void) {
uint8_t offtime = (remote_time_state >> kVestelAcOffTimeOffset) & 0xFF;
return (offtime >> 3) * 60 + (offtime & 0x7) * 10;
}
// Set the Sleep state of the A/C.
void IRVestelAC::setSleep(const bool state) {
remote_state.turbo_sleep_normal = state ? kVestelACSleep : kVestelACNormal;
void IRVestelAc::setSleep(const bool state) {
remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset);
remote_state |= (uint64_t)(state ? kVestelAcSleep : kVestelAcNormal)
<< kVestelAcTurboSleepOffset;
use_time_state = false;
}
// Return the Sleep state of the A/C.
bool IRVestelAC::getSleep() {
return remote_state.turbo_sleep_normal == kVestelACSleep;
bool IRVestelAc::getSleep() {
return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcSleep;
}
// Set the Turbo state of the A/C.
void IRVestelAC::setTurbo(const bool state) {
remote_state.turbo_sleep_normal = state ? kVestelACTurbo : kVestelACNormal;
void IRVestelAc::setTurbo(const bool state) {
remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset);
remote_state |= (uint64_t)(state ? kVestelAcTurbo : kVestelAcNormal)
<< kVestelAcTurboSleepOffset;
use_time_state = false;
}
// Return the Turbo state of the A/C.
bool IRVestelAC::getTurbo() {
return remote_state.turbo_sleep_normal == kVestelACTurbo;
bool IRVestelAc::getTurbo() {
return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcTurbo;
}
// Set the Ion state of the A/C.
void IRVestelAC::setIon(const bool state) {
remote_state.ion = state ? kVestelACIon : 0;
void IRVestelAc::setIon(const bool state) {
remote_state &= ~((uint64_t)0x1 << kVestelAcIonOffset);
remote_state |= (uint64_t)(state ? 1 : 0) << kVestelAcIonOffset;
use_time_state = false;
}
// Return the Ion state of the A/C.
bool IRVestelAC::getIon() { return remote_state.ion == kVestelACIon; }
bool IRVestelAc::getIon() { return (remote_state >> kVestelAcIonOffset) & 1; }
// Set the Swing Roaming state of the A/C.
void IRVestelAC::setSwing(const bool state) {
remote_state.swing = state ? kVestelACSwing : 0xF;
void IRVestelAc::setSwing(const bool state) {
remote_state &= ~((uint64_t)0xF << kVestelAcSwingOffset);
remote_state |= (uint64_t)(state ? kVestelAcSwing : 0xF)
<< kVestelAcSwingOffset;
use_time_state = false;
}
// Return the Swing Roaming state of the A/C.
bool IRVestelAC::getSwing() { return remote_state.swing == kVestelACSwing; }
bool IRVestelAc::getSwing() {
return ((remote_state >> kVestelAcSwingOffset) & 0xF) == kVestelAcSwing;
}
// Calculate the checksum for a given array.
// Args:
// state: The state to calculate the checksum over.
// Returns:
// The 8 bit checksum value.
uint8_t IRVestelAC::calcChecksum(const uint64_t state) {
uint8_t IRVestelAc::calcChecksum(const uint64_t state) {
// Just counts the set bits +1 on stream and take inverse after mask
uint8_t sum = 0;
uint64_t temp_state = state & kVestelACCRCMask;
uint64_t temp_state = state & kVestelAcCRCMask;
for (; temp_state; temp_state >>= 1)
if (temp_state & 1) sum++;
sum += 2;
@@ -321,46 +378,48 @@ uint8_t IRVestelAC::calcChecksum(const uint64_t state) {
// state: The state to verify the checksum of.
// Returns:
// A boolean.
bool IRVestelAC::validChecksum(const uint64_t state) {
return (((state >> 12) & 0xFF) == calcChecksum(state));
bool IRVestelAc::validChecksum(const uint64_t state) {
return (((state >> kVestelAcChecksumOffset) & 0xFF) == calcChecksum(state));
}
// Calculate & set the checksum for the current internal state of the remote.
void IRVestelAC::checksum() {
void IRVestelAc::checksum() {
// Stored the checksum value in the last byte.
remote_state.CRC = calcChecksum(remote_state.rawCode);
remote_time_state.CRC = calcChecksum(remote_time_state.rawCode);
remote_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset);
remote_state |= (uint64_t)calcChecksum(remote_state)
<< kVestelAcChecksumOffset;
remote_time_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset);
remote_time_state |= (uint64_t)calcChecksum(remote_time_state)
<< kVestelAcChecksumOffset;
}
bool IRVestelAC::isTimeCommand() {
return (remote_state.power == 0x00 || use_time_state);
bool IRVestelAc::isTimeCommand() {
return (remote_state >> kVestelAcPowerOffset == 0x00 || use_time_state);
}
// Convert the internal state into a human readable string.
#ifdef ARDUINO
String IRVestelAC::toString() {
String IRVestelAc::toString() {
String result = "";
#else
std::string IRVestelAC::toString() {
std::string IRVestelAc::toString() {
std::string result = "";
#endif // ARDUINO
if (isTimeCommand()) {
result += "Time: " + IRHaierAC::timeToString(getTime());
result += ", Timer: ";
result += remote_time_state.t_timer_mode
? IRHaierAC::timeToString(getTimer())
: "Off";
result += isTimerActive() ? IRHaierAC::timeToString(getTimer()) : "Off";
result += ", On Timer: ";
result += (remote_time_state.t_on_active && !remote_time_state.t_timer_mode)
result += (isOnTimerActive() && !isTimerActive())
? IRHaierAC::timeToString(getOnTimer())
: "Off";
result += ", Off Timer: ";
result += remote_time_state.t_off_active
? IRHaierAC::timeToString(getOffTimer())
: "Off";
result +=
isOffTimerActive() ? IRHaierAC::timeToString(getOffTimer()) : "Off";
return result;
}
// Not a time command, it's a normal command.
@@ -368,19 +427,19 @@ std::string IRVestelAC::toString() {
result += (getPower() ? "On" : "Off");
result += ", Mode: " + uint64ToString(getMode());
switch (getMode()) {
case kVestelACAuto:
case kVestelAcAuto:
result += " (AUTO)";
break;
case kVestelACCool:
case kVestelAcCool:
result += " (COOL)";
break;
case kVestelACHeat:
case kVestelAcHeat:
result += " (HEAT)";
break;
case kVestelACDry:
case kVestelAcDry:
result += " (DRY)";
break;
case kVestelACFan:
case kVestelAcFan:
result += " (FAN)";
break;
default:
@@ -389,22 +448,22 @@ std::string IRVestelAC::toString() {
result += ", Temp: " + uint64ToString(getTemp()) + "C";
result += ", Fan: " + uint64ToString(getFan());
switch (getFan()) {
case kVestelACFanAuto:
case kVestelAcFanAuto:
result += " (AUTO)";
break;
case kVestelACFanLow:
case kVestelAcFanLow:
result += " (LOW)";
break;
case kVestelACFanMed:
case kVestelAcFanMed:
result += " (MEDIUM)";
break;
case kVestelACFanHigh:
case kVestelAcFanHigh:
result += " (HIGH)";
break;
case kVestelACFanAutoCool:
case kVestelAcFanAutoCool:
result += " (AUTO COOL)";
break;
case kVestelACFanAutoHot:
case kVestelAcFanAutoHot:
result += " (AUTO HOT)";
break;
default:
@@ -433,13 +492,13 @@ std::string IRVestelAC::toString() {
//
// Status: Alpha / Needs testing against a real device.
//
bool IRrecv::decodeVestelAC(decode_results* results, uint16_t nbits,
bool IRrecv::decodeVestelAc(decode_results* results, uint16_t nbits,
bool strict) {
if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
return false;
if (strict)
if (nbits != kVestelACBits)
if (nbits != kVestelAcBits)
return false; // Not strictly a Vestel AC message.
uint64_t data = 0;
@@ -449,25 +508,25 @@ bool IRrecv::decodeVestelAC(decode_results* results, uint16_t nbits,
return false; // We can't possibly capture a Vestel packet that big.
// Header
if (!matchMark(results->rawbuf[offset++], kVestelACHdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kVestelACHdrSpace)) return false;
if (!matchMark(results->rawbuf[offset++], kVestelAcHdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kVestelAcHdrSpace)) return false;
// Data (Normal)
match_result_t data_result =
matchData(&(results->rawbuf[offset]), nbits, kVestelACBitMark,
kVestelACOneSpace, kVestelACBitMark, kVestelACZeroSpace,
kVestelACTolerance, kMarkExcess, false);
matchData(&(results->rawbuf[offset]), nbits, kVestelAcBitMark,
kVestelAcOneSpace, kVestelAcBitMark, kVestelAcZeroSpace,
kVestelAcTolerance, kMarkExcess, false);
if (data_result.success == false) return false;
offset += data_result.used;
data = data_result.data;
// Footer
if (!matchMark(results->rawbuf[offset++], kVestelACBitMark)) return false;
if (!matchMark(results->rawbuf[offset++], kVestelAcBitMark)) return false;
// Compliance
if (strict)
if (!IRVestelAC::validChecksum(data_result.data)) return false;
if (!IRVestelAc::validChecksum(data_result.data)) return false;
// Success
results->decode_type = VESTEL_AC;
+85 -79
View File
@@ -1,5 +1,6 @@
// Copyright 2018 Erdem U. Altinyurt
// (Used Midea.h as template)
// Copyright 2019 David Conran
#ifndef IR_VESTEL_H_
#define IR_VESTEL_H_
@@ -21,87 +22,88 @@
// Vestel added by Erdem U. Altinyurt
// Structure of a Command message (56 bits)
// Signature: 12 bits. e.g. 0x201
// Checksum: 8 bits
// Swing: 4 bits. (auto 0xA, stop 0xF)
// turbo_sleep_normal: 4bits. (normal 0x1, sleep 0x3, turbo 0x7)
// Unused: 8 bits. (0x00)
// Temperature: 4 bits. (Celcius, but offset by -16 degrees. e.g. 0x0 = 16C)
// Fan Speed: 4 bits (auto 0x1, low 0x5, mid 0x9, high 0xB, 0xD auto hot,
// 0xC auto cool)
// Mode: 3 bits. (auto 0x0, cold 0x1, dry 0x2, fan 0x3, hot 0x4)
// unknown/unused: 6 bits.
// Ion flag: 1 bit.
// unknown/unused: 1 bit.
// Power/message type: 4 bits. (on 0xF, off 0xC, 0x0 == Timer mesage)
//
// Structure of a Time(r) message (56 bits)
// Signature: 12 bits. e.g. 0x201
// Checksum: 8 bits
// Off Minutes: 3 bits. (Stored in 10 min increments. eg. xx:20 is 0x2)
// Off Hours: 5 bits. (0x17 == 11PM / 23:00)
// On Minutes: 3 bits. (Stored in 10 min increments. eg. xx:20 is 0x2)
// On Hours: 5 bits. (0x9 == 9AM / 09:00)
// Clock Hours: 5 bits.
// On Timer flag: 1 bit.
// Off Timer flag: 1 bit.
// Timer mode flag: 1 bit. (Off after X many hours/mins, not at clock time.)
// Clock Minutes: 8 bits. (0-59)
// Power/message type: 4 bits. (0x0 == Timer mesage, else see Comman message)
// Constants
const uint16_t kVestelACHdrMark = 3110;
const uint16_t kVestelACHdrSpace = 9066;
const uint16_t kVestelACBitMark = 520;
const uint16_t kVestelACOneSpace = 1535;
const uint16_t kVestelACZeroSpace = 480;
const uint16_t kVestelACTolerance = 30;
const uint16_t kVestelAcHdrMark = 3110;
const uint16_t kVestelAcHdrSpace = 9066;
const uint16_t kVestelAcBitMark = 520;
const uint16_t kVestelAcOneSpace = 1535;
const uint16_t kVestelAcZeroSpace = 480;
const uint16_t kVestelAcTolerance = 30;
const uint8_t kVestelACMinTempH = 16;
const uint8_t kVestelACMinTempC = 18;
const uint8_t kVestelACMaxTemp = 30;
const uint8_t kVestelAcMinTempH = 16;
const uint8_t kVestelAcMinTempC = 18;
const uint8_t kVestelAcMaxTemp = 30;
const uint64_t kVestelACCRCMask = 0xFFFFFFFFFFF00000;
const uint64_t kVestelAcCRCMask = 0xFFFFFFFFFFF00000;
const uint8_t kVestelACAuto = 0;
const uint8_t kVestelACCool = 1;
const uint8_t kVestelACDry = 2;
const uint8_t kVestelACFan = 3;
const uint8_t kVestelACHeat = 4;
const uint8_t kVestelAcAuto = 0;
const uint8_t kVestelAcCool = 1;
const uint8_t kVestelAcDry = 2;
const uint8_t kVestelAcFan = 3;
const uint8_t kVestelAcHeat = 4;
const uint8_t kVestelACFanAuto = 1;
const uint8_t kVestelACFanLow = 5;
const uint8_t kVestelACFanMed = 9;
const uint8_t kVestelACFanHigh = 0xB;
const uint8_t kVestelACFanAutoCool = 0xC;
const uint8_t kVestelACFanAutoHot = 0xD;
const uint8_t kVestelAcFanAuto = 1;
const uint8_t kVestelAcFanLow = 5;
const uint8_t kVestelAcFanMed = 9;
const uint8_t kVestelAcFanHigh = 0xB;
const uint8_t kVestelAcFanAutoCool = 0xC;
const uint8_t kVestelAcFanAutoHot = 0xD;
const uint8_t kVestelACNormal = 1;
const uint8_t kVestelACSleep = 3;
const uint8_t kVestelACTurbo = 7;
const uint8_t kVestelACIon = 4;
const uint8_t kVestelACSwing = 0xA;
const uint8_t kVestelAcNormal = 1;
const uint8_t kVestelAcSleep = 3;
const uint8_t kVestelAcTurbo = 7;
const uint8_t kVestelAcIon = 4;
const uint8_t kVestelAcSwing = 0xA;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked-bitfield-compat"
union VestelACState {
// Remotes Command Stack
struct {
uint16_t footer : 12; // 0x201 footer
uint8_t CRC : 8;
uint8_t swing : 4; // auto 0xA, stop 0xF
uint8_t turbo_sleep_normal : 4; // normal 0x1, sleep 0x3, turbo 0x7
uint8_t zero : 8; // 0x00
uint8_t temp : 4; // temp-16 degree Celcius
uint8_t fan : 4; // auto 0x1, low 0x5, mid 0x9, high 0xB, 0xD auto hot, 0xC
// auto cool
uint8_t mode : 4; // auto 0x0, cold 0x1, dry 0x2, fan 0x3, hot 0x4
uint8_t ion : 4; // on 0x4, off 0x0
uint8_t power : 4; // on 0xF, off 0xC
uint8_t not_used : 8;
} __attribute__((packed)); // avoids padding.
const uint8_t kVestelAcChecksumOffset = 12;
const uint8_t kVestelAcSwingOffset = 20;
const uint8_t kVestelAcTurboSleepOffset = 24;
const uint8_t kVestelAcTempOffset = 36;
const uint8_t kVestelAcFanOffset = 40;
const uint8_t kVestelAcModeOffset = 44;
const uint8_t kVestelAcIonOffset = 50;
const uint8_t kVestelAcPowerOffset = 52;
const uint8_t kVestelAcOffTimeOffset = 20;
const uint8_t kVestelAcOnTimeOffset = 28;
const uint8_t kVestelAcHourOffset = 36; // 5 bits
const uint8_t kVestelAcOnTimerFlagOffset = kVestelAcHourOffset + 5;
const uint8_t kVestelAcOffTimerFlagOffset = kVestelAcHourOffset + 6;
const uint8_t kVestelAcTimerFlagOffset = kVestelAcHourOffset + 7;
const uint8_t kVestelAcMinuteOffset = 44;
uint64_t rawCode;
// Remotes Timer Stack for programming AC unit for turn of after some time or
// self wakeup - turn off at defined time. There are no timer functions
// implemented.
// Here is the stack only for decoding and reverse enginering purposes.
struct {
uint16_t t_footer : 12; // 0x201 footer
uint8_t t_CRC : 8;
// timer regs has 0x18 hour mask & 0x3=Minute mask minutes are divided to 10
// format. Need to multiply with 10 Examples: 0x01= xx:10 and 0x08 = 01:00,
// 0x03= 00:30 0x08=01:00 0x10=02:00 0x44=08:40
uint8_t t_turnOffMinute : 3; // off minute/10
uint8_t t_turnOffHour : 5;
uint8_t t_turnOnMinute : 3; // on minute/10
uint8_t t_turnOnHour : 5;
uint8_t t_hour : 5; // actual time hour
uint8_t t_on_active : 1;
uint8_t t_off_active : 1;
uint8_t t_timer_mode : 1; // For timer operation, also need t_on_active bit
uint8_t t_minute : 8; // actual time minute
uint16_t t_not_used : 16; // 00
} __attribute__((packed)); // avoids padding.
};
#pragma GCC diagnostic pop
class IRVestelAC {
class IRVestelAc {
public:
explicit IRVestelAC(uint16_t pin);
explicit IRVestelAc(uint16_t pin);
void stateReset();
#if SEND_VESTEL_AC
@@ -140,20 +142,24 @@ class IRVestelAC {
void setIon(const bool state);
bool getIon(void);
bool isTimeCommand(void);
bool isOnTimerActive(void);
void setOnTimerActive(const bool on);
bool isOffTimerActive(void);
void setOffTimerActive(const bool on);
bool isTimerActive(void);
void setTimerActive(const bool on);
static uint8_t calcChecksum(const uint64_t state);
#ifdef ARDUINO
String toString();
#else
std::string toString();
#endif
#ifndef UNIT_TEST
// private:
#endif
VestelACState remote_state;
VestelACState remote_time_state;
bool use_time_state = false;
private:
uint64_t remote_state;
uint64_t remote_time_state;
bool use_time_state;
void checksum();
static uint8_t calcChecksum(const uint64_t state);
IRsend _irsend;
};
+309 -1
View File
@@ -1,7 +1,8 @@
// Copyright 2017 David Conran
// Copyright 2017,2019 David Conran
#include "IRsend_test.h"
#include "IRsend.h"
#include "IRutils.h"
#include "gtest/gtest.h"
// Tests sendData().
@@ -288,3 +289,310 @@ TEST(TestLowLevelSend, SpaceNoModulation) {
irsend.space(1000);
EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence);
}
// Test expected to work/produce a message for irsend:send()
TEST(TestSend, GenericSimpleSendMethod) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
irsend.reset();
ASSERT_TRUE(irsend.send(AIWA_RC_T501, 0x1234, kAiwaRcT501Bits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type);
EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(CARRIER_AC, 0x1234, kCarrierAcBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type);
EXPECT_EQ(kCarrierAcBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(COOLIX, 0x1234, kCoolixBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(COOLIX, irsend.capture.decode_type);
EXPECT_EQ(kCoolixBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(DENON, 0x1234, kDenonBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(DENON, irsend.capture.decode_type);
EXPECT_EQ(kDenonBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(DISH, 0x1234, kDishBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(DISH, irsend.capture.decode_type);
EXPECT_EQ(kDishBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(GICABLE, 0x1234, kGicableBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(GICABLE, irsend.capture.decode_type);
EXPECT_EQ(kGicableBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(GREE, 0x0009205000200050, kGreeBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(GREE, irsend.capture.decode_type);
EXPECT_EQ(kGreeBits, irsend.capture.bits);
// No simple value test for gree as it decodes to an Array.
irsend.reset();
ASSERT_TRUE(irsend.send(JVC, 0x1234, kJvcBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(JVC, irsend.capture.decode_type);
EXPECT_EQ(kJvcBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(LASERTAG, 0x123, kLasertagBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(LASERTAG, irsend.capture.decode_type);
EXPECT_EQ(kLasertagBits, irsend.capture.bits);
EXPECT_EQ(0x123, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(LG, 0x700992, kLgBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(LG, irsend.capture.decode_type);
EXPECT_EQ(kLgBits, irsend.capture.bits);
EXPECT_EQ(0x700992, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(LG, 0x700992, kLg32Bits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(LG, irsend.capture.decode_type);
EXPECT_EQ(kLg32Bits, irsend.capture.bits);
EXPECT_EQ(0x700992, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(LG2, 0x880094D, kLgBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(LG2, irsend.capture.decode_type);
EXPECT_EQ(kLgBits, irsend.capture.bits);
EXPECT_EQ(0x880094D, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(LUTRON, 0x1234, kLutronBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(LUTRON, irsend.capture.decode_type);
EXPECT_EQ(kLutronBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(MAGIQUEST, 0x560F40020455, kMagiquestBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type);
EXPECT_EQ(kMagiquestBits, irsend.capture.bits);
EXPECT_EQ(0x560F40020455, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(MIDEA, 0xA18263FFFF6E, kMideaBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(MIDEA, irsend.capture.decode_type);
EXPECT_EQ(kMideaBits, irsend.capture.bits);
EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(MITSUBISHI, 0x1234, kMitsubishiBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type);
EXPECT_EQ(kMitsubishiBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(MITSUBISHI2, 0x1234, kMitsubishiBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type);
EXPECT_EQ(kMitsubishiBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(NIKAI, 0x1234, kNikaiBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(NIKAI, irsend.capture.decode_type);
EXPECT_EQ(kNikaiBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(NEC, 0x4BB640BF, kNECBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(NEC, irsend.capture.decode_type);
EXPECT_EQ(kNECBits, irsend.capture.bits);
EXPECT_EQ(0x4BB640BF, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(NEC_LIKE, 0x12345678, kNECBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(NEC_LIKE, irsend.capture.decode_type);
EXPECT_EQ(kNECBits, irsend.capture.bits);
EXPECT_EQ(0x12345678, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(PANASONIC, 0x40040190ED7C, kPanasonicBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(PIONEER, 0x659A05FAF50AC53A, kPioneerBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(PIONEER, irsend.capture.decode_type);
EXPECT_EQ(kPioneerBits, irsend.capture.bits);
EXPECT_EQ(0x659A05FAF50AC53A, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(RC5, 0x175, kRC5Bits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(RC5, irsend.capture.decode_type);
EXPECT_EQ(kRC5Bits, irsend.capture.bits);
EXPECT_EQ(0x175, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(RC6, 0xC800F740C, kRC6_36Bits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(RC6, irsend.capture.decode_type);
EXPECT_EQ(kRC6_36Bits, irsend.capture.bits);
EXPECT_EQ(0xC800F740C, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(RCMM, 0x1234, kRCMMBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(RCMM, irsend.capture.decode_type);
EXPECT_EQ(kRCMMBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(SAMSUNG, 0xE0E09966, kSamsungBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SAMSUNG, irsend.capture.decode_type);
EXPECT_EQ(kSamsungBits, irsend.capture.bits);
EXPECT_EQ(0xE0E09966, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(SAMSUNG36, 0x1234, kSamsung36Bits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SAMSUNG36, irsend.capture.decode_type);
EXPECT_EQ(kSamsung36Bits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(SANYO_LC7461, 0x2468DCB56A9, kSanyoLC7461Bits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type);
EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits);
EXPECT_EQ(0x2468DCB56A9, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(SHARP, 0x7266, kSharpBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SHARP, irsend.capture.decode_type);
EXPECT_EQ(kSharpBits, irsend.capture.bits);
EXPECT_EQ(0x7266, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(SHERWOOD, 0x4BB640BF, kSherwoodBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(NEC, irsend.capture.decode_type);
EXPECT_EQ(kSherwoodBits, irsend.capture.bits);
EXPECT_EQ(0x4BB640BF, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(SONY, 0x1234, kSony20Bits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(SONY, irsend.capture.decode_type);
EXPECT_EQ(kSony20Bits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(TECO, 0x1234, kTecoBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TECO, irsend.capture.decode_type);
EXPECT_EQ(kTecoBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(VESTEL_AC, 0xF4410001FF1201, kVestelAcBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type);
EXPECT_EQ(kVestelAcBits, irsend.capture.bits);
EXPECT_EQ(0xF4410001FF1201, irsend.capture.value);
irsend.reset();
ASSERT_TRUE(irsend.send(WHYNTER, 0x1234, kWhynterBits));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(WHYNTER, irsend.capture.decode_type);
EXPECT_EQ(kWhynterBits, irsend.capture.bits);
EXPECT_EQ(0x1234, irsend.capture.value);
}
// Test some expected types to NOT work/produce a message via irsend:send()
TEST(TestSend, GenericSimpleSendMethodFailure) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Check nothing is sent for unexpected protocols
irsend.reset();
ASSERT_FALSE(irsend.send(KELVINATOR, 0x1234, kKelvinatorBits));
irsend.makeDecodeResult();
ASSERT_FALSE(irrecv.decode(&irsend.capture));
// For every A/C protocol which decodes to having a state[].
for (int i = 0; i < 200; i++) {
if (hasACState((decode_type_t)i) && i != GREE) { // Gree is an exception.
// Check it fails.
ASSERT_FALSE(irsend.send((decode_type_t)i, 0, 0));
}
}
// Test some other special cases.
ASSERT_FALSE(irsend.send(UNKNOWN, 0, 0));
ASSERT_FALSE(irsend.send(UNUSED, 0, 0));
ASSERT_FALSE(irsend.send(RAW, 0, 0));
ASSERT_FALSE(irsend.send(PRONTO, 0, 0));
ASSERT_FALSE(irsend.send(GLOBALCACHE, 0, 0));
}
+23 -3
View File
@@ -36,7 +36,7 @@ TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \
ir_Toshiba_test ir_Midea_test ir_Magiquest_test ir_Lasertag_test \
ir_Carrier_test ir_Haier_test ir_Hitachi_test ir_GICable_test \
ir_Whirlpool_test ir_Lutron_test ir_Electra_test ir_Pioneer_test \
ir_MWM_test ir_Vestel_test
ir_MWM_test ir_Vestel_test ir_Teco_test ir_Tcl_test
# All Google Test headers. Usually you shouldn't change this
# definition.
@@ -80,7 +80,7 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_Nikai.o ir_Toshiba.o \
ir_Midea.o ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o \
ir_Hitachi.o ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o \
ir_Pioneer.o ir_MWM.o ir_Vestel.o
ir_Pioneer.o ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o
# All the IR Protocol header files.
PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \
@@ -100,7 +100,9 @@ PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \
$(USER_DIR)/ir_LG.h \
$(USER_DIR)/ir_Panasonic.h \
$(USER_DIR)/ir_Whirlpool.h \
$(USER_DIR)/ir_Vestel.h
$(USER_DIR)/ir_Vestel.h \
$(USER_DIR)/ir_Tcl.h \
$(USER_DIR)/ir_Teco.h
# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o ir_GlobalCache.o \
$(PROTOCOLS) gtest_main.a
@@ -505,3 +507,21 @@ ir_Vestel_test.o : ir_Vestel_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
ir_Vestel_test : $(COMMON_OBJ) ir_Vestel_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
ir_Teco.o : $(USER_DIR)/ir_Teco.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Teco.cpp
ir_Teco_test.o : ir_Teco_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Teco_test.cpp
ir_Teco_test : $(COMMON_OBJ) ir_Teco_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
ir_Tcl.o : $(USER_DIR)/ir_Tcl.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Tcl.cpp
ir_Tcl_test.o : ir_Tcl_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Tcl_test.cpp
ir_Tcl_test : $(COMMON_OBJ) ir_Tcl_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
+105 -6
View File
@@ -15,6 +15,14 @@ TEST(TestSendCoolix, SendDataOnly) {
irsend.reset();
irsend.sendCOOLIX(0x0);
EXPECT_EQ(
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s5040"
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
@@ -28,6 +36,14 @@ TEST(TestSendCoolix, SendDataOnly) {
irsend.reset();
irsend.sendCOOLIX(0xAA55AA);
EXPECT_EQ(
"m4480s4480"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
"m560s5040"
"m4480s4480"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680"
@@ -41,6 +57,14 @@ TEST(TestSendCoolix, SendDataOnly) {
irsend.reset();
irsend.sendCOOLIX(0xFFFFFF);
EXPECT_EQ(
"m4480s4480"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s5040"
"m4480s4480"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
@@ -114,6 +138,10 @@ TEST(TestSendCoolix, SendUnusualSize) {
irsend.reset();
irsend.sendCOOLIX(0x0, 8);
EXPECT_EQ(
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
"m560s5040"
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680"
@@ -123,6 +151,24 @@ TEST(TestSendCoolix, SendUnusualSize) {
irsend.reset();
irsend.sendCOOLIX(0x1234567890ABCDEF, 64);
EXPECT_EQ(
"m4480s4480"
"m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560"
"m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680"
"m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560"
"m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s1680"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560m560s1680"
"m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560"
"m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680"
"m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560m560s560"
"m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680"
"m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560"
"m560s1680m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680"
"m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560"
"m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560"
"m560s5040"
"m4480s4480"
"m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560"
"m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680"
@@ -411,7 +457,7 @@ TEST(TestCoolixACClass, HumanReadable) {
// Initial starting point.
EXPECT_EQ(
"Power: On, Fan: 5 (AUTO), Mode: 2 (AUTO), Temp: 25C, "
"Power: On, Mode: 2 (AUTO), Fan: 5 (AUTO), Temp: 25C, "
"Zone Follow: Off, Sensor Temp: Ignored",
ircoolix.toString());
@@ -420,11 +466,11 @@ TEST(TestCoolixACClass, HumanReadable) {
ircoolix.setMode(kCoolixCool);
ircoolix.setFan(kCoolixFanMin);
EXPECT_EQ(
"Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 22C, "
"Power: On, Mode: 0 (COOL), Fan: 4 (MIN), Temp: 22C, "
"Zone Follow: On, Sensor Temp: 24C",
ircoolix.toString());
ircoolix.setSwing();
EXPECT_EQ("Power: On, Fan: 3 (UNKNOWN), Swing: Toggle", ircoolix.toString());
EXPECT_EQ("Power: On, Swing: Toggle", ircoolix.toString());
ircoolix.setPower(false);
EXPECT_EQ("Power: Off", ircoolix.toString());
}
@@ -434,12 +480,12 @@ TEST(TestCoolixACClass, KnownExamples) {
ircoolix.setRaw(0b101100101011111111100100);
EXPECT_EQ(
"Power: On, Fan: 5 (AUTO), Mode: 4 (FAN), Zone Follow: Off, "
"Power: On, Mode: 4 (FAN), Fan: 5 (AUTO), Zone Follow: Off, "
"Sensor Temp: Ignored",
ircoolix.toString());
ircoolix.setRaw(0b101100101001111100000000);
EXPECT_EQ(
"Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 17C, "
"Power: On, Mode: 0 (COOL), Fan: 4 (MIN), Temp: 17C, "
"Zone Follow: Off, Sensor Temp: Ignored",
ircoolix.toString());
}
@@ -449,7 +495,7 @@ TEST(TestCoolixACClass, Issue579FanAuto0) {
ircoolix.setRaw(0xB21F28);
EXPECT_EQ(
"Power: On, Fan: 0 (AUTO0), Mode: 2 (AUTO), Temp: 20C, "
"Power: On, Mode: 2 (AUTO), Fan: 0 (AUTO0), Temp: 20C, "
"Zone Follow: Off, Sensor Temp: Ignored",
ircoolix.toString());
}
@@ -491,3 +537,56 @@ TEST(TestCoolixACClass, RealCaptureExample) {
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
}
// Tests to debug/fix:
// https://github.com/markszabo/IRremoteESP8266/issues/624
TEST(TestCoolixACClass, Issue624HandleSpecialStatesBetter) {
IRCoolixAC ac(0);
ac.begin();
// Default
EXPECT_EQ(
"Power: On, Mode: 2 (AUTO), Fan: 5 (AUTO), Temp: 25C, Zone Follow: Off, "
"Sensor Temp: Ignored",
ac.toString());
EXPECT_EQ(0xB2BFC8, ac.getRaw());
// Change of settings.
ac.setPower(true);
ac.setTemp(24);
ac.setMode(kCoolixCool);
ac.setFan(kCoolixFanAuto);
EXPECT_EQ(
"Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, "
"Sensor Temp: Ignored",
ac.toString());
EXPECT_EQ(0xB2BF40, ac.getRaw());
// Turn the unit off.
ac.setPower(false);
EXPECT_EQ(
"Power: Off",
ac.toString());
EXPECT_EQ(kCoolixOff, ac.getRaw());
// Repeat change of settings.
ac.setPower(true);
ac.setTemp(24);
ac.setMode(kCoolixCool);
ac.setFan(kCoolixFanAuto);
EXPECT_EQ(
"Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, "
"Sensor Temp: Ignored",
ac.toString());
EXPECT_EQ(0xB2BF40, ac.getRaw());
// Now test if we setRaw() a special state first.
ac.setRaw(kCoolixSwing);
// Repeat change of settings.
ac.setPower(true);
ac.setTemp(24);
ac.setMode(kCoolixCool);
ac.setFan(kCoolixFanAuto);
EXPECT_EQ(
"Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, "
"Sensor Temp: Ignored",
ac.toString());
EXPECT_EQ(0xB2BF40, ac.getRaw());
}
+51
View File
@@ -420,3 +420,54 @@ TEST(TestDecodeLG2, RealLG2Example) {
EXPECT_EQ(kLgBits, irsend.capture.bits);
EXPECT_EQ(0x880094D, irsend.capture.value);
}
// Tests for issue reported in
// https://github.com/markszabo/IRremoteESP8266/issues/620
TEST(TestDecodeLG, Issue620) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Raw data as reported in initial comment of Issue #620
uint16_t rawData[59] = {
8886, 4152,
560, 1538, 532, 502, 532, 504, 530, 484, 558, 1536,
508, 516, 558, 502, 532, 484, 558, 502, 532, 500,
534, 508, 532, 502, 532, 1518, 558, 510, 532, 484,
556, 486, 556, 510, 532, 1518, 558, 1560, 532, 1528,
556, 504, 530, 506, 530, 1520, 558, 508, 534, 500,
532, 512, 530, 484, 556, 1536, 532}; // LG 8808721
irsend.sendRaw(rawData, 59, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(LG, irsend.capture.decode_type);
EXPECT_EQ(28, irsend.capture.bits);
EXPECT_EQ(0x8808721, irsend.capture.value);
EXPECT_EQ(0x88, irsend.capture.address);
EXPECT_EQ(0x872, irsend.capture.command);
irsend.reset();
// Resend the same code as the report is a sent code doesn't decode
// to the same message code.
irsend.sendLG(0x8808721);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(LG, irsend.capture.decode_type);
EXPECT_EQ(28, irsend.capture.bits);
EXPECT_EQ(0x8808721, irsend.capture.value);
EXPECT_EQ(0x88, irsend.capture.address);
EXPECT_EQ(0x872, irsend.capture.command);
// The following seems to match the rawData above.
EXPECT_EQ(
"m8500s4250"
"m550s1600m550s550m550s550m550s550m550s1600"
"m550s550m550s550m550s550m550s550m550s550"
"m550s550m550s550m550s1600m550s550m550s550"
"m550s550m550s550m550s1600m550s1600m550s1600"
"m550s550m550s550m550s1600m550s550m550s550"
"m550s550m550s550m550s1600m550"
"s55550",
irsend.outputStr());
}
+144 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 David Conran
// Copyright 2017, 2018, 2019 David Conran
#include "ir_Samsung.h"
#include "IRrecv.h"
@@ -7,6 +7,13 @@
#include "IRsend_test.h"
#include "gtest/gtest.h"
// General housekeeping
TEST(TestSamsung, Housekeeping) {
ASSERT_EQ("SAMSUNG", typeToString(SAMSUNG));
ASSERT_FALSE(hasACState(SAMSUNG));
}
// Tests for sendSAMSUNG().
// Test sending typical data only.
@@ -281,6 +288,12 @@ TEST(TestDecodeSamsung, FailToDecodeNonSamsungExample) {
ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false));
}
// General housekeeping
TEST(TestSamsungAC, Housekeeping) {
ASSERT_EQ("SAMSUNG_AC", typeToString(SAMSUNG_AC));
ASSERT_TRUE(hasACState(SAMSUNG_AC));
}
// Tests for sendSamsungAC().
// Test sending typical data only.
@@ -976,3 +989,133 @@ TEST(TestDecodeSamsungAC, Issue604DecodeExtended) {
"Beep: Off, Clean: Off, Quiet: Off",
samsung.toString());
}
TEST(TestSendSamsung36, SendDataOnly) {
IRsendTest irsend(0);
irsend.begin();
irsend.reset();
irsend.sendSamsung36(0);
EXPECT_EQ(
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s4480"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560"
"m560s26880",
irsend.outputStr());
irsend.sendSamsung36(0x400E00FF);
EXPECT_EQ(
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s4480"
"m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s1680m560s1680m560s1680m560s1680"
"m560s26880",
irsend.outputStr());
irsend.reset();
}
// General housekeeping
TEST(TestSamsung36, Housekeeping) {
ASSERT_EQ("SAMSUNG36", typeToString(SAMSUNG36));
ASSERT_FALSE(hasACState(SAMSUNG36));
}
// Test sending with different repeats.
TEST(TestSendSamsung36, SendWithRepeats) {
IRsendTest irsend(0);
irsend.begin();
irsend.reset();
irsend.sendSamsung36(0x400E00FF, kSamsung36Bits, 1); // 1 repeat.
EXPECT_EQ(
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s4480"
"m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s1680m560s1680m560s1680m560s1680"
"m560s26880"
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s4480"
"m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s1680m560s1680m560s1680m560s1680"
"m560s26880",
irsend.outputStr());
irsend.sendSamsung36(0x400E00FF, kSamsung36Bits, 2); // 2 repeats.
EXPECT_EQ(
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s4480"
"m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s1680m560s1680m560s1680m560s1680"
"m560s26880"
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s4480"
"m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s1680m560s1680m560s1680m560s1680"
"m560s26880"
"m4480s4480"
"m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560"
"m560s4480"
"m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560"
"m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680"
"m560s1680m560s1680m560s1680m560s1680"
"m560s26880",
irsend.outputStr());
}
TEST(TestDecodeSamsung36, RealExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
irsend.reset();
uint16_t rawData[77] = {
4542, 4438, 568, 432, 562, 436, 536, 462, 538, 460, 538, 460, 564, 1434,
564, 434, 534, 464, 536, 462, 562, 436, 536, 464, 564, 432, 538, 462, 536,
464, 534, 464, 564, 420, 566, 4414, 538, 1462, 566, 1432, 562, 1436, 536,
462, 564, 436, 562, 436, 560, 436, 562, 436, 562, 436, 560, 438, 536, 462,
562, 436, 562, 1436, 562, 1434, 536, 1462, 564, 1434, 562, 1436, 564,
1436, 534, 1462, 534, 1464, 536}; // UNKNOWN E4CD1208
irsend.sendRaw(rawData, 77, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(SAMSUNG36, irsend.capture.decode_type);
EXPECT_EQ(kSamsung36Bits, irsend.capture.bits);
EXPECT_EQ(0x400E00FF, irsend.capture.value);
EXPECT_EQ(0xE00FF, irsend.capture.command);
EXPECT_EQ(0x400, irsend.capture.address);
}
TEST(TestDecodeSamsung36, SyntheticExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
irsend.reset();
irsend.sendSamsung36(0x400E00FF);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodeSamsung36(&irsend.capture));
ASSERT_EQ(SAMSUNG36, irsend.capture.decode_type);
EXPECT_EQ(kSamsung36Bits, irsend.capture.bits);
EXPECT_EQ(0x400E00FF, irsend.capture.value);
EXPECT_EQ(0xE00FF, irsend.capture.command);
EXPECT_EQ(0x400, irsend.capture.address);
}
+247
View File
@@ -0,0 +1,247 @@
// Copyright 2019 David Conran
#include "ir_Tcl.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
// General housekeeping
TEST(TestTcl112Ac, Housekeeping) {
ASSERT_EQ("TCL112AC", typeToString(TCL112AC));
ASSERT_TRUE(hasACState(TCL112AC));
}
// Tests for decodeTcl112Ac().
// Decode a real Tcl112Ac A/C example from Issue #619
TEST(TestDecodeTcl112Ac, DecodeRealExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
irsend.reset();
// Tcl112Ac A/C example from Issue #619 On.txt
uint16_t rawData[227] = {
3030, 1658, 494, 1066, 494, 1068, 498, 320, 494,
326, 498, 320, 494, 1068, 500, 320, 494, 332,
494, 1068, 500, 1062, 496, 324, 492, 1044, 524,
322, 492, 326, 498, 1062, 494, 1074, 494, 326,
500, 1062, 496, 1066, 490, 328, 496, 322, 492,
1070, 498, 322, 494, 332, 492, 1068, 498, 320,
494, 326, 498, 320, 496, 324, 500, 320, 494,
324, 490, 336, 500, 320, 496, 324, 490, 328,
496, 322, 492, 328, 498, 322, 492, 326, 498,
328, 496, 322, 492, 328, 498, 1064, 494, 326,
498, 320, 494, 1066, 490, 330, 496, 330, 494,
1066, 490, 1070, 498, 322, 492, 328, 498, 322,
492, 326, 498, 322, 492, 332, 492, 1068, 498,
1062, 494, 1066, 500, 318, 496, 324, 490, 328,
496, 324, 492, 334, 490, 328, 496, 324, 492,
328, 496, 322, 492, 328, 498, 320, 494, 1068,
500, 326, 500, 320, 492, 326, 500, 320, 496,
324, 500, 318, 496, 324, 490, 328, 496, 330,
496, 324, 490, 328, 496, 324, 490, 328, 498,
322, 492, 328, 498, 320, 492, 334, 492, 328,
498, 322, 494, 326, 498, 320, 494, 324, 500,
322, 492, 324, 490, 336, 498, 320, 494, 324,
500, 320, 496, 324, 490, 328, 498, 322, 492,
328, 496, 1070, 496, 1064, 492, 1070, 498, 322,
494, 326, 500, 320, 494, 324, 500, 320, 494,
324, 470}; // UNKNOWN CE60D6B9
uint8_t expectedState[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x07, 0x40, 0x00, 0x00, 0x00, 0x80, 0x03};
irsend.sendRaw(rawData, 227, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(TCL112AC, irsend.capture.decode_type);
EXPECT_EQ(kTcl112AcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
IRTcl112Ac ac(0);
ac.setRaw(irsend.capture.state);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 24C", ac.toString());
}
// Decode a synthetic Tcl112Ac A/C example from Issue #619
TEST(TestDecodeTcl112Ac, DecodeSyntheticExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
irsend.reset();
uint8_t expectedState[kTcl112AcStateLength] = {0x23, 0xCB, 0x26, 0x01, 0x00,
0x24, 0x03, 0x07, 0x40, 0x00,
0x00, 0x00, 0x80, 0x03};
irsend.sendTcl112Ac(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(TCL112AC, irsend.capture.decode_type);
EXPECT_EQ(kTcl112AcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
}
TEST(TestTcl112AcClass, Temperature) {
const uint8_t temp16C[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB};
const uint8_t temp16point5C[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x0F, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xEB};
const uint8_t temp19point5C[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x0C, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xE8};
const uint8_t temp31C[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBC};
IRTcl112Ac ac(0);
ac.setRaw(temp16C);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 16C", ac.toString());
ac.setRaw(temp16point5C);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 16.5C", ac.toString());
ac.setRaw(temp19point5C);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 19.5C", ac.toString());
ac.setRaw(temp31C);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 31C", ac.toString());
ac.setTemp(kTcl112AcTempMin);
EXPECT_EQ(kTcl112AcTempMin, ac.getTemp());
ac.setTemp(kTcl112AcTempMin + 1);
EXPECT_EQ(kTcl112AcTempMin + 1, ac.getTemp());
ac.setTemp(kTcl112AcTempMax);
EXPECT_EQ(kTcl112AcTempMax, ac.getTemp());
ac.setTemp(kTcl112AcTempMin - 1);
EXPECT_EQ(kTcl112AcTempMin, ac.getTemp());
ac.setTemp(kTcl112AcTempMax + 0.5);
EXPECT_EQ(kTcl112AcTempMax, ac.getTemp());
ac.setTemp(23);
EXPECT_EQ(23, ac.getTemp());
ac.setTemp(27.4);
EXPECT_EQ(27, ac.getTemp());
ac.setTemp(22.5);
EXPECT_EQ(22.5, ac.getTemp());
ac.setTemp(25.6);
EXPECT_EQ(25.5, ac.getTemp());
ac.setTemp(0);
EXPECT_EQ(kTcl112AcTempMin, ac.getTemp());
ac.setTemp(255);
EXPECT_EQ(kTcl112AcTempMax, ac.getTemp());
}
TEST(TestTcl112AcClass, OperatingMode) {
IRTcl112Ac ac(0);
ac.begin();
ac.setMode(kTcl112AcAuto);
EXPECT_EQ(kTcl112AcAuto, ac.getMode());
ac.setMode(kTcl112AcCool);
EXPECT_EQ(kTcl112AcCool, ac.getMode());
ac.setMode(kTcl112AcHeat);
EXPECT_EQ(kTcl112AcHeat, ac.getMode());
ac.setMode(kTcl112AcFan);
EXPECT_EQ(kTcl112AcFan, ac.getMode());
ac.setMode(kTcl112AcDry);
EXPECT_EQ(kTcl112AcDry, ac.getMode());
ac.setMode(kTcl112AcHeat - 1);
EXPECT_EQ(kTcl112AcAuto, ac.getMode());
ac.setMode(kTcl112AcCool);
EXPECT_EQ(kTcl112AcCool, ac.getMode());
ac.setMode(kTcl112AcAuto + 1);
EXPECT_EQ(kTcl112AcAuto, ac.getMode());
ac.setMode(kTcl112AcCool);
ac.setMode(255);
EXPECT_EQ(kTcl112AcAuto, ac.getMode());
ac.setMode(kTcl112AcCool);
ac.setMode(0);
EXPECT_EQ(kTcl112AcAuto, ac.getMode());
const uint8_t automode[] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x08,
0x07, 0x00, 0x00, 0x00, 0x00, 0x80, 0x48};
ac.setRaw(automode);
EXPECT_EQ("Power: On, Mode: 8 (AUTO), Temp: 24C", ac.toString());
}
TEST(TestTcl112AcClass, Power) {
IRTcl112Ac ac(0);
ac.begin();
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
ac.setPower(false);
EXPECT_EQ(false, ac.getPower());
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
ac.off();
EXPECT_EQ(false, ac.getPower());
ac.on();
EXPECT_TRUE(ac.getPower());
const uint8_t on[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB};
ac.setRaw(on);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 16C", ac.toString());
const uint8_t off[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x03,
0x07, 0x40, 0x00, 0x00, 0x00, 0x80, 0xCB};
ac.setRaw(off);
EXPECT_EQ("Power: Off, Mode: 3 (COOL), Temp: 24C", ac.toString());
}
TEST(TestTcl112AcClass, Checksum) {
uint8_t temp16C[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB};
uint8_t temp31C[kTcl112AcStateLength] = {
0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBC};
IRTcl112Ac ac(0);
EXPECT_EQ(0xCB, ac.calcChecksum(temp16C));
ac.setRaw(temp16C);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 16C", ac.toString());
ac.setRaw(temp31C);
EXPECT_EQ("Power: On, Mode: 3 (COOL), Temp: 31C", ac.toString());
EXPECT_EQ(0xBC, ac.calcChecksum(temp31C));
EXPECT_TRUE(IRTcl112Ac::validChecksum(temp16C));
EXPECT_TRUE(IRTcl112Ac::validChecksum(temp31C));
EXPECT_TRUE(ac.validChecksum(temp31C));
ac.setRaw(temp16C);
EXPECT_TRUE(ac.validChecksum(ac.getRaw()));
ac.setTemp(31);
EXPECT_TRUE(ac.validChecksum(ac.getRaw()));
EXPECT_EQ(0xBC, ac.calcChecksum(ac.getRaw()));
}
+356
View File
@@ -0,0 +1,356 @@
// Copyright 2019 David Conran
#include "ir_Teco.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
// General housekeeping
TEST(TestTeco, Housekeeping) {
ASSERT_EQ("TECO", typeToString(TECO));
ASSERT_FALSE(hasACState(TECO)); // Uses uint64_t, not uint8_t*.
}
// Tests for sendTeco()
// Test sending typical data only.
TEST(TestSendTeco, SendDataOnly) {
IRsendTest irsend(0);
irsend.begin();
irsend.reset();
irsend.sendTeco(0x250002BC9);
EXPECT_EQ(
"m9000s4440"
"m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650"
"m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580"
"m620s580m620s1650m620s580"
"m620s1000000",
irsend.outputStr());
}
// Test sending typical data with repeats.
TEST(TestSendTeco, SendWithRepeats) {
IRsendTest irsend(0);
irsend.begin();
irsend.reset();
irsend.sendTeco(0x250002BC9, kTecoBits, 2); // two repeats.
EXPECT_EQ(
"m9000s4440"
"m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650"
"m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580"
"m620s580m620s1650m620s580"
"m620s1000000"
"m9000s4440"
"m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650"
"m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580"
"m620s580m620s1650m620s580"
"m620s1000000"
"m9000s4440"
"m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650"
"m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580"
"m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580"
"m620s580m620s1650m620s580"
"m620s1000000",
irsend.outputStr());
}
// Tests for IRTeco class.
TEST(TestTecoACClass, Power) {
IRTecoAc ac(0);
ac.begin();
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
ac.setPower(false);
EXPECT_EQ(false, ac.getPower());
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
ac.off();
EXPECT_EQ(false, ac.getPower());
ac.on();
EXPECT_TRUE(ac.getPower());
}
TEST(TestTecoACClass, OperatingMode) {
IRTecoAc ac(0);
ac.begin();
ac.setMode(kTecoAuto);
EXPECT_EQ(kTecoAuto, ac.getMode());
ac.setMode(kTecoCool);
EXPECT_EQ(kTecoCool, ac.getMode());
ac.setMode(kTecoHeat);
EXPECT_EQ(kTecoHeat, ac.getMode());
ac.setMode(kTecoFan);
EXPECT_EQ(kTecoFan, ac.getMode());
ac.setMode(kTecoDry);
EXPECT_EQ(kTecoDry, ac.getMode());
ac.setMode(kTecoAuto - 1);
EXPECT_EQ(kTecoAuto, ac.getMode());
ac.setMode(kTecoCool);
EXPECT_EQ(kTecoCool, ac.getMode());
ac.setMode(kTecoHeat + 1);
EXPECT_EQ(kTecoAuto, ac.getMode());
ac.setMode(255);
EXPECT_EQ(kTecoAuto, ac.getMode());
}
TEST(TestTecoACClass, Temperature) {
IRTecoAc ac(0);
ac.begin();
ac.setTemp(kTecoMinTemp);
EXPECT_EQ(kTecoMinTemp, ac.getTemp());
ac.setTemp(kTecoMinTemp + 1);
EXPECT_EQ(kTecoMinTemp + 1, ac.getTemp());
ac.setTemp(kTecoMaxTemp);
EXPECT_EQ(kTecoMaxTemp, ac.getTemp());
ac.setTemp(kTecoMinTemp - 1);
EXPECT_EQ(kTecoMinTemp, ac.getTemp());
ac.setTemp(kTecoMaxTemp + 1);
EXPECT_EQ(kTecoMaxTemp, ac.getTemp());
ac.setTemp(23);
EXPECT_EQ(23, ac.getTemp());
ac.setTemp(0);
EXPECT_EQ(kTecoMinTemp, ac.getTemp());
ac.setTemp(255);
EXPECT_EQ(kTecoMaxTemp, ac.getTemp());
}
TEST(TestTecoACClass, FanSpeed) {
IRTecoAc ac(0);
ac.begin();
ac.setFan(kTecoFanLow);
ac.setFan(kTecoFanAuto);
EXPECT_EQ(kTecoFanAuto, ac.getFan());
ac.setFan(kTecoFanLow);
EXPECT_EQ(kTecoFanLow, ac.getFan());
ac.setFan(kTecoFanMed);
EXPECT_EQ(kTecoFanMed, ac.getFan());
ac.setFan(kTecoFanHigh);
EXPECT_EQ(kTecoFanHigh, ac.getFan());
ac.setFan(kTecoFanHigh);
EXPECT_EQ(kTecoFanHigh, ac.getFan());
}
TEST(TestTecoACClass, Swing) {
IRTecoAc ac(0);
ac.begin();
ac.setSwing(true);
EXPECT_TRUE(ac.getSwing());
ac.setSwing(false);
EXPECT_EQ(false, ac.getSwing());
ac.setSwing(true);
EXPECT_TRUE(ac.getSwing());
}
TEST(TestTecoACClass, Sleep) {
IRTecoAc ac(0);
ac.begin();
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());
ac.setSleep(false);
EXPECT_EQ(false, ac.getSleep());
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());
}
TEST(TestTecoACClass, MessageConstuction) {
IRTecoAc ac(0);
EXPECT_EQ(
"Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, "
"Swing: Off",
ac.toString());
ac.setPower(true);
ac.setMode(kTecoCool);
ac.setTemp(21);
ac.setFan(kTecoFanHigh);
ac.setSwing(false);
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, "
"Swing: Off",
ac.toString());
ac.setSwing(true);
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, "
"Swing: On",
ac.toString());
ac.setSwing(false);
ac.setFan(kTecoFanLow);
ac.setSleep(true);
ac.setMode(kTecoHeat);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: On, "
"Swing: Off",
ac.toString());
ac.setSleep(false);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: Off, "
"Swing: Off",
ac.toString());
ac.setTemp(25);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 1 (Low), Sleep: Off, "
"Swing: Off",
ac.toString());
}
TEST(TestTecoACClass, ReconstructKnownMessage) {
IRTecoAc ac(0);
const uint64_t expected = 0x250002BC9;
ASSERT_FALSE(ac.getRaw() == expected);
ac.setPower(true);
ac.setMode(kTecoCool);
ac.setTemp(27);
ac.setFan(kTecoFanAuto);
ac.setSleep(true);
ac.setSwing(true);
EXPECT_EQ(expected, ac.getRaw());
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, "
"Swing: On",
ac.toString());
}
// Tests for decodeTeco().
// Decode normal "synthetic" messages.
TEST(TestDecodeTeco, NormalDecodeWithStrict) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// With the specific decoder.
uint64_t expectedState = kTecoReset;
irsend.reset();
irsend.sendTeco(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodeTeco(&irsend.capture, kTecoBits, true));
EXPECT_EQ(TECO, irsend.capture.decode_type);
EXPECT_EQ(kTecoBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(expectedState, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(0, irsend.capture.command);
// With the all the decoders.
irsend.reset();
irsend.sendTeco(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TECO, irsend.capture.decode_type);
EXPECT_EQ(kTecoBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(expectedState, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(0, irsend.capture.command);
IRTecoAc ac(0);
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
"Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, "
"Swing: Off",
ac.toString());
}
// Decode a real message from Raw Data.
TEST(TestDecodeTeco, RealNormalExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRTecoAc ac(0);
irsend.begin();
uint16_t rawData1[73] = {
9076, 4442, 670, 1620, 670, 516, 670, 516, 666, 1626, 670, 516,
664, 520, 666, 1626, 666, 1626, 664, 1626, 666, 1626, 666, 520,
666, 1626, 666, 520, 666, 1626, 666, 520, 666, 516, 670, 514,
670, 516, 666, 520, 670, 516, 666, 520, 666, 516, 672, 514, 670,
516, 666, 520, 666, 516, 672, 514, 670, 516, 666, 1624, 666, 520,
666, 1626, 666, 520, 666, 516, 672, 1620, 670, 516, 670};
uint64_t expected1 = 0b01001010000000000000010101111001001; // 0x250002BC9
irsend.reset();
irsend.sendRaw(rawData1, 73, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TECO, irsend.capture.decode_type);
EXPECT_EQ(kTecoBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(expected1, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(0, irsend.capture.command);
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, "
"Swing: On",
ac.toString());
uint16_t rawData2[73] = {
9048, 4472, 636, 548, 636, 1654, 638, 546, 642, 1650, 642, 546, 638,
1654, 638, 1654, 638, 546, 638, 1654, 636, 546, 642, 1650, 640, 548,
636, 548, 638, 546, 636, 546, 642, 542, 642, 546, 638, 546, 638, 546,
636, 548, 642, 542, 642, 546, 636, 548, 636, 546, 642, 542, 642, 546,
638, 546, 638, 546, 636, 1654, 642, 542, 642, 1650, 642, 546, 638, 546,
638, 1654, 638, 546, 642}; // TECO 25000056A
uint64_t expected2 = 0b01001010000000000000000010101101010; // 0x25000056A
irsend.reset();
irsend.sendRaw(rawData2, 73, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TECO, irsend.capture.decode_type);
EXPECT_EQ(kTecoBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(expected2, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(0, irsend.capture.command);
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
"Power: On, Mode: 2 (DRY), Temp: 21C, Fan: 2 (Med), Sleep: Off, "
"Swing: On",
ac.toString());
}
+91 -91
View File
@@ -7,15 +7,15 @@
#include "IRsend_test.h"
#include "gtest/gtest.h"
// Tests for sendVestelAC()
// Tests for sendVestelAc()
// Test sending typical data only.
TEST(TestSendVestelAC, SendDataOnly) {
TEST(TestSendVestelAc, SendDataOnly) {
IRsendTest irsend(0);
irsend.begin();
irsend.reset();
irsend.sendVestelAC(0x0F00D9001FEF201ULL);
irsend.sendVestelAc(0x0F00D9001FEF201ULL);
EXPECT_EQ(
"m3110s9066"
"m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480"
@@ -30,12 +30,12 @@ TEST(TestSendVestelAC, SendDataOnly) {
}
// Test sending typical data with repeats.
TEST(TestSendVestelAC, SendWithRepeats) {
TEST(TestSendVestelAc, SendWithRepeats) {
IRsendTest irsend(0);
irsend.begin();
irsend.reset();
irsend.sendVestelAC(0x0F00D9001FEF201ULL, kVestelACBits, 2); // two repeats.
irsend.sendVestelAc(0x0F00D9001FEF201ULL, kVestelAcBits, 2); // two repeats.
EXPECT_EQ(
"m3110s9066"
"m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480"
@@ -67,10 +67,10 @@ TEST(TestSendVestelAC, SendWithRepeats) {
irsend.outputStr());
}
// Tests for IRVestelAC class.
// Tests for IRVestelAc class.
TEST(TestVestelACClass, Power) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Power) {
IRVestelAc ac(0);
ac.begin();
ac.setPower(true);
@@ -90,91 +90,91 @@ TEST(TestVestelACClass, Power) {
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, OperatingMode) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, OperatingMode) {
IRVestelAc ac(0);
ac.begin();
ac.setMode(kVestelACAuto);
EXPECT_EQ(kVestelACAuto, ac.getMode());
ac.setMode(kVestelAcAuto);
EXPECT_EQ(kVestelAcAuto, ac.getMode());
ac.setMode(kVestelACCool);
EXPECT_EQ(kVestelACCool, ac.getMode());
ac.setMode(kVestelAcCool);
EXPECT_EQ(kVestelAcCool, ac.getMode());
ac.setMode(kVestelACHeat);
EXPECT_EQ(kVestelACHeat, ac.getMode());
ac.setMode(kVestelAcHeat);
EXPECT_EQ(kVestelAcHeat, ac.getMode());
ac.setMode(kVestelACFan);
EXPECT_EQ(kVestelACFan, ac.getMode());
ac.setMode(kVestelAcFan);
EXPECT_EQ(kVestelAcFan, ac.getMode());
ac.setMode(kVestelACDry);
EXPECT_EQ(kVestelACDry, ac.getMode());
ac.setMode(kVestelAcDry);
EXPECT_EQ(kVestelAcDry, ac.getMode());
ac.setMode(kVestelACAuto - 1);
EXPECT_EQ(kVestelACAuto, ac.getMode());
ac.setMode(kVestelAcAuto - 1);
EXPECT_EQ(kVestelAcAuto, ac.getMode());
ac.setMode(kVestelACCool);
EXPECT_EQ(kVestelACCool, ac.getMode());
ac.setMode(kVestelAcCool);
EXPECT_EQ(kVestelAcCool, ac.getMode());
ac.setMode(kVestelACHeat + 1);
EXPECT_EQ(kVestelACAuto, ac.getMode());
ac.setMode(kVestelAcHeat + 1);
EXPECT_EQ(kVestelAcAuto, ac.getMode());
ac.setMode(255);
EXPECT_EQ(kVestelACAuto, ac.getMode());
EXPECT_EQ(kVestelAcAuto, ac.getMode());
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, Temperature) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Temperature) {
IRVestelAc ac(0);
ac.begin();
ac.setTemp(kVestelACMinTempC);
EXPECT_EQ(kVestelACMinTempC, ac.getTemp());
ac.setTemp(kVestelAcMinTempC);
EXPECT_EQ(kVestelAcMinTempC, ac.getTemp());
ac.setTemp(kVestelACMinTempC + 1);
EXPECT_EQ(kVestelACMinTempC + 1, ac.getTemp());
ac.setTemp(kVestelAcMinTempC + 1);
EXPECT_EQ(kVestelAcMinTempC + 1, ac.getTemp());
ac.setTemp(kVestelACMaxTemp);
EXPECT_EQ(kVestelACMaxTemp, ac.getTemp());
ac.setTemp(kVestelAcMaxTemp);
EXPECT_EQ(kVestelAcMaxTemp, ac.getTemp());
ac.setTemp(kVestelACMinTempC - 1);
EXPECT_EQ(kVestelACMinTempC, ac.getTemp());
ac.setTemp(kVestelAcMinTempC - 1);
EXPECT_EQ(kVestelAcMinTempC, ac.getTemp());
ac.setTemp(kVestelACMaxTemp + 1);
EXPECT_EQ(kVestelACMaxTemp, ac.getTemp());
ac.setTemp(kVestelAcMaxTemp + 1);
EXPECT_EQ(kVestelAcMaxTemp, ac.getTemp());
ac.setTemp(23);
EXPECT_EQ(23, ac.getTemp());
ac.setTemp(0);
EXPECT_EQ(kVestelACMinTempC, ac.getTemp());
EXPECT_EQ(kVestelAcMinTempC, ac.getTemp());
ac.setTemp(255);
EXPECT_EQ(kVestelACMaxTemp, ac.getTemp());
EXPECT_EQ(kVestelAcMaxTemp, ac.getTemp());
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, FanSpeed) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, FanSpeed) {
IRVestelAc ac(0);
ac.begin();
ac.setFan(kVestelACFanLow);
ac.setFan(kVestelAcFanLow);
ac.setFan(kVestelACFanAuto);
EXPECT_EQ(kVestelACFanAuto, ac.getFan());
ac.setFan(kVestelAcFanAuto);
EXPECT_EQ(kVestelAcFanAuto, ac.getFan());
ac.setFan(kVestelACFanLow);
EXPECT_EQ(kVestelACFanLow, ac.getFan());
ac.setFan(kVestelACFanMed);
EXPECT_EQ(kVestelACFanMed, ac.getFan());
ac.setFan(kVestelACFanHigh);
EXPECT_EQ(kVestelACFanHigh, ac.getFan());
ac.setFan(kVestelAcFanLow);
EXPECT_EQ(kVestelAcFanLow, ac.getFan());
ac.setFan(kVestelAcFanMed);
EXPECT_EQ(kVestelAcFanMed, ac.getFan());
ac.setFan(kVestelAcFanHigh);
EXPECT_EQ(kVestelAcFanHigh, ac.getFan());
ac.setFan(kVestelACFanHigh);
EXPECT_EQ(kVestelACFanHigh, ac.getFan());
ac.setFan(kVestelAcFanHigh);
EXPECT_EQ(kVestelAcFanHigh, ac.getFan());
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, Swing) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Swing) {
IRVestelAc ac(0);
ac.begin();
ac.setSwing(true);
@@ -188,8 +188,8 @@ TEST(TestVestelACClass, Swing) {
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, Ion) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Ion) {
IRVestelAc ac(0);
ac.begin();
ac.setIon(true);
@@ -203,8 +203,8 @@ TEST(TestVestelACClass, Ion) {
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, Turbo) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Turbo) {
IRVestelAc ac(0);
ac.begin();
ac.setTurbo(true);
@@ -218,8 +218,8 @@ TEST(TestVestelACClass, Turbo) {
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, Sleep) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Sleep) {
IRVestelAc ac(0);
ac.begin();
ac.setSleep(true);
@@ -233,8 +233,8 @@ TEST(TestVestelACClass, Sleep) {
EXPECT_FALSE(ac.isTimeCommand());
}
TEST(TestVestelACClass, Time) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Time) {
IRVestelAc ac(0);
ac.begin();
ac.setTime(0);
@@ -251,8 +251,8 @@ TEST(TestVestelACClass, Time) {
EXPECT_EQ(23 * 60 + 59, ac.getTime());
}
TEST(TestVestelACClass, OnTimer) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, OnTimer) {
IRVestelAc ac(0);
ac.begin();
ac.setOnTimer(0);
@@ -272,8 +272,8 @@ TEST(TestVestelACClass, OnTimer) {
EXPECT_EQ(23 * 60 + 50, ac.getOnTimer());
}
TEST(TestVestelACClass, OffTimer) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, OffTimer) {
IRVestelAc ac(0);
ac.begin();
ac.setOffTimer(0);
@@ -293,8 +293,8 @@ TEST(TestVestelACClass, OffTimer) {
EXPECT_EQ(23 * 60 + 50, ac.getOffTimer());
}
TEST(TestVestelACClass, Timer) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, Timer) {
IRVestelAc ac(0);
ac.begin();
ac.setTimer(0);
@@ -315,16 +315,16 @@ TEST(TestVestelACClass, Timer) {
EXPECT_EQ(0, ac.getOnTimer());
}
TEST(TestVestelACClass, MessageConstuction) {
IRVestelAC ac(0);
TEST(TestVestelAcClass, MessageConstuction) {
IRVestelAc ac(0);
EXPECT_EQ(
"Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (AUTO HOT), Sleep: Off, "
"Turbo: Off, Ion: Off, Swing: Off",
ac.toString());
ac.setMode(kVestelACCool);
ac.setMode(kVestelAcCool);
ac.setTemp(21);
ac.setFan(kVestelACFanHigh);
ac.setFan(kVestelAcFanHigh);
EXPECT_FALSE(ac.isTimeCommand());
EXPECT_EQ(
"Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (HIGH), Sleep: Off, "
@@ -341,7 +341,7 @@ TEST(TestVestelACClass, MessageConstuction) {
// Now change a few already set things.
ac.setSleep(true);
ac.setMode(kVestelACHeat);
ac.setMode(kVestelAcHeat);
EXPECT_EQ(
"Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 11 (HIGH), Sleep: On, "
"Turbo: Off, Ion: On, Swing: On",
@@ -357,7 +357,7 @@ TEST(TestVestelACClass, MessageConstuction) {
EXPECT_FALSE(ac.isTimeCommand());
// Check that the checksum is valid.
EXPECT_TRUE(IRVestelAC::validChecksum(ac.getRaw()));
EXPECT_TRUE(IRVestelAc::validChecksum(ac.getRaw()));
ac.setTime(23 * 60 + 59);
EXPECT_TRUE(ac.isTimeCommand());
EXPECT_EQ(
@@ -392,10 +392,10 @@ TEST(TestVestelACClass, MessageConstuction) {
ac.toString());
}
// Tests for decodeVestelAC().
// Tests for decodeVestelAc().
// Decode normal "synthetic" messages.
TEST(TestDecodeVestelAC, NormalDecodeWithStrict) {
TEST(TestDecodeVestelAc, NormalDecodeWithStrict) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
@@ -403,11 +403,11 @@ TEST(TestDecodeVestelAC, NormalDecodeWithStrict) {
// With the specific decoder.
uint64_t expectedState = 0x0F00D9001FEF201ULL;
irsend.reset();
irsend.sendVestelAC(expectedState);
irsend.sendVestelAc(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodeVestelAC(&irsend.capture, kVestelACBits, true));
ASSERT_TRUE(irrecv.decodeVestelAc(&irsend.capture, kVestelAcBits, true));
EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type);
EXPECT_EQ(kVestelACBits, irsend.capture.bits);
EXPECT_EQ(kVestelAcBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(expectedState, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
@@ -415,17 +415,17 @@ TEST(TestDecodeVestelAC, NormalDecodeWithStrict) {
// With the all the decoders.
irsend.reset();
irsend.sendVestelAC(expectedState);
irsend.sendVestelAc(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type);
EXPECT_EQ(kVestelACBits, irsend.capture.bits);
EXPECT_EQ(kVestelAcBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(expectedState, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(0, irsend.capture.command);
IRVestelAC ac(0);
IRVestelAc ac(0);
ac.begin();
ac.setRaw(irsend.capture.value);
EXPECT_EQ(
@@ -435,10 +435,10 @@ TEST(TestDecodeVestelAC, NormalDecodeWithStrict) {
}
// Decode a real message from Raw Data.
TEST(TestDecodeVestelAC, RealNormalExample) {
TEST(TestDecodeVestelAc, RealNormalExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRVestelAC ac(0);
IRVestelAc ac(0);
irsend.begin();
uint16_t rawData[115] = {
@@ -457,7 +457,7 @@ TEST(TestDecodeVestelAC, RealNormalExample) {
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type);
EXPECT_EQ(kVestelACBits, irsend.capture.bits);
EXPECT_EQ(kVestelAcBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(0xF4410001FF1201ULL, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
@@ -470,10 +470,10 @@ TEST(TestDecodeVestelAC, RealNormalExample) {
ac.toString());
}
TEST(TestDecodeVestelAC, RealTimerExample) {
TEST(TestDecodeVestelAc, RealTimerExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRVestelAC ac(0);
IRVestelAc ac(0);
irsend.begin();
uint16_t rawData[115] = {
@@ -492,7 +492,7 @@ TEST(TestDecodeVestelAC, RealTimerExample) {
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type);
EXPECT_EQ(kVestelACBits, irsend.capture.bits);
EXPECT_EQ(kVestelAcBits, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(0x2D6570B8EE201ULL, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.address);
@@ -505,7 +505,7 @@ TEST(TestDecodeVestelAC, RealTimerExample) {
}
// General housekeeping
TEST(TestDecodeVestelAC, Housekeeping) {
TEST(TestDecodeVestelAc, Housekeeping) {
ASSERT_EQ("VESTEL_AC", typeToString(VESTEL_AC));
ASSERT_FALSE(hasACState(VESTEL_AC)); // Uses uint64_t, not uint8_t*.
}
+7 -1
View File
@@ -48,7 +48,7 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
ir_Pronto.o ir_GlobalCache.o ir_Nikai.o ir_Toshiba.o ir_Midea.o \
ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o ir_Hitachi.o \
ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o ir_Pioneer.o \
ir_MWM.o ir_Vestel.o
ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o
# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS)
@@ -197,3 +197,9 @@ ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS)
ir_Vestel.o : $(USER_DIR)/ir_Vestel.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Vestel.cpp
ir_Teco.o : $(USER_DIR)/ir_Teco.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Teco.cpp
ir_Tcl.o : $(USER_DIR)/ir_Tcl.cpp $(USER_DIR)/ir_Tcl.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Tcl.cpp