Skip to content

Commit

Permalink
GREE: Add model support for YX1FSF/Soleus Air Windown A/C (#1823)
Browse files Browse the repository at this point in the history
* Allow detecting/setting new model.
* Allow setting Econo(Energy Saver) operation mode.
* Update supported model info.
* Add unit tests to cover new changes.

Fixes #1821
  • Loading branch information
crankyoldgit authored Jun 16, 2022
1 parent 4888fd7 commit f706f99
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 17 deletions.
2 changes: 2 additions & 0 deletions src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3472,6 +3472,8 @@ int16_t IRac::strToModel(const char *str, const int16_t def) {
return gree_ac_remote_model_t::YAW1F;
} else if (!STRCASECMP(str, kYbofbStr)) {
return gree_ac_remote_model_t::YBOFB;
} else if (!STRCASECMP(str, kYx1fsfStr)) {
return gree_ac_remote_model_t::YX1FSF;
// Haier models
} else if (!STRCASECMP(str, kV9014557AStr)) {
return haier_ac176_remote_model_t::V9014557_A;
Expand Down
4 changes: 3 additions & 1 deletion src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ enum fujitsu_ac_remote_model_t {
/// Gree A/C model numbers
enum gree_ac_remote_model_t {
YAW1F = 1, // (1) Ultimate, EKOKAI, RusClimate (Default)
YBOFB, // (2) Green, YBOFB2, YAPOF3
YBOFB, // (2) Green, YBOFB2, YAPOF3
YX1FSF, // (3) Soleus Air window unit (Similar to YAW1F, but with an
// Operation mode of Energy Saver (Econo))
};

/// HAIER_AC176 A/C model numbers
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ IRTEXT_CONST_STRING(kBitsStr, D_STR_BITS); ///< "Bits"
// Model Names
IRTEXT_CONST_STRING(kYaw1fStr, D_STR_YAW1F); ///< "YAW1F"
IRTEXT_CONST_STRING(kYbofbStr, D_STR_YBOFB); ///< "YBOFB"
IRTEXT_CONST_STRING(kYx1fsfStr, D_STR_YX1FSF); ///< "YX1FSF"
IRTEXT_CONST_STRING(kV9014557AStr, D_STR_V9014557_A); ///< "V9014557-A"
IRTEXT_CONST_STRING(kV9014557BStr, D_STR_V9014557_B); ///< "V9014557-B"
IRTEXT_CONST_STRING(kRlt0541htaaStr, D_STR_RLT0541HTA_A); ///< "R-LT0541-HTA-A"
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ extern IRTEXT_CONST_PTR(kXFanStr);
extern IRTEXT_CONST_PTR(kYaw1fStr);
extern IRTEXT_CONST_PTR(kYbofbStr);
extern IRTEXT_CONST_PTR(kYesStr);
extern IRTEXT_CONST_PTR(kYx1fsfStr);
extern IRTEXT_CONST_PTR(kZoneFollowStr);
extern IRTEXT_CONST_PTR(kAllProtocolNamesStr);

Expand Down
7 changes: 4 additions & 3 deletions src/IRutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,10 @@ namespace irutils {
break;
case decode_type_t::GREE:
switch (model) {
case gree_ac_remote_model_t::YAW1F: return kYaw1fStr;
case gree_ac_remote_model_t::YBOFB: return kYbofbStr;
default: return kUnknownStr;
case gree_ac_remote_model_t::YAW1F: return kYaw1fStr;
case gree_ac_remote_model_t::YBOFB: return kYbofbStr;
case gree_ac_remote_model_t::YX1FSF: return kYx1fsfStr;
default: return kUnknownStr;
}
break;
case decode_type_t::HAIER_AC176:
Expand Down
28 changes: 22 additions & 6 deletions src/ir_Gree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ void IRGreeAC::setRaw(const uint8_t new_code[]) {
else
_model = gree_ac_remote_model_t::YBOFB;
}
if (_.Mode == kGreeEcono) _model = gree_ac_remote_model_t::YX1FSF;
}

/// Calculate and set the checksum values for the internal state.
Expand All @@ -186,7 +187,8 @@ bool IRGreeAC::validChecksum(const uint8_t state[], const uint16_t length) {
void IRGreeAC::setModel(const gree_ac_remote_model_t model) {
switch (model) {
case gree_ac_remote_model_t::YAW1F:
case gree_ac_remote_model_t::YBOFB: _model = model; break;
case gree_ac_remote_model_t::YBOFB:
case gree_ac_remote_model_t::YX1FSF: _model = model; break;
default: _model = gree_ac_remote_model_t::YAW1F;
}
}
Expand Down Expand Up @@ -291,6 +293,7 @@ void IRGreeAC::setMode(const uint8_t new_mode) {
case kGreeDry: setFan(1); break;
case kGreeCool:
case kGreeFan:
case kGreeEcono:
case kGreeHeat: break;
// If we get an unexpected mode, default to AUTO.
default: mode = kGreeAuto;
Expand Down Expand Up @@ -352,11 +355,17 @@ bool IRGreeAC::getTurbo(void) const { return _.Turbo; }

/// Set the Econo setting of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRGreeAC::setEcono(const bool on) { _.Econo = on; }
void IRGreeAC::setEcono(const bool on) {
_.Econo = on;
if (on && getModel() == gree_ac_remote_model_t::YX1FSF)
setMode(kGreeEcono);
}

/// Get the Econo setting of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRGreeAC::getEcono(void) const { return _.Econo; }
bool IRGreeAC::getEcono(void) const {
return _.Econo || getMode() == kGreeEcono;
}

/// Set the Vertical Swing mode of the A/C.
/// @param[in] automatic Do we use the automatic setting?
Expand Down Expand Up @@ -589,7 +598,7 @@ stdAc::state_t IRGreeAC::toCommon(void) {
result.swingv = toCommonSwingV(_.SwingV);
result.swingh = toCommonSwingH(_.SwingH);
result.turbo = _.Turbo;
result.econo = _.Econo;
result.econo = getEcono();
result.light = _.Light;
result.clean = _.Xfan;
result.sleep = _.Sleep ? 0 : -1;
Expand All @@ -608,8 +617,15 @@ String IRGreeAC::toString(void) {
result.reserve(220); // Reserve some heap for the string to reduce fragging.
result += addModelToString(decode_type_t::GREE, _model, false);
result += addBoolToString(_.Power, kPowerStr);
result += addModeToString(_.Mode, kGreeAuto, kGreeCool, kGreeHeat,
kGreeDry, kGreeFan);
if (_model == gree_ac_remote_model_t::YX1FSF && _.Mode == kGreeEcono) {
result += addIntToString(_.Mode, kModeStr);
result += kSpaceLBraceStr;
result += kEconoStr;
result += ')';
} else {
result += addModeToString(_.Mode, kGreeAuto, kGreeCool, kGreeHeat,
kGreeDry, kGreeFan);
}
result += addTempToString(getTemp(), !_.UseFahrenheit);
result += addFanToString(_.Fan, kGreeFanMax, kGreeFanMin, kGreeFanAuto,
kGreeFanAuto, kGreeFanMed);
Expand Down
16 changes: 10 additions & 6 deletions src/ir_Gree.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright 2016 David Conran
// Copyright 2016-2022 David Conran

/// @file
/// @brief Support for Gree A/C protocols.
/// @see https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1508
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1821

// Supports:
// Brand: Ultimate, Model: Heat Pump
Expand All @@ -15,6 +16,7 @@
// Brand: Gree, Model: YAA1FBF remote
// Brand: Gree, Model: YB1F2F remote
// Brand: Gree, Model: YAN1F1 remote
// Brand: Gree, Model: YX1F2F remote (YX1FSF)
// Brand: Gree, Model: VIR09HP115V1AH A/C
// Brand: Gree, Model: VIR12HP230V1AH A/C
// Brand: Amana, Model: PBC093G00CC A/C
Expand All @@ -23,6 +25,7 @@
// Brand: Cooper & Hunter, Model: CH-S09FTXG A/C
// Brand: Vailland, Model: YACIFB remote
// Brand: Vailland, Model: VAI5-035WNI A/C
// Brand: Soleus Air, Model: window A/C (YX1FSF)

#ifndef IR_GREE_H_
#define IR_GREE_H_
Expand Down Expand Up @@ -86,11 +89,12 @@ union GreeProtocol{

// Constants

const uint8_t kGreeAuto = 0;
const uint8_t kGreeCool = 1;
const uint8_t kGreeDry = 2;
const uint8_t kGreeFan = 3;
const uint8_t kGreeHeat = 4;
const uint8_t kGreeAuto = 0;
const uint8_t kGreeCool = 1;
const uint8_t kGreeDry = 2;
const uint8_t kGreeFan = 3;
const uint8_t kGreeHeat = 4;
const uint8_t kGreeEcono = 5;

const uint8_t kGreeFanAuto = 0;
const uint8_t kGreeFanMin = 1;
Expand Down
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_YBOFB
#define D_STR_YBOFB "YBOFB"
#endif // D_STR_YBOFB
#ifndef D_STR_YX1FSF
#define D_STR_YX1FSF "YX1FSF"
#endif // D_STR_YX1FSF
#ifndef D_STR_V9014557_A
#define D_STR_V9014557_A "V9014557-A"
#endif // D_STR_V9014557_A
Expand Down
42 changes: 41 additions & 1 deletion test/ir_Gree_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ TEST(TestGreeClass, OperatingMode) {
ac.setMode(kGreeHeat);
EXPECT_EQ(kGreeHeat, ac.getMode());

ac.setMode(kGreeEcono);
EXPECT_EQ(kGreeEcono, ac.getMode());

ASSERT_NE(kGreeFanMax, 1);
ac.setFan(kGreeFanMax);
ac.setMode(kGreeDry); // Dry should lock the fan to speed 1.
Expand All @@ -337,7 +340,7 @@ TEST(TestGreeClass, OperatingMode) {
ac.setMode(kGreeFan);
EXPECT_EQ(kGreeFan, ac.getMode());

ac.setMode(kGreeHeat + 1);
ac.setMode(kGreeEcono + 1);
EXPECT_EQ(kGreeAuto, ac.getMode());

ac.setMode(255);
Expand Down Expand Up @@ -798,3 +801,40 @@ TEST(TestGreeClass, DisplayTempSource) {
ac.setRaw(state);
EXPECT_EQ(2, ac.getDisplayTempSource());
}

TEST(TestUtils, Housekeeping) {
ASSERT_EQ("GREE", typeToString(decode_type_t::GREE));
ASSERT_EQ(decode_type_t::GREE, strToDecodeType("GREE"));
ASSERT_TRUE(hasACState(decode_type_t::GREE));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::GREE));
ASSERT_EQ(kGreeBits, IRsend::defaultBits(decode_type_t::GREE));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::GREE));
ASSERT_EQ(gree_ac_remote_model_t::YAW1F, IRac::strToModel("YAW1F"));
ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE,
gree_ac_remote_model_t::YAW1F), "YAW1F");
ASSERT_EQ(gree_ac_remote_model_t::YBOFB, IRac::strToModel("YBOFB"));
ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE,
gree_ac_remote_model_t::YBOFB), "YBOFB");
ASSERT_EQ(gree_ac_remote_model_t::YX1FSF, IRac::strToModel("YX1FSF"));
ASSERT_EQ(irutils::modelToStr(decode_type_t::GREE,
gree_ac_remote_model_t::YX1FSF), "YX1FSF");
}

TEST(TestGreeClass, Issue1821EnergySaver) {
IRGreeAC ac(kGpioUnused);
ac.begin();

// https://github.com/crankyoldgit/IRremoteESP8266/issues/1821#issue-1271458457
const uint8_t energy[8] = {0x1D, 0x09, 0x60, 0x58, 0x00, 0x20, 0x00, 0xA0};

ac.setRaw(energy);
EXPECT_EQ(kGreeEcono, ac.getMode());
EXPECT_TRUE(ac.getEcono());
EXPECT_EQ(gree_ac_remote_model_t::YX1FSF, ac.getModel());
EXPECT_EQ(
"Model: 3 (YX1FSF), Power: On, Mode: 5 (Econo), Temp: 77F, Fan: 1 (Low), "
"Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, "
"Sleep: Off, Swing(V) Mode: Manual, Swing(V): 0 (Last), "
"Swing(H): 0 (Off), Timer: Off, Display Temp: 0 (Off)",
ac.toString());
}

0 comments on commit f706f99

Please sign in to comment.