mirror of
https://github.com/crankyoldgit/IRremoteESP8266.git
synced 2026-01-12 00:05:10 +08:00
[HAIER_AC176/HAIER_AC_YRW02] Implement Quiet setting. (#1635)
* Change `setTurbo()` & `getTurbo()` to operate on Booleans only. * Add `setQuiet()` & `getQuiet()` methods. * Limit Quiet & Turbo to `Cool` & `Heat` operating modes. * Quiet & Turbo are mutually exclusive. * Improve unit testing. * General code style cleanups. Ref #1634 FYI @PtilopsisLeucotis
This commit is contained in:
11
src/IRac.cpp
11
src/IRac.cpp
@@ -1116,20 +1116,21 @@ void IRac::haier(IRHaierAC *ac,
|
||||
/// @param[in] fan The speed setting for the fan.
|
||||
/// @param[in] swingv The vertical swing setting.
|
||||
/// @param[in] turbo Run the device in turbo/powerful mode.
|
||||
/// @param[in] quiet Run the device in quiet mode.
|
||||
/// @param[in] filter Turn on the (ion/pollen/etc) filter mode.
|
||||
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
|
||||
void IRac::haier176(IRHaierAC176 *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan,
|
||||
const stdAc::swingv_t swingv, const bool turbo,
|
||||
const bool filter, const int16_t sleep) {
|
||||
const bool quiet, const bool filter, const int16_t sleep) {
|
||||
ac->begin();
|
||||
ac->setMode(ac->convertMode(mode));
|
||||
ac->setTemp(degrees);
|
||||
ac->setFan(ac->convertFan(fan));
|
||||
ac->setSwing(ac->convertSwingV(swingv));
|
||||
// No Horizontal Swing setting available.
|
||||
// No Quiet setting available.
|
||||
ac->setQuiet(quiet);
|
||||
ac->setTurbo(turbo);
|
||||
// No Light setting available.
|
||||
ac->setHealth(filter);
|
||||
@@ -1150,20 +1151,22 @@ void IRac::haier176(IRHaierAC176 *ac,
|
||||
/// @param[in] fan The speed setting for the fan.
|
||||
/// @param[in] swingv The vertical swing setting.
|
||||
/// @param[in] turbo Run the device in turbo/powerful mode.
|
||||
/// @param[in] quiet Run the device in quiet mode.
|
||||
/// @param[in] filter Turn on the (ion/pollen/etc) filter mode.
|
||||
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
|
||||
void IRac::haierYrwo2(IRHaierACYRW02 *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan,
|
||||
const stdAc::swingv_t swingv, const bool turbo,
|
||||
const bool filter, const int16_t sleep) {
|
||||
const bool quiet, const bool filter,
|
||||
const int16_t sleep) {
|
||||
ac->begin();
|
||||
ac->setMode(ac->convertMode(mode));
|
||||
ac->setTemp(degrees);
|
||||
ac->setFan(ac->convertFan(fan));
|
||||
ac->setSwing(ac->convertSwingV(swingv));
|
||||
// No Horizontal Swing setting available.
|
||||
// No Quiet setting available.
|
||||
ac->setQuiet(quiet);
|
||||
ac->setTurbo(turbo);
|
||||
// No Light setting available.
|
||||
ac->setHealth(filter);
|
||||
|
||||
@@ -262,7 +262,7 @@ void electra(IRElectraAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan,
|
||||
const stdAc::swingv_t swingv,
|
||||
const bool turbo, const bool filter,
|
||||
const bool turbo, const bool quiet, const bool filter,
|
||||
const int16_t sleep = -1);
|
||||
#endif // SEND_HAIER_AC176
|
||||
#if SEND_HAIER_AC_YRW02
|
||||
@@ -270,7 +270,7 @@ void electra(IRElectraAc *ac,
|
||||
const bool on, const stdAc::opmode_t mode,
|
||||
const float degrees, const stdAc::fanspeed_t fan,
|
||||
const stdAc::swingv_t swingv,
|
||||
const bool turbo, const bool filter,
|
||||
const bool turbo, const bool quiet, const bool filter,
|
||||
const int16_t sleep = -1);
|
||||
#endif // SEND_HAIER_AC_YRW02
|
||||
#if SEND_HITACHI_AC
|
||||
|
||||
117
src/ir_Haier.cpp
117
src/ir_Haier.cpp
@@ -629,24 +629,27 @@ uint8_t IRHaierAC176::getButton(void) const {
|
||||
/// Set the operating mode of the A/C.
|
||||
/// @param[in] mode The desired operating mode.
|
||||
void IRHaierAC176::setMode(uint8_t mode) {
|
||||
uint8_t new_mode = mode;
|
||||
_.Button = kHaierAcYrw02ButtonMode;
|
||||
switch (mode) {
|
||||
case kHaierAcYrw02Auto:
|
||||
case kHaierAcYrw02Cool:
|
||||
case kHaierAcYrw02Dry:
|
||||
case kHaierAcYrw02Fan:
|
||||
// Turbo & Quiet is only available in Cool/Heat mode.
|
||||
_.Turbo = false;
|
||||
_.Quiet = false;
|
||||
// FALL-THRU
|
||||
case kHaierAcYrw02Cool:
|
||||
case kHaierAcYrw02Heat:
|
||||
case kHaierAcYrw02Fan: break;
|
||||
default: new_mode = kHaierAcYrw02Auto; // Unexpected, default to auto mode.
|
||||
_.Button = kHaierAcYrw02ButtonMode;
|
||||
_.Mode = mode;
|
||||
break;
|
||||
default:
|
||||
setMode(kHaierAcYrw02Auto); // Unexpected, default to auto mode.
|
||||
}
|
||||
_.Mode = new_mode;
|
||||
}
|
||||
|
||||
/// Get the operating mode setting of the A/C.
|
||||
/// @return The current operating mode setting.
|
||||
uint8_t IRHaierAC176::getMode(void) const {
|
||||
return _.Mode;
|
||||
}
|
||||
uint8_t IRHaierAC176::getMode(void) const { return _.Mode; }
|
||||
|
||||
/// Set the temperature.
|
||||
/// @param[in] celsius The temperature in degrees celsius.
|
||||
@@ -668,9 +671,7 @@ void IRHaierAC176::setTemp(const uint8_t celsius) {
|
||||
|
||||
/// Get the current temperature setting.
|
||||
/// @return The current setting for temp. in degrees celsius.
|
||||
uint8_t IRHaierAC176::getTemp(void) const {
|
||||
return _.Temp + kHaierAcMinTemp;
|
||||
}
|
||||
uint8_t IRHaierAC176::getTemp(void) const { return _.Temp + kHaierAcMinTemp; }
|
||||
|
||||
/// Set the Health (filter) setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
@@ -681,15 +682,11 @@ void IRHaierAC176::setHealth(const bool on) {
|
||||
|
||||
/// Get the Health (filter) setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRHaierAC176::getHealth(void) const {
|
||||
return _.Health;
|
||||
}
|
||||
bool IRHaierAC176::getHealth(void) const { return _.Health; }
|
||||
|
||||
/// Get the value of the current power setting.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRHaierAC176::getPower(void) const {
|
||||
return _.Power;
|
||||
}
|
||||
bool IRHaierAC176::getPower(void) const { return _.Power; }
|
||||
|
||||
/// Change the power setting.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
@@ -706,9 +703,7 @@ void IRHaierAC176::off(void) { setPower(false); }
|
||||
|
||||
/// Get the Sleep setting of the A/C.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRHaierAC176::getSleep(void) const {
|
||||
return _.Sleep;
|
||||
}
|
||||
bool IRHaierAC176::getSleep(void) const { return _.Sleep; }
|
||||
|
||||
/// Set the Sleep setting of the A/C.
|
||||
/// @param[in] on true, the setting is on. false, the setting is off.
|
||||
@@ -718,30 +713,42 @@ void IRHaierAC176::setSleep(const bool on) {
|
||||
}
|
||||
|
||||
/// Get the Turbo setting of the A/C.
|
||||
/// @return The current turbo speed setting.
|
||||
uint8_t IRHaierAC176::getTurbo(void) const {
|
||||
return _.Turbo;
|
||||
}
|
||||
/// @return The current turbo setting.
|
||||
bool IRHaierAC176::getTurbo(void) const { return _.Turbo; }
|
||||
|
||||
/// Set the Turbo setting of the A/C.
|
||||
/// @param[in] speed The desired turbo speed setting.
|
||||
/// @note Valid speeds are kHaierAcYrw02TurboOff, kHaierAcYrw02TurboLow, &
|
||||
/// kHaierAcYrw02TurboHigh.
|
||||
void IRHaierAC176::setTurbo(uint8_t speed) {
|
||||
switch (speed) {
|
||||
case kHaierAcYrw02TurboOff:
|
||||
case kHaierAcYrw02TurboLow:
|
||||
case kHaierAcYrw02TurboHigh:
|
||||
_.Turbo = speed;
|
||||
/// @param[in] on The desired turbo setting.
|
||||
/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode
|
||||
void IRHaierAC176::setTurbo(const bool on) {
|
||||
switch (getMode()) {
|
||||
case kHaierAcYrw02Cool:
|
||||
case kHaierAcYrw02Heat:
|
||||
_.Turbo = on;
|
||||
_.Button = kHaierAcYrw02ButtonTurbo;
|
||||
if (on) _.Quiet = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the Quiet setting of the A/C.
|
||||
/// @return The current Quiet setting.
|
||||
bool IRHaierAC176::getQuiet(void) const { return _.Quiet; }
|
||||
|
||||
/// Set the Quiet setting of the A/C.
|
||||
/// @param[in] on The desired Quiet setting.
|
||||
/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode
|
||||
void IRHaierAC176::setQuiet(const bool on) {
|
||||
switch (getMode()) {
|
||||
case kHaierAcYrw02Cool:
|
||||
case kHaierAcYrw02Heat:
|
||||
_.Quiet = on;
|
||||
_.Button = kHaierAcYrw02ButtonTurbo;
|
||||
if (on) _.Turbo = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current fan speed setting.
|
||||
/// @return The current fan speed.
|
||||
uint8_t IRHaierAC176::getFan(void) const {
|
||||
return _.Fan;
|
||||
}
|
||||
uint8_t IRHaierAC176::getFan(void) const { return _.Fan; }
|
||||
|
||||
/// Set the speed of the fan.
|
||||
/// @param[in] speed The desired setting.
|
||||
@@ -948,20 +955,6 @@ stdAc::swingv_t IRHaierAC176::toCommonSwingV(const uint8_t pos) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the Turbo setting of the A/C into native turbo setting.
|
||||
/// @param[in] speed The enum to be converted.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRHaierAC176::toCommonTurbo(const uint8_t speed) {
|
||||
return speed == kHaierAcYrw02TurboHigh;
|
||||
}
|
||||
|
||||
/// Convert the Turbo setting of the A/C into native quiet setting.
|
||||
/// @param[in] speed The enum to be converted.
|
||||
/// @return true, the setting is on. false, the setting is off.
|
||||
bool IRHaierAC176::toCommonQuiet(const uint8_t speed) {
|
||||
return speed == kHaierAcYrw02TurboLow;
|
||||
}
|
||||
|
||||
/// Convert the current internal state into its stdAc::state_t equivalent.
|
||||
/// @return The stdAc equivalent of the native settings.
|
||||
stdAc::state_t IRHaierAC176::toCommon(void) const {
|
||||
@@ -976,8 +969,8 @@ stdAc::state_t IRHaierAC176::toCommon(void) const {
|
||||
result.swingv = toCommonSwingV(_.Swing);
|
||||
result.filter = _.Health;
|
||||
result.sleep = _.Sleep ? 0 : -1;
|
||||
result.quiet = toCommonQuiet(_.Turbo);
|
||||
result.turbo = toCommonTurbo(_.Turbo);
|
||||
result.turbo = _.Turbo;
|
||||
result.quiet = _.Quiet;
|
||||
// Not supported.
|
||||
result.swingh = stdAc::swingh_t::kOff;
|
||||
result.econo = false;
|
||||
@@ -1036,22 +1029,8 @@ String IRHaierAC176::toString(void) const {
|
||||
result += addFanToString(_.Fan, kHaierAcYrw02FanHigh, kHaierAcYrw02FanLow,
|
||||
kHaierAcYrw02FanAuto, kHaierAcYrw02FanAuto,
|
||||
kHaierAcYrw02FanMed);
|
||||
result += addIntToString(_.Turbo, kTurboStr);
|
||||
result += kSpaceLBraceStr;
|
||||
switch (_.Turbo) {
|
||||
case kHaierAcYrw02TurboOff:
|
||||
result += kOffStr;
|
||||
break;
|
||||
case kHaierAcYrw02TurboLow:
|
||||
result += kLowStr;
|
||||
break;
|
||||
case kHaierAcYrw02TurboHigh:
|
||||
result += kHighStr;
|
||||
break;
|
||||
default:
|
||||
result += kUnknownStr;
|
||||
}
|
||||
result += ')';
|
||||
result += addBoolToString(_.Turbo, kTurboStr);
|
||||
result += addBoolToString(_.Quiet, kQuietStr);
|
||||
result += addIntToString(_.Swing, kSwingStr);
|
||||
result += kSpaceLBraceStr;
|
||||
switch (_.Swing) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2018 crankyoldgit
|
||||
// Copyright 2018-2021 crankyoldgit
|
||||
/// @file
|
||||
/// @brief Support for Haier A/C protocols.
|
||||
/// The specifics of reverse engineering the protocols details:
|
||||
@@ -133,51 +133,6 @@ const uint8_t kHaierAcSleepBit = 0b01000000;
|
||||
#define HAIER_AC_FAN_MED kHaierAcFanMed
|
||||
#define HAIER_AC_FAN_HIGH kHaierAcFanHigh
|
||||
|
||||
/// Native representation of a Haier YRW02 A/C message.
|
||||
union HaierYRW02Protocol{
|
||||
uint8_t raw[kHaierACYRW02StateLength]; ///< The state in native form
|
||||
struct {
|
||||
// Byte 0
|
||||
uint8_t Prefix;
|
||||
// Byte 1
|
||||
uint8_t Swing:4;
|
||||
uint8_t Temp :4; // 16C~30C
|
||||
// Byte 2
|
||||
uint8_t :8;
|
||||
// Byte 3
|
||||
uint8_t :1;
|
||||
uint8_t Health:1;
|
||||
uint8_t :6;
|
||||
// Byte 4
|
||||
uint8_t :6;
|
||||
uint8_t Power:1;
|
||||
uint8_t :1;
|
||||
// Byte 5
|
||||
uint8_t :5;
|
||||
uint8_t Fan:3;
|
||||
// Byte 6
|
||||
uint8_t :6;
|
||||
uint8_t Turbo:2;
|
||||
// Byte 7
|
||||
uint8_t :5;
|
||||
uint8_t Mode:3;
|
||||
// Byte 8
|
||||
uint8_t :7;
|
||||
uint8_t Sleep:1;
|
||||
// Byte 9
|
||||
uint8_t :8;
|
||||
// Byte 10
|
||||
uint8_t :8;
|
||||
// Byte 11
|
||||
uint8_t :8;
|
||||
// Byte 12
|
||||
uint8_t Button:4;
|
||||
uint8_t :4;
|
||||
// Byte 13
|
||||
uint8_t Sum;
|
||||
};
|
||||
};
|
||||
|
||||
const uint8_t kHaierAcYrw02Prefix = 0xA6;
|
||||
const uint8_t kHaierAc176Prefix = 0xB7;
|
||||
|
||||
@@ -193,10 +148,6 @@ const uint8_t kHaierAcYrw02FanMed = 0b010;
|
||||
const uint8_t kHaierAcYrw02FanLow = 0b011;
|
||||
const uint8_t kHaierAcYrw02FanAuto = 0b101; // HAIER_AC176 uses `0` in Fan2
|
||||
|
||||
const uint8_t kHaierAcYrw02TurboOff = 0x0;
|
||||
const uint8_t kHaierAcYrw02TurboHigh = 0x1;
|
||||
const uint8_t kHaierAcYrw02TurboLow = 0x2;
|
||||
|
||||
const uint8_t kHaierAcYrw02Auto = 0b000; // 0
|
||||
const uint8_t kHaierAcYrw02Cool = 0b001; // 1
|
||||
const uint8_t kHaierAcYrw02Dry = 0b010; // 2
|
||||
@@ -244,7 +195,8 @@ union HaierAc176Protocol{
|
||||
uint8_t Fan :3;
|
||||
// Byte 6
|
||||
uint8_t OffTimerMins:6;
|
||||
uint8_t Turbo :2;
|
||||
uint8_t Turbo :1;
|
||||
uint8_t Quiet :1;
|
||||
// Byte 7
|
||||
uint8_t OnTimerHrs :5;
|
||||
uint8_t Mode :3;
|
||||
@@ -295,8 +247,6 @@ union HaierAc176Protocol{
|
||||
#define HAIER_AC_YRW02_FAN_LOW kHaierAcYrw02FanLow
|
||||
#define HAIER_AC_YRW02_FAN_AUTO kHaierAcYrw02FanAuto
|
||||
#define HAIER_AC_YRW02_TURBO_OFF kHaierAcYrw02TurboOff
|
||||
#define HAIER_AC_YRW02_TURBO_HIGH kHaierAcYrw02TurboHigh
|
||||
#define HAIER_AC_YRW02_TURBO_LOW kHaierAcYrw02TurboLow
|
||||
#define HAIER_AC_YRW02_AUTO kHaierAcYrw02Auto
|
||||
#define HAIER_AC_YRW02_COOL kHaierAcYrw02Cool
|
||||
#define HAIER_AC_YRW02_DRY kHaierAcYrw02Dry
|
||||
@@ -422,8 +372,10 @@ class IRHaierAC176 {
|
||||
bool getHealth(void) const;
|
||||
void setHealth(const bool on);
|
||||
|
||||
uint8_t getTurbo(void) const;
|
||||
void setTurbo(const uint8_t speed);
|
||||
bool getTurbo(void) const;
|
||||
void setTurbo(const bool on);
|
||||
bool getQuiet(void) const;
|
||||
void setQuiet(const bool on);
|
||||
|
||||
uint8_t getSwing(void) const;
|
||||
void setSwing(const uint8_t pos);
|
||||
|
||||
@@ -789,18 +789,19 @@ TEST(TestIRac, Haier176) {
|
||||
IRrecv capture(kGpioUnused);
|
||||
const char expected[] =
|
||||
"Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 23C, "
|
||||
"Fan: 2 (Medium), Turbo: 1 (High), Swing: 1 (Highest), Sleep: On, "
|
||||
"Fan: 2 (Medium), Turbo: On, Quiet: Off, Swing: 1 (Highest), Sleep: On, "
|
||||
"Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off";
|
||||
ac.begin();
|
||||
irac.haier176(&ac,
|
||||
true, // Power
|
||||
stdAc::opmode_t::kCool, // Mode
|
||||
23, // Celsius
|
||||
stdAc::fanspeed_t::kMedium, // Fan speed
|
||||
stdAc::swingv_t::kHigh, // Vertical swing
|
||||
true, // Turbo
|
||||
true, // Filter
|
||||
8 * 60 + 0); // Sleep time
|
||||
true, // Power
|
||||
stdAc::opmode_t::kCool, // Mode
|
||||
23, // Celsius
|
||||
stdAc::fanspeed_t::kMedium, // Fan speed
|
||||
stdAc::swingv_t::kHigh, // Vertical swing
|
||||
true, // Turbo
|
||||
false, // Quiet
|
||||
true, // Filter
|
||||
8 * 60 + 0); // Sleep time
|
||||
ASSERT_EQ(expected, ac.toString());
|
||||
ac._irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
|
||||
@@ -817,19 +818,20 @@ TEST(TestIRac, HaierYrwo2) {
|
||||
IRrecv capture(kGpioUnused);
|
||||
char expected[] =
|
||||
"Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 23C, "
|
||||
"Fan: 2 (Medium), Turbo: 1 (High), Swing: 1 (Highest), Sleep: On, "
|
||||
"Fan: 2 (Medium), Turbo: Off, Quiet: On, Swing: 1 (Highest), Sleep: On, "
|
||||
"Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off";
|
||||
|
||||
ac.begin();
|
||||
irac.haierYrwo2(&ac,
|
||||
true, // Power
|
||||
stdAc::opmode_t::kCool, // Mode
|
||||
23, // Celsius
|
||||
stdAc::fanspeed_t::kMedium, // Fan speed
|
||||
stdAc::swingv_t::kHigh, // Vertical swing
|
||||
true, // Turbo
|
||||
true, // Filter
|
||||
8 * 60 + 0); // Sleep time
|
||||
true, // Power
|
||||
stdAc::opmode_t::kCool, // Mode
|
||||
23, // Celsius
|
||||
stdAc::fanspeed_t::kMedium, // Fan speed
|
||||
stdAc::swingv_t::kHigh, // Vertical swing
|
||||
false, // Turbo
|
||||
true, // Quiet
|
||||
true, // Filter
|
||||
8 * 60 + 0); // Sleep time
|
||||
ASSERT_EQ(expected, ac.toString());
|
||||
ac._irsend.makeDecodeResult();
|
||||
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user