diff --git a/src/IRac.cpp b/src/IRac.cpp index f9d9647d..35ff4e53 100644 --- a/src/IRac.cpp +++ b/src/IRac.cpp @@ -1502,16 +1502,21 @@ void IRac::lg(IRLgAc *ac, const lg_ac_remote_model_t model, /// @param[in] degrees The temperature setting in degrees. /// @param[in] fan The speed setting for the fan. /// @param[in] swingv The vertical swing setting. +/// @param[in] quiet Run the device in quiet/silent mode. +/// @param[in] quiet_prev The device's previous quiet/silent mode. /// @param[in] turbo Toggle the device's turbo/powerful mode. /// @param[in] econo Toggle the device's economical mode. /// @param[in] light Toggle the LED/Display mode. +/// @param[in] clean Turn on the self-cleaning mode. e.g. XFan, dry filters etc /// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on. /// @note On Danby A/C units, swingv controls the Ion Filter instead. void IRac::midea(IRMideaAC *ac, const bool on, const stdAc::opmode_t mode, const bool celsius, const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, - const bool econo, const bool light, const int16_t sleep) { + const stdAc::swingv_t swingv, + const bool quiet, const bool quiet_prev, + const bool turbo, const bool econo, const bool light, + const bool clean, const int16_t sleep) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); @@ -1520,12 +1525,12 @@ void IRac::midea(IRMideaAC *ac, ac->setFan(ac->convertFan(fan)); ac->setSwingVToggle(swingv != stdAc::swingv_t::kOff); // No Horizontal swing setting available. - // No Quiet setting available. + ac->setQuiet(quiet, quiet_prev); ac->setTurboToggle(turbo); ac->setEconoToggle(econo); ac->setLightToggle(light); // No Filter setting available. - // No Clean setting available. + ac->setCleanToggle(clean); // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. // No Clock setting available. @@ -2530,6 +2535,7 @@ stdAc::state_t IRac::handleToggles(const stdAc::state_t desired, result.turbo = desired.turbo ^ prev->turbo; result.econo = desired.econo ^ prev->econo; result.light = desired.light ^ prev->light; + result.clean = desired.clean ^ prev->clean; // FALL THRU case decode_type_t::CORONA_AC: case decode_type_t::HITACHI_AC344: @@ -2645,6 +2651,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { const stdAc::swingv_t prev_swingv = (prev != NULL) ? prev->swingv : stdAc::swingv_t::kOff; #endif // (SEND_LG || SEND_SHARP_AC) +#if SEND_MIDEA + const bool prev_quiet = (prev != NULL) ? prev->quiet : !send.quiet; +#endif // SEND_MIDEA // Per vendor settings & setup. switch (send.protocol) { #if SEND_AIRTON @@ -2945,8 +2954,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { { IRMideaAC ac(_pin, _inverted, _modulation); midea(&ac, send.power, send.mode, send.celsius, send.degrees, - send.fanspeed, send.swingv, send.turbo, send.econo, send.light, - send.sleep); + send.fanspeed, send.swingv, send.quiet, prev_quiet, send.turbo, + send.econo, send.light, send.sleep); break; } #endif // SEND_MIDEA diff --git a/src/IRac.h b/src/IRac.h index 9954eecb..7a2ebd29 100644 --- a/src/IRac.h +++ b/src/IRac.h @@ -338,8 +338,10 @@ void electra(IRElectraAc *ac, void midea(IRMideaAC *ac, const bool on, const stdAc::opmode_t mode, const bool celsius, const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, const bool econo, - const bool light, const int16_t sleep = -1); + const stdAc::swingv_t swingv, + const bool quiet, const bool quiet_prev, const bool turbo, + const bool econo, const bool light, const bool clean, + const int16_t sleep = -1); #endif // SEND_MIDEA #if SEND_MIRAGE void mirage(IRMirageAc *ac, const stdAc::state_t state); diff --git a/src/ir_Midea.cpp b/src/ir_Midea.cpp index 8b3b645d..4fbc0797 100644 --- a/src/ir_Midea.cpp +++ b/src/ir_Midea.cpp @@ -42,6 +42,7 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::addToggleToString; using irutils::minsToString; #if SEND_MIDEA @@ -100,10 +101,13 @@ IRMideaAC::IRMideaAC(const uint16_t pin, const bool inverted, void IRMideaAC::stateReset(void) { // Power On, Mode Auto, Fan Auto, Temp = 25C/77F _.remote_state = 0xA1826FFFFF62; - _SwingVToggle = false; + _CleanToggle = false; _EconoToggle = false; - _TurboToggle = false; + _8CHeatToggle = false; _LightToggle = false; + _Quiet = _Quiet_prev = false; + _SwingVToggle = false; + _TurboToggle = false; #if KAYSUN_AC _SwingVStep = false; #endif // KAYSUN_AC @@ -135,6 +139,19 @@ void IRMideaAC::send(const uint16_t repeat) { if (_LightToggle && !isLightToggle()) _irsend.sendMidea(kMideaACToggleLight, kMideaBits, repeat); _LightToggle = false; + if (getMode() <= kMideaACAuto) { // Only available in Cool, Dry, or Auto mode + if (_CleanToggle && !isCleanToggle()) + _irsend.sendMidea(kMideaACToggleSelfClean, kMideaBits, repeat); + _CleanToggle = false; + } else if (getMode() == kMideaACHeat) { // Only available in Heat mode + if (_8CHeatToggle && !is8CHeatToggle()) + _irsend.sendMidea(kMideaACToggle8CHeat, kMideaBits, repeat); + _8CHeatToggle = false; + } + if (_Quiet != _Quiet_prev) + _irsend.sendMidea(_Quiet ? kMideaACQuietOn : kMideaACQuietOff, + kMideaBits, repeat); + _Quiet_prev = _Quiet; } #endif // SEND_MIDEA @@ -410,6 +427,75 @@ bool IRMideaAC::getLightToggle(void) { return _LightToggle; } +/// Is the current state a Self-Clean toggle message? +/// @return true, it is. false, it isn't. +bool IRMideaAC::isCleanToggle(void) const { + return _.remote_state == kMideaACToggleSelfClean; +} + +/// Set the A/C to toggle the Self Clean mode for the next send. +/// @note Only works in Cool, Dry, or Auto modes. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMideaAC::setCleanToggle(const bool on) { + _CleanToggle = on && getMode() <= kMideaACAuto; +} + +// Get the Self-Clean toggle state of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRMideaAC::getCleanToggle(void) { + _CleanToggle |= isCleanToggle(); + return _CleanToggle; +} + +/// Is the current state a 8C Heat (Freeze Protect) toggle message? +/// @note Only works in Heat mode. +/// @return true, it is. false, it isn't. +bool IRMideaAC::is8CHeatToggle(void) const { + return _.remote_state == kMideaACToggle8CHeat; +} + +/// Set the A/C to toggle the 8C Heat (Freeze Protect) mode for the next send. +/// @note Only works in Heat mode. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMideaAC::set8CHeatToggle(const bool on) { + _8CHeatToggle = on && getMode() == kMideaACHeat; +} + +// Get the 8C Heat (Freeze Protect) toggle state of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRMideaAC::get8CHeatToggle(void) { + _8CHeatToggle |= is8CHeatToggle(); + return _8CHeatToggle; +} + +/// Is the current state a Quiet(Silent) message? +/// @return true, it is. false, it isn't. +bool IRMideaAC::isQuiet(void) const { + return (_.remote_state == kMideaACQuietOff || + _.remote_state == kMideaACQuietOn); +} + +/// Set the Quiet (Silent) mode for the next send. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMideaAC::setQuiet(const bool on) { _Quiet = on; } + +/// Set the Quiet (Silent) mode for the next send. +/// @param[in] on true, the setting is on. false, the setting is off. +/// @param[in] prev true, previously the setting was on. false, setting was off. +void IRMideaAC::setQuiet(const bool on, const bool prev) { + setQuiet(on); + _Quiet_prev = prev; +} + +// Get the Quiet (Silent) mode state of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRMideaAC::getQuiet(void) const { + if (isQuiet()) + return _.remote_state == kMideaACQuietOn; + else + return _Quiet; +} + /// Calculate the checksum for a given state. /// @param[in] state The value to calc the checksum of. /// @return The calculated checksum value. @@ -566,7 +652,7 @@ stdAc::fanspeed_t IRMideaAC::toCommonFanSpeed(const uint8_t speed) { /// @param[in] prev A Ptr to the previous state. /// @return The stdAc equivalent of the native settings. stdAc::state_t IRMideaAC::toCommon(const stdAc::state_t *prev) { - stdAc::state_t result; + stdAc::state_t result{}; if (prev != NULL) { result = *prev; } else { @@ -577,7 +663,6 @@ stdAc::state_t IRMideaAC::toCommon(const stdAc::state_t *prev) { result.swingv = stdAc::swingv_t::kOff; result.quiet = false; result.turbo = false; - result.clean = false; result.econo = false; result.filter = false; result.light = false; @@ -597,6 +682,7 @@ stdAc::state_t IRMideaAC::toCommon(const stdAc::state_t *prev) { result.fanspeed = toCommonFanSpeed(_.Fan); result.sleep = _.Sleep ? 0 : -1; result.econo = getEconoToggle(); + result.clean ^= getCleanToggle(); return result; } @@ -612,7 +698,7 @@ String IRMideaAC::toString(void) { case kMideaACTypeCommand: result += kCommandStr; break; case kMideaACTypeSpecial: result += kSpecialStr; break; case kMideaACTypeFollow: result += kFollowStr; break; - default: result += kUnknownStr; + default: result += kUnknownStr; } result += ')'; if (message_type != kMideaACTypeSpecial) { @@ -643,13 +729,16 @@ String IRMideaAC::toString(void) { kMideaACFanAuto, kMideaACFanAuto, kMideaACFanMed); result += addBoolToString(_.Sleep, kSleepStr); } - result += addBoolToString(getSwingVToggle(), kSwingVToggleStr); + result += addToggleToString(getSwingVToggle(), kSwingVStr); #if KAYSUN_AC result += addBoolToString(getSwingVStep(), kStepStr); #endif // KAYSUN_AC - result += addBoolToString(getEconoToggle(), kEconoToggleStr); - result += addBoolToString(getTurboToggle(), kTurboToggleStr); - result += addBoolToString(getLightToggle(), kLightToggleStr); + result += addToggleToString(getEconoToggle(), kEconoStr); + result += addToggleToString(getTurboToggle(), kTurboStr); + result += addBoolToString(getQuiet(), kQuietStr); + result += addToggleToString(getLightToggle(), kLightStr); + result += addToggleToString(getCleanToggle(), kCleanStr); + result += addToggleToString(get8CHeatToggle(), k8CHeatStr); return result; } diff --git a/src/ir_Midea.h b/src/ir_Midea.h index eaeaa04d..092bf4fb 100644 --- a/src/ir_Midea.h +++ b/src/ir_Midea.h @@ -5,6 +5,7 @@ /// Midea added by crankyoldgit & bwze /// @see https://docs.google.com/spreadsheets/d/1TZh4jWrx4h9zzpYUI9aYXMl1fYOiqu-xVuOOMqagxrs/edit?usp=sharing /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1342#issuecomment-733721085 +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1733 // Supports: // Brand: Pioneer System, Model: RYBO12GMFILCAD A/C (12K BTU) (MIDEA) @@ -24,6 +25,9 @@ // Brand: Danby, Model: R09C/BCGE remote (MIDEA) // Brand: Trotec, Model: TROTEC PAC 3900 X (MIDEA) // Brand: Trotec, Model: RG57H(B)/BGE remote (MIDEA) +// Brand: Lennox, Model: RG57A6/BGEFU1 remote (MIDEA) +// Brand: Lennox, Model: MWMA009S4-3P A/C (MIDEA) +// Brand: Lennox, Model: MWMA012S4-3P A/C (MIDEA) #ifndef IR_MIDEA_H_ #define IR_MIDEA_H_ @@ -123,9 +127,16 @@ const uint8_t kMideaACFanHigh = 3; // 0b11 // const uint64_t kMideaACToggleIonizer = 0xA201FFFFFF7C; kSwingVToggleStr = kIonStr; #endif // DANBY_DAC -const uint64_t kMideaACToggleEcono = 0xA202FFFFFF7E; -const uint64_t kMideaACToggleLight = 0xA208FFFFFF75; -const uint64_t kMideaACToggleTurbo = 0xA209FFFFFF74; +const uint64_t kMideaACToggleEcono = 0xA202FFFFFF7E; +const uint64_t kMideaACToggleLight = 0xA208FFFFFF75; +const uint64_t kMideaACToggleTurbo = 0xA209FFFFFF74; +// Mode must be Auto, Cool, or Dry +const uint64_t kMideaACToggleSelfClean = 0xA20DFFFFFF70; +// 8C Heat AKA Freeze Protection +const uint64_t kMideaACToggle8CHeat = 0xA20FFFFFFF73; // Only in Heat +const uint64_t kMideaACQuietOn = 0xA212FFFFFF6E; +const uint64_t kMideaACQuietOff = 0xA213FFFFFF6F; + const uint8_t kMideaACTypeCommand = 0b001; ///< Message type const uint8_t kMideaACTypeSpecial = 0b010; ///< Message type const uint8_t kMideaACTypeFollow = 0b100; ///< Message type @@ -202,6 +213,16 @@ class IRMideaAC { bool isLightToggle(void) const; void setLightToggle(const bool on); bool getLightToggle(void); + bool isCleanToggle(void) const; + void setCleanToggle(const bool on); + bool getCleanToggle(void); + bool is8CHeatToggle(void) const; + void set8CHeatToggle(const bool on); + bool get8CHeatToggle(void); + bool isQuiet(void) const; + void setQuiet(const bool on); + void setQuiet(const bool on, const bool prev); + bool getQuiet(void) const; uint8_t getType(void) const; bool isOnTimerEnabled(void) const; uint16_t getOnTimer(void) const; @@ -225,13 +246,17 @@ class IRMideaAC { /// @endcond #endif // UNIT_TEST MideaProtocol _; + bool _CleanToggle; + bool _EconoToggle; + bool _8CHeatToggle; + bool _LightToggle; + bool _Quiet; + bool _Quiet_prev; bool _SwingVToggle; #if KAYSUN_AC bool _SwingVStep; #endif // KAYSUN_AC - bool _EconoToggle; bool _TurboToggle; - bool _LightToggle; void checksum(void); static uint8_t calcChecksum(const uint64_t state); void setType(const uint8_t type); diff --git a/test/IRac_test.cpp b/test/IRac_test.cpp index 2988e4b4..2990f400 100644 --- a/test/IRac_test.cpp +++ b/test/IRac_test.cpp @@ -1359,8 +1359,8 @@ TEST(TestIRac, Midea) { char expected[] = "Type: 1 (Command), Power: On, Mode: 1 (Dry), Celsius: On, " "Temp: 27C/80F, On Timer: Off, Off Timer: Off, Fan: 2 (Medium), " - "Sleep: On, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off"; + "Sleep: On, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -"; ac.begin(); irac.midea(&ac, @@ -1370,9 +1370,12 @@ TEST(TestIRac, Midea) { 27, // Degrees stdAc::fanspeed_t::kMedium, // Fan speed stdAc::swingv_t::kOff, // Swing(V) + false, // Silent/Quiet + false, // Previous Silent/Quiet setting false, // Turbo false, // Econo false, // Light + false, // Clean 8 * 60 + 0); // Sleep time ASSERT_EQ(expected, ac.toString()); diff --git a/test/ir_Midea_test.cpp b/test/ir_Midea_test.cpp index 713fcd0e..0660f8af 100644 --- a/test/ir_Midea_test.cpp +++ b/test/ir_Midea_test.cpp @@ -448,8 +448,8 @@ TEST(TestMideaACClass, HumanReadableOutput) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.off(); ac.setTemp(25, true); ac.setFan(kMideaACFanHigh); @@ -458,21 +458,21 @@ TEST(TestMideaACClass, HumanReadableOutput) { EXPECT_EQ( "Type: 1 (Command), Power: Off, Mode: 1 (Dry), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 3 (High), " - "Sleep: On, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: On, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setUseCelsius(true); EXPECT_EQ( "Type: 1 (Command), Power: Off, Mode: 1 (Dry), Celsius: On, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 3 (High), " - "Sleep: On, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: On, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setRaw(0xA19867FFFF7E); EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 0 (Cool), Celsius: Off, " "Temp: 21C/69F, On Timer: Off, Off Timer: Off, Fan: 3 (High), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } // Tests for decodeMidea(). @@ -681,8 +681,8 @@ TEST(TestDecodeMidea, DecodeRealExample) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 18C/65F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -733,16 +733,16 @@ TEST(TestMideaACClass, CelsiusRemoteTemp) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 0 (Cool), Celsius: On, " "Temp: 17C/62F, On Timer: Off, Off Timer: Off, Fan: 1 (Low), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setRaw(on_cool_low_17c); EXPECT_EQ(17, ac.getTemp(true)); EXPECT_EQ(62, ac.getTemp(false)); EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 0 (Cool), Celsius: On, " "Temp: 17C/62F, On Timer: Off, Off Timer: Off, Fan: 1 (Low), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setTemp(17, true); EXPECT_EQ(17, ac.getTemp(true)); EXPECT_EQ(62, ac.getTemp(false)); @@ -752,8 +752,8 @@ TEST(TestMideaACClass, CelsiusRemoteTemp) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 0 (Cool), Celsius: On, " "Temp: 30C/86F, On Timer: Off, Off Timer: Off, Fan: 1 (Low), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } // https://github.com/crankyoldgit/IRremoteESP8266/issues/819 @@ -766,18 +766,18 @@ TEST(TestMideaACClass, SwingV) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: On, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): Toggle, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setSwingVToggle(false); ASSERT_FALSE(ac.getSwingVToggle()); EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setRaw(kMideaACToggleSwingV); - EXPECT_EQ("Type: 2 (Special), Swing(V) Toggle: On, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", + EXPECT_EQ("Type: 2 (Special), Swing(V): Toggle, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } @@ -791,18 +791,18 @@ TEST(TestMideaACClass, Econo) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: On, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: Toggle, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setEconoToggle(false); ASSERT_FALSE(ac.getEconoToggle()); EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setRaw(kMideaACToggleEcono); - EXPECT_EQ("Type: 2 (Special), Swing(V) Toggle: Off, Econo Toggle: On, " - "Turbo Toggle: Off, Light Toggle: Off", + EXPECT_EQ("Type: 2 (Special), Swing(V): -, Econo: Toggle, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } @@ -815,18 +815,20 @@ TEST(TestMideaACClass, Turbo) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: On, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: Toggle, Quiet: Off, Light: -, Clean: -, 8C Heat: -", + ac.toString()); ac.setTurboToggle(false); ASSERT_FALSE(ac.getTurboToggle()); EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", + ac.toString()); ac.setRaw(kMideaACToggleTurbo); - EXPECT_EQ("Type: 2 (Special), Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: On, Light Toggle: Off", + EXPECT_EQ("Type: 2 (Special), Swing(V): -, Econo: -, " + "Turbo: Toggle, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } @@ -839,18 +841,105 @@ TEST(TestMideaACClass, Light) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: On", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: Toggle, Clean: -, 8C Heat: -", + ac.toString()); ac.setLightToggle(false); ASSERT_FALSE(ac.getLightToggle()); EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", + ac.toString()); ac.setRaw(kMideaACToggleLight); - EXPECT_EQ("Type: 2 (Special), Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: On", + EXPECT_EQ("Type: 2 (Special), Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: Toggle, Clean: -, 8C Heat: -", + ac.toString()); +} + +TEST(TestMideaACClass, Clean) { + IRMideaAC ac(kGpioUnused); + ac.setCleanToggle(false); + ASSERT_FALSE(ac.getCleanToggle()); + ac.setCleanToggle(true); + ASSERT_TRUE(ac.getCleanToggle()); + EXPECT_EQ( + "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " + "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: Toggle, 8C Heat: -", + ac.toString()); + ac.setCleanToggle(false); + ASSERT_FALSE(ac.getCleanToggle()); + EXPECT_EQ( + "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " + "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", + ac.toString()); + ac.setRaw(kMideaACToggleSelfClean); + EXPECT_EQ("Type: 2 (Special), Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: Toggle, 8C Heat: -", + ac.toString()); +} + +TEST(TestMideaACClass, FreezeProtectionAKA8CHeat) { + IRMideaAC ac(kGpioUnused); + ac.set8CHeatToggle(false); + ASSERT_FALSE(ac.get8CHeatToggle()); + ASSERT_NE(kMideaACHeat, ac.getMode()); + ac.set8CHeatToggle(true); // Not in heat mode so it should not work. + ASSERT_FALSE(ac.get8CHeatToggle()); + ac.setMode(kMideaACHeat); // Now it should work + ac.set8CHeatToggle(true); + ASSERT_TRUE(ac.get8CHeatToggle()); + EXPECT_EQ( + "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: Off, " + "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: Toggle", + ac.toString()); + ac.set8CHeatToggle(false); + ASSERT_FALSE(ac.get8CHeatToggle()); + EXPECT_EQ( + "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: Off, " + "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", + ac.toString()); + ac.setRaw(kMideaACToggle8CHeat); + EXPECT_EQ("Type: 2 (Special), Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: Toggle", + ac.toString()); +} + +TEST(TestMideaACClass, Quiet) { + IRMideaAC ac(kGpioUnused); + ac.setQuiet(false); + ASSERT_FALSE(ac.getQuiet()); + ac.setQuiet(true); + ASSERT_TRUE(ac.getQuiet()); + EXPECT_EQ( + "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " + "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: On, Light: -, Clean: -, 8C Heat: -", + ac.toString()); + ac.setQuiet(false); + ASSERT_FALSE(ac.getQuiet()); + EXPECT_EQ( + "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " + "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); + ac.setRaw(kMideaACQuietOn); + EXPECT_EQ("Type: 2 (Special), Swing(V): -, Econo: -, " + "Turbo: -, Quiet: On, Light: -, Clean: -, 8C Heat: -", + ac.toString()); + ac.setRaw(kMideaACQuietOff); + EXPECT_EQ("Type: 2 (Special), Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } @@ -1067,8 +1156,8 @@ TEST(TestDecodeMidea, Issue1318_self_decode) { EXPECT_EQ( "Type: 4 (Follow), Power: On, Mode: 3 (Heat), Celsius: On, " "Temp: 24C/75F, SensorTemp: 24C/75F, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", IRAcUtils::resultAcToString(&irsend.capture)); EXPECT_EQ( "f38000d50" @@ -1146,32 +1235,32 @@ TEST(TestMideaACClass, SensorTemp) { EXPECT_EQ( "Type: 4 (Follow), Power: On, Mode: 2 (Auto), Celsius: On, " "Temp: 23C/73F, SensorTemp: 0C/32F, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setRaw(0xA482467F134E); // 18C EXPECT_EQ(18, ac.getSensorTemp(true)); EXPECT_TRUE(ac.getEnableSensorTemp()); EXPECT_EQ( "Type: 4 (Follow), Power: On, Mode: 2 (Auto), Celsius: On, " "Temp: 23C/73F, SensorTemp: 18C/64F, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setRaw(0xA482467F266B); // 37C EXPECT_EQ(37, ac.getSensorTemp(true)); EXPECT_TRUE(ac.getEnableSensorTemp()); EXPECT_EQ( "Type: 4 (Follow), Power: On, Mode: 2 (Auto), Celsius: On, " "Temp: 23C/73F, SensorTemp: 37C/98F, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setRaw(0xA482607F2B43); // 74F EXPECT_EQ(74, ac.getSensorTemp(false)); EXPECT_TRUE(ac.getEnableSensorTemp()); EXPECT_EQ( "Type: 4 (Follow), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 17C/62F, SensorTemp: 23C/74F, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } TEST(TestMideaACClass, MessageType) { @@ -1202,8 +1291,8 @@ TEST(TestMideaACClass, ConstructKnownMessage) { EXPECT_EQ( "Type: 4 (Follow), Power: On, Mode: 2 (Auto), Celsius: On, " "Temp: 23C/73F, SensorTemp: 25C/77F, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); EXPECT_EQ(followme_25C, ac.getRaw()); } @@ -1217,8 +1306,8 @@ TEST(TestMideaACClass, OnTimer) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: On, " "Temp: 30C/86F, On Timer: 07:00, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setOnTimer(0); // Disable / Timer off. EXPECT_FALSE(ac.isOnTimerEnabled()); EXPECT_EQ(kMideaACTypeCommand, ac.getType()); @@ -1229,8 +1318,8 @@ TEST(TestMideaACClass, OnTimer) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: On, " "Temp: 30C/86F, On Timer: 03:30, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); // Limit to max time. ac.setOnTimer(25 * 60); // 25h EXPECT_TRUE(ac.isOnTimerEnabled()); @@ -1239,8 +1328,8 @@ TEST(TestMideaACClass, OnTimer) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: On, " "Temp: 30C/86F, On Timer: 24:00, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } @@ -1254,8 +1343,8 @@ TEST(TestMideaACClass, OffTimer) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: On, " "Temp: 30C/86F, On Timer: Off, Off Timer: 00:30, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.setOffTimer(0); // Disable / Timer off. EXPECT_FALSE(ac.isOffTimerEnabled()); EXPECT_EQ(kMideaACTypeCommand, ac.getType()); @@ -1266,8 +1355,8 @@ TEST(TestMideaACClass, OffTimer) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: On, " "Temp: 30C/86F, On Timer: Off, Off Timer: 03:30, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); // Limit to max time. ac.setOffTimer(25 * 60); // 25h EXPECT_TRUE(ac.isOffTimerEnabled()); @@ -1276,8 +1365,8 @@ TEST(TestMideaACClass, OffTimer) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: On, " "Temp: 30C/86F, On Timer: Off, Off Timer: 24:00, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", ac.toString()); + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", ac.toString()); } // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1318#issuecomment-725406813 @@ -1294,16 +1383,16 @@ TEST(TestMideaACClass, SendingSwingV) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 2 (Auto), Celsius: Off, " "Temp: 25C/77F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), " - "Sleep: Off, Swing(V) Toggle: Off, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", + "Sleep: Off, Swing(V): -, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", IRAcUtils::resultAcToString(&ac._irsend.capture)); // Decode the second/following message which should be the swing toggle. EXPECT_TRUE(irrecv.decodeMidea(&ac._irsend.capture, 201)); EXPECT_EQ(MIDEA, ac._irsend.capture.decode_type); EXPECT_EQ(kMideaBits, ac._irsend.capture.bits); EXPECT_EQ( - "Type: 2 (Special), Swing(V) Toggle: On, Econo Toggle: Off, " - "Turbo Toggle: Off, Light Toggle: Off", + "Type: 2 (Special), Swing(V): Toggle, Econo: -, " + "Turbo: -, Quiet: Off, Light: -, Clean: -, 8C Heat: -", IRAcUtils::resultAcToString(&ac._irsend.capture)); } @@ -1318,8 +1407,8 @@ TEST(TestMideaACClass, Issue1342) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: Off, " "Temp: 21C/70F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), Sleep: Off, " - "Swing(V) Toggle: Off, Econo Toggle: Off, Turbo Toggle: Off, " - "Light Toggle: Off", + "Swing(V): -, Econo: -, Turbo: -, Quiet: Off, " + "Light: -, Clean: -, 8C Heat: -", ac.toString()); ac.stateReset(); // Remove any existing info so we can build from scratch. ASSERT_NE(0xA1A368FFFF45, ac.getRaw()); @@ -1337,8 +1426,8 @@ TEST(TestMideaACClass, Issue1342) { EXPECT_EQ( "Type: 1 (Command), Power: On, Mode: 3 (Heat), Celsius: Off, " "Temp: 21C/70F, On Timer: Off, Off Timer: Off, Fan: 0 (Auto), Sleep: Off, " - "Swing(V) Toggle: Off, Econo Toggle: Off, Turbo Toggle: Off, " - "Light Toggle: Off", + "Swing(V): -, Econo: -, Turbo: -, Quiet: Off, " + "Light: -, Clean: -, 8C Heat: -", ac.toString()); EXPECT_EQ(0xA1A368FFFF45, ac.getRaw()); }