mirror of
https://github.com/crankyoldgit/IRremoteESP8266.git
synced 2026-01-12 00:05:10 +08:00
Add basic support for HITACHI_AC3 protocol. (#1063)
* Supports Hitachi PC-LH3B * Add send & decode routines. - Support all known state/bit sizes captured so far. * Update ancillary support routines. * Add synthetic and real unit test cases. * very basic IRHitachiAc3 class added. - Enough code to verify the checksum/integrity check for the protocol. - Add integrity check to `decodeHitachiAc3()` For #1060
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<!--- WARNING: Do NOT edit this file directly.
|
||||
It is generated by './tools/scrape_supported_devices.py'.
|
||||
Last generated: Sat Mar 7 23:57:26 2020 --->
|
||||
Last generated: Tue Mar 17 13:45:51 2020 --->
|
||||
# IR Protocols supported by this library
|
||||
|
||||
| Protocol | Brand | Model | A/C Model | Detailed A/C Support |
|
||||
@@ -28,7 +28,7 @@
|
||||
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[RusClimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | EACS/I-09HAR_X/N3 A/C<BR>YAW1F remote | YAW1F<BR>YBOFB | Yes |
|
||||
| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | YAW1F<BR>YBOFB | Yes |
|
||||
| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C<BR>HSU07-HEA03 remote<BR>YR-W02 remote | | Yes |
|
||||
| [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote<BR>RAR-8P2 remote<BR>RAS-35THA6 remote<BR>RAS-AJ25H A/C<BR>Series VI A/C (Circa 2007) | | Yes |
|
||||
| [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | LT0541-HTA remote<BR>PC-LH3B (HITACHI_AC3)<BR>RAR-8P2 remote<BR>RAS-35THA6 remote<BR>RAS-AJ25H A/C<BR>Series VI A/C (Circa 2007) | | Yes |
|
||||
| [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - |
|
||||
| [JVC](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_JVC.cpp) | **Unknown** | | | - |
|
||||
| [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | YAPOF3 remote | | Yes |
|
||||
@@ -107,6 +107,7 @@
|
||||
- HITACHI_AC
|
||||
- HITACHI_AC1
|
||||
- HITACHI_AC2
|
||||
- HITACHI_AC3
|
||||
- HITACHI_AC424
|
||||
- INAX
|
||||
- JVC
|
||||
|
||||
@@ -1518,6 +1518,23 @@ bool parseStringAndSendAirCon(IRsend *irsend, const decode_type_t irType,
|
||||
// Lastly, it should never exceed the maximum "normal" size.
|
||||
stateSize = std::min(stateSize, kFujitsuAcStateLength);
|
||||
break;
|
||||
case HITACHI_AC3:
|
||||
// HitachiAc3 has two distinct & different size states, so make a best
|
||||
// guess which one we are being presented with based on the number of
|
||||
// hexadecimal digits provided. i.e. Zero-pad if you need to to get
|
||||
// the correct length/byte size.
|
||||
stateSize = inputLength / 2; // Every two hex chars is a byte.
|
||||
// Use at least the minimum size.
|
||||
stateSize = std::max(stateSize,
|
||||
(uint16_t) (kHitachiAc3MinStateLength));
|
||||
// If we think it isn't a "short" message.
|
||||
if (stateSize > kHitachiAc3MinStateLength)
|
||||
// Then it probably the "normal" size.
|
||||
stateSize = std::max(stateSize,
|
||||
(uint16_t) (kHitachiAc3StateLength));
|
||||
// Lastly, it should never exceed the maximum "normal" size.
|
||||
stateSize = std::min(stateSize, kHitachiAc3StateLength);
|
||||
break;
|
||||
case MWM:
|
||||
// MWM has variable size states, so make a best guess
|
||||
// which one we are being presented with based on the number of
|
||||
|
||||
@@ -641,10 +641,28 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
|
||||
if (decodeHaierACYRW02(results, offset)) return true;
|
||||
#endif
|
||||
#if DECODE_HITACHI_AC424
|
||||
// HitachiAc424 should be checked before HitachiAC & HitachiAC2
|
||||
// HitachiAc424 should be checked before HitachiAC, HitachiAC2,
|
||||
// & HitachiAC184
|
||||
DPRINTLN("Attempting Hitachi AC 424 decode");
|
||||
if (decodeHitachiAc424(results, offset, kHitachiAc424Bits)) return true;
|
||||
#endif // DECODE_HITACHI_AC2
|
||||
#endif // DECODE_HITACHI_AC424
|
||||
#if DECODE_MITSUBISHI136
|
||||
// Needs to happen before HitachiAc3 decode.
|
||||
DPRINTLN("Attempting Mitsubishi136 decode");
|
||||
if (decodeMitsubishi136(results, offset)) return true;
|
||||
#endif // DECODE_MITSUBISHI136
|
||||
#if DECODE_HITACHI_AC3
|
||||
// HitachiAc3 should be checked before HitachiAC & HitachiAC2
|
||||
// Attempt normal before the short version.
|
||||
DPRINTLN("Attempting Hitachi AC3 decode");
|
||||
// Order these in decreasing bit size, as it is more optimal.
|
||||
if (decodeHitachiAc3(results, offset, kHitachiAc3Bits) ||
|
||||
decodeHitachiAc3(results, offset, kHitachiAc3Bits - 4 * 8) ||
|
||||
decodeHitachiAc3(results, offset, kHitachiAc3Bits - 6 * 8) ||
|
||||
decodeHitachiAc3(results, offset, kHitachiAc3MinBits + 2 * 8) ||
|
||||
decodeHitachiAc3(results, offset, kHitachiAc3MinBits))
|
||||
return true;
|
||||
#endif // DECODE_HITACHI_AC3
|
||||
#if DECODE_HITACHI_AC2
|
||||
// HitachiAC2 should be checked before HitachiAC
|
||||
DPRINTLN("Attempting Hitachi AC2 decode");
|
||||
@@ -759,10 +777,6 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
|
||||
DPRINTLN("Attempting Daikin152 decode");
|
||||
if (decodeDaikin152(results, offset)) return true;
|
||||
#endif // DECODE_DAIKIN152
|
||||
#if DECODE_MITSUBISHI136
|
||||
DPRINTLN("Attempting Mitsubishi136 decode");
|
||||
if (decodeMitsubishi136(results, offset)) return true;
|
||||
#endif // DECODE_MITSUBISHI136
|
||||
#if DECODE_SYMPHONY
|
||||
DPRINTLN("Attempting Symphony decode");
|
||||
if (decodeSymphony(results, offset)) return true;
|
||||
|
||||
@@ -485,6 +485,12 @@ class IRrecv {
|
||||
const uint16_t nbits = kHitachiAc1Bits,
|
||||
const bool strict = true);
|
||||
#endif
|
||||
#if DECODE_HITACHI_AC3
|
||||
bool decodeHitachiAc3(decode_results *results,
|
||||
uint16_t offset = kStartOffset,
|
||||
const uint16_t nbits = kHitachiAc3Bits,
|
||||
const bool strict = true);
|
||||
#endif // DECODE_HITACHI_AC3
|
||||
#if DECODE_HITACHI_AC424
|
||||
bool decodeHitachiAc424(decode_results *results,
|
||||
uint16_t offset = kStartOffset,
|
||||
|
||||
@@ -411,6 +411,20 @@
|
||||
#define SEND_HITACHI_AC2 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_HITACHI_AC2
|
||||
|
||||
#ifndef DECODE_HITACHI_AC3
|
||||
#define DECODE_HITACHI_AC3 _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_HITACHI_AC3
|
||||
#ifndef SEND_HITACHI_AC3
|
||||
#define SEND_HITACHI_AC3 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_HITACHI_AC3
|
||||
|
||||
#ifndef DECODE_HITACHI_AC424
|
||||
#define DECODE_HITACHI_AC424 _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_HITACHI_AC424
|
||||
#ifndef SEND_HITACHI_AC424
|
||||
#define SEND_HITACHI_AC424 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_HITACHI_AC424
|
||||
|
||||
#ifndef DECODE_GICABLE
|
||||
#define DECODE_GICABLE _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_GICABLE
|
||||
@@ -558,13 +572,6 @@
|
||||
#define SEND_DAIKIN152 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_DAIKIN152
|
||||
|
||||
#ifndef DECODE_HITACHI_AC424
|
||||
#define DECODE_HITACHI_AC424 _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_HITACHI_AC424
|
||||
#ifndef SEND_HITACHI_AC424
|
||||
#define SEND_HITACHI_AC424 _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_HITACHI_AC424
|
||||
|
||||
#ifndef DECODE_EPSON
|
||||
#define DECODE_EPSON _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_EPSON
|
||||
@@ -589,7 +596,7 @@
|
||||
DECODE_DAIKIN216 || DECODE_SHARP_AC || DECODE_DAIKIN160 || \
|
||||
DECODE_NEOCLIMA || DECODE_DAIKIN176 || DECODE_DAIKIN128 || \
|
||||
DECODE_AMCOR || DECODE_DAIKIN152 || DECODE_MITSUBISHI136 || \
|
||||
DECODE_MITSUBISHI112 || DECODE_HITACHI_AC424)
|
||||
DECODE_MITSUBISHI112 || DECODE_HITACHI_AC424 || DECODE_HITACHI_AC3)
|
||||
#define DECODE_AC true // We need some common infrastructure for decoding A/Cs.
|
||||
#else
|
||||
#define DECODE_AC false // We don't need that infrastructure.
|
||||
@@ -703,8 +710,9 @@ enum decode_type_t {
|
||||
SONY_38K,
|
||||
EPSON, // 75
|
||||
SYMPHONY,
|
||||
HITACHI_AC3,
|
||||
// Add new entries before this one, and update it to point to the last entry.
|
||||
kLastDecodeType = SYMPHONY,
|
||||
kLastDecodeType = HITACHI_AC3,
|
||||
};
|
||||
|
||||
// Message lengths & required repeat values
|
||||
@@ -782,6 +790,10 @@ const uint16_t kHitachiAc1StateLength = 13;
|
||||
const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8;
|
||||
const uint16_t kHitachiAc2StateLength = 53;
|
||||
const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8;
|
||||
const uint16_t kHitachiAc3StateLength = 27;
|
||||
const uint16_t kHitachiAc3Bits = kHitachiAc3StateLength * 8;
|
||||
const uint16_t kHitachiAc3MinStateLength = 15;
|
||||
const uint16_t kHitachiAc3MinBits = kHitachiAc3MinStateLength * 8;
|
||||
const uint16_t kHitachiAc424StateLength = 53;
|
||||
const uint16_t kHitachiAc424Bits = kHitachiAc424StateLength * 8;
|
||||
const uint16_t kInaxBits = 24;
|
||||
|
||||
@@ -618,6 +618,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
|
||||
return kHitachiAc1Bits;
|
||||
case HITACHI_AC2:
|
||||
return kHitachiAc2Bits;
|
||||
case HITACHI_AC3:
|
||||
return kHitachiAc3Bits;
|
||||
case HITACHI_AC424:
|
||||
return kHitachiAc424Bits;
|
||||
case KELVINATOR:
|
||||
@@ -959,6 +961,11 @@ bool IRsend::send(const decode_type_t type, const unsigned char *state,
|
||||
sendHitachiAC2(state, nbytes);
|
||||
break;
|
||||
#endif // SEND_HITACHI_AC2
|
||||
#if SEND_HITACHI_AC3
|
||||
case HITACHI_AC3:
|
||||
sendHitachiAc3(state, nbytes);
|
||||
break;
|
||||
#endif // SEND_HITACHI_AC3
|
||||
#if SEND_HITACHI_AC424
|
||||
case HITACHI_AC424:
|
||||
sendHitachiAc424(state, nbytes);
|
||||
|
||||
@@ -471,6 +471,12 @@ class IRsend {
|
||||
const uint16_t nbytes = kHitachiAc2StateLength,
|
||||
const uint16_t repeat = kHitachiAcDefaultRepeat);
|
||||
#endif
|
||||
#if SEND_HITACHI_AC3
|
||||
void sendHitachiAc3(const unsigned char data[],
|
||||
const uint16_t nbytes, // No default as there as so many
|
||||
// different sizes
|
||||
const uint16_t repeat = kHitachiAcDefaultRepeat);
|
||||
#endif // SEND_HITACHI_AC3
|
||||
#if SEND_HITACHI_AC424
|
||||
void sendHitachiAc424(const unsigned char data[],
|
||||
const uint16_t nbytes = kHitachiAc424StateLength,
|
||||
|
||||
@@ -147,6 +147,8 @@ decode_type_t strToDecodeType(const char * const str) {
|
||||
return decode_type_t::HITACHI_AC1;
|
||||
else if (!strcasecmp(str, "HITACHI_AC2"))
|
||||
return decode_type_t::HITACHI_AC2;
|
||||
else if (!strcasecmp(str, "HITACHI_AC3"))
|
||||
return decode_type_t::HITACHI_AC3;
|
||||
else if (!strcasecmp(str, "HITACHI_AC424"))
|
||||
return decode_type_t::HITACHI_AC424;
|
||||
else if (!strcasecmp(str, "INAX"))
|
||||
@@ -347,6 +349,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) {
|
||||
case HITACHI_AC2:
|
||||
result = F("HITACHI_AC2");
|
||||
break;
|
||||
case HITACHI_AC3:
|
||||
result = F("HITACHI_AC3");
|
||||
break;
|
||||
case HITACHI_AC424:
|
||||
result = F("HITACHI_AC424");
|
||||
break;
|
||||
@@ -530,6 +535,7 @@ bool hasACState(const decode_type_t protocol) {
|
||||
case HITACHI_AC:
|
||||
case HITACHI_AC1:
|
||||
case HITACHI_AC2:
|
||||
case HITACHI_AC3:
|
||||
case HITACHI_AC424:
|
||||
case KELVINATOR:
|
||||
case MITSUBISHI136:
|
||||
|
||||
@@ -37,6 +37,14 @@ const uint16_t kHitachiAc424BitMark = 463;
|
||||
const uint16_t kHitachiAc424OneSpace = 1208;
|
||||
const uint16_t kHitachiAc424ZeroSpace = 372;
|
||||
|
||||
// Support for HitachiAc3 protocol
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1060
|
||||
const uint16_t kHitachiAc3HdrMark = 3400; // Header
|
||||
const uint16_t kHitachiAc3HdrSpace = 1660; // Header
|
||||
const uint16_t kHitachiAc3BitMark = 460;
|
||||
const uint16_t kHitachiAc3OneSpace = 1250;
|
||||
const uint16_t kHitachiAc3ZeroSpace = 410;
|
||||
|
||||
using irutils::addBoolToString;
|
||||
using irutils::addIntToString;
|
||||
using irutils::addLabeledString;
|
||||
@@ -800,3 +808,142 @@ String IRHitachiAc424::toString(void) {
|
||||
result += ')';
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#if SEND_HITACHI_AC3
|
||||
// Send HITACHI_AC3 messages
|
||||
//
|
||||
// Note: This protocol is almost exactly the same as HitachiAC424 except this
|
||||
// variant has subtle timing differences.
|
||||
// There are five(5) typical sizes:
|
||||
// * kHitachiAc3MinStateLength (Cancel Timer)
|
||||
// * kHitachiAc3MinStateLength + 2 (Change Temp)
|
||||
// * kHitachiAc3StateLength - 6 (Change Mode)
|
||||
// * kHitachiAc3StateLength- 4 (Normal)
|
||||
// * kHitachiAc3StateLength (Set Timer)
|
||||
//
|
||||
// Args:
|
||||
// data: An array of bytes containing the IR command.
|
||||
// It is assumed to be in LSBF order for this code.
|
||||
// nbytes: Nr. of bytes of data in the array.
|
||||
// repeat: Nr. of times the message is to be repeated.
|
||||
//
|
||||
// Status: BETA / Probably working fine.
|
||||
void IRsend::sendHitachiAc3(const uint8_t data[], const uint16_t nbytes,
|
||||
const uint16_t repeat) {
|
||||
// Header + Data + Footer
|
||||
sendGeneric(kHitachiAc3HdrMark, kHitachiAc3HdrSpace,
|
||||
kHitachiAc3BitMark, kHitachiAc3OneSpace,
|
||||
kHitachiAc3BitMark, kHitachiAc3ZeroSpace,
|
||||
kHitachiAc3BitMark, kHitachiAcMinGap,
|
||||
data, nbytes, // Bytes
|
||||
kHitachiAcFreq, false, repeat, kDutyDefault);
|
||||
}
|
||||
#endif // SEND_HITACHI_AC3
|
||||
|
||||
|
||||
// Class for handling the remote control on a Hitachi_AC3 53 A/C message
|
||||
IRHitachiAc3::IRHitachiAc3(const uint16_t pin, const bool inverted,
|
||||
const bool use_modulation)
|
||||
: _irsend(pin, inverted, use_modulation) { stateReset(); }
|
||||
|
||||
// Reset to auto fan, cooling, 23° Celcius
|
||||
void IRHitachiAc3::stateReset(void) {
|
||||
for (uint8_t i = 0; i < kHitachiAc3StateLength; i++)
|
||||
remote_state[i] = 0x00;
|
||||
remote_state[0] = 0x01;
|
||||
remote_state[1] = 0x10;
|
||||
remote_state[3] = 0x40;
|
||||
remote_state[5] = 0xFF;
|
||||
remote_state[7] = 0xE8;
|
||||
remote_state[9] = 0x89;
|
||||
remote_state[11] = 0x0B;
|
||||
remote_state[13] = 0x3F;
|
||||
remote_state[15] = 0x15;
|
||||
remote_state[21] = 0x4B;
|
||||
remote_state[23] = 0x18;
|
||||
setInvertedStates();
|
||||
}
|
||||
|
||||
void IRHitachiAc3::setInvertedStates(const uint16_t length) {
|
||||
for (uint8_t i = 3; i < length - 1; i += 2)
|
||||
remote_state[i + 1] = ~remote_state[i];
|
||||
}
|
||||
|
||||
bool IRHitachiAc3::hasInvertedStates(const uint8_t state[],
|
||||
const uint16_t length) {
|
||||
for (uint8_t i = 3; i < length - 1; i += 2)
|
||||
if ((state[i + 1] ^ state[i]) != 0xFF) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void IRHitachiAc3::begin(void) { _irsend.begin(); }
|
||||
|
||||
uint8_t *IRHitachiAc3::getRaw(void) {
|
||||
setInvertedStates();
|
||||
return remote_state;
|
||||
}
|
||||
|
||||
void IRHitachiAc3::setRaw(const uint8_t new_code[], const uint16_t length) {
|
||||
memcpy(remote_state, new_code, std::min(length, kHitachiAc3StateLength));
|
||||
}
|
||||
|
||||
#if DECODE_HITACHI_AC3
|
||||
// Decode the supplied HitachiAc3 A/C message.
|
||||
//
|
||||
// Note: This protocol is almost exactly the same as HitachiAC424 except this
|
||||
// variant has subtle timing differences and multiple lengths.
|
||||
//
|
||||
// Args:
|
||||
// results: Ptr to the data to decode and where to store the decode result.
|
||||
// offset: The starting index to use when attempting to decode the raw data.
|
||||
// Typically/Defaults to kStartOffset.
|
||||
// nbits: The number of data bits to expect. Typically kHitachiAc3Bits.
|
||||
// strict: Flag indicating if we should perform strict matching.
|
||||
// Returns:
|
||||
// boolean: True if it can decode it, false if it can't.
|
||||
//
|
||||
// Status: BETA / Probably works fine.
|
||||
//
|
||||
// Supported devices:
|
||||
// Hitachi PC-LH3B
|
||||
//
|
||||
// Ref:
|
||||
// https://github.com/crankyoldgit/IRremoteESP8266/issues/1060
|
||||
bool IRrecv::decodeHitachiAc3(decode_results *results, uint16_t offset,
|
||||
const uint16_t nbits,
|
||||
const bool strict) {
|
||||
if (results->rawlen < 2 * nbits + kHeader + kFooter - 1 + offset)
|
||||
return false; // Too short a message to match.
|
||||
if (strict) {
|
||||
// Check the requested bit length.
|
||||
switch (nbits) {
|
||||
case kHitachiAc3MinBits: // Cancel Timer (Min Size)
|
||||
case kHitachiAc3MinBits + 2 * 8: // Change Temp
|
||||
case kHitachiAc3Bits - 6 * 8: // Change Mode
|
||||
case kHitachiAc3Bits - 4 * 8: // Normal
|
||||
case kHitachiAc3Bits: // Set Temp (Max Size)
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Header + Data + Footer
|
||||
if (!matchGeneric(results->rawbuf + offset, results->state,
|
||||
results->rawlen - offset, nbits,
|
||||
kHitachiAc3HdrMark, kHitachiAc3HdrSpace,
|
||||
kHitachiAc3BitMark, kHitachiAc3OneSpace,
|
||||
kHitachiAc3BitMark, kHitachiAc3ZeroSpace,
|
||||
kHitachiAc3BitMark, kHitachiAcMinGap, true,
|
||||
kUseDefTol, 0, false))
|
||||
return false; // We failed to find any data.
|
||||
|
||||
// Compliance
|
||||
if (strict && !IRHitachiAc3::hasInvertedStates(results->state, nbits / 8))
|
||||
return false;
|
||||
// Success
|
||||
results->decode_type = decode_type_t::HITACHI_AC3;
|
||||
results->bits = nbits;
|
||||
return true;
|
||||
}
|
||||
#endif // DECODE_HITACHI_AC3
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Hitachi A/C
|
||||
//
|
||||
// Copyright 2018-2019 David Conran
|
||||
// Copyright 2018-2020 David Conran
|
||||
|
||||
// Supports:
|
||||
// Brand: Hitachi, Model: RAS-35THA6 remote
|
||||
@@ -8,6 +8,7 @@
|
||||
// Brand: Hitachi, Model: Series VI A/C (Circa 2007)
|
||||
// Brand: Hitachi, Model: RAR-8P2 remote
|
||||
// Brand: Hitachi, Model: RAS-AJ25H A/C
|
||||
// Brand: Hitachi, Model: PC-LH3B (HITACHI_AC3)
|
||||
|
||||
#ifndef IR_HITACHI_H_
|
||||
#define IR_HITACHI_H_
|
||||
@@ -175,4 +176,32 @@ class IRHitachiAc424 {
|
||||
uint8_t _previoustemp;
|
||||
};
|
||||
|
||||
class IRHitachiAc3 {
|
||||
public:
|
||||
explicit IRHitachiAc3(const uint16_t pin, const bool inverted = false,
|
||||
const bool use_modulation = true);
|
||||
|
||||
void stateReset(void);
|
||||
#if SEND_HITACHI_AC3
|
||||
void send(const uint16_t repeat = kHitachiAcDefaultRepeat);
|
||||
uint8_t calibrate(void) { return _irsend.calibrate(); }
|
||||
#endif // SEND_HITACHI_AC3
|
||||
void begin(void);
|
||||
uint8_t getMode(void);
|
||||
uint8_t* getRaw(void);
|
||||
void setRaw(const uint8_t new_code[],
|
||||
const uint16_t length = kHitachiAc3StateLength);
|
||||
static bool hasInvertedStates(const uint8_t state[], const uint16_t length);
|
||||
#ifndef UNIT_TEST
|
||||
|
||||
private:
|
||||
IRsend _irsend;
|
||||
#else
|
||||
IRsendTest _irsend;
|
||||
#endif
|
||||
// The state of the IR remote in IR code form.
|
||||
uint8_t remote_state[kHitachiAc3StateLength];
|
||||
void setInvertedStates(const uint16_t length = kHitachiAc3StateLength);
|
||||
};
|
||||
|
||||
#endif // IR_HITACHI_H_
|
||||
|
||||
@@ -816,6 +816,11 @@ TEST(TestUtils, Housekeeping) {
|
||||
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC2));
|
||||
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC2));
|
||||
|
||||
ASSERT_EQ("HITACHI_AC3", typeToString(decode_type_t::HITACHI_AC3));
|
||||
ASSERT_EQ(decode_type_t::HITACHI_AC3, strToDecodeType("HITACHI_AC3"));
|
||||
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC3));
|
||||
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC3));
|
||||
|
||||
ASSERT_EQ("HITACHI_AC424", typeToString(decode_type_t::HITACHI_AC424));
|
||||
ASSERT_EQ(decode_type_t::HITACHI_AC424, strToDecodeType("HITACHI_AC424"));
|
||||
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC424));
|
||||
@@ -1113,7 +1118,7 @@ TEST(TestIRHitachiAc424Class, HumanReadable) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc424Class, toCommon) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
ac.setPower(true);
|
||||
ac.setMode(kHitachiAc424Cool);
|
||||
ac.setTemp(20);
|
||||
@@ -1139,3 +1144,365 @@ TEST(TestIRHitachiAc424Class, toCommon) {
|
||||
ASSERT_EQ(-1, ac.toCommon().sleep);
|
||||
ASSERT_EQ(-1, ac.toCommon().clock);
|
||||
}
|
||||
|
||||
TEST(TestDecodeHitachiAc3, SyntheticExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
uint8_t expected[kHitachiAc3StateLength - 4] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE6, 0x19, 0x89, 0x76, 0x01,
|
||||
0xFE, 0x3F, 0xC0, 0x2F, 0xD0, 0x18, 0xE7, 0x00, 0xFF, 0xA0, 0x5F};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendHitachiAc3(expected, kHitachiAc3StateLength - 4);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
ASSERT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc3Bits - 32, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
|
||||
}
|
||||
|
||||
// Decode a 'real' HitachiAc3 message.
|
||||
TEST(TestDecodeHitachiAc3, RealExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
uint8_t expected[kHitachiAc3StateLength - 4] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE6, 0x19, 0x89, 0x76, 0x01,
|
||||
0xFE, 0x3F, 0xC0, 0x2F, 0xD0, 0x18, 0xE7, 0x00, 0xFF, 0xA0, 0x5F};
|
||||
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1060#issuecomment-597519432
|
||||
uint16_t rawData[371] = {
|
||||
// Power Off
|
||||
3422, 1660, 464, 1264, 438, 426, 438, 402, 486, 426, 440, 402, 462, 402,
|
||||
488, 428, 438, 402, 460, 404, 488, 426, 440, 424, 436, 428, 462, 1240,
|
||||
466, 398, 462, 404, 486, 426, 438, 402, 464, 400, 490, 400, 464, 426, 438,
|
||||
402, 488, 428, 436, 428, 462, 376, 486, 404, 474, 416, 438, 400, 488, 402,
|
||||
462, 426, 438, 426, 458, 1246, 464, 426, 436, 1244, 488, 1266, 434, 1268,
|
||||
436, 1242, 486, 1242, 462, 1240, 464, 426, 462, 1266, 438, 1242, 462,
|
||||
1240, 514, 1214, 466, 1236, 462, 1266, 464, 1264, 438, 1266, 438, 1240,
|
||||
488, 400, 466, 424, 440, 402, 486, 404, 462, 402, 464, 402, 488, 426, 438,
|
||||
402, 462, 402, 488, 1264, 438, 1242, 460, 428, 462, 428, 436, 1264, 440,
|
||||
1240, 488, 1240, 464, 1240, 460, 402, 490, 424, 440, 1264, 438, 1242, 512,
|
||||
402, 438, 426, 466, 398, 464, 1266, 440, 400, 462, 402, 488, 1264, 438,
|
||||
402, 462, 402, 482, 432, 438, 1264, 436, 404, 488, 1240, 462, 1264, 438,
|
||||
402, 486, 1246, 456, 1266, 438, 1238, 488, 402, 462, 1240, 462, 402, 512,
|
||||
402, 438, 428, 438, 426, 462, 430, 434, 428, 438, 402, 512, 376, 462,
|
||||
1240, 464, 1264, 458, 1270, 436, 1242, 462, 1240, 486, 1242, 460, 1242,
|
||||
462, 1242, 486, 1240, 464, 1240, 464, 1238, 492, 1264, 436, 1266, 440,
|
||||
400, 488, 426, 436, 430, 434, 430, 460, 404, 462, 426, 438, 402, 488, 426,
|
||||
436, 1264, 466, 1238, 462, 1242, 462, 1266, 438, 1238, 490, 1264, 438,
|
||||
426, 438, 1240, 486, 406, 462, 402, 462, 400, 488, 428, 436, 426, 438,
|
||||
402, 484, 1268, 438, 426, 436, 1242, 488, 1266, 436, 402, 462, 402, 502,
|
||||
386, 464, 1240, 464, 1240, 488, 426, 438, 426, 438, 402, 488, 1240, 462,
|
||||
1266, 438, 1242, 486, 428, 440, 424, 438, 1266, 460, 1268, 438, 1264, 438,
|
||||
404, 486, 428, 438, 426, 438, 402, 490, 400, 462, 426, 436, 402, 490, 426,
|
||||
438, 1240, 462, 1268, 460, 1268, 434, 1266, 436, 1240, 514, 1238, 438,
|
||||
1240, 488, 1240, 460, 406, 464, 426, 436, 402, 488, 402, 462, 402, 462,
|
||||
1264, 462, 404, 462, 1266, 434, 1268, 464, 1264, 438, 1242, 464, 1238,
|
||||
488, 1266, 438, 402, 462, 1268, 458, 430, 410};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawData, 371, kHitachiAcFreq);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc3Bits - 32, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
|
||||
}
|
||||
|
||||
TEST(TestDecodeHitachiAc3, SyntheticTempChangeExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint16_t expectedLength = kHitachiAc3MinStateLength + 2;
|
||||
uint8_t expected[expectedLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE3, 0x1C, 0x89, 0x76, 0x08,
|
||||
0xF7, 0x3F, 0xC0, 0x15, 0xEA};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendHitachiAc3(expected, expectedLength);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
ASSERT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(expectedLength * 8, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
|
||||
}
|
||||
|
||||
// Decode a 'real' Temp Change HitachiAc3 message.
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1060#issuecomment-597592537
|
||||
TEST(TestDecodeHitachiAc3, RealTempChangeExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc3MinStateLength + 2] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE3, 0x1C, 0x89, 0x76, 0x08,
|
||||
0xF7, 0x3F, 0xC0, 0x15, 0xEA};
|
||||
const uint16_t expectedBits = kHitachiAc3MinBits + 2 * 8;
|
||||
|
||||
const uint16_t rawData[275] = {
|
||||
// Change Temp
|
||||
3422, 1636, 490, 1242, 484, 380, 488, 400, 466, 426, 432, 406, 490, 400,
|
||||
464, 426, 462, 398, 466, 376, 492, 400, 458, 404, 490, 400, 466, 1262,
|
||||
434, 430, 464, 400, 490, 400, 458, 380, 490, 374, 490, 426, 432, 430, 464,
|
||||
400, 464, 426, 460, 402, 468, 372, 490, 400, 460, 404, 490, 374, 490, 400,
|
||||
484, 378, 490, 398, 464, 1240, 490, 398, 466, 1238, 464, 1266, 434, 1268,
|
||||
466, 1238, 466, 1240, 484, 1218, 490, 400, 460, 1246, 484, 1242, 466,
|
||||
1214, 488, 1240, 486, 1218, 490, 1214, 488, 1266, 434, 1242, 490, 1214,
|
||||
490, 424, 460, 404, 464, 374, 492, 424, 434, 430, 466, 400, 464, 426, 464,
|
||||
376, 492, 1236, 464, 1240, 488, 402, 466, 374, 490, 400, 458, 1244, 490,
|
||||
1238, 496, 1234, 436, 404, 488, 400, 464, 1240, 484, 1244, 464, 1238, 466,
|
||||
426, 434, 430, 466, 400, 464, 1264, 434, 406, 490, 374, 490, 1264, 458,
|
||||
404, 466, 400, 466, 424, 466, 1238, 464, 400, 466, 1238, 486, 1216, 490,
|
||||
400, 464, 1240, 486, 1240, 466, 1238, 460, 432, 432, 430, 468, 374, 488,
|
||||
426, 462, 1242, 464, 400, 466, 426, 434, 404, 490, 374, 490, 1240, 484,
|
||||
1244, 466, 1240, 462, 428, 436, 1242, 490, 1212, 490, 1264, 466, 1236,
|
||||
466, 1214, 490, 1240, 488, 1240, 466, 1236, 466, 1264, 434, 1268, 464,
|
||||
400, 494, 400, 430, 406, 488, 376, 488, 428, 432, 432, 462, 402, 462, 426,
|
||||
458, 1220, 488, 1214, 490, 1240, 484, 406, 466, 1212, 490, 426, 462, 1216,
|
||||
488, 400, 464, 402, 488, 402, 462, 374, 492, 1262, 460, 380, 488, 1240,
|
||||
464, 428, 462, 1214, 492, 1236, 462, 1216, 490};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawData, 275, kHitachiAcFreq);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(expectedBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, expectedBits);
|
||||
}
|
||||
|
||||
// Decode a 'real' Cancel Timer HitachiAc3 message.
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1060#issuecomment-598631576
|
||||
TEST(TestDecodeHitachiAc3, RealCancelTimerExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc3MinStateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE2, 0x1D, 0x89, 0x76, 0x0D,
|
||||
0xF2, 0x3F, 0xC0};
|
||||
const uint16_t expectedBits = kHitachiAc3MinBits;
|
||||
|
||||
const uint16_t rawData[243] = {
|
||||
// Cancel Timer
|
||||
3368, 1688, 460, 1244, 456, 434, 458, 406, 456, 408, 480, 410, 458, 406,
|
||||
458, 406, 484, 406, 458, 406, 458, 432, 428, 464, 456, 380, 458, 1242,
|
||||
458, 432, 456, 406, 486, 378, 430, 458, 456, 408, 458, 406, 456, 434, 456,
|
||||
410, 454, 408, 454, 434, 460, 404, 458, 406, 454, 436, 456, 408, 458, 406,
|
||||
458, 432, 456, 434, 430, 1246, 484, 404, 484, 1218, 458, 1244, 484, 1244,
|
||||
460, 1244, 456, 1270, 430, 1274, 460, 404, 484, 1218, 486, 1244, 456,
|
||||
1244, 456, 1248, 454, 1272, 460, 1268, 432, 1246, 484, 1244, 458, 1244,
|
||||
462, 404, 456, 434, 458, 432, 432, 408, 456, 434, 460, 404, 460, 404, 484,
|
||||
406, 432, 432, 458, 1298, 402, 432, 460, 404, 460, 404, 482, 1244, 460,
|
||||
1270, 462, 1214, 456, 1272, 460, 404, 456, 1246, 486, 1244, 458, 1244,
|
||||
458, 406, 454, 460, 434, 404, 460, 1268, 430, 460, 432, 406, 458, 1244,
|
||||
456, 434, 458, 406, 456, 432, 460, 1268, 432, 406, 458, 1244, 484, 1272,
|
||||
432, 430, 432, 1298, 378, 1298, 458, 1244, 484, 406, 460, 1242, 458, 406,
|
||||
458, 1246, 456, 1272, 458, 406, 458, 432, 458, 404, 460, 404, 456, 408,
|
||||
484, 1272, 432, 432, 432, 406, 454, 1272, 458, 1246, 458, 1244, 484, 1268,
|
||||
436, 1242, 458, 1298, 402, 1274, 456, 1244, 458, 1244, 486, 1242, 458,
|
||||
408, 486, 378, 454, 460, 434, 406, 458, 406, 484, 406, 458, 406, 458, 408,
|
||||
452, 1302, 434, 1244, 430};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawData, 243, kHitachiAcFreq);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(expectedBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, expectedBits);
|
||||
}
|
||||
|
||||
TEST(TestDecodeHitachiAc3, SyntheticCancelTimerExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc3MinStateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE2, 0x1D, 0x89, 0x76, 0x0D,
|
||||
0xF2, 0x3F, 0xC0};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendHitachiAc3(expected, kHitachiAc3MinStateLength);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
ASSERT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc3MinBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
|
||||
}
|
||||
|
||||
// Decode a 'real' Set Timer HitachiAc3 message.
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1060#issuecomment-598631576
|
||||
TEST(TestDecodeHitachiAc3, RealSetTimerExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc3StateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE8, 0x17, 0x89, 0x76, 0x0B,
|
||||
0xF4, 0x3F, 0xC0, 0x15, 0xEA, 0x00, 0xFF, 0x00, 0xFF, 0x4B, 0xB4, 0x18,
|
||||
0xE7, 0x00, 0xFF};
|
||||
const uint16_t expectedBits = kHitachiAc3Bits;
|
||||
|
||||
const uint16_t rawData[435] = {
|
||||
// Set Timer
|
||||
3364, 1668, 486, 1244, 458, 406, 456, 436, 430, 434, 430, 434, 456, 408,
|
||||
484, 432, 428, 432, 414, 450, 458, 432, 432, 432, 430, 436, 458, 1270,
|
||||
430, 408, 456, 408, 454, 462, 404, 460, 428, 408, 486, 404, 456, 408, 458,
|
||||
406, 484, 406, 456, 434, 432, 408, 484, 406, 454, 436, 404, 432, 486, 430,
|
||||
430, 408, 456, 432, 458, 1270, 406, 434, 456, 1246, 484, 1244, 456, 1274,
|
||||
432, 1244, 486, 1268, 432, 1244, 454, 412, 454, 1272, 430, 1272, 456,
|
||||
1274, 456, 1246, 456, 1244, 458, 1270, 458, 1246, 456, 1254, 450, 1246,
|
||||
484, 408, 456, 434, 430, 408, 486, 430, 404, 460, 430, 408, 486, 404, 458,
|
||||
406, 458, 406, 486, 404, 458, 432, 430, 1272, 456, 408, 458, 1244, 458,
|
||||
1244, 456, 1274, 456, 1246, 456, 1270, 460, 1250, 426, 460, 404, 1270,
|
||||
484, 432, 404, 462, 402, 460, 458, 1244, 456, 386, 452, 460, 458, 1244,
|
||||
458, 406, 458, 406, 486, 430, 416, 1260, 458, 406, 484, 1270, 406, 1296,
|
||||
430, 410, 482, 1246, 456, 1246, 456, 1246, 456, 434, 458, 1244, 456, 1272,
|
||||
458, 408, 458, 1244, 456, 410, 484, 404, 454, 410, 456, 408, 484, 406,
|
||||
458, 432, 430, 1246, 484, 406, 454, 1248, 458, 1244, 486, 1248, 428, 1270,
|
||||
456, 1266, 464, 1244, 458, 1246, 456, 1246, 484, 1270, 430, 1246, 456,
|
||||
434, 430, 460, 406, 432, 430, 432, 484, 432, 406, 432, 458, 406, 484, 432,
|
||||
432, 1266, 434, 1274, 430, 1298, 428, 408, 456, 1246, 486, 430, 432, 1270,
|
||||
404, 434, 484, 432, 430, 408, 456, 406, 460, 1268, 458, 408, 456, 1246,
|
||||
486, 406, 456, 1244, 456, 1248, 456, 1300, 430, 408, 456, 408, 484, 432,
|
||||
430, 434, 428, 434, 460, 430, 404, 434, 458, 406, 486, 1242, 458, 1270,
|
||||
430, 1246, 484, 1244, 456, 1270, 432, 1248, 484, 1244, 456, 1246, 456,
|
||||
408, 486, 404, 456, 408, 456, 432, 462, 430, 406, 458, 432, 432, 428,
|
||||
436, 456, 1246, 456, 1246, 484, 1244, 454, 1268, 438, 1244, 488, 1266,
|
||||
430, 1246, 458, 1244, 486, 1244, 430, 1298, 430, 434, 460, 1242, 458, 430,
|
||||
430, 408, 486, 1242, 456, 434, 404, 462, 456, 430, 432, 1246, 456, 408,
|
||||
486, 1270, 430, 1246, 460, 404, 482, 1246, 458, 406, 456, 408, 484, 404,
|
||||
458, 1270, 430, 1274, 458, 432, 430, 408, 456, 406, 486, 1244, 458, 1242,
|
||||
458, 1246, 484, 406, 458, 432, 430, 1246, 486, 1242, 456, 1272, 430, 434,
|
||||
458, 406, 458, 406, 458, 406, 486, 404, 458, 406, 458, 430, 430, 460, 430,
|
||||
1270, 430, 1248, 484, 1244, 456, 1244, 458, 1246, 484, 1244, 456, 1246,
|
||||
460, 1244, 458}; // UNKNOWN D3A5A0BA
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawData, 435, kHitachiAcFreq);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(expectedBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, expectedBits);
|
||||
}
|
||||
|
||||
TEST(TestDecodeHitachiAc3, SyntheticSetTimerExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc3StateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE8, 0x17, 0x89, 0x76, 0x0B,
|
||||
0xF4, 0x3F, 0xC0, 0x15, 0xEA, 0x00, 0xFF, 0x00, 0xFF, 0x4B, 0xB4, 0x18,
|
||||
0xE7, 0x00, 0xFF};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendHitachiAc3(expected, kHitachiAc3StateLength);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
ASSERT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc3Bits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
|
||||
}
|
||||
|
||||
// Decode a 'real' Change Mode HitachiAc3 message.
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1060#issuecomment-598631576
|
||||
TEST(TestDecodeHitachiAc3, RealChangeModeExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc3StateLength - 6] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE5, 0x1A, 0x89, 0x76, 0x04,
|
||||
0xFB, 0x3F, 0xC0, 0x1B, 0xE4, 0x14, 0xEB, 0x02, 0xFD};
|
||||
const uint16_t expectedBits = kHitachiAc3Bits - 6 * 8;
|
||||
|
||||
const uint16_t rawData[339] = {
|
||||
// Change Mode
|
||||
3364, 1666, 488, 1268, 404, 434, 454, 434, 460, 404, 458, 406, 458, 406,
|
||||
484, 432, 432, 430, 432, 408, 484, 406, 458, 432, 432, 406, 486, 1242,
|
||||
458, 430, 430, 408, 454, 436, 456, 408, 458, 406, 484, 432, 428, 434, 430,
|
||||
408, 484, 406, 458, 430, 432, 408, 484, 430, 430, 432, 432, 408, 482, 408,
|
||||
456, 408, 458, 432, 458, 1246, 458, 430, 430, 1246, 486, 1242, 458, 1270,
|
||||
432, 1246, 486, 1242, 458, 1268, 432, 434, 430, 1272, 456, 1246, 458,
|
||||
1270, 460, 1244, 458, 1246, 456, 1272, 460, 1242, 456, 1270, 434, 1246,
|
||||
486, 430, 430, 434, 432, 406, 484, 430, 432, 432, 430, 408, 484, 432, 432,
|
||||
432, 430, 1246, 484, 406, 458, 1246, 456, 408, 486, 404, 458, 1268, 434,
|
||||
1270, 430, 1274, 456, 408, 458, 1270, 460, 404, 458, 1244, 458, 1246, 486,
|
||||
430, 430, 432, 460, 378, 488, 1240, 460, 404, 458, 408, 486, 1242, 458,
|
||||
432, 430, 434, 460, 430, 432, 1246, 458, 406, 488, 1240, 430, 1272, 458,
|
||||
406, 486, 1242, 430, 1298, 430, 1274, 428, 432, 430, 436, 456, 408, 482,
|
||||
1248, 458, 406, 430, 462, 456, 404, 458, 432, 430, 408, 486, 1266, 436,
|
||||
1242, 458, 406, 486, 1242, 456, 1246, 458, 1244, 488, 1240, 458, 1244,
|
||||
458, 1272, 460, 1242, 456, 1246, 458, 1246, 486, 1242, 458, 1270, 432,
|
||||
406, 458, 458, 434, 430, 432, 406, 486, 406, 456, 408, 458, 432, 484, 406,
|
||||
430, 1272, 460, 1216, 486, 1242, 456, 1246, 458, 406, 486, 1268, 432,
|
||||
1244, 458, 406, 486, 404, 460, 432, 430, 406, 488, 402, 458, 1272, 428,
|
||||
434, 460, 404, 460, 1242, 458, 1246, 480, 1244, 462, 428, 432, 432, 460,
|
||||
1244, 458, 432, 430, 1246, 488, 402, 456, 408, 458, 406, 486, 1268, 432,
|
||||
1246, 460, 430, 460, 1244, 458, 406, 458, 1244, 486, 1242, 458, 1244, 458,
|
||||
432, 462, 1242, 456, 408, 456, 406, 486, 428, 434, 406, 458, 406, 456,
|
||||
434, 458, 1244, 460, 430, 462, 1240, 458, 1244, 460, 1244, 486, 1244, 458,
|
||||
1242, 488, 1214, 460}; // UNKNOWN C1EA1036
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawData, 339, kHitachiAcFreq);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(expectedBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, expectedBits);
|
||||
}
|
||||
|
||||
TEST(TestDecodeHitachiAc3, SyntheticChangeModeExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc3StateLength - 6] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE5, 0x1A, 0x89, 0x76, 0x04,
|
||||
0xFB, 0x3F, 0xC0, 0x1B, 0xE4, 0x14, 0xEB, 0x02, 0xFD};
|
||||
const uint16_t expectedBits = kHitachiAc3Bits - 6 * 8;
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendHitachiAc3(expected, kHitachiAc3StateLength - 6);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
ASSERT_EQ(HITACHI_AC3, irsend.capture.decode_type);
|
||||
ASSERT_EQ(expectedBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
|
||||
}
|
||||
|
||||
TEST(TestHitachiAc3Class, hasInvertedStates) {
|
||||
const uint8_t good_state[kHitachiAc3StateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE8, 0x17, 0x89, 0x76, 0x0B,
|
||||
0xF4, 0x3F, 0xC0, 0x15, 0xEA, 0x00, 0xFF, 0x00, 0xFF, 0x4B, 0xB4, 0x18,
|
||||
0xE7, 0x00, 0xFF};
|
||||
// bad_state[kHitachiAc3MinStateLength + 1] has been modified to be different.
|
||||
// i.e. Anything larger than kHitachiAc3MinStateLength should fail.
|
||||
// kHitachiAc3MinStateLength or shorter should pass.
|
||||
const uint8_t bad_state[kHitachiAc3StateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xE8, 0x17, 0x89, 0x76, 0x0B,
|
||||
0xF4, 0x3F, 0xC0, 0x15, 0xE0, 0x00, 0xFF, 0x00, 0xFF, 0x4B, 0xB4, 0x18,
|
||||
0xE7, 0x00, 0xFF};
|
||||
|
||||
EXPECT_TRUE(IRHitachiAc3::hasInvertedStates(good_state,
|
||||
kHitachiAc3StateLength));
|
||||
|
||||
for (uint8_t len = kHitachiAc3StateLength;
|
||||
len > kHitachiAc3MinStateLength;
|
||||
len -= 2) {
|
||||
EXPECT_FALSE(IRHitachiAc3::hasInvertedStates(bad_state, len));
|
||||
}
|
||||
EXPECT_TRUE(IRHitachiAc3::hasInvertedStates(bad_state,
|
||||
kHitachiAc3MinStateLength));
|
||||
EXPECT_TRUE(IRHitachiAc3::hasInvertedStates(bad_state,
|
||||
kHitachiAc3MinStateLength - 2));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user