From ae11fc401d6e8e8e58826754f2ba423bdb0f35ed Mon Sep 17 00:00:00 2001 From: David Date: Fri, 3 Apr 2020 23:42:44 +1000 Subject: [PATCH] Add On & Off timers for HITACHI_AC1 For #1056 --- src/ir_Hitachi.cpp | 36 +++++++++++++++++++++++++++++++++--- src/ir_Hitachi.h | 15 ++++++++++++++- test/IRac_test.cpp | 3 ++- test/ir_Hitachi_test.cpp | 13 +++++++++---- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/ir_Hitachi.cpp b/src/ir_Hitachi.cpp index fea6d02ea..8ef3d78ef 100644 --- a/src/ir_Hitachi.cpp +++ b/src/ir_Hitachi.cpp @@ -52,6 +52,7 @@ using irutils::addModeToString; using irutils::addModelToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::minsToString; using irutils::setBit; using irutils::setBits; @@ -390,7 +391,7 @@ void IRHitachiAc1::begin(void) { _irsend.begin(); } uint8_t IRHitachiAc1::calcChecksum(const uint8_t state[], const uint16_t length) { uint8_t sum = 0; - for (uint16_t i = 5; i < length - 1; i++) { + for (uint16_t i = kHitachiAc1ChecksumStartByte; i < length - 1; i++) { sum += reverseBits(GETBITS8(state[i], kLowNibble, kNibbleSize), kNibbleSize); sum += reverseBits(GETBITS8(state[i], kHighNibble, kNibbleSize), @@ -545,6 +546,30 @@ uint8_t IRHitachiAc1::getSleep(void) { kHitachiAc1SleepSize); } +void IRHitachiAc1::setOnTimer(const uint16_t mins) { + const uint16_t mins_lsb = reverseBits(mins, kHitachiAc1TimerSize); + remote_state[kHitachiAc1OnTimerLowByte] = GETBITS16(mins_lsb, 8, 8); + remote_state[kHitachiAc1OnTimerHighByte] = GETBITS16(mins_lsb, 0, 8); +} + +uint16_t IRHitachiAc1::getOnTimer(void) { + return reverseBits( + (remote_state[kHitachiAc1OnTimerLowByte] << 8) | + remote_state[kHitachiAc1OnTimerHighByte], kHitachiAc1TimerSize); +} + +void IRHitachiAc1::setOffTimer(const uint16_t mins) { + const uint16_t mins_lsb = reverseBits(mins, kHitachiAc1TimerSize); + remote_state[kHitachiAc1OffTimerLowByte] = GETBITS16(mins_lsb, 8, 8); + remote_state[kHitachiAc1OffTimerHighByte] = GETBITS16(mins_lsb, 0, 8); +} + +uint16_t IRHitachiAc1::getOffTimer(void) { + return reverseBits( + (remote_state[kHitachiAc1OffTimerLowByte] << 8) | + remote_state[kHitachiAc1OffTimerHighByte], kHitachiAc1TimerSize); +} + void IRHitachiAc1::setSleep(const uint8_t mode) { switch (mode) { case kHitachiAc1Sleep1: @@ -643,9 +668,14 @@ String IRHitachiAc1::toString(void) { kHitachiAc1FanMed); result += addBoolToString(getSwingToggle(), kSwingVToggleStr); result += addBoolToString(getSwing(), kSwingVModeStr); - result += addLabeledString((getSleep() != 0) ? uint64ToString(getSleep()) - : kOffStr, + result += addLabeledString(getSleep() ? uint64ToString(getSleep()) : kOffStr, kSleepStr); + result += addLabeledString(getOnTimer() ? minsToString(getOnTimer()) + : kOffStr, + kOnTimerStr); + result += addLabeledString(getOffTimer() ? minsToString(getOffTimer()) + : kOffStr, + kOffTimerStr); return result; } diff --git a/src/ir_Hitachi.h b/src/ir_Hitachi.h index a7d4d1e96..20202bd09 100644 --- a/src/ir_Hitachi.h +++ b/src/ir_Hitachi.h @@ -109,6 +109,14 @@ const uint8_t kHitachiAc1TempByte = 6; const uint8_t kHitachiAc1TempOffset = 2; const uint8_t kHitachiAc1TempSize = 5; // Mask 0b01111100 const uint8_t kHitachiAc1TempDelta = 7; +// Note: Timers are nr. of minutes & stored in LSB order. +// Byte[7-8] (Off Timer) +const uint8_t kHitachiAc1TimerSize = 16; // Mask 0b1111111111111111 +const uint8_t kHitachiAc1OffTimerLowByte = 7; +const uint8_t kHitachiAc1OffTimerHighByte = 8; +// Byte[9-10] (On Timer) +const uint8_t kHitachiAc1OnTimerLowByte = 9; +const uint8_t kHitachiAc1OnTimerHighByte = 10; // Byte[11] (Power/Swing/Sleep) const uint8_t kHitachiAc1PowerByte = 11; const uint8_t kHitachiAc1PowerOffset = 5; // Mask 0b00100000 @@ -125,7 +133,8 @@ const uint8_t kHitachiAc1Sleep2 = 0b010; // TODO(soumaxetuirk): Confirm this value. It looks wrong. const uint8_t kHitachiAc1Sleep3 = 0b1110; // ???? const uint8_t kHitachiAc1Sleep4 = 0b100; - +// Byte[12] (Checksum) +const uint8_t kHitachiAc1ChecksumStartByte = 5; // Classes @@ -211,6 +220,10 @@ class IRHitachiAc1 { bool getSwing(void); void setSleep(const uint8_t mode); uint8_t getSleep(void); + void setOnTimer(const uint16_t mins); + uint16_t getOnTimer(void); + void setOffTimer(const uint16_t mins); + uint16_t getOffTimer(void); uint8_t* getRaw(void); void setRaw(const uint8_t new_code[], const uint16_t length = kHitachiAc1StateLength); diff --git a/test/IRac_test.cpp b/test/IRac_test.cpp index f63bc8607..e63343ed9 100644 --- a/test/IRac_test.cpp +++ b/test/IRac_test.cpp @@ -638,7 +638,8 @@ TEST(TestIRac, Hitachi1) { char expected[] = "Model: 1 (R-LT0541-HTA-A), Power: On, Power Toggle: Off, " "Mode: 15 (Auto), Temp: 19C, Fan: 4 (Medium), " - "Swing(V) Toggle: On, Swing(V) Mode: On, Sleep: 1"; + "Swing(V) Toggle: On, Swing(V) Mode: On, Sleep: 1, " + "On Timer: Off, Off Timer: Off"; ac.begin(); irac.hitachi1(&ac, diff --git a/test/ir_Hitachi_test.cpp b/test/ir_Hitachi_test.cpp index 62f7c5c86..5efa9565e 100644 --- a/test/ir_Hitachi_test.cpp +++ b/test/ir_Hitachi_test.cpp @@ -575,7 +575,8 @@ TEST(TestDecodeHitachiAC1, NormalRealExample) { EXPECT_EQ( "Model: 2 (R-LT0541-HTA-B), Power: Off, Power Toggle: On, " "Mode: 6 (Cool), Temp: 23C, Fan: 1 (Auto), " - "Swing(V) Toggle: Off, Swing(V) Mode: Off, Sleep: Off", + "Swing(V) Toggle: Off, Swing(V) Mode: Off, Sleep: Off, " + "On Timer: Off, Off Timer: Off", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -1601,17 +1602,20 @@ TEST(TestIRHitachiAc1Class, HumanReadable) { EXPECT_EQ( "Model: 1 (R-LT0541-HTA-A), Power: On, Power Toggle: On, Mode: 6 (Cool), " "Temp: 32C, Fan: 1 (Auto), Swing(V) Toggle: Off, Swing(V) Mode: Off, " - "Sleep: Off", + "Sleep: Off, On Timer: Off, Off Timer: Off", ac.toString()); ac.setModel(hitachi_ac1_remote_model_t::R_LT0541_HTA_B); ac.setSwing(true); ac.setSwingToggle(true); ac.setSleep(kHitachiAc1Sleep2); ac.setPowerToggle(false); + ac.setOnTimer(2 * 60 + 39); + ac.setOffTimer(10 * 60 + 17); EXPECT_EQ( "Model: 2 (R-LT0541-HTA-B), Power: On, Power Toggle: Off, " "Mode: 6 (Cool), Temp: 32C, Fan: 1 (Auto), " - "Swing(V) Toggle: On, Swing(V) Mode: On, Sleep: 2", + "Swing(V) Toggle: On, Swing(V) Mode: On, Sleep: 2, " + "On Timer: 02:39, Off Timer: 10:17", ac.toString()); } @@ -1698,7 +1702,8 @@ TEST(TestIRHitachiAc1Class, ReconstructKnownGood) { EXPECT_EQ( "Model: 2 (R-LT0541-HTA-B), Power: Off, Power Toggle: On, " "Mode: 6 (Cool), Temp: 23C, Fan: 1 (Auto), " - "Swing(V) Toggle: Off, Swing(V) Mode: Off, Sleep: Off", + "Swing(V) Toggle: Off, Swing(V) Mode: Off, Sleep: Off, " + "On Timer: Off, Off Timer: Off", ac.toString()); }