mirror of
https://github.com/crankyoldgit/IRremoteESP8266.git
synced 2026-01-12 00:05:10 +08:00
HITACHI_AC296: Add IRac class support & tests. (#1776)
* Fix max temp issue. * Set special temp for auto operation mode. * Merge into the `IRac` class so it is supported fully. * Add `.toString()` output. * Add real & synthetic decoding examples. * General code style cleanup(s). * Add supporting Unit Tests. Ref: #1758 Fixes #1757
This commit is contained in:
55
src/IRac.cpp
55
src/IRac.cpp
@@ -230,6 +230,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
|
||||
#if SEND_HITACHI_AC264
|
||||
case decode_type_t::HITACHI_AC264:
|
||||
#endif
|
||||
#if SEND_HITACHI_AC296
|
||||
case decode_type_t::HITACHI_AC296:
|
||||
#endif
|
||||
#if SEND_HITACHI_AC344
|
||||
case decode_type_t::HITACHI_AC344:
|
||||
#endif
|
||||
@@ -1341,6 +1344,35 @@ void IRac::hitachi264(IRHitachiAc264 *ac,
|
||||
}
|
||||
#endif // SEND_HITACHI_AC264
|
||||
|
||||
#if SEND_HITACHI_AC296
|
||||
/// Send a Hitachi 296-bit A/C message with the supplied settings.
|
||||
/// @param[in, out] ac A Ptr to an IRHitachiAc296 object to use.
|
||||
/// @param[in] on The power setting.
|
||||
/// @param[in] mode The operation mode setting.
|
||||
/// @param[in] degrees The temperature setting in degrees.
|
||||
/// @param[in] fan The speed setting for the fan.
|
||||
void IRac::hitachi296(IRHitachiAc296 *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan) {
|
||||
ac->begin();
|
||||
ac->setMode(ac->convertMode(mode));
|
||||
ac->setTemp(degrees);
|
||||
ac->setFan(ac->convertFan(fan));
|
||||
ac->setPower(on);
|
||||
// No Swing(V) setting available.
|
||||
// No Swing(H) setting available.
|
||||
// No Quiet setting available.
|
||||
// No Turbo setting available.
|
||||
// No Light setting available.
|
||||
// No Filter setting available.
|
||||
// No Clean setting available.
|
||||
// No Beep setting available.
|
||||
// No Sleep setting available.
|
||||
// No Clock setting available.
|
||||
ac->send();
|
||||
}
|
||||
#endif // SEND_HITACHI_AC296
|
||||
|
||||
#if SEND_HITACHI_AC344
|
||||
/// Send a Hitachi 344-bit A/C message with the supplied settings.
|
||||
/// @param[in, out] ac A Ptr to an IRHitachiAc344 object to use.
|
||||
@@ -2946,6 +2978,14 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
|
||||
break;
|
||||
}
|
||||
#endif // SEND_HITACHI_AC264
|
||||
#if SEND_HITACHI_AC296
|
||||
case HITACHI_AC296:
|
||||
{
|
||||
IRHitachiAc296 ac(_pin, _inverted, _modulation);
|
||||
hitachi296(&ac, send.power, send.mode, degC, send.fanspeed);
|
||||
break;
|
||||
}
|
||||
#endif // SEND_HITACHI_AC296
|
||||
#if SEND_HITACHI_AC344
|
||||
case HITACHI_AC344:
|
||||
{
|
||||
@@ -3808,6 +3848,13 @@ namespace IRAcUtils {
|
||||
return ac.toString();
|
||||
}
|
||||
#endif // DECODE_HITACHI_AC264
|
||||
#if DECODE_HITACHI_AC296
|
||||
case decode_type_t::HITACHI_AC296: {
|
||||
IRHitachiAc296 ac(kGpioUnused);
|
||||
ac.setRaw(result->state);
|
||||
return ac.toString();
|
||||
}
|
||||
#endif // DECODE_HITACHI_AC296
|
||||
#if DECODE_HITACHI_AC344
|
||||
case decode_type_t::HITACHI_AC344: {
|
||||
IRHitachiAc344 ac(kGpioUnused);
|
||||
@@ -4273,6 +4320,14 @@ namespace IRAcUtils {
|
||||
break;
|
||||
}
|
||||
#endif // DECODE_HITACHI_AC264
|
||||
#if DECODE_HITACHI_AC296
|
||||
case decode_type_t::HITACHI_AC296: {
|
||||
IRHitachiAc296 ac(kGpioUnused);
|
||||
ac.setRaw(decode->state);
|
||||
*result = ac.toCommon();
|
||||
break;
|
||||
}
|
||||
#endif // DECODE_HITACHI_AC296
|
||||
#if DECODE_HITACHI_AC344
|
||||
case decode_type_t::HITACHI_AC344: {
|
||||
IRHitachiAc344 ac(kGpioUnused);
|
||||
|
||||
@@ -305,6 +305,11 @@ void electra(IRElectraAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan);
|
||||
#endif // SEND_HITACHI_AC264
|
||||
#if SEND_HITACHI_AC296
|
||||
void hitachi296(IRHitachiAc296 *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan);
|
||||
#endif // SEND_HITACHI_AC296
|
||||
#if SEND_HITACHI_AC344
|
||||
void hitachi344(IRHitachiAc344 *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
|
||||
@@ -1723,10 +1723,15 @@ void IRsend::sendHitachiAc296(const unsigned char data[],
|
||||
}
|
||||
#endif // SEND_HITACHIAC296
|
||||
|
||||
// Class constructor for handling detailed Hitachi_AC296 37 byte A/C messages.
|
||||
/// @param[in] pin GPIO to be used when sending.
|
||||
/// @param[in] inverted Is the output signal to be inverted?
|
||||
/// @param[in] use_modulation Is frequency modulation to be used?
|
||||
IRHitachiAc296::IRHitachiAc296(const uint16_t pin, const bool inverted,
|
||||
const bool use_modulation)
|
||||
: _irsend(pin, inverted, use_modulation) { stateReset(); }
|
||||
|
||||
/// Reset the internal state to auto fan, heating, & 24° Celsius
|
||||
void IRHitachiAc296::stateReset(void) {
|
||||
// Header
|
||||
_.raw[0] = 0x01;
|
||||
@@ -1785,18 +1790,13 @@ void IRHitachiAc296::send(const uint16_t repeat) {
|
||||
}
|
||||
#endif // SEND_HITACHI_AC296
|
||||
|
||||
|
||||
/// Get the value of the current power setting.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRHitachiAc296::getPower(void) const {
|
||||
return _.Power;
|
||||
}
|
||||
bool IRHitachiAc296::getPower(void) const { return _.Power; }
|
||||
|
||||
/// Change the power setting.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
void IRHitachiAc296::setPower(const bool on) {
|
||||
_.Power = on;
|
||||
}
|
||||
void IRHitachiAc296::setPower(const bool on) { _.Power = on; }
|
||||
|
||||
/// Change the power setting to On.
|
||||
void IRHitachiAc296::on(void) { setPower(true); }
|
||||
@@ -1806,52 +1806,106 @@ void IRHitachiAc296::off(void) { setPower(false); }
|
||||
|
||||
/// Get the operating mode setting of the A/C.
|
||||
/// @return The current operating mode setting.
|
||||
uint8_t IRHitachiAc296::getMode(void) const {
|
||||
return _.Mode;
|
||||
}
|
||||
uint8_t IRHitachiAc296::getMode(void) const { return _.Mode; }
|
||||
|
||||
/// Set the operating mode of the A/C.
|
||||
/// @param[in] mode The desired operating mode.
|
||||
void IRHitachiAc296::setMode(const uint8_t mode) {
|
||||
uint8_t newMode = mode;
|
||||
switch (mode) {
|
||||
case kHitachiAc296Heat:
|
||||
case kHitachiAc296Cool:
|
||||
case kHitachiAc296Auto: break;
|
||||
default: newMode = kHitachiAc296Auto;
|
||||
case kHitachiAc296Dehumidify:
|
||||
case kHitachiAc296AutoDehumidifying:
|
||||
case kHitachiAc296Auto:
|
||||
_.Mode = mode;
|
||||
setTemp(getTemp()); // Reset the temp to handle "Auto"'s special temp.
|
||||
break;
|
||||
default:
|
||||
setMode(kHitachiAc296Auto);
|
||||
}
|
||||
}
|
||||
|
||||
_.Mode = newMode;
|
||||
/// Convert a stdAc::opmode_t enum into its native mode.
|
||||
/// @param[in] mode The enum to be converted.
|
||||
/// @return The native equivalent of the enum.
|
||||
uint8_t IRHitachiAc296::convertMode(const stdAc::opmode_t mode) {
|
||||
switch (mode) {
|
||||
case stdAc::opmode_t::kCool: return kHitachiAc296Cool;
|
||||
case stdAc::opmode_t::kHeat: return kHitachiAc296Heat;
|
||||
case stdAc::opmode_t::kDry: return kHitachiAc296Dehumidify;
|
||||
default: return kHitachiAc296Auto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a native mode into its stdAc equivalent.
|
||||
/// @param[in] mode The native setting to be converted.
|
||||
/// @return The stdAc equivalent of the native setting.
|
||||
stdAc::opmode_t IRHitachiAc296::toCommonMode(const uint8_t mode) {
|
||||
switch (mode) {
|
||||
case kHitachiAc296DryCool:
|
||||
case kHitachiAc296Cool: return stdAc::opmode_t::kCool;
|
||||
case kHitachiAc296Heat: return stdAc::opmode_t::kHeat;
|
||||
case kHitachiAc296AutoDehumidifying:
|
||||
case kHitachiAc296Dehumidify: return stdAc::opmode_t::kDry;
|
||||
default: return stdAc::opmode_t::kAuto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current temperature setting.
|
||||
/// @return The current setting for temp. in degrees celsius.
|
||||
uint8_t IRHitachiAc296::getTemp(void) const {
|
||||
return _.Temp;
|
||||
}
|
||||
uint8_t IRHitachiAc296::getTemp(void) const { return _.Temp; }
|
||||
|
||||
/// Set the temperature.
|
||||
/// @param[in] celsius The temperature in degrees celsius.
|
||||
void IRHitachiAc296::setTemp(const uint8_t celsius) {
|
||||
uint8_t temp;
|
||||
temp = std::min(celsius, kHitachiAc296MaxTemp);
|
||||
_.Temp = std::max(temp, kHitachiAc296MinTemp);
|
||||
uint8_t temp = celsius;
|
||||
if (getMode() == kHitachiAc296Auto) { // Special temp for auto mode
|
||||
temp = kHitachiAc296TempAuto;
|
||||
} else { // Normal temp setting.
|
||||
temp = std::min(temp, kHitachiAc296MaxTemp);
|
||||
temp = std::max(temp, kHitachiAc296MinTemp);
|
||||
}
|
||||
_.Temp = temp;
|
||||
}
|
||||
|
||||
/// Get the current fan speed setting.
|
||||
/// @return The current fan speed.
|
||||
uint8_t IRHitachiAc296::getFan(void) const {
|
||||
return _.Fan;
|
||||
}
|
||||
uint8_t IRHitachiAc296::getFan(void) const { return _.Fan; }
|
||||
|
||||
/// Set the speed of the fan.
|
||||
/// @param[in] speed The desired setting.
|
||||
void IRHitachiAc296::setFan(const uint8_t speed) {
|
||||
uint8_t newSpeed = speed;
|
||||
newSpeed = std::max(newSpeed, kHitachiAc296FanSilent);
|
||||
uint8_t newSpeed = std::max(speed, kHitachiAc296FanSilent);
|
||||
_.Fan = std::min(newSpeed, kHitachiAc296FanAuto);
|
||||
}
|
||||
|
||||
/// Convert a stdAc::fanspeed_t enum into it's native speed.
|
||||
/// @param[in] speed The enum to be converted.
|
||||
/// @return The native equivalent of the enum.
|
||||
uint8_t IRHitachiAc296::convertFan(const stdAc::fanspeed_t speed) {
|
||||
switch (speed) {
|
||||
case stdAc::fanspeed_t::kMin: return kHitachiAc296FanSilent;
|
||||
case stdAc::fanspeed_t::kLow: return kHitachiAc296FanLow;
|
||||
case stdAc::fanspeed_t::kMedium: return kHitachiAc296FanMedium;
|
||||
case stdAc::fanspeed_t::kHigh:
|
||||
case stdAc::fanspeed_t::kMax: return kHitachiAc296FanHigh;
|
||||
default: return kHitachiAc296FanAuto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a native fan speed into its stdAc equivalent.
|
||||
/// @param[in] speed The native setting to be converted.
|
||||
/// @return The stdAc equivalent of the native setting.
|
||||
stdAc::fanspeed_t IRHitachiAc296::toCommonFanSpeed(const uint8_t speed) {
|
||||
switch (speed) {
|
||||
case kHitachiAc296FanHigh: return stdAc::fanspeed_t::kHigh;
|
||||
case kHitachiAc296FanMedium: return stdAc::fanspeed_t::kMedium;
|
||||
case kHitachiAc296FanLow: return stdAc::fanspeed_t::kLow;
|
||||
case kHitachiAc296FanSilent: return stdAc::fanspeed_t::kMin;
|
||||
default: return stdAc::fanspeed_t::kAuto;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a PTR to the internal state/code for this protocol.
|
||||
/// @return PTR to a code for this protocol based on the current internal state.
|
||||
uint8_t *IRHitachiAc296::getRaw(void) {
|
||||
@@ -1866,6 +1920,49 @@ void IRHitachiAc296::setRaw(const uint8_t new_code[], const uint16_t length) {
|
||||
memcpy(_.raw, new_code, std::min(length, kHitachiAc296StateLength));
|
||||
}
|
||||
|
||||
|
||||
/// Convert the current internal state into its stdAc::state_t equivalent.
|
||||
/// @return The stdAc equivalent of the native settings.
|
||||
stdAc::state_t IRHitachiAc296::toCommon(void) const {
|
||||
stdAc::state_t result{};
|
||||
result.protocol = decode_type_t::HITACHI_AC296;
|
||||
result.model = -1; // No models used.
|
||||
result.power = getPower();
|
||||
result.mode = toCommonMode(_.Mode);
|
||||
result.celsius = true;
|
||||
result.degrees = _.Temp;
|
||||
result.fanspeed = toCommonFanSpeed(_.Fan);
|
||||
result.quiet = _.Fan == kHitachiAc296FanSilent;
|
||||
// Not supported.
|
||||
result.swingv = stdAc::swingv_t::kOff;
|
||||
result.swingh = stdAc::swingh_t::kOff;
|
||||
result.turbo = false;
|
||||
result.clean = false;
|
||||
result.econo = false;
|
||||
result.filter = false;
|
||||
result.light = false;
|
||||
result.beep = false;
|
||||
result.sleep = -1;
|
||||
result.clock = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Convert the current internal state into a human readable string.
|
||||
/// @return A human readable string.
|
||||
String IRHitachiAc296::toString(void) const {
|
||||
String result = "";
|
||||
result.reserve(70); // Reserve some heap for the string to reduce fragging.
|
||||
result += addBoolToString(_.Power, kPowerStr, false);
|
||||
result += addModeToString(_.Mode, kHitachiAc296Auto, kHitachiAc296Cool,
|
||||
kHitachiAc296Heat, kHitachiAc1Dry,
|
||||
kHitachiAc296Auto);
|
||||
result += addTempToString(getTemp());
|
||||
result += addFanToString(_.Fan, kHitachiAc296FanHigh, kHitachiAc296FanLow,
|
||||
kHitachiAc296FanAuto, kHitachiAc296FanSilent,
|
||||
kHitachiAc296FanMedium);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if DECODE_HITACHI_AC296
|
||||
/// Decode the supplied Hitachi 37-byte A/C message.
|
||||
/// Status: STABLE / Working on a real device.
|
||||
@@ -1879,14 +1976,13 @@ void IRHitachiAc296::setRaw(const uint8_t new_code[], const uint16_t length) {
|
||||
bool IRrecv::decodeHitachiAc296(decode_results *results, uint16_t offset,
|
||||
const uint16_t nbits,
|
||||
const bool strict) {
|
||||
uint16_t used = matchGeneric(results->rawbuf + offset, results->state,
|
||||
results->rawlen - offset, nbits,
|
||||
kHitachiAcHdrMark, kHitachiAcHdrSpace,
|
||||
kHitachiAcBitMark, kHitachiAcOneSpace,
|
||||
kHitachiAcBitMark, kHitachiAcZeroSpace,
|
||||
kHitachiAcBitMark, kHitachiAcMinGap, true,
|
||||
kUseDefTol, 0, false);
|
||||
if (used == 0) return false;
|
||||
if (!matchGeneric(results->rawbuf + offset, results->state,
|
||||
results->rawlen - offset, nbits,
|
||||
kHitachiAcHdrMark, kHitachiAcHdrSpace,
|
||||
kHitachiAcBitMark, kHitachiAcOneSpace,
|
||||
kHitachiAcBitMark, kHitachiAcZeroSpace,
|
||||
kHitachiAcBitMark, kHitachiAcMinGap, true,
|
||||
kUseDefTol, 0, false)) return false;
|
||||
|
||||
// Compliance
|
||||
if (strict && !IRHitachiAc296::hasInvertedStates(results->state, nbits / 8))
|
||||
|
||||
@@ -358,9 +358,9 @@ const uint8_t kHitachiAc296FanMedium = 0b011;
|
||||
const uint8_t kHitachiAc296FanHigh = 0b100;
|
||||
const uint8_t kHitachiAc296FanAuto = 0b101;
|
||||
|
||||
const uint8_t kHitachiAc296TempSize = 5;
|
||||
const uint8_t kHitachiAc296TempAuto = 1; // Special value for "Auto" op mode.
|
||||
const uint8_t kHitachiAc296MinTemp = 16;
|
||||
const uint8_t kHitachiAc296MaxTemp = 32;
|
||||
const uint8_t kHitachiAc296MaxTemp = 31; // Max value you can store in 5 bits.
|
||||
|
||||
const uint8_t kHitachiAc296PowerOn = 1;
|
||||
const uint8_t kHitachiAc296PowerOff = 0;
|
||||
@@ -629,7 +629,7 @@ class IRHitachiAc296 {
|
||||
|
||||
#if SEND_HITACHI_AC296
|
||||
void send(const uint16_t repeat = kHitachiAcDefaultRepeat);
|
||||
#endif
|
||||
#endif // SEND_HITACHI_AC296
|
||||
void begin(void);
|
||||
void on(void);
|
||||
void off(void);
|
||||
@@ -645,7 +645,12 @@ class IRHitachiAc296 {
|
||||
uint8_t* getRaw(void);
|
||||
void setRaw(const uint8_t new_code[],
|
||||
const uint16_t length = kHitachiAc296StateLength);
|
||||
|
||||
static uint8_t convertMode(const stdAc::opmode_t mode);
|
||||
static uint8_t convertFan(const stdAc::fanspeed_t speed);
|
||||
static stdAc::opmode_t toCommonMode(const uint8_t mode);
|
||||
static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
|
||||
stdAc::state_t toCommon(void) const;
|
||||
String toString(void) const;
|
||||
#ifndef UNIT_TEST
|
||||
|
||||
private:
|
||||
|
||||
@@ -973,6 +973,34 @@ TEST(TestIRac, Hitachi264) {
|
||||
EXPECT_EQ(25, r.degrees);
|
||||
}
|
||||
|
||||
TEST(TestIRac, Hitachi296) {
|
||||
IRHitachiAc296 ac(kGpioUnused);
|
||||
IRac irac(kGpioUnused);
|
||||
IRrecv capture(kGpioUnused);
|
||||
char expected[] =
|
||||
"Power: On, Mode: 6 (Heat), Temp: 20C, Fan: 2 (Low)";
|
||||
|
||||
ac.begin();
|
||||
irac.hitachi296(&ac,
|
||||
true, // Power
|
||||
stdAc::opmode_t::kHeat, // Mode
|
||||
20, // Celsius
|
||||
stdAc::fanspeed_t::kLow); // Fan speed
|
||||
|
||||
ASSERT_EQ(expected, ac.toString());
|
||||
ac._irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
|
||||
ASSERT_EQ(HITACHI_AC296, ac._irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc296Bits, ac._irsend.capture.bits);
|
||||
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
|
||||
stdAc::state_t r, p;
|
||||
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
|
||||
EXPECT_EQ(decode_type_t::HITACHI_AC296, r.protocol);
|
||||
EXPECT_TRUE(r.power);
|
||||
EXPECT_EQ(stdAc::opmode_t::kHeat, r.mode);
|
||||
EXPECT_EQ(20, r.degrees);
|
||||
}
|
||||
|
||||
TEST(TestIRac, Hitachi344) {
|
||||
IRHitachiAc344 ac(kGpioUnused);
|
||||
IRac irac(kGpioUnused);
|
||||
|
||||
@@ -191,7 +191,7 @@ TEST(TestSendHitachiAC, SendUnexpectedSizes) {
|
||||
|
||||
// Tests for IRHitachiAc class.
|
||||
TEST(TestIRHitachiAcClass, SetAndGetPower) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.on();
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
ac.off();
|
||||
@@ -203,7 +203,7 @@ TEST(TestIRHitachiAcClass, SetAndGetPower) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAcClass, SetAndGetSwing) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setSwingVertical(true);
|
||||
ac.setSwingHorizontal(true);
|
||||
EXPECT_TRUE(ac.getSwingVertical());
|
||||
@@ -222,7 +222,7 @@ TEST(TestIRHitachiAcClass, SetAndGetSwing) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAcClass, SetAndGetTemp) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setTemp(25);
|
||||
EXPECT_EQ(25, ac.getTemp());
|
||||
ac.setTemp(kHitachiAcMinTemp);
|
||||
@@ -238,7 +238,7 @@ TEST(TestIRHitachiAcClass, SetAndGetTemp) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAcClass, SetAndGetMode) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setMode(kHitachiAcCool);
|
||||
ac.setFan(kHitachiAcFanAuto);
|
||||
EXPECT_EQ(kHitachiAcCool, ac.getMode());
|
||||
@@ -261,7 +261,7 @@ TEST(TestIRHitachiAcClass, SetAndGetMode) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAcClass, SetAndGetFan) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setMode(kHitachiAcCool); // All fan options are available in this mode.
|
||||
ac.setFan(kHitachiAcFanAuto);
|
||||
EXPECT_EQ(kHitachiAcFanAuto, ac.getFan());
|
||||
@@ -293,7 +293,7 @@ TEST(TestIRHitachiAcClass, SetAndGetFan) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAcClass, HumanReadable) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
|
||||
ac.setMode(kHitachiAcHeat);
|
||||
ac.setTemp(kHitachiAcMaxTemp);
|
||||
@@ -316,7 +316,7 @@ TEST(TestIRHitachiAcClass, HumanReadable) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAcClass, ChecksumCalculation) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
|
||||
const uint8_t originalstate[kHitachiAcStateLength] = {
|
||||
0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80,
|
||||
@@ -426,7 +426,7 @@ TEST(TestDecodeHitachiAC, NormalRealExample1) {
|
||||
EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAcBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits);
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setRaw(irsend.capture.state);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 4 (Cool), Temp: 16C, Fan: 1 (Auto), "
|
||||
@@ -494,7 +494,7 @@ TEST(TestDecodeHitachiAC, NormalRealExample2) {
|
||||
EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAcBits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits);
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setRaw(irsend.capture.state);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 3 (Heat), Temp: 32C, Fan: 5 (High), "
|
||||
@@ -777,7 +777,7 @@ TEST(TestDecodeHitachiAC2, NormalRealExample) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAcClass, toCommon) {
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setPower(true);
|
||||
ac.setMode(kHitachiAcCool);
|
||||
ac.setTemp(20);
|
||||
@@ -865,6 +865,15 @@ TEST(TestUtils, Housekeeping) {
|
||||
IRsend::defaultBits(decode_type_t::HITACHI_AC264));
|
||||
ASSERT_EQ(kNoRepeat,
|
||||
IRsend::minRepeats(decode_type_t::HITACHI_AC264));
|
||||
|
||||
ASSERT_EQ("HITACHI_AC296", typeToString(decode_type_t::HITACHI_AC296));
|
||||
ASSERT_EQ(decode_type_t::HITACHI_AC296, strToDecodeType("HITACHI_AC296"));
|
||||
ASSERT_TRUE(hasACState(decode_type_t::HITACHI_AC296));
|
||||
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::HITACHI_AC296));
|
||||
ASSERT_EQ(kHitachiAc296Bits,
|
||||
IRsend::defaultBits(decode_type_t::HITACHI_AC296));
|
||||
ASSERT_EQ(kNoRepeat,
|
||||
IRsend::minRepeats(decode_type_t::HITACHI_AC296));
|
||||
}
|
||||
|
||||
// Decode a 'real' HitachiAc424 message.
|
||||
@@ -954,7 +963,7 @@ TEST(TestDecodeHitachiAc424, RealExample) {
|
||||
EXPECT_EQ(HITACHI_AC424, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc424Bits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, kHitachiAc424Bits);
|
||||
IRHitachiAc ac(0);
|
||||
IRHitachiAc ac(kGpioUnused);
|
||||
ac.setRaw(irsend.capture.state);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 5 (Auto), "
|
||||
@@ -988,7 +997,7 @@ TEST(TestDecodeHitachiAc424, SyntheticExample) {
|
||||
|
||||
// Tests for IRHitachiAc424 class.
|
||||
TEST(TestIRHitachiAc424Class, SetInvertedStates) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
|
||||
uint8_t raw[kHitachiAc424StateLength] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -1010,7 +1019,7 @@ TEST(TestIRHitachiAc424Class, SetInvertedStates) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc424Class, SetAndGetPower) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
ac.on();
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
ac.off();
|
||||
@@ -1024,7 +1033,7 @@ TEST(TestIRHitachiAc424Class, SetAndGetPower) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc424Class, SetAndGetTemp) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
ac.setTemp(25);
|
||||
EXPECT_EQ(25, ac.getTemp());
|
||||
ac.setTemp(kHitachiAc424MinTemp);
|
||||
@@ -1038,7 +1047,7 @@ TEST(TestIRHitachiAc424Class, SetAndGetTemp) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc424Class, SetAndGetMode) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
ac.setMode(kHitachiAc424Cool);
|
||||
ac.setFan(kHitachiAc424FanAuto);
|
||||
ac.setTemp(25);
|
||||
@@ -1058,7 +1067,7 @@ TEST(TestIRHitachiAc424Class, SetAndGetMode) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc424Class, SetAndGetFan) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
ac.setMode(kHitachiAc424Cool); // All fan options are available in this mode.
|
||||
ac.setFan(kHitachiAc424FanAuto);
|
||||
EXPECT_EQ(kHitachiAc424FanAuto, ac.getFan());
|
||||
@@ -1103,7 +1112,7 @@ TEST(TestIRHitachiAc424Class, SetAndGetFan) {
|
||||
|
||||
|
||||
TEST(TestIRHitachiAc424Class, SetAndGetButton) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
ac.on();
|
||||
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonPowerMode);
|
||||
ac.setButton(kHitachiAc424ButtonTempUp);
|
||||
@@ -1113,7 +1122,7 @@ TEST(TestIRHitachiAc424Class, SetAndGetButton) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc424Class, ToggleSwingVertical) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
ac.on();
|
||||
EXPECT_EQ(ac.getButton(), kHitachiAc424ButtonPowerMode);
|
||||
ac.setSwingVToggle(true);
|
||||
@@ -1125,7 +1134,7 @@ TEST(TestIRHitachiAc424Class, ToggleSwingVertical) {
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc424Class, HumanReadable) {
|
||||
IRHitachiAc424 ac(0);
|
||||
IRHitachiAc424 ac(kGpioUnused);
|
||||
|
||||
ac.setMode(kHitachiAc424Heat);
|
||||
ac.setTemp(kHitachiAc424MaxTemp);
|
||||
@@ -2231,3 +2240,172 @@ TEST(TestIRHitachiAc264Class, Issue1729_PowerOntoOff) {
|
||||
EXPECT_FALSE(irac.getState().power);
|
||||
EXPECT_FALSE(irac.next.power);
|
||||
}
|
||||
|
||||
// Decode a 'real' HitachiAc296 message.
|
||||
TEST(TestDecodeHitachiAc296, RealExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
const uint8_t expected[kHitachiAc296StateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xCC, 0x33, 0x92,
|
||||
0x6D, 0x44, 0xBB, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00,
|
||||
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x57, 0xA8, 0xF1, 0x0E, 0x00,
|
||||
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x03, 0xFC};
|
||||
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/pull/1758#issuecomment-1066017940
|
||||
// Power: ON, Temp: -- (not used in auto mode), Fan: Auto, Mode: Auto
|
||||
const uint16_t rawData[595] = {
|
||||
3298, 1712, 358, 1278, 362, 516, 356, 518, 358, 514, 358, 518, 358, 516,
|
||||
360, 516, 358, 520, 362, 514, 358, 516, 360, 514, 362, 514, 360, 1280,
|
||||
358, 518, 358, 514, 362, 518, 360, 516, 358, 516, 358, 516, 360, 516, 358,
|
||||
516, 358, 518, 358, 516, 360, 518, 362, 516, 358, 514, 360, 514, 360, 516,
|
||||
360, 516, 358, 516, 362, 1280, 356, 520, 360, 1276, 362, 1276, 360, 1282,
|
||||
360, 1280, 356, 1280, 358, 1278, 362, 514, 362, 1280, 360, 1280, 360,
|
||||
1278, 358, 1280, 358, 1280, 358, 1278, 360, 1280, 358, 1278, 360, 1282,
|
||||
360, 514, 360, 514, 362, 516, 356, 516, 362, 514, 360, 516, 358, 516, 358,
|
||||
520, 360, 516, 358, 516, 362, 1276, 360, 1278, 360, 514, 358, 516, 360,
|
||||
1278, 360, 1282, 360, 1276, 362, 1278, 360, 514, 358, 518, 358, 1278, 360,
|
||||
1278, 360, 514, 360, 518, 360, 516, 358, 1280, 358, 516, 360, 516, 360,
|
||||
1278, 360, 518, 356, 516, 360, 1282, 360, 1278, 362, 514, 360, 1278, 360,
|
||||
1278, 360, 516, 358, 1278, 360, 1280, 358, 520, 358, 516, 358, 516, 360,
|
||||
1276, 360, 516, 358, 514, 360, 514, 364, 1276, 358, 522, 358, 1278, 360,
|
||||
1280, 358, 516, 360, 1278, 360, 1276, 360, 1278, 362, 514, 358, 1286, 358,
|
||||
514, 358, 514, 362, 1278, 360, 514, 360, 518, 358, 516, 358, 518, 358,
|
||||
518, 360, 1276, 360, 1278, 362, 514, 360, 1276, 360, 1276, 362, 1280, 358,
|
||||
1276, 360, 1284, 358, 516, 358, 516, 360, 516, 360, 514, 360, 516, 358,
|
||||
516, 360, 518, 356, 518, 358, 1280, 358, 1278, 362, 1276, 360, 1280, 360,
|
||||
1276, 360, 1278, 362, 1278, 358, 1282, 358, 516, 358, 518, 358, 514, 360,
|
||||
516, 358, 516, 360, 514, 360, 514, 358, 520, 360, 1278, 360, 1280, 358,
|
||||
1280, 360, 1278, 360, 1278, 358, 1278, 360, 1278, 362, 1282, 360, 516,
|
||||
360, 516, 358, 516, 360, 518, 356, 516, 358, 516, 362, 514, 358, 520, 358,
|
||||
1280, 358, 1278, 362, 1276, 362, 1276, 360, 1276, 360, 1278, 360, 1278,
|
||||
360, 1282, 360, 514, 362, 514, 360, 516, 360, 514, 360, 516, 360, 516,
|
||||
360, 516, 358, 520, 362, 1278, 358, 1278, 362, 1276, 360, 1280, 358, 1276,
|
||||
362, 1276, 362, 1278, 360, 1284, 358, 516, 358, 514, 360, 516, 360, 514,
|
||||
360, 516, 360, 512, 362, 514, 360, 518, 360, 1276, 362, 1276, 362, 1278,
|
||||
358, 1280, 360, 1278, 360, 1278, 360, 1276, 362, 1282, 360, 1278, 362,
|
||||
1278, 362, 1276, 362, 512, 360, 1278, 362, 514, 360, 1278, 358, 520, 358,
|
||||
516, 360, 514, 360, 516, 358, 1278, 362, 514, 360, 1278, 358, 516, 362,
|
||||
1282, 360, 1276, 360, 516, 360, 516, 358, 518, 358, 1276, 362, 1278, 360,
|
||||
1278, 360, 1284, 358, 516, 360, 1278, 362, 1276, 360, 1278, 360, 516, 360,
|
||||
512, 362, 512, 362, 518, 362, 514, 362, 514, 358, 514, 360, 514, 360, 518,
|
||||
358, 514, 358, 516, 360, 518, 360, 1278, 360, 1278, 360, 1276, 362, 1276,
|
||||
362, 1276, 362, 1278, 358, 1278, 362, 1284, 358, 514, 362, 512, 360, 514,
|
||||
362, 516, 360, 514, 360, 514, 360, 512, 362, 520, 360, 1276, 362, 1278,
|
||||
362, 1276, 364, 1274, 360, 1278, 362, 1278, 360, 1278, 360, 1282, 362,
|
||||
512, 360, 514, 362, 512, 362, 514, 360, 516, 362, 512, 362, 516, 360, 518,
|
||||
360, 1278, 360, 1276, 362, 1278, 360, 1274, 364, 1276, 362, 1276, 360,
|
||||
1278, 360, 1280, 362, 1276, 362, 1276, 364, 512, 360, 514, 362, 512, 362,
|
||||
512, 362, 512, 362, 520, 358, 516, 360, 514, 360, 1276, 360, 1276, 362,
|
||||
1276, 362, 1278, 360, 1278, 360, 1280, 362}; // HITACHI_AC296
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawData, 595, kHitachiAcFreq);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(HITACHI_AC296, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc296Bits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 7 (Auto), Temp: 1C, Fan: 5 (Auto)",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
stdAc::state_t r, p;
|
||||
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
|
||||
}
|
||||
|
||||
// Decode a 'Synthetic' HitachiAc296 message.
|
||||
TEST(TestDecodeHitachiAc296, SyntheticExample) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/pull/1758#issuecomment-1066017940
|
||||
// Power: ON, Temp: 24, Fan: Quiet (1), Mode: Cool
|
||||
const uint8_t expected[kHitachiAc296StateLength] = {
|
||||
0x01, 0x10, 0x00, 0x40, 0xBF, 0xFF, 0x00, 0xCC, 0x33, 0x98,
|
||||
0x67, 0x42, 0xBD, 0x60, 0x9F, 0x00, 0xFF, 0x00, 0xFF, 0x00,
|
||||
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x13, 0xEC, 0xF1, 0x0E, 0x00,
|
||||
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x03, 0xFC};
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendHitachiAc296(expected);
|
||||
irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(HITACHI_AC296, irsend.capture.decode_type);
|
||||
ASSERT_EQ(kHitachiAc296Bits, irsend.capture.bits);
|
||||
EXPECT_STATE_EQ(expected, irsend.capture.state, kHitachiAc296Bits);
|
||||
EXPECT_EQ(
|
||||
"Power: On, Mode: 3 (Cool), Temp: 24C, Fan: 1 (Quiet)",
|
||||
IRAcUtils::resultAcToString(&irsend.capture));
|
||||
stdAc::state_t r, p;
|
||||
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc296Class, SetAndGetPower) {
|
||||
IRHitachiAc296 ac(kGpioUnused);
|
||||
ac.on();
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
ac.off();
|
||||
EXPECT_FALSE(ac.getPower());
|
||||
ac.setPower(true);
|
||||
EXPECT_TRUE(ac.getPower());
|
||||
ac.setPower(false);
|
||||
EXPECT_FALSE(ac.getPower());
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc296Class, SetAndGetTemp) {
|
||||
IRHitachiAc296 ac(kGpioUnused);
|
||||
ac.setTemp(25);
|
||||
EXPECT_EQ(25, ac.getTemp());
|
||||
ac.setTemp(kHitachiAc296MinTemp);
|
||||
EXPECT_EQ(kHitachiAc296MinTemp, ac.getTemp());
|
||||
ac.setTemp(kHitachiAc296MinTemp - 1);
|
||||
EXPECT_EQ(kHitachiAc296MinTemp, ac.getTemp());
|
||||
ac.setTemp(kHitachiAc296MaxTemp);
|
||||
EXPECT_EQ(kHitachiAc296MaxTemp, ac.getTemp());
|
||||
ac.setTemp(kHitachiAc296MaxTemp + 1);
|
||||
EXPECT_EQ(kHitachiAc296MaxTemp, ac.getTemp());
|
||||
// Check the handling of the special temp value for auto operation mode,
|
||||
ac.setMode(kHitachiAc296Cool);
|
||||
ac.setTemp(kHitachiAc296TempAuto);
|
||||
EXPECT_EQ(kHitachiAc296MinTemp, ac.getTemp());
|
||||
ac.setMode(kHitachiAc296Auto);
|
||||
EXPECT_EQ(kHitachiAc296TempAuto, ac.getTemp());
|
||||
ac.setTemp(kHitachiAc296TempAuto);
|
||||
EXPECT_EQ(kHitachiAc296TempAuto, ac.getTemp());
|
||||
ac.setTemp(kHitachiAc296MinTemp);
|
||||
EXPECT_EQ(kHitachiAc296TempAuto, ac.getTemp());
|
||||
ac.setMode(kHitachiAc296Cool);
|
||||
EXPECT_NE(kHitachiAc296TempAuto, ac.getTemp());
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc296Class, SetAndGetMode) {
|
||||
IRHitachiAc296 ac(kGpioUnused);
|
||||
ac.setMode(kHitachiAc296Cool);
|
||||
ac.setFan(kHitachiAc296FanAuto);
|
||||
ac.setTemp(25);
|
||||
EXPECT_EQ(25, ac.getTemp());
|
||||
EXPECT_EQ(kHitachiAc296Cool, ac.getMode());
|
||||
EXPECT_EQ(kHitachiAc296FanAuto, ac.getFan());
|
||||
ac.setMode(kHitachiAc296Heat);
|
||||
EXPECT_EQ(25, ac.getTemp());
|
||||
EXPECT_EQ(kHitachiAc296Heat, ac.getMode());
|
||||
ac.setMode(kHitachiAc296Dehumidify);
|
||||
EXPECT_EQ(kHitachiAc296Dehumidify, ac.getMode());
|
||||
}
|
||||
|
||||
TEST(TestIRHitachiAc296Class, SetAndGetFan) {
|
||||
IRHitachiAc296 ac(kGpioUnused);
|
||||
ac.setMode(kHitachiAc296Cool);
|
||||
ac.setFan(kHitachiAc296FanAuto);
|
||||
EXPECT_EQ(kHitachiAc296FanAuto, ac.getFan());
|
||||
ac.setFan(kHitachiAc296FanLow);
|
||||
EXPECT_EQ(kHitachiAc296FanLow, ac.getFan());
|
||||
ac.setFan(kHitachiAc296FanHigh);
|
||||
EXPECT_EQ(kHitachiAc296FanHigh, ac.getFan());
|
||||
ac.setFan(kHitachiAc296FanAuto + 1);
|
||||
EXPECT_EQ(kHitachiAc296FanAuto, ac.getFan());
|
||||
ac.setFan(kHitachiAc296FanSilent - 1);
|
||||
EXPECT_EQ(kHitachiAc296FanSilent, ac.getFan());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user