| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865 |
- // Copyright 2018 crankyoldgit
- // The specifics of reverse engineering the protocols details:
- // * HSU07-HEA03 by kuzin2006.
- // * YR-W02/HSU-09HMC203 by non7top.
- #include "ir_Haier.h"
- #ifndef UNIT_TEST
- #include <Arduino.h>
- #else
- #include <string>
- #endif
- #include "IRremoteESP8266.h"
- #include "IRutils.h"
- // HH HH AAA IIIII EEEEEEE RRRRRR
- // HH HH AAAAA III EE RR RR
- // HHHHHHH AA AA III EEEEE RRRRRR
- // HH HH AAAAAAA III EE RR RR
- // HH HH AA AA IIIII EEEEEEE RR RR
- // Supported devices:
- // * Haier HSU07-HEA03 Remote control.
- // * Haier YR-W02 Remote control
- // * Haier HSU-09HMC203 A/C unit.
- // Ref:
- // https://github.com/markszabo/IRremoteESP8266/issues/404
- // https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0
- // https://github.com/markszabo/IRremoteESP8266/issues/485
- // https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods
- // Constants
- const uint16_t kHaierAcHdr = 3000;
- const uint16_t kHaierAcHdrGap = 4300;
- const uint16_t kHaierAcBitMark = 520;
- const uint16_t kHaierAcOneSpace = 1650;
- const uint16_t kHaierAcZeroSpace = 650;
- const uint32_t kHaierAcMinGap = 150000; // Completely made up value.
- #if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02)
- // Send a Haier A/C message. (HSU07-HEA03 remote)
- //
- // Args:
- // data: An array of bytes containing the IR command.
- // nbytes: Nr. of bytes of data in the array. (>=kHaierACStateLength)
- // repeat: Nr. of times the message is to be repeated. (Default = 0).
- //
- // Status: Beta / Probably working.
- //
- void IRsend::sendHaierAC(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
- if (nbytes < kHaierACStateLength) return;
- for (uint16_t r = 0; r <= repeat; r++) {
- enableIROut(38000);
- mark(kHaierAcHdr);
- space(kHaierAcHdr);
- sendGeneric(kHaierAcHdr, kHaierAcHdrGap, kHaierAcBitMark, kHaierAcOneSpace,
- kHaierAcBitMark, kHaierAcZeroSpace, kHaierAcBitMark,
- kHaierAcMinGap, data, nbytes, 38, true,
- 0, // Repeats handled elsewhere
- 50);
- }
- }
- #endif // (SEND_HAIER_AC || SEND_HAIER_AC_YRW02)
- #if SEND_HAIER_AC_YRW02
- // Send a Haier YR-W02 remote A/C message.
- //
- // Args:
- // data: An array of bytes containing the IR command.
- // nbytes: Nr. of bytes of data in the array. (>=kHaierACYRW02StateLength)
- // repeat: Nr. of times the message is to be repeated. (Default = 0).
- //
- // Status: Alpha / Untested on a real device.
- //
- void IRsend::sendHaierACYRW02(unsigned char data[], uint16_t nbytes,
- uint16_t repeat) {
- if (nbytes >= kHaierACYRW02StateLength) sendHaierAC(data, nbytes, repeat);
- }
- #endif // SEND_HAIER_AC_YRW02
- // Class for emulating a Haier HSU07-HEA03 remote
- IRHaierAC::IRHaierAC(uint16_t pin) : _irsend(pin) { stateReset(); }
- void IRHaierAC::begin() { _irsend.begin(); }
- #if SEND_HAIER_AC
- void IRHaierAC::send() {
- checksum();
- _irsend.sendHaierAC(remote_state);
- }
- #endif // SEND_HAIER_AC
- void IRHaierAC::checksum() {
- remote_state[8] = sumBytes(remote_state, kHaierACStateLength - 1);
- }
- bool IRHaierAC::validChecksum(uint8_t state[], const uint16_t length) {
- if (length < 2) return false; // 1 byte of data can't have a checksum.
- return (state[length - 1] == sumBytes(state, length - 1));
- }
- void IRHaierAC::stateReset() {
- for (uint8_t i = 1; i < kHaierACStateLength; i++) remote_state[i] = 0x0;
- remote_state[0] = kHaierAcPrefix;
- remote_state[2] = 0b00100000;
- setTemp(kHaierAcDefTemp);
- setFan(kHaierAcFanAuto);
- setMode(kHaierAcAuto);
- setCommand(kHaierAcCmdOn);
- }
- uint8_t* IRHaierAC::getRaw() {
- checksum();
- return remote_state;
- }
- void IRHaierAC::setRaw(uint8_t new_code[]) {
- for (uint8_t i = 0; i < kHaierACStateLength; i++) {
- remote_state[i] = new_code[i];
- }
- }
- void IRHaierAC::setCommand(uint8_t state) {
- remote_state[1] &= 0b11110000;
- switch (state) {
- case kHaierAcCmdOff:
- case kHaierAcCmdOn:
- case kHaierAcCmdMode:
- case kHaierAcCmdFan:
- case kHaierAcCmdTempUp:
- case kHaierAcCmdTempDown:
- case kHaierAcCmdSleep:
- case kHaierAcCmdTimerSet:
- case kHaierAcCmdTimerCancel:
- case kHaierAcCmdHealth:
- case kHaierAcCmdSwing:
- remote_state[1] |= (state & 0b00001111);
- }
- }
- uint8_t IRHaierAC::getCommand() { return remote_state[1] & (0b00001111); }
- void IRHaierAC::setFan(uint8_t speed) {
- uint8_t new_speed = kHaierAcFanAuto;
- switch (speed) {
- case kHaierAcFanLow:
- new_speed = 3;
- break;
- case kHaierAcFanMed:
- new_speed = 1;
- break;
- case kHaierAcFanHigh:
- new_speed = 2;
- break;
- default:
- new_speed = kHaierAcFanAuto; // Default to auto for anything else.
- }
- if (speed != getFan()) setCommand(kHaierAcCmdFan);
- remote_state[5] &= 0b11111100;
- remote_state[5] |= new_speed;
- }
- uint8_t IRHaierAC::getFan() {
- switch (remote_state[5] & 0b00000011) {
- case 1:
- return kHaierAcFanMed;
- case 2:
- return kHaierAcFanHigh;
- case 3:
- return kHaierAcFanLow;
- default:
- return kHaierAcFanAuto;
- }
- }
- void IRHaierAC::setMode(uint8_t mode) {
- uint8_t new_mode = mode;
- setCommand(kHaierAcCmdMode);
- if (mode > kHaierAcFan) // If out of range, default to auto mode.
- new_mode = kHaierAcAuto;
- remote_state[7] &= 0b00011111;
- remote_state[7] |= (new_mode << 5);
- }
- uint8_t IRHaierAC::getMode() { return (remote_state[7] & 0b11100000) >> 5; }
- void IRHaierAC::setTemp(const uint8_t celsius) {
- uint8_t temp = celsius;
- if (temp < kHaierAcMinTemp)
- temp = kHaierAcMinTemp;
- else if (temp > kHaierAcMaxTemp)
- temp = kHaierAcMaxTemp;
- uint8_t old_temp = getTemp();
- if (old_temp == temp) return;
- if (old_temp > temp)
- setCommand(kHaierAcCmdTempDown);
- else
- setCommand(kHaierAcCmdTempUp);
- remote_state[1] &= 0b00001111; // Clear the previous temp.
- remote_state[1] |= ((temp - kHaierAcMinTemp) << 4);
- }
- uint8_t IRHaierAC::getTemp() {
- return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp;
- }
- void IRHaierAC::setHealth(bool state) {
- setCommand(kHaierAcCmdHealth);
- remote_state[4] &= 0b11011111;
- remote_state[4] |= (state << 5);
- }
- bool IRHaierAC::getHealth(void) { return remote_state[4] & (1 << 5); }
- void IRHaierAC::setSleep(bool state) {
- setCommand(kHaierAcCmdSleep);
- remote_state[7] &= 0b10111111;
- remote_state[7] |= (state << 6);
- }
- bool IRHaierAC::getSleep(void) { return remote_state[7] & 0b01000000; }
- uint16_t IRHaierAC::getTime(const uint8_t ptr[]) {
- return (ptr[0] & 0b00011111) * 60 + (ptr[1] & 0b00111111);
- }
- int16_t IRHaierAC::getOnTimer() {
- if (remote_state[3] & 0b10000000) // Check if the timer is turned on.
- return getTime(remote_state + 6);
- else
- return -1;
- }
- int16_t IRHaierAC::getOffTimer() {
- if (remote_state[3] & 0b01000000) // Check if the timer is turned on.
- return getTime(remote_state + 4);
- else
- return -1;
- }
- uint16_t IRHaierAC::getCurrTime() { return getTime(remote_state + 2); }
- void IRHaierAC::setTime(uint8_t ptr[], const uint16_t nr_mins) {
- uint16_t mins = nr_mins;
- if (nr_mins > kHaierAcMaxTime) mins = kHaierAcMaxTime;
- // Hours
- ptr[0] &= 0b11100000;
- ptr[0] |= (mins / 60);
- // Minutes
- ptr[1] &= 0b11000000;
- ptr[1] |= (mins % 60);
- }
- void IRHaierAC::setOnTimer(const uint16_t nr_mins) {
- setCommand(kHaierAcCmdTimerSet);
- remote_state[3] |= 0b10000000;
- setTime(remote_state + 6, nr_mins);
- }
- void IRHaierAC::setOffTimer(const uint16_t nr_mins) {
- setCommand(kHaierAcCmdTimerSet);
- remote_state[3] |= 0b01000000;
- setTime(remote_state + 4, nr_mins);
- }
- void IRHaierAC::cancelTimers() {
- setCommand(kHaierAcCmdTimerCancel);
- remote_state[3] &= 0b00111111;
- }
- void IRHaierAC::setCurrTime(const uint16_t nr_mins) {
- setTime(remote_state + 2, nr_mins);
- }
- uint8_t IRHaierAC::getSwing() { return (remote_state[2] & 0b11000000) >> 6; }
- void IRHaierAC::setSwing(const uint8_t state) {
- if (state == getSwing()) return; // Nothing to do.
- setCommand(kHaierAcCmdSwing);
- switch (state) {
- case kHaierAcSwingOff:
- case kHaierAcSwingUp:
- case kHaierAcSwingDown:
- case kHaierAcSwingChg:
- remote_state[2] &= 0b00111111;
- remote_state[2] |= (state << 6);
- break;
- }
- }
- // Convert a Haier time into a human readable string.
- #ifdef ARDUINO
- String IRHaierAC::timeToString(const uint16_t nr_mins) {
- String result = "";
- #else
- std::string IRHaierAC::timeToString(const uint16_t nr_mins) {
- std::string result = "";
- #endif // ARDUINO
- if (nr_mins / 24 < 10) result += "0"; // Zero pad.
- result += uint64ToString(nr_mins / 60);
- result += ":";
- if (nr_mins % 60 < 10) result += "0"; // Zero pad.
- result += uint64ToString(nr_mins % 60);
- return result;
- }
- // Convert the internal state into a human readable string.
- #ifdef ARDUINO
- String IRHaierAC::toString() {
- String result = "";
- #else
- std::string IRHaierAC::toString() {
- std::string result = "";
- #endif // ARDUINO
- uint8_t cmd = getCommand();
- result += "Command: " + uint64ToString(cmd) + " (";
- switch (cmd) {
- case kHaierAcCmdOff:
- result += "Off";
- break;
- case kHaierAcCmdOn:
- result += "On";
- break;
- case kHaierAcCmdMode:
- result += "Mode";
- break;
- case kHaierAcCmdFan:
- result += "Fan";
- break;
- case kHaierAcCmdTempUp:
- result += "Temp Up";
- break;
- case kHaierAcCmdTempDown:
- result += "Temp Down";
- break;
- case kHaierAcCmdSleep:
- result += "Sleep";
- break;
- case kHaierAcCmdTimerSet:
- result += "Timer Set";
- break;
- case kHaierAcCmdTimerCancel:
- result += "Timer Cancel";
- break;
- case kHaierAcCmdHealth:
- result += "Health";
- break;
- case kHaierAcCmdSwing:
- result += "Swing";
- break;
- default:
- result += "Unknown";
- }
- result += ")";
- result += ", Mode: " + uint64ToString(getMode());
- switch (getMode()) {
- case kHaierAcAuto:
- result += " (AUTO)";
- break;
- case kHaierAcCool:
- result += " (COOL)";
- break;
- case kHaierAcHeat:
- result += " (HEAT)";
- break;
- case kHaierAcDry:
- result += " (DRY)";
- break;
- case kHaierAcFan:
- result += " (FAN)";
- break;
- default:
- result += " (UNKNOWN)";
- }
- result += ", Temp: " + uint64ToString(getTemp()) + "C";
- result += ", Fan: " + uint64ToString(getFan());
- switch (getFan()) {
- case kHaierAcFanAuto:
- result += " (AUTO)";
- break;
- case kHaierAcFanHigh:
- result += " (MAX)";
- break;
- }
- result += ", Swing: " + uint64ToString(getSwing()) + " (";
- switch (getSwing()) {
- case kHaierAcSwingOff:
- result += "Off";
- break;
- case kHaierAcSwingUp:
- result += "Up";
- break;
- case kHaierAcSwingDown:
- result += "Down";
- break;
- case kHaierAcSwingChg:
- result += "Chg";
- break;
- default:
- result += "Unknown";
- }
- result += ")";
- result += ", Sleep: ";
- if (getSleep())
- result += "On";
- else
- result += "Off";
- result += ", Health: ";
- if (getHealth())
- result += "On";
- else
- result += "Off";
- result += ", Current Time: " + timeToString(getCurrTime());
- result += ", On Timer: ";
- if (getOnTimer() >= 0)
- result += timeToString(getOnTimer());
- else
- result += "Off";
- result += ", Off Timer: ";
- if (getOffTimer() >= 0)
- result += timeToString(getOffTimer());
- else
- result += "Off";
- return result;
- }
- // End of IRHaierAC class.
- // Class for emulating a Haier YRW02 remote
- IRHaierACYRW02::IRHaierACYRW02(uint16_t pin) : _irsend(pin) { stateReset(); }
- void IRHaierACYRW02::begin() { _irsend.begin(); }
- #if SEND_HAIER_AC_YRW02
- void IRHaierACYRW02::send() {
- checksum();
- _irsend.sendHaierACYRW02(remote_state);
- }
- #endif // SEND_HAIER_AC_YRW02
- void IRHaierACYRW02::checksum() {
- remote_state[kHaierACYRW02StateLength - 1] =
- sumBytes(remote_state, kHaierACYRW02StateLength - 1);
- }
- bool IRHaierACYRW02::validChecksum(uint8_t state[], const uint16_t length) {
- if (length < 2) return false; // 1 byte of data can't have a checksum.
- return (state[length - 1] == sumBytes(state, length - 1));
- }
- void IRHaierACYRW02::stateReset() {
- for (uint8_t i = 1; i < kHaierACYRW02StateLength; i++) remote_state[i] = 0x0;
- remote_state[0] = kHaierAcYrw02Prefix;
- setTemp(kHaierAcDefTemp);
- setHealth(true);
- setTurbo(kHaierAcYrw02TurboOff);
- setSleep(false);
- setFan(kHaierAcYrw02FanAuto);
- setSwing(kHaierAcYrw02SwingOff);
- setMode(kHaierAcYrw02Auto);
- setPower(true);
- }
- uint8_t* IRHaierACYRW02::getRaw() {
- checksum();
- return remote_state;
- }
- void IRHaierACYRW02::setRaw(uint8_t new_code[]) {
- for (uint8_t i = 0; i < kHaierACYRW02StateLength; i++) {
- remote_state[i] = new_code[i];
- }
- }
- void IRHaierACYRW02::setButton(uint8_t button) {
- switch (button) {
- case kHaierAcYrw02ButtonTempUp:
- case kHaierAcYrw02ButtonTempDown:
- case kHaierAcYrw02ButtonSwing:
- case kHaierAcYrw02ButtonFan:
- case kHaierAcYrw02ButtonPower:
- case kHaierAcYrw02ButtonMode:
- case kHaierAcYrw02ButtonHealth:
- case kHaierAcYrw02ButtonTurbo:
- case kHaierAcYrw02ButtonSleep:
- remote_state[12] &= 0b11110000;
- remote_state[12] |= (button & 0b00001111);
- }
- }
- uint8_t IRHaierACYRW02::getButton() { return remote_state[12] & (0b00001111); }
- void IRHaierACYRW02::setMode(uint8_t mode) {
- uint8_t new_mode = mode;
- setButton(kHaierAcYrw02ButtonMode);
- switch (mode) {
- case kHaierAcYrw02Auto:
- case kHaierAcYrw02Cool:
- case kHaierAcYrw02Dry:
- case kHaierAcYrw02Heat:
- case kHaierAcYrw02Fan:
- break;
- default: // If unexpected, default to auto mode.
- new_mode = kHaierAcYrw02Auto;
- }
- remote_state[7] &= 0b0001111;
- remote_state[7] |= (new_mode << 4);
- }
- uint8_t IRHaierACYRW02::getMode() { return remote_state[7] >> 4; }
- void IRHaierACYRW02::setTemp(const uint8_t celcius) {
- uint8_t temp = celcius;
- if (temp < kHaierAcMinTemp)
- temp = kHaierAcMinTemp;
- else if (temp > kHaierAcMaxTemp)
- temp = kHaierAcMaxTemp;
- uint8_t old_temp = getTemp();
- if (old_temp == temp) return;
- if (old_temp > temp)
- setButton(kHaierAcYrw02ButtonTempDown);
- else
- setButton(kHaierAcYrw02ButtonTempUp);
- remote_state[1] &= 0b00001111; // Clear the previous temp.
- remote_state[1] |= ((temp - kHaierAcMinTemp) << 4);
- }
- uint8_t IRHaierACYRW02::getTemp() {
- return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp;
- }
- void IRHaierACYRW02::setHealth(bool state) {
- setButton(kHaierAcYrw02ButtonHealth);
- remote_state[3] &= 0b11111101;
- remote_state[3] |= (state << 1);
- }
- bool IRHaierACYRW02::getHealth(void) { return remote_state[3] & 0b00000010; }
- bool IRHaierACYRW02::getPower() { return remote_state[4] & kHaierAcYrw02Power; }
- void IRHaierACYRW02::setPower(bool state) {
- setButton(kHaierAcYrw02ButtonPower);
- if (state)
- remote_state[4] |= kHaierAcYrw02Power;
- else
- remote_state[4] &= ~kHaierAcYrw02Power;
- }
- void IRHaierACYRW02::on() { setPower(true); }
- void IRHaierACYRW02::off() { setPower(false); }
- bool IRHaierACYRW02::getSleep() { return remote_state[8] & kHaierAcYrw02Sleep; }
- void IRHaierACYRW02::setSleep(bool state) {
- setButton(kHaierAcYrw02ButtonSleep);
- if (state)
- remote_state[8] |= kHaierAcYrw02Sleep;
- else
- remote_state[8] &= ~kHaierAcYrw02Sleep;
- }
- uint8_t IRHaierACYRW02::getTurbo() { return remote_state[6] >> 6; }
- void IRHaierACYRW02::setTurbo(uint8_t speed) {
- switch (speed) {
- case kHaierAcYrw02TurboOff:
- case kHaierAcYrw02TurboLow:
- case kHaierAcYrw02TurboHigh:
- remote_state[6] &= 0b00111111;
- remote_state[6] |= (speed << 6);
- setButton(kHaierAcYrw02ButtonTurbo);
- }
- }
- uint8_t IRHaierACYRW02::getFan() { return remote_state[5] >> 4; }
- void IRHaierACYRW02::setFan(uint8_t speed) {
- switch (speed) {
- case kHaierAcYrw02FanLow:
- case kHaierAcYrw02FanMed:
- case kHaierAcYrw02FanHigh:
- case kHaierAcYrw02FanAuto:
- remote_state[5] &= 0b00001111;
- remote_state[5] |= (speed << 4);
- setButton(kHaierAcYrw02ButtonFan);
- }
- }
- uint8_t IRHaierACYRW02::getSwing() { return remote_state[1] & 0b00001111; }
- void IRHaierACYRW02::setSwing(uint8_t state) {
- uint8_t newstate = state;
- switch (state) {
- case kHaierAcYrw02SwingOff:
- case kHaierAcYrw02SwingAuto:
- case kHaierAcYrw02SwingTop:
- case kHaierAcYrw02SwingMiddle:
- case kHaierAcYrw02SwingBottom:
- case kHaierAcYrw02SwingDown:
- setButton(kHaierAcYrw02ButtonSwing);
- break;
- default:
- return; // Unexpected value so don't do anything.
- }
- // Heat mode has no MIDDLE setting, use BOTTOM instead.
- if (state == kHaierAcYrw02SwingMiddle && getMode() == kHaierAcYrw02Heat)
- newstate = kHaierAcYrw02SwingBottom;
- // BOTTOM is only allowed if we are in Heat mode, otherwise MIDDLE.
- if (state == kHaierAcYrw02SwingBottom && getMode() != kHaierAcYrw02Heat)
- newstate = kHaierAcYrw02SwingMiddle;
- remote_state[1] &= 0b11110000;
- remote_state[1] |= newstate;
- }
- // Convert the internal state into a human readable string.
- #ifdef ARDUINO
- String IRHaierACYRW02::toString() {
- String result = "";
- #else
- std::string IRHaierACYRW02::toString() {
- std::string result = "";
- #endif // ARDUINO
- result += "Power: ";
- if (getPower())
- result += "On";
- else
- result += "Off";
- uint8_t cmd = getButton();
- result += ", Button: " + uint64ToString(cmd) + " (";
- switch (cmd) {
- case kHaierAcYrw02ButtonPower:
- result += "Power";
- break;
- case kHaierAcYrw02ButtonMode:
- result += "Mode";
- break;
- case kHaierAcYrw02ButtonFan:
- result += "Fan";
- break;
- case kHaierAcYrw02ButtonTempUp:
- result += "Temp Up";
- break;
- case kHaierAcYrw02ButtonTempDown:
- result += "Temp Down";
- break;
- case kHaierAcYrw02ButtonSleep:
- result += "Sleep";
- break;
- case kHaierAcYrw02ButtonHealth:
- result += "Health";
- break;
- case kHaierAcYrw02ButtonSwing:
- result += "Swing";
- break;
- case kHaierAcYrw02ButtonTurbo:
- result += "Turbo";
- break;
- default:
- result += "Unknown";
- }
- result += ")";
- result += ", Mode: " + uint64ToString(getMode());
- switch (getMode()) {
- case kHaierAcYrw02Auto:
- result += " (Auto)";
- break;
- case kHaierAcYrw02Cool:
- result += " (Cool)";
- break;
- case kHaierAcYrw02Heat:
- result += " (Heat)";
- break;
- case kHaierAcYrw02Dry:
- result += " (Dry)";
- break;
- case kHaierAcYrw02Fan:
- result += " (Fan)";
- break;
- default:
- result += " (UNKNOWN)";
- }
- result += ", Temp: " + uint64ToString(getTemp()) + "C";
- result += ", Fan: " + uint64ToString(getFan());
- switch (getFan()) {
- case kHaierAcYrw02FanAuto:
- result += " (Auto)";
- break;
- case kHaierAcYrw02FanHigh:
- result += " (High)";
- break;
- case kHaierAcYrw02FanLow:
- result += " (Low)";
- break;
- case kHaierAcYrw02FanMed:
- result += " (Med)";
- break;
- default:
- result += " (Unknown)";
- }
- result += ", Turbo: " + uint64ToString(getTurbo()) + " (";
- switch (getTurbo()) {
- case kHaierAcYrw02TurboOff:
- result += "Off";
- break;
- case kHaierAcYrw02TurboLow:
- result += "Low";
- break;
- case kHaierAcYrw02TurboHigh:
- result += "High";
- break;
- default:
- result += "Unknown";
- }
- result += ")";
- result += ", Swing: " + uint64ToString(getSwing()) + " (";
- switch (getSwing()) {
- case kHaierAcYrw02SwingOff:
- result += "Off";
- break;
- case kHaierAcYrw02SwingAuto:
- result += "Auto";
- break;
- case kHaierAcYrw02SwingBottom:
- result += "Bottom";
- break;
- case kHaierAcYrw02SwingDown:
- result += "Down";
- break;
- case kHaierAcYrw02SwingTop:
- result += "Top";
- break;
- case kHaierAcYrw02SwingMiddle:
- result += "Middle";
- break;
- default:
- result += "Unknown";
- }
- result += ")";
- result += ", Sleep: ";
- if (getSleep())
- result += "On";
- else
- result += "Off";
- result += ", Health: ";
- if (getHealth())
- result += "On";
- else
- result += "Off";
- return result;
- }
- // End of IRHaierACYRW02 class.
- #if (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02)
- // Decode the supplied Haier HSU07-HEA03 remote message.
- //
- // Args:
- // results: Ptr to the data to decode and where to store the decode result.
- // nbits: The number of data bits to expect. Typically kHaierACBits.
- // strict: Flag indicating if we should perform strict matching.
- // Returns:
- // boolean: True if it can decode it, false if it can't.
- //
- // Status: BETA / Appears to be working.
- //
- bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits,
- bool strict) {
- if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte.
- return false;
- if (strict) {
- if (nbits != kHaierACBits)
- return false; // Not strictly a HAIER_AC message.
- }
- if (results->rawlen < (2 * nbits + kHeader) + kFooter - 1)
- return false; // Can't possibly be a valid HAIER_AC message.
- uint16_t offset = kStartOffset;
- // Header
- if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false;
- if (!matchSpace(results->rawbuf[offset++], kHaierAcHdr)) return false;
- if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false;
- if (!matchSpace(results->rawbuf[offset++], kHaierAcHdrGap)) return false;
- // Data
- for (uint16_t i = 0; i < nbits / 8; i++) {
- match_result_t data_result =
- matchData(&(results->rawbuf[offset]), 8, kHaierAcBitMark,
- kHaierAcOneSpace, kHaierAcBitMark, kHaierAcZeroSpace);
- if (data_result.success == false) return false;
- offset += data_result.used;
- results->state[i] = (uint8_t)data_result.data;
- }
- // Footer
- if (!matchMark(results->rawbuf[offset++], kHaierAcBitMark)) return false;
- if (offset < results->rawlen &&
- !matchAtLeast(results->rawbuf[offset++], kHaierAcMinGap))
- return false;
- // Compliance
- if (strict) {
- if (results->state[0] != kHaierAcPrefix) return false;
- if (!IRHaierAC::validChecksum(results->state, nbits / 8)) return false;
- }
- // Success
- results->decode_type = HAIER_AC;
- results->bits = nbits;
- return true;
- }
- #endif // (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02)
- #if DECODE_HAIER_AC_YRW02
- // Decode the supplied Haier YR-W02 remote A/C message.
- //
- // Args:
- // results: Ptr to the data to decode and where to store the decode result.
- // nbits: The number of data bits to expect. Typically kHaierACYRW02Bits.
- // strict: Flag indicating if we should perform strict matching.
- // Returns:
- // boolean: True if it can decode it, false if it can't.
- //
- // Status: BETA / Appears to be working.
- //
- bool IRrecv::decodeHaierACYRW02(decode_results* results, uint16_t nbits,
- bool strict) {
- if (strict) {
- if (nbits != kHaierACYRW02Bits)
- return false; // Not strictly a HAIER_AC_YRW02 message.
- }
- // The protocol is almost exactly the same as HAIER_AC
- if (!decodeHaierAC(results, nbits, false)) return false;
- // Compliance
- if (strict) {
- if (results->state[0] != kHaierAcYrw02Prefix) return false;
- if (!IRHaierACYRW02::validChecksum(results->state, nbits / 8)) return false;
- }
- // Success
- // It looks correct, but we haven't check the checksum etc.
- results->decode_type = HAIER_AC_YRW02;
- return true;
- }
- #endif // DECODE_HAIER_AC_YRW02
|