diff --git a/src/IRsend.h b/src/IRsend.h index 06d168375..3391a4e6f 100644 --- a/src/IRsend.h +++ b/src/IRsend.h @@ -118,7 +118,8 @@ struct state_t { /// Fujitsu A/C model numbers enum fujitsu_ac_remote_model_t { - ARRAH2E = 1, ///< (1) AR-RAH2E, AR-RAC1E, AR-RAE1E, AR-RCE1E (Default) + ARRAH2E = 1, ///< (1) AR-RAH2E, AR-RAC1E, AR-RAE1E, AR-RCE1E, AR-RAH2U, + ///< AR-REG1U (Default) ///< Warning: Use on incorrect models can cause the A/C to lock ///< up, requring the A/C to be physically powered off to fix. ///< e.g. AR-RAH1U may lock up with a Swing command. diff --git a/src/ir_Fujitsu.cpp b/src/ir_Fujitsu.cpp index 1b0bfab18..0c2a84331 100644 --- a/src/ir_Fujitsu.cpp +++ b/src/ir_Fujitsu.cpp @@ -184,7 +184,13 @@ void IRFujitsuAC::checkSum(void) { } } if (_model != fujitsu_ac_remote_model_t::ARRY4) { - if (_model != fujitsu_ac_remote_model_t::ARREW4E) _.Clean = false; + switch (_model) { + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREW4E: + break; + default: + _.Clean = false; + } _.Filter = false; } // Set the On/Off/Sleep timer Nr of mins. @@ -290,7 +296,8 @@ void IRFujitsuAC::buildFromState(const uint16_t length) { setCmd(kFujitsuAcCmdStayOn); // Currently the only way we know how to tell ARRAH2E & ARRY4 apart is if // either the raw Filter or Clean setting is on. - if (_model == fujitsu_ac_remote_model_t::ARRAH2E && (_.Filter || _.Clean)) + if (_model == fujitsu_ac_remote_model_t::ARRAH2E && (_.Filter || _.Clean) && + !get10CHeat()) setModel(fujitsu_ac_remote_model_t::ARRY4); if (_state_length == kFujitsuAcStateLength && _.OutsideQuiet) setModel(fujitsu_ac_remote_model_t::ARREB1E); @@ -578,7 +585,7 @@ void IRFujitsuAC::setFilter(const bool on) { bool IRFujitsuAC::getFilter(void) const { switch (_model) { case fujitsu_ac_remote_model_t::ARRY4: return _.Filter; - default: return false; + default: return false; } } @@ -587,6 +594,7 @@ bool IRFujitsuAC::getFilter(void) const { void IRFujitsuAC::set10CHeat(const bool on) { switch (_model) { // Only selected models support this. + case fujitsu_ac_remote_model_t::ARRAH2E: case fujitsu_ac_remote_model_t::ARREW4E: setClean(on); // 10C Heat uses the same bit as Clean if (on) { @@ -605,6 +613,7 @@ void IRFujitsuAC::set10CHeat(const bool on) { /// @return true, the setting is on. false, the setting is off. bool IRFujitsuAC::get10CHeat(void) const { switch (_model) { + case fujitsu_ac_remote_model_t::ARRAH2E: case fujitsu_ac_remote_model_t::ARREW4E: return (_.Clean && _.Power && _.Mode == kFujitsuAcModeFan && _.Fan == kFujitsuAcFanAuto && _.Swing == kFujitsuAcSwingOff); @@ -810,7 +819,11 @@ stdAc::state_t IRFujitsuAC::toCommon(const stdAc::state_t *prev) { if (isLongCode() || prev == NULL) { result.mode = toCommonMode(_.Mode); result.celsius = getCelsius(); - result.degrees = getTemp(); + { + const float minHeat = result.celsius ? kFujitsuAcMinHeat + : kFujitsuAcMinHeatF; + result.degrees = get10CHeat() ? minHeat : getTemp(); + } result.fanspeed = toCommonFanSpeed(_.Fan); uint8_t swing = _.Swing; switch (result.model) { @@ -848,7 +861,7 @@ stdAc::state_t IRFujitsuAC::toCommon(const stdAc::state_t *prev) { /// @return A human readable string. String IRFujitsuAC::toString(void) const { String result = ""; - result.reserve(100); // Reserve some heap for the string to reduce fragging. + result.reserve(180); // Reserve some heap for the string to reduce fragging. fujitsu_ac_remote_model_t model = _model; result += addModelToString(decode_type_t::FUJITSU_AC, model, false); result += addIntToString(_.Id, kIdStr); @@ -857,7 +870,12 @@ String IRFujitsuAC::toString(void) const { result += addModeToString(_.Mode, kFujitsuAcModeAuto, kFujitsuAcModeCool, kFujitsuAcModeHeat, kFujitsuAcModeDry, kFujitsuAcModeFan); - result += addTempFloatToString(getTemp(), getCelsius()); + { + const bool isCelsius = getCelsius(); + const float minHeat = isCelsius ? kFujitsuAcMinHeat : kFujitsuAcMinHeatF; + result += addTempFloatToString(get10CHeat() ? minHeat : getTemp(), + isCelsius); + } result += addFanToString(_.Fan, kFujitsuAcFanHigh, kFujitsuAcFanLow, kFujitsuAcFanAuto, kFujitsuAcFanQuiet, kFujitsuAcFanMed); @@ -874,8 +892,14 @@ String IRFujitsuAC::toString(void) const { result += addBoolToString(getFilter(), kFilterStr); // FALL THRU default: // e.g. ARREW4E - if (model == fujitsu_ac_remote_model_t::ARREW4E) - result += addBoolToString(get10CHeat(), k10CHeatStr); + switch (model) { + case fujitsu_ac_remote_model_t::ARRAH2E: + case fujitsu_ac_remote_model_t::ARREW4E: + result += addBoolToString(get10CHeat(), k10CHeatStr); + break; + default: + break; + } result += addIntToString(_.Swing, kSwingStr); result += kSpaceLBraceStr; switch (_.Swing) { diff --git a/src/ir_Fujitsu.h b/src/ir_Fujitsu.h index 09cb9ee83..370044b69 100644 --- a/src/ir_Fujitsu.h +++ b/src/ir_Fujitsu.h @@ -30,6 +30,7 @@ // Brand: Fujitsu, Model: AR-DL10 remote (ARDB1) // Brand: Fujitsu, Model: ASU30C1 A/C (ARDB1) // Brand: Fujitsu, Model: AR-RAH1U remote (ARREB1E) +// Brand: Fujitsu, Model: AR-RAH2U remote (ARRAH2E) // Brand: Fujitsu, Model: ASU12RLF A/C (ARREB1E) // Brand: Fujitsu, Model: AR-REW4E remote (ARREW4E) // Brand: Fujitsu, Model: ASYG09KETA-B A/C (ARREW4E) @@ -37,6 +38,7 @@ // Brand: Fujitsu, Model: ASTG09K A/C (ARREW4E) // Brand: Fujitsu, Model: ASTG18K A/C (ARREW4E) // Brand: Fujitsu, Model: AR-REW1E remote (ARREW4E) +// Brand: Fujitsu, Model: AR-REG1U remote (ARRAH2E) #ifndef IR_FUJITSU_H_ #define IR_FUJITSU_H_ @@ -128,9 +130,11 @@ const uint8_t kFujitsuAcFanMed = 0x02; const uint8_t kFujitsuAcFanLow = 0x03; const uint8_t kFujitsuAcFanQuiet = 0x04; +const float kFujitsuAcMinHeat = 10; // 10C const float kFujitsuAcMinTemp = 16; // 16C const float kFujitsuAcMaxTemp = 30; // 30C const uint8_t kFujitsuAcTempOffsetC = kFujitsuAcMinTemp; +const float kFujitsuAcMinHeatF = 50; // 50F const float kFujitsuAcMinTempF = 60; // 60F const float kFujitsuAcMaxTempF = 88; // 88F const uint8_t kFujitsuAcTempOffsetF = 44; diff --git a/test/IRac_test.cpp b/test/IRac_test.cpp index 1947ea532..30d9f7e4f 100644 --- a/test/IRac_test.cpp +++ b/test/IRac_test.cpp @@ -623,9 +623,9 @@ TEST(TestIRac, Fujitsu) { "Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, " "Fan: 2 (Medium), Command: N/A"; std::string arrah2e_expected = - "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, " - "Fan: 2 (Medium), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Sleep Timer: 03:00"; + "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, " + "Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00"; std::string arry4_expected = "Model: 5 (ARRY4), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, " "Fan: 2 (Medium), Clean: On, Filter: On, Swing: 0 (Off), Command: N/A"; @@ -658,20 +658,21 @@ TEST(TestIRac, Fujitsu) { ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); ac._irsend.reset(); + // Try to set the device to 10C Heat mode. irac.fujitsu(&ac, ARRAH2E, // Model true, // Power - stdAc::opmode_t::kCool, // Mode + stdAc::opmode_t::kFan, // Mode (Fan needed for 10C Heat) true, // Celsius - 19, // Degrees - stdAc::fanspeed_t::kMedium, // Fan speed - stdAc::swingv_t::kOff, // Vertical swing - stdAc::swingh_t::kOff, // Horizontal swing + 19, // Degrees (Ignored in 10C Heat) + stdAc::fanspeed_t::kAuto, // Fan speed (Auto needed for 10C) + stdAc::swingv_t::kOff, // Vertical swing (Ditto) + stdAc::swingh_t::kOff, // Horizontal swing (Ditto) false, // Quiet false, // Turbo (Powerful) false, // Econo true, // Filter - true, // Clean + true, // Clean (Needed for 10C Heat) 3 * 60); // Sleep ASSERT_EQ(arrah2e_expected, ac.toString()); ac._irsend.makeDecodeResult(); diff --git a/test/ir_Fujitsu_test.cpp b/test/ir_Fujitsu_test.cpp index 638ec6ee4..ed5ee59f1 100644 --- a/test/ir_Fujitsu_test.cpp +++ b/test/ir_Fujitsu_test.cpp @@ -22,7 +22,7 @@ TEST(TestIRFujitsuACClass, GetRawDefault) { EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, " + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off", ac.toString()); @@ -45,7 +45,7 @@ TEST(TestIRFujitsuACClass, GetRawTurnOff) { EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8); EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, " + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off", ac.toString()); @@ -66,8 +66,8 @@ TEST(TestIRFujitsuACClass, GetRawStepHoriz) { EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), " - "Command: Step Swing(H), Timer: Off", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 3 (Swing(V)+Swing(H)), Command: Step Swing(H), Timer: Off", ac.toString()); } @@ -80,8 +80,8 @@ TEST(TestIRFujitsuACClass, GetRawStepVert) { EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), " - "Command: Step Swing(V), Timer: Off", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 3 (Swing(V)+Swing(H)), Command: Step Swing(V), Timer: Off", ac.toString()); ac.setModel(ARDB1); @@ -106,7 +106,7 @@ TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) { 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB}; EXPECT_STATE_EQ(expected, ac.getRaw(), 16 * 8); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 25C, " - "Fan: 4 (Quiet), Clean: Off, Filter: Off, " + "Fan: 4 (Quiet), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 2 (Swing(H)), Command: N/A, Timer: Off", ac.toString()); } @@ -126,7 +126,7 @@ TEST(TestIRFujitsuACClass, GetRawWithFan) { EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 20C, " - "Fan: 2 (Medium), Clean: Off, Filter: Off, " + "Fan: 2 (Medium), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 2 (Swing(H)), Command: N/A, Timer: Off", ac.toString()); @@ -149,7 +149,7 @@ TEST(TestIRFujitsuACClass, SetRaw) { EXPECT_STATE_EQ(expected_default_arrah2e, ac.getRaw(), ac.getStateLength() * 8); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 1 (High), Clean: Off, Filter: Off, " + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 3 (Swing(V)+Swing(H)), Command: N/A, " "Timer: Off", ac.toString()); @@ -363,7 +363,7 @@ TEST(TestDecodeFujitsuAC, SyntheticLongMessages) { ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 18C, " - "Fan: 4 (Quiet), Clean: Off, Filter: Off, " + "Fan: 4 (Quiet), Clean: Off, Filter: Off, 10C Heat: Off, " "Swing: 1 (Swing(V)), Command: N/A, " "Timer: Off", ac.toString()); @@ -539,8 +539,8 @@ TEST(TestDecodeFujitsuAC, Issue414) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 4 (Heat), Temp: 24C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // Resend it using the state this time. @@ -719,7 +719,7 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) { // the option is set. Otheriwse they appear the same. EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " "Command: N/A, Timer: Off", ac.toString()); ac.setModel(fujitsu_ac_remote_model_t::ARREB1E); EXPECT_EQ( @@ -822,8 +822,8 @@ TEST(TestDecodeFujitsuAC, Issue726) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 24C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); } @@ -855,16 +855,16 @@ TEST(TestIRFujitsuACClass, Clean) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // Now it is in ARRAH2E model mode, it shouldn't accept setting it on. ac.setClean(true); EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // But ARRY4 does. ac.setModel(fujitsu_ac_remote_model_t::ARRY4); @@ -901,8 +901,8 @@ TEST(TestIRFujitsuACClass, Filter) { EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Timer: Off", + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, Timer: Off", ac.toString()); // Now it is in ARRAH2E model mode, it shouldn't accept setting it on. ac.setFilter(true); @@ -930,8 +930,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOffSleepTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "On Timer: 12:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, Swing: 0 (Off), " + "Command: N/A, On Timer: 12:00", ac.toString()); const uint8_t timer_on_8h30m[kFujitsuAcStateLength] = { @@ -944,8 +944,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOffSleepTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "On Timer: 08:30", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, On Timer: 08:30", ac.toString()); // TIMER OFF 11H @@ -959,8 +959,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Off Timer: 11:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Off Timer: 11:00", ac.toString()); // TIMER OFF 0.5H @@ -974,8 +974,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Off Timer: 00:30", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Off Timer: 00:30", ac.toString()); // TIMER SLEEP 3H @@ -989,8 +989,8 @@ TEST(TestIRFujitsuACClass, Timers) { EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Sleep Timer: 03:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00", ac.toString()); // Re-construct a known timer state from scratch. @@ -1007,8 +1007,8 @@ TEST(TestIRFujitsuACClass, Timers) { ac.setOffTimer(30); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Off Timer: 00:30", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Off Timer: 00:30", ac.toString()); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_STATE_EQ(timer_off_30m, ac.getRaw(), ac.getStateLength() * 8); @@ -1016,8 +1016,8 @@ TEST(TestIRFujitsuACClass, Timers) { ac.setOnTimer(12 * 60); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "On Timer: 12:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, On Timer: 12:00", ac.toString()); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_EQ(12 * 60, ac.getOnTimer()); @@ -1029,8 +1029,8 @@ TEST(TestIRFujitsuACClass, Timers) { ac.setSleepTimer(3 * 60); EXPECT_EQ( "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, " - "Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, " - "Sleep Timer: 03:00", + "Fan: 1 (High), Clean: Off, Filter: Off, 10C Heat: Off, " + "Swing: 0 (Off), Command: N/A, Sleep Timer: 03:00", ac.toString()); EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength()); EXPECT_STATE_EQ(timer_sleep_3h, ac.getRaw(), ac.getStateLength() * 8); @@ -1118,7 +1118,7 @@ TEST(TestIRFujitsuACClass, Heat10Deg) { 0x69, 0x0B, 0x00, 0x23, 0x06, 0x23, 0x20, 0xEF}; ac.setRaw(heat_on, kFujitsuAcStateLength); EXPECT_EQ( - "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, " + "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 10C, " "Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, " "Outside Quiet: Off, Timer: Off", ac.toString()); @@ -1134,7 +1134,7 @@ TEST(TestIRFujitsuACClass, Heat10Deg) { ac.set10CHeat(true); EXPECT_TRUE(ac.get10CHeat()); EXPECT_EQ( - "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, " + "Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 10C, " "Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, " "Outside Quiet: Off, Timer: Off", ac.toString()); @@ -1408,3 +1408,41 @@ TEST(TestIRFujitsuACClass, toCommon_Issue1780HandlePrev) { ASSERT_EQ(stdAc::opmode_t::kCool, result_inc_prev.mode); ASSERT_EQ(stdAc::fanspeed_t::kMin, result_inc_prev.fanspeed); } + +TEST(TestIRFujitsuACClass, Improve10CHeat) { + IRFujitsuAC ac(kGpioUnused); + // Data from https://docs.google.com/spreadsheets/d/1RdmJdOZ3zxYlLXzluKTp4L6VVdjDXKgizwwIyTTG8MA/edit#gid=0&range=G2 + const uint8_t Arrah2u_10CHeatOn[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x41, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x20, 0x64}; + ASSERT_FALSE(ac.get10CHeat()); + ac.setRaw(Arrah2u_10CHeatOn, 16); + ASSERT_TRUE(ac.get10CHeat()); + ASSERT_EQ( + "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, Swing: 0 (Off), " + "Command: N/A, Timer: Off", + ac.toString()); + EXPECT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol); + ASSERT_TRUE(ac.get10CHeat()); + EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model); + EXPECT_EQ(kFujitsuAcMinHeat, ac.toCommon().degrees); + + ac.stateReset(); + // Data from https://docs.google.com/spreadsheets/d/1RdmJdOZ3zxYlLXzluKTp4L6VVdjDXKgizwwIyTTG8MA/edit#gid=0&range=G8 + const uint8_t Arreg1u_10CHeatOn[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x61, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x20, 0x44}; + ASSERT_FALSE(ac.get10CHeat()); + ac.setRaw(Arreg1u_10CHeatOn, 16); + ASSERT_TRUE(ac.get10CHeat()); + ASSERT_EQ( + "Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 10C, " + "Fan: 0 (Auto), Clean: Off, Filter: Off, 10C Heat: On, Swing: 0 (Off), " + "Command: N/A, Timer: Off", + ac.toString()); + EXPECT_EQ(decode_type_t::FUJITSU_AC, ac.toCommon().protocol); + ASSERT_TRUE(ac.get10CHeat()); + EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.toCommon().model); + EXPECT_EQ(kFujitsuAcMinHeat, ac.toCommon().degrees); +}