Skip to content

Commit

Permalink
HAIER_AC160: Experimental Light support.
Browse files Browse the repository at this point in the history
* Report the button press code.
* Make a guess at how the setting works.
  - i.e. The button code toggles the light on and off.
* Adjust `toCommon()` to handle previous state.
* Handle the light toggles appropriately.
* Add a unit test case.

For #1804
  • Loading branch information
crankyoldgit committed Aug 11, 2022
1 parent e8c6a4f commit 1a26423
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 7 deletions.
14 changes: 11 additions & 3 deletions src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,13 +1215,16 @@ void IRac::haier(IRHaierAC *ac,
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] quiet Run the device in quiet mode.
/// @param[in] clean Turn on the clean mode.
/// @param[in] light Turn on the LED/Display mode.
/// @param[in] prevlight Previous LED/Display mode.
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
void IRac::haier160(IRHaierAC160 *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 quiet, const bool clean,
const bool light, const bool prevlight,
const int16_t sleep) {
ac->begin();
// No Model setting available.
Expand All @@ -1233,13 +1236,14 @@ void IRac::haier160(IRHaierAC160 *ac,
// No Horizontal Swing setting available.
ac->setQuiet(quiet);
ac->setTurbo(turbo);
// No Light setting available.
// No Filter setting available.
ac->setClean(clean);
// No Clean setting available.
// No Beep setting available.
ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off.
ac->setPower(on);
// Light needs to be sent last as the "button" value seems to control it.
ac->setLightToggle(light ^ prevlight);
ac->send();
}
#endif // SEND_HAIER_AC160
Expand Down Expand Up @@ -2808,6 +2812,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_HAIER_AC160)
const bool prev_light = (prev != NULL) ? prev->light : !send.light;
#endif // (SEND_HAIER_AC160)
#if SEND_MIDEA
const bool prev_quiet = (prev != NULL) ? prev->quiet : !send.quiet;
#endif // SEND_MIDEA
Expand Down Expand Up @@ -3027,7 +3034,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
{
IRHaierAC160 ac(_pin, _inverted, _modulation);
haier160(&ac, send.power, send.mode, send.celsius, send.degrees,
send.fanspeed, send.swingv, send.turbo, send.clean, send.sleep);
send.fanspeed, send.swingv, send.turbo, send.clean,
send.light, prev_light, send.sleep);
break;
}
#endif // SEND_HAIER_AC160
Expand Down Expand Up @@ -4415,7 +4423,7 @@ namespace IRAcUtils {
case decode_type_t::HAIER_AC160: {
IRHaierAC160 ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
*result = ac.toCommon(prev);
break;
}
#endif // DECODE_HAIER_AC160
Expand Down
3 changes: 2 additions & 1 deletion src/IRac.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ void electra(IRElectraAc *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 quiet, const bool filter,
const bool turbo, const bool quiet, const bool clean,
const bool light, const bool prevlight,
const int16_t sleep = -1);
#endif // SEND_HAIER_AC160
#if SEND_HAIER_AC176
Expand Down
31 changes: 29 additions & 2 deletions src/ir_Haier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1751,6 +1751,20 @@ void IRHaierAC160::setQuiet(const bool on) {
}
}

/// Get the value of the current Light toggle setting.
/// @return true, the setting is on. false, the setting is off.
/// @note This setting seems to be controlled just by the button setting.
bool IRHaierAC160::getLightToggle(void) const {
return _.Button == kHaierAc160ButtonLight;
}

/// Set the Light Toggle setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
/// @note This setting seems to be controlled just by the button setting.
void IRHaierAC160::setLightToggle(const bool on) {
_.Button = on ? kHaierAc160ButtonLight : kHaierAcYrw02ButtonPower;
}

/// Get the current fan speed setting.
/// @return The current fan speed.
uint8_t IRHaierAC160::getFan(void) const { return _.Fan; }
Expand Down Expand Up @@ -1970,9 +1984,19 @@ stdAc::swingv_t IRHaierAC160::toCommonSwingV(const uint8_t pos) {
}

/// Convert the current internal state into its stdAc::state_t equivalent.
/// @param[in] prev Ptr to the previous state if required.
/// @return The stdAc equivalent of the native settings.
stdAc::state_t IRHaierAC160::toCommon(void) const {
stdAc::state_t IRHaierAC160::toCommon(const stdAc::state_t *prev) const {
stdAc::state_t result{};
// Start with the previous state if given it.
if (prev != NULL) {
result = *prev;
} else {
// Set defaults for non-zero values that are not implicitly set for when
// there is no previous state.
// e.g. Any setting that toggles should probably go here.
result.light = false;
}
result.protocol = decode_type_t::HAIER_AC160;
result.power = _.Power;
result.mode = toCommonMode(_.Mode);
Expand All @@ -1985,11 +2009,11 @@ stdAc::state_t IRHaierAC160::toCommon(void) const {
result.turbo = _.Turbo;
result.quiet = _.Quiet;
result.clean = _.Clean && _.Clean2;
result.light ^= getLightToggle();
// Not supported.
result.filter = false;
result.model = -1;
result.econo = false;
result.light = false;
result.beep = true;
result.clock = -1;
return result;
Expand Down Expand Up @@ -2044,6 +2068,9 @@ String IRHaierAC160::toString(void) const {
case kHaierAc160ButtonClean:
result += kCleanStr;
break;
case kHaierAc160ButtonLight:
result += kLightStr;
break;
case kHaierAcYrw02ButtonCFAB:
result += kCelsiusFahrenheitStr;
break;
Expand Down
5 changes: 4 additions & 1 deletion src/ir_Haier.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ const uint8_t kHaierAcYrw02ButtonTurbo = 0b01000;
const uint8_t kHaierAcYrw02ButtonSleep = 0b01011;
const uint8_t kHaierAcYrw02ButtonTimer = 0b10000;
const uint8_t kHaierAcYrw02ButtonLock = 0b10100;
const uint8_t kHaierAc160ButtonLight = 0b10101;
const uint8_t kHaierAc160ButtonClean = 0b11001;
const uint8_t kHaierAcYrw02ButtonCFAB = 0b11010;

Expand Down Expand Up @@ -596,6 +597,8 @@ class IRHaierAC160 {
void setSleep(const bool on);
bool getClean(void) const;
void setClean(const bool on);
bool getLightToggle(void) const;
void setLightToggle(const bool on);

bool getTurbo(void) const;
void setTurbo(const bool on);
Expand Down Expand Up @@ -627,7 +630,7 @@ class IRHaierAC160 {
static stdAc::swingv_t toCommonSwingV(const uint8_t pos);
static bool toCommonTurbo(const uint8_t speed);
static bool toCommonQuiet(const uint8_t speed);
stdAc::state_t toCommon(void) const;
stdAc::state_t toCommon(const stdAc::state_t *prev = NULL) const;
String toString(void) const;
#ifndef UNIT_TEST

Expand Down
2 changes: 2 additions & 0 deletions test/IRac_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,8 @@ TEST(TestIRac, Haier160) {
true, // Turbo
false, // Quiet
true, // Clean
true, // Light
true, // Light (prev)
8 * 60 + 0); // Sleep time
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
Expand Down
31 changes: 31 additions & 0 deletions test/ir_Haier_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1946,3 +1946,34 @@ TEST(TestHaierAC160Class, SwingV) {
EXPECT_EQ(kHaierAc160SwingVLow, ac.getSwingV());
EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton());
}

TEST(TestHaierAC160Class, Light) {
IRHaierAC160 ac(kGpioUnused);
ac.begin();

ac.setLightToggle(true);
EXPECT_TRUE(ac.getLightToggle());
EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton());

ac.setButton(kHaierAcYrw02ButtonTempUp);
ac.setLightToggle(false);
EXPECT_FALSE(ac.getLightToggle());
EXPECT_NE(kHaierAc160ButtonLight, ac.getButton());

ac.setLightToggle(true);
EXPECT_TRUE(ac.getLightToggle());
EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton());

const uint8_t light_press[kHaierAC160StateLength] = {
0xA6, 0xAC, 0x00, 0x00, 0x40, 0x60, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x15, 0x27, 0xB5, 0x00, 0x60, 0x00, 0x00, 0x15};
ac.setRaw(light_press);
EXPECT_TRUE(ac.getLightToggle());
EXPECT_EQ(kHaierAc160ButtonLight, ac.getButton());
EXPECT_EQ(
"Power: On, Button: 21 (Light), Mode: 1 (Cool), Temp: 26C, "
"Fan: 3 (Low), Turbo: Off, Quiet: Off, Swing(V): 12 (Auto), "
"Sleep: Off, Clean: Off, Timer Mode: 0 (N/A), "
"On Timer: Off, Off Timer: Off, Lock: Off",
ac.toString());
}

0 comments on commit 1a26423

Please sign in to comment.