Skip to content

Commit 21f26e0

Browse files
[HAIER_AC176/HAIER_AC_YRW02] Add support degree Fahrenheit (#1659)
* Add support degree Fahrenheit * Update IRac * Add button `Celsius/Fahrenheit` * Update related tests
1 parent 0f3fa4d commit 21f26e0

File tree

6 files changed

+185
-47
lines changed

6 files changed

+185
-47
lines changed

src/IRac.cpp

+16-7
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,7 @@ void IRac::haier(IRHaierAC *ac,
11121112
/// @param[in, out] ac A Ptr to an IRHaierAC176 object to use.
11131113
/// @param[in] on The power setting.
11141114
/// @param[in] mode The operation mode setting.
1115+
/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit.
11151116
/// @param[in] degrees The temperature setting in degrees.
11161117
/// @param[in] fan The speed setting for the fan.
11171118
/// @param[in] swingv The vertical swing setting.
@@ -1122,12 +1123,15 @@ void IRac::haier(IRHaierAC *ac,
11221123
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
11231124
void IRac::haier176(IRHaierAC176 *ac,
11241125
const bool on, const stdAc::opmode_t mode,
1125-
const float degrees, const stdAc::fanspeed_t fan,
1126-
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
1126+
const bool celsius, const float degrees,
1127+
const stdAc::fanspeed_t fan,
1128+
const stdAc::swingv_t swingv,
1129+
const stdAc::swingh_t swingh,
11271130
const bool turbo, const bool quiet, const bool filter,
11281131
const int16_t sleep) {
11291132
ac->begin();
11301133
ac->setMode(ac->convertMode(mode));
1134+
ac->setUseFahrenheit(!celsius);
11311135
ac->setTemp(degrees);
11321136
ac->setFan(ac->convertFan(fan));
11331137
ac->setSwingV(ac->convertSwingV(swingv));
@@ -1149,6 +1153,7 @@ void IRac::haier176(IRHaierAC176 *ac,
11491153
/// @param[in, out] ac A Ptr to an IRHaierACYRW02 object to use.
11501154
/// @param[in] on The power setting.
11511155
/// @param[in] mode The operation mode setting.
1156+
/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit.
11521157
/// @param[in] degrees The temperature setting in degrees.
11531158
/// @param[in] fan The speed setting for the fan.
11541159
/// @param[in] swingv The vertical swing setting.
@@ -1159,13 +1164,15 @@ void IRac::haier176(IRHaierAC176 *ac,
11591164
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
11601165
void IRac::haierYrwo2(IRHaierACYRW02 *ac,
11611166
const bool on, const stdAc::opmode_t mode,
1162-
const float degrees, const stdAc::fanspeed_t fan,
1167+
const bool celsius, const float degrees,
1168+
const stdAc::fanspeed_t fan,
11631169
const stdAc::swingv_t swingv,
11641170
const stdAc::swingh_t swingh,
11651171
const bool turbo, const bool quiet, const bool filter,
11661172
const int16_t sleep) {
11671173
ac->begin();
11681174
ac->setMode(ac->convertMode(mode));
1175+
ac->setUseFahrenheit(!celsius);
11691176
ac->setTemp(degrees);
11701177
ac->setFan(ac->convertFan(fan));
11711178
ac->setSwingV(ac->convertSwingV(swingv));
@@ -2797,17 +2804,19 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
27972804
case HAIER_AC176:
27982805
{
27992806
IRHaierAC176 ac(_pin, _inverted, _modulation);
2800-
haier176(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
2801-
send.swingh, send.turbo, send.filter, send.sleep);
2807+
haier176(&ac, send.power, send.mode, send.celsius, send.degrees,
2808+
send.fanspeed, send.swingv, send.swingh, send.turbo,
2809+
send.filter, send.sleep);
28022810
break;
28032811
}
28042812
#endif // SEND_HAIER_AC176
28052813
#if SEND_HAIER_AC_YRW02
28062814
case HAIER_AC_YRW02:
28072815
{
28082816
IRHaierACYRW02 ac(_pin, _inverted, _modulation);
2809-
haierYrwo2(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
2810-
send.swingh, send.turbo, send.filter, send.sleep);
2817+
haierYrwo2(&ac, send.power, send.mode, send.celsius, send.degrees,
2818+
send.fanspeed, send.swingv, send.swingh, send.turbo,
2819+
send.filter, send.sleep);
28112820
break;
28122821
}
28132822
#endif // SEND_HAIER_AC_YRW02

src/IRac.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,19 @@ void electra(IRElectraAc *ac,
261261
#if SEND_HAIER_AC176
262262
void haier176(IRHaierAC176 *ac,
263263
const bool on, const stdAc::opmode_t mode,
264-
const float degrees, const stdAc::fanspeed_t fan,
265-
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
266-
const bool turbo, const bool quiet, const bool filter,
264+
const bool celsius, const float degrees,
265+
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
266+
const stdAc::swingh_t swingh, const bool turbo,
267+
const bool quiet, const bool filter,
267268
const int16_t sleep = -1);
268269
#endif // SEND_HAIER_AC176
269270
#if SEND_HAIER_AC_YRW02
270271
void haierYrwo2(IRHaierACYRW02 *ac,
271272
const bool on, const stdAc::opmode_t mode,
272-
const float degrees, const stdAc::fanspeed_t fan,
273-
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
274-
const bool turbo, const bool quiet, const bool filter,
273+
const bool celsius, const float degrees,
274+
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
275+
const stdAc::swingh_t swingh, const bool turbo,
276+
const bool quiet, const bool filter,
275277
const int16_t sleep = -1);
276278
#endif // SEND_HAIER_AC_YRW02
277279
#if SEND_HITACHI_AC

src/ir_Haier.cpp

+91-18
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ void IRHaierAC176::stateReset(void) {
584584
std::memset(_.raw, 0, sizeof _.raw);
585585
_.Prefix = kHaierAcYrw02Prefix;
586586
_.Prefix2 = kHaierAc176Prefix;
587-
_.Temp = kHaierAcDefTemp - kHaierAcMinTemp;
587+
_.Temp = kHaierAcYrw02DefTempC - kHaierAcYrw02MinTempC;
588588
_.Health = true;
589589
setFan(kHaierAcYrw02FanAuto);
590590
_.Power = true;
@@ -619,6 +619,7 @@ void IRHaierAC176::setButton(uint8_t button) {
619619
case kHaierAcYrw02ButtonTurbo:
620620
case kHaierAcYrw02ButtonSleep:
621621
case kHaierAcYrw02ButtonLock:
622+
case kHaierAcYrw02ButtonCF:
622623
_.Button = button;
623624
}
624625
}
@@ -654,27 +655,96 @@ void IRHaierAC176::setMode(uint8_t mode) {
654655
/// @return The current operating mode setting.
655656
uint8_t IRHaierAC176::getMode(void) const { return _.Mode; }
656657

657-
/// Set the temperature.
658-
/// @param[in] celsius The temperature in degrees celsius.
659-
void IRHaierAC176::setTemp(const uint8_t celsius) {
660-
uint8_t temp = celsius;
661-
if (temp < kHaierAcMinTemp)
662-
temp = kHaierAcMinTemp;
663-
else if (temp > kHaierAcMaxTemp)
664-
temp = kHaierAcMaxTemp;
658+
/// Set the default temperature units to use.
659+
/// @param[in] on Use Fahrenheit as the units.
660+
/// true is Fahrenheit, false is Celsius.
661+
void IRHaierAC176::setUseFahrenheit(const bool on) { _.UseFahrenheit = on; }
662+
663+
/// Get the default temperature units in use.
664+
/// @return true is Fahrenheit, false is Celsius.
665+
bool IRHaierAC176::getUseFahrenheit(void) const { return _.UseFahrenheit; }
665666

667+
/// Set the temperature.
668+
/// @param[in] degree The temperature in degrees.
669+
/// @param[in] fahrenheit Use units of Fahrenheit and set that as units used.
670+
void IRHaierAC176::setTemp(const uint8_t degree, const bool fahrenheit) {
666671
uint8_t old_temp = getTemp();
667-
if (old_temp == temp) return;
668-
if (old_temp > temp)
669-
_.Button = kHaierAcYrw02ButtonTempDown;
670-
else
671-
_.Button = kHaierAcYrw02ButtonTempUp;
672-
_.Temp = temp - kHaierAcMinTemp;
672+
if (old_temp == degree) return;
673+
674+
if (_.UseFahrenheit == fahrenheit) {
675+
if (old_temp > degree)
676+
_.Button = kHaierAcYrw02ButtonTempDown;
677+
else
678+
_.Button = kHaierAcYrw02ButtonTempUp;
679+
} else {
680+
_.Button = kHaierAcYrw02ButtonCF;
681+
}
682+
_.UseFahrenheit = fahrenheit;
683+
684+
uint8_t temp = degree;
685+
if (fahrenheit) {
686+
if (temp < kHaierAcYrw02MinTempF)
687+
temp = kHaierAcYrw02MinTempF;
688+
else if (temp > kHaierAcYrw02MaxTempF)
689+
temp = kHaierAcYrw02MaxTempF;
690+
if (degree >= 77) { temp++; }
691+
if (degree >= 79) { temp++; }
692+
// See at IRHaierAC176::getTemp() comments for clarification
693+
_.ExtraDegreeF = temp % 2;
694+
_.Temp = (temp - kHaierAcYrw02MinTempF -_.ExtraDegreeF) >> 1;
695+
} else {
696+
if (temp < kHaierAcYrw02MinTempC)
697+
temp = kHaierAcYrw02MinTempC;
698+
else if (temp > kHaierAcYrw02MaxTempC)
699+
temp = kHaierAcYrw02MaxTempC;
700+
_.Temp = temp - kHaierAcYrw02MinTempC;
701+
}
673702
}
674703

675704
/// Get the current temperature setting.
676705
/// @return The current setting for temp. in degrees celsius.
677-
uint8_t IRHaierAC176::getTemp(void) const { return _.Temp + kHaierAcMinTemp; }
706+
uint8_t IRHaierAC176::getTemp(void) const {
707+
if (!_.UseFahrenheit) { return _.Temp + kHaierAcYrw02MinTempC; }
708+
uint8_t degree = _.Temp*2 + kHaierAcYrw02MinTempF + _.ExtraDegreeF;
709+
// The way of coding the temperature in degree Fahrenheit is
710+
// kHaierAcYrw02MinTempF + Temp*2 + ExtraDegreeF, for example
711+
// Temp = 0b0011, ExtraDegreeF = 0b1, temperature is 60 + 3*2 + 1 = 67F
712+
// But around 78F there is unconsistency, see table below
713+
//
714+
// | Fahrenheit | Temp | ExtraDegreeF |
715+
// | 60F | 0b0000 | 0b0 |
716+
// | 61F | 0b0000 | 0b1 |
717+
// | 62F | 0b0001 | 0b0 |
718+
// | 63F | 0b0001 | 0b1 |
719+
// | 64F | 0b0010 | 0b0 |
720+
// | 65F | 0b0010 | 0b1 |
721+
// | 66F | 0b0011 | 0b0 |
722+
// | 67F | 0b0011 | 0b1 |
723+
// | 68F | 0b0100 | 0b0 |
724+
// | 69F | 0b0100 | 0b1 |
725+
// | 70F | 0b0101 | 0b0 |
726+
// | 71F | 0b0101 | 0b1 |
727+
// | 72F | 0b0110 | 0b0 |
728+
// | 73F | 0b0110 | 0b1 |
729+
// | 74F | 0b0111 | 0b0 |
730+
// | 75F | 0b0111 | 0b1 |
731+
// | 76F | 0b1000 | 0b0 |
732+
// | Not Used | 0b1000 | 0b1 |
733+
// | 77F | 0b1001 | 0b0 |
734+
// | Not Used | 0b1001 | 0b1 |
735+
// | 78F | 0b1010 | 0b0 |
736+
// | 79F | 0b1010 | 0b1 |
737+
// | 80F | 0b1011 | 0b0 |
738+
// | 81F | 0b1011 | 0b1 |
739+
// | 82F | 0b1100 | 0b0 |
740+
// | 83F | 0b1100 | 0b1 |
741+
// | 84F | 0b1101 | 0b0 |
742+
// | 86F | 0b1110 | 0b0 |
743+
// | 85F | 0b1101 | 0b1 |
744+
if (degree >= 77) { degree--; }
745+
if (degree >= 79) { degree--; }
746+
return degree;
747+
}
678748

679749
/// Set the Health (filter) setting of the A/C.
680750
/// @param[in] on true, the setting is on. false, the setting is off.
@@ -1038,7 +1108,7 @@ stdAc::state_t IRHaierAC176::toCommon(void) const {
10381108
result.model = -1; // No models used.
10391109
result.power = _.Power;
10401110
result.mode = toCommonMode(_.Mode);
1041-
result.celsius = true;
1111+
result.celsius = !_.UseFahrenheit;
10421112
result.degrees = getTemp();
10431113
result.fanspeed = toCommonFanSpeed(_.Fan);
10441114
result.swingv = toCommonSwingV(_.SwingV);
@@ -1102,14 +1172,17 @@ String IRHaierAC176::toString(void) const {
11021172
case kHaierAcYrw02ButtonLock:
11031173
result += kLockStr;
11041174
break;
1175+
case kHaierAcYrw02ButtonCF:
1176+
result += kCelsiusFahrenheitStr;
1177+
break;
11051178
default:
11061179
result += kUnknownStr;
11071180
}
11081181
result += ')';
11091182
result += addModeToString(_.Mode, kHaierAcYrw02Auto, kHaierAcYrw02Cool,
11101183
kHaierAcYrw02Heat, kHaierAcYrw02Dry,
11111184
kHaierAcYrw02Fan);
1112-
result += addTempToString(getTemp());
1185+
result += addTempToString(getTemp(), !_.UseFahrenheit);
11131186
result += addFanToString(_.Fan, kHaierAcYrw02FanHigh, kHaierAcYrw02FanLow,
11141187
kHaierAcYrw02FanAuto, kHaierAcYrw02FanAuto,
11151188
kHaierAcYrw02FanMed);

src/ir_Haier.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ const uint8_t kHaierAcSleepBit = 0b01000000;
133133
#define HAIER_AC_FAN_MED kHaierAcFanMed
134134
#define HAIER_AC_FAN_HIGH kHaierAcFanHigh
135135

136+
const uint8_t kHaierAcYrw02MinTempC = 16;
137+
const uint8_t kHaierAcYrw02MaxTempC = 30;
138+
const uint8_t kHaierAcYrw02MinTempF = 60;
139+
const uint8_t kHaierAcYrw02MaxTempF = 86;
140+
const uint8_t kHaierAcYrw02DefTempC = 25;
141+
136142
const uint8_t kHaierAcYrw02Prefix = 0xA6;
137143
const uint8_t kHaierAc176Prefix = 0xB7;
138144

@@ -173,6 +179,7 @@ const uint8_t kHaierAcYrw02ButtonTurbo = 0b01000;
173179
const uint8_t kHaierAcYrw02ButtonSleep = 0b01011;
174180
const uint8_t kHaierAcYrw02ButtonTimer = 0b10000;
175181
const uint8_t kHaierAcYrw02ButtonLock = 0b10100;
182+
const uint8_t kHaierAcYrw02ButtonCF = 0b11010;
176183

177184
const uint8_t kHaierAcYrw02NoTimers = 0b000;
178185
const uint8_t kHaierAcYrw02OffTimer = 0b001;
@@ -218,7 +225,10 @@ union HaierAc176Protocol{
218225
// Byte 9
219226
uint8_t :8;
220227
// Byte 10
221-
uint8_t :8;
228+
uint8_t ExtraDegreeF :1;
229+
uint8_t :4;
230+
uint8_t UseFahrenheit:1;
231+
uint8_t :2;
222232
// Byte 11
223233
uint8_t :8;
224234
// Byte 12
@@ -365,7 +375,9 @@ class IRHaierAC176 {
365375
void setButton(const uint8_t button);
366376
uint8_t getButton(void) const;
367377

368-
void setTemp(const uint8_t temp);
378+
void setUseFahrenheit(const bool on);
379+
bool getUseFahrenheit(void) const;
380+
void setTemp(const uint8_t temp, const bool fahrenheit = false);
369381
uint8_t getTemp(void) const;
370382

371383
void setFan(const uint8_t speed);

test/IRac_test.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,8 @@ TEST(TestIRac, Haier176) {
798798
irac.haier176(&ac,
799799
true, // Power
800800
stdAc::opmode_t::kCool, // Mode
801-
23, // Celsius
801+
true, // Celsius
802+
23, // Degrees
802803
stdAc::fanspeed_t::kMedium, // Fan speed
803804
stdAc::swingv_t::kHigh, // Vertical swing
804805
stdAc::swingh_t::kOff, // Horizontal swing
@@ -830,7 +831,8 @@ TEST(TestIRac, HaierYrwo2) {
830831
irac.haierYrwo2(&ac,
831832
true, // Power
832833
stdAc::opmode_t::kCool, // Mode
833-
23, // Celsius
834+
true, // Celsius
835+
23, // Degrees
834836
stdAc::fanspeed_t::kMedium, // Fan speed
835837
stdAc::swingv_t::kHigh, // Vertical swing
836838
stdAc::swingh_t::kAuto, // Vertical swing

0 commit comments

Comments
 (0)