// Copyright 2019 David Conran // Provide a universal/standard interface for sending A/C nessages. // It does not provide complete and maximum granular control but tries // to off most common functionallity across all supported devices. #include "IRac.h" #ifndef UNIT_TEST #include #endif #include #ifndef ARDUINO #include #endif #include "IRsend.h" #include "IRremoteESP8266.h" #include "IRtext.h" #include "IRutils.h" #include "ir_Amcor.h" #include "ir_Argo.h" #include "ir_Coolix.h" #include "ir_Daikin.h" #include "ir_Electra.h" #include "ir_Fujitsu.h" #include "ir_Haier.h" #include "ir_Hitachi.h" #include "ir_Kelvinator.h" #include "ir_Midea.h" #include "ir_Mitsubishi.h" #include "ir_MitsubishiHeavy.h" #include "ir_Neoclima.h" #include "ir_Panasonic.h" #include "ir_Samsung.h" #include "ir_Sharp.h" #include "ir_Tcl.h" #include "ir_Teco.h" #include "ir_Toshiba.h" #include "ir_Trotec.h" #include "ir_Vestel.h" #include "ir_Whirlpool.h" IRac::IRac(const uint16_t pin, const bool inverted, const bool use_modulation) { _pin = pin; _inverted = inverted; _modulation = use_modulation; initState(&next); _prev = next; } void IRac::initState(stdAc::state_t *state, const decode_type_t vendor, const int16_t model, const bool power, const stdAc::opmode_t mode, const float degrees, const bool celsius, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool econo, const bool light, const bool filter, const bool clean, const bool beep, const int16_t sleep, const int16_t clock) { state->protocol = vendor; state->model = model; state->power = power; state->mode = mode; state->degrees = degrees; state->celsius = celsius; state->fanspeed = fan; state->swingv = swingv; state->swingh = swingh; state->quiet = quiet; state->turbo = turbo; state->econo = econo; state->light = light; state->filter = filter; state->clean = clean; state->beep = beep; state->sleep = sleep; state->clock = clock; } void IRac::initState(stdAc::state_t *state) { initState(state, decode_type_t::UNKNOWN, -1, false, stdAc::opmode_t::kOff, 25, true, // 25 degrees Celsius stdAc::fanspeed_t::kAuto, stdAc::swingv_t::kOff, stdAc::swingh_t::kOff, false, false, false, false, false, false, false, -1, -1); } stdAc::state_t IRac::getState(void) { return next; } stdAc::state_t IRac::getStatePrev(void) { return _prev; } // Is the given protocol supported by the IRac class? bool IRac::isProtocolSupported(const decode_type_t protocol) { switch (protocol) { #if SEND_AMCOR case decode_type_t::AMCOR: #endif #if SEND_ARGO case decode_type_t::ARGO: #endif #if SEND_COOLIX case decode_type_t::COOLIX: #endif #if SEND_DAIKIN case decode_type_t::DAIKIN: #endif #if SEND_DAIKIN128 case decode_type_t::DAIKIN128: #endif #if SEND_DAIKIN152 case decode_type_t::DAIKIN152: #endif #if SEND_DAIKIN160 case decode_type_t::DAIKIN160: #endif #if SEND_DAIKIN176 case decode_type_t::DAIKIN176: #endif #if SEND_DAIKIN2 case decode_type_t::DAIKIN2: #endif #if SEND_DAIKIN216 case decode_type_t::DAIKIN216: #endif #if SEND_ELECTRA_AC case decode_type_t::ELECTRA_AC: #endif #if SEND_FUJITSU_AC case decode_type_t::FUJITSU_AC: #endif #if SEND_GOODWEATHER case decode_type_t::GOODWEATHER: #endif #if SEND_GREE case decode_type_t::GREE: #endif #if SEND_HAIER_AC case decode_type_t::HAIER_AC: #endif #if SEND_HAIER_AC_YRW02 case decode_type_t::HAIER_AC_YRW02: #endif #if SEND_HITACHI_AC case decode_type_t::HITACHI_AC: #endif #if SEND_HITACHI_AC424 case decode_type_t::HITACHI_AC424: #endif #if SEND_KELVINATOR case decode_type_t::KELVINATOR: #endif #if SEND_MIDEA case decode_type_t::MIDEA: #endif #if SEND_MITSUBISHI_AC case decode_type_t::MITSUBISHI_AC: #endif #if SEND_MITSUBISHI112 case decode_type_t::MITSUBISHI112: #endif #if SEND_MITSUBISHI136 case decode_type_t::MITSUBISHI136: #endif #if SEND_MITSUBISHIHEAVY case decode_type_t::MITSUBISHI_HEAVY_88: case decode_type_t::MITSUBISHI_HEAVY_152: #endif #if SEND_NEOCLIMA case decode_type_t::NEOCLIMA: #endif #if SEND_PANASONIC_AC case decode_type_t::PANASONIC_AC: #endif #if SEND_SAMSUNG_AC case decode_type_t::SAMSUNG_AC: #endif #if SEND_SHARP_AC case decode_type_t::SHARP_AC: #endif #if SEND_TCL112AC case decode_type_t::TCL112AC: #endif #if SEND_TECO case decode_type_t::TECO: #endif #if SEND_TOSHIBA_AC case decode_type_t::TOSHIBA_AC: #endif #if SEND_TROTEC case decode_type_t::TROTEC: #endif #if SEND_VESTEL_AC case decode_type_t::VESTEL_AC: #endif #if SEND_WHIRLPOOL_AC case decode_type_t::WHIRLPOOL_AC: #endif return true; default: return false; } } #if SEND_AMCOR void IRac::amcor(IRAmcorAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); // No Swing setting available. // No Quiet setting available. // No Light setting available. // No Filter setting available. // No Turbo setting available. // No Economy setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. ac->send(); } #endif // SEND_AMCOR #if SEND_ARGO void IRac::argo(IRArgoAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const int16_t sleep) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setFlap(ac->convertSwingV(swingv)); // No Quiet setting available. // No Light setting available. // No Filter setting available. ac->setMax(turbo); // No Economy setting available. // No Clean setting available. // No Beep setting available. ac->setNight(sleep >= 0); // Convert to a boolean. ac->send(); } #endif // SEND_ARGO #if SEND_COOLIX void IRac::coolix(IRCoolixAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool turbo, const bool light, const bool clean, const int16_t sleep) { ac->begin(); ac->setPower(on); if (!on) { // after turn off AC no more commands should // be accepted ac->send(); return; } ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); // No Filter setting available. // No Beep setting available. // No Clock setting available. // No Econo setting available. // No Quiet setting available. if (swingv != stdAc::swingv_t::kOff || swingh != stdAc::swingh_t::kOff) { // Swing has a special command that needs to be sent independently. ac->setSwing(); ac->send(); } if (turbo) { // Turbo has a special command that needs to be sent independently. ac->setTurbo(); ac->send(); } if (sleep > 0) { // Sleep has a special command that needs to be sent independently. ac->setSleep(); ac->send(); } if (light) { // Light has a special command that needs to be sent independently. ac->setLed(); ac->send(); } if (clean) { // Clean has a special command that needs to be sent independently. ac->setClean(); ac->send(); } ac->send(); } #endif // SEND_COOLIX #if SEND_DAIKIN void IRac::daikin(IRDaikinESP *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool econo, const bool clean) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical((int8_t)swingv >= 0); ac->setSwingHorizontal((int8_t)swingh >= 0); ac->setQuiet(quiet); // No Light setting available. // No Filter setting available. ac->setPowerful(turbo); ac->setEcono(econo); ac->setMold(clean); // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_DAIKIN #if SEND_DAIKIN128 void IRac::daikin128(IRDaikin128 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool quiet, const bool turbo, const bool light, const bool econo, const int16_t sleep, const int16_t clock) { ac->begin(); ac->setPowerToggle(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical((int8_t)swingv >= 0); // No Horizontal Swing setting avaliable. ac->setQuiet(quiet); ac->setLightToggle(light ? kDaikin128BitWall : 0); // No Filter setting available. ac->setPowerful(turbo); ac->setEcono(econo); // No Clean setting available. // No Beep setting available. ac->setSleep(sleep > 0); if (clock >= 0) ac->setClock(clock); ac->send(); } #endif // SEND_DAIKIN128 #if SEND_DAIKIN152 void IRac::daikin152(IRDaikin152 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool quiet, const bool turbo, const bool econo) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingV((int8_t)swingv >= 0); // No Horizontal Swing setting avaliable. ac->setQuiet(quiet); // No Light setting available. // No Filter setting available. ac->setPowerful(turbo); ac->setEcono(econo); // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_DAIKIN152 #if SEND_DAIKIN160 void IRac::daikin160(IRDaikin160 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(ac->convertSwingV(swingv)); ac->send(); } #endif // SEND_DAIKIN160 #if SEND_DAIKIN176 void IRac::daikin176(IRDaikin176 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingh_t swingh) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingHorizontal(ac->convertSwingH(swingh)); ac->send(); } #endif // SEND_DAIKIN176 #if SEND_DAIKIN2 void IRac::daikin2(IRDaikin2 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool light, const bool econo, const bool filter, const bool clean, const bool beep, const int16_t sleep, const int16_t clock) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(ac->convertSwingV(swingv)); ac->setSwingHorizontal(ac->convertSwingH(swingh)); ac->setQuiet(quiet); ac->setLight(light ? 1 : 3); // On/High is 1, Off is 3. ac->setPowerful(turbo); ac->setEcono(econo); ac->setPurify(filter); ac->setMold(clean); ac->setClean(true); // Hardwire auto clean to be on per request (@sheppy99) ac->setBeep(beep ? 2 : 3); // On/Loud is 2, Off is 3. if (sleep > 0) ac->enableSleepTimer(sleep); if (clock >= 0) ac->setCurrentTime(clock); ac->send(); } #endif // SEND_DAIKIN2 #if SEND_DAIKIN216 void IRac::daikin216(IRDaikin216 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical((int8_t)swingv >= 0); ac->setSwingHorizontal((int8_t)swingh >= 0); ac->setQuiet(quiet); ac->setPowerful(turbo); ac->send(); } #endif // SEND_DAIKIN216 #if SEND_ELECTRA_AC void IRac::electra(IRElectraAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingV(swingv != stdAc::swingv_t::kOff); ac->setSwingH(swingh != stdAc::swingh_t::kOff); // No Quiet setting available. // No Turbo setting available. // No Light setting available. // No Econo setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_ELECTRA_AC #if SEND_FUJITSU_AC void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool econo, const bool filter, const bool clean) { ac->begin(); ac->setModel(model); if (on) { // Do all special messages (except "Off") first, // These need to be sent separately. switch (ac->getModel()) { // Some functions are only available on some models. case fujitsu_ac_remote_model_t::ARREB1E: if (turbo) { ac->setCmd(kFujitsuAcCmdPowerful); // Powerful is a separate command. ac->send(); } if (econo) { ac->setCmd(kFujitsuAcCmdEcono); // Econo is a separate command. ac->send(); } break; default: {}; } // Normal operation. ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFanSpeed(ac->convertFan(fan)); uint8_t swing = kFujitsuAcSwingOff; if (swingv > stdAc::swingv_t::kOff) swing |= kFujitsuAcSwingVert; if (swingh > stdAc::swingh_t::kOff) swing |= kFujitsuAcSwingHoriz; ac->setSwing(swing); if (quiet) ac->setFanSpeed(kFujitsuAcFanQuiet); // No Light setting available. ac->setFilter(filter); ac->setClean(clean); // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->on(); // Ref: Issue #860 } else { // Off is special case/message. We don't need to send other messages. ac->off(); } ac->send(); } #endif // SEND_FUJITSU_AC #if SEND_GOODWEATHER void IRac::goodweather(IRGoodweatherAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool light, const int16_t sleep) { ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(swingv == stdAc::swingv_t::kOff ? kGoodweatherSwingOff : kGoodweatherSwingSlow); ac->setTurbo(turbo); ac->setLight(light); // No Clean setting available. ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. // No Horizontal Swing setting available. // No Econo setting available. // No Filter setting available. // No Beep setting available. // No Quiet setting available. // No Clock setting available. ac->setPower(on); ac->send(); } #endif // SEND_GOODWEATHER #if SEND_GREE void IRac::gree(IRGreeAC *ac, const gree_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool light, const bool clean, const int16_t sleep) { ac->begin(); ac->setModel(model); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(swingv == stdAc::swingv_t::kAuto, // Set auto flag. ac->convertSwingV(swingv)); ac->setLight(light); ac->setTurbo(turbo); ac->setXFan(clean); ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. // No Horizontal Swing setting available. // No Econo setting available. // No Filter setting available. // No Beep setting available. // No Quiet setting available. // No Clock setting available. ac->send(); } #endif // SEND_GREE #if SEND_HAIER_AC void IRac::haier(IRHaierAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool filter, const int16_t sleep, const int16_t clock) { ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(ac->convertSwingV(swingv)); // No Horizontal Swing setting available. // No Quiet setting available. // No Turbo setting available. // No Light setting available. ac->setHealth(filter); // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. if (clock >=0) ac->setCurrTime(clock); if (on) ac->setCommand(kHaierAcCmdOn); else ac->setCommand(kHaierAcCmdOff); ac->send(); } #endif // SEND_HAIER_AC #if SEND_HAIER_AC_YRW02 void IRac::haierYrwo2(IRHaierACYRW02 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool filter, const int16_t sleep) { ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(ac->convertSwingV(swingv)); // No Horizontal Swing setting available. // No Quiet setting available. ac->setTurbo(turbo); // No Light setting available. ac->setHealth(filter); // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. ac->setPower(on); ac->send(); } #endif // SEND_HAIER_AC_YRW02 #if SEND_HITACHI_AC void IRac::hitachi(IRHitachiAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(swingv != stdAc::swingv_t::kOff); ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff); // No Quiet setting available. // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_HITACHI_AC #if SEND_HITACHI_AC424 void IRac::hitachi424(IRHitachiAc424 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv) { ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setPower(on); // SwingVToggle is special. Needs to be last method called. ac->setSwingVToggle(swingv != stdAc::swingv_t::kOff); // No Swing(H) setting available. // No Quiet setting available. // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_HITACHI_AC424 #if SEND_KELVINATOR void IRac::kelvinator(IRKelvinatorAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool light, const bool filter, const bool clean) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan((uint8_t)fan); // No conversion needed. ac->setSwingVertical((int8_t)swingv >= 0); ac->setSwingHorizontal((int8_t)swingh >= 0); ac->setQuiet(quiet); ac->setTurbo(turbo); ac->setLight(light); ac->setIonFilter(filter); ac->setXFan(clean); // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_KELVINATOR #if SEND_MIDEA void IRac::midea(IRMideaAC *ac, const bool on, const stdAc::opmode_t mode, const bool celsius, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const int16_t sleep) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setUseCelsius(celsius); ac->setTemp(degrees, celsius); ac->setFan(ac->convertFan(fan)); ac->setSwingVToggle(swingv != stdAc::swingv_t::kOff); // No Horizontal swing setting available. // No Quiet setting available. // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. // No Clock setting available. ac->send(); } #endif // SEND_MIDEA #if SEND_MITSUBISHI_AC void IRac::mitsubishi(IRMitsubishiAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const int16_t clock) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setVane(ac->convertSwingV(swingv)); ac->setWideVane(ac->convertSwingH(swingh)); if (quiet) ac->setFan(kMitsubishiAcFanSilent); // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. if (clock >= 0) ac->setClock(clock / 10); // Clock is in 10 min increments. ac->send(); } #endif // SEND_MITSUBISHI_AC #if SEND_MITSUBISHI112 void IRac::mitsubishi112(IRMitsubishi112 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingV(ac->convertSwingV(swingv)); ac->setSwingH(ac->convertSwingH(swingh)); ac->setQuiet(quiet); // FIXME - Econo // ac->setEcono(econo); // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_MITSUBISHI112 #if SEND_MITSUBISHI136 void IRac::mitsubishi136(IRMitsubishi136 *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool quiet) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingV(ac->convertSwingV(swingv)); // No Horizontal Swing setting available. ac->setQuiet(quiet); // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_MITSUBISHI136 #if SEND_MITSUBISHIHEAVY void IRac::mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool turbo, const bool econo, const bool clean) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(ac->convertSwingV(swingv)); ac->setSwingHorizontal(ac->convertSwingH(swingh)); // No Quiet setting available. ac->setTurbo(turbo); // No Light setting available. ac->setEcono(econo); // No Filter setting available. ac->setClean(clean); // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } void IRac::mitsubishiHeavy152(IRMitsubishiHeavy152Ac *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool econo, const bool filter, const bool clean, const int16_t sleep) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(ac->convertSwingV(swingv)); ac->setSwingHorizontal(ac->convertSwingH(swingh)); ac->setSilent(quiet); ac->setTurbo(turbo); // No Light setting available. ac->setEcono(econo); ac->setClean(clean); ac->setFilter(filter); // No Beep setting available. ac->setNight(sleep >= 0); // Sleep is either on/off, so convert to boolean. // No Clock setting available. ac->send(); } #endif // SEND_MITSUBISHIHEAVY #if SEND_NEOCLIMA void IRac::neoclima(IRNeoclimaAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool turbo, const bool light, const bool filter, const int16_t sleep) { ac->begin(); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingV(swingv != stdAc::swingv_t::kOff); ac->setSwingH(swingh != stdAc::swingh_t::kOff); // No Quiet setting available. ac->setTurbo(turbo); ac->setLight(light); // No Econo setting available. ac->setIon(filter); // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. // No Clock setting available. ac->setPower(on); ac->send(); } #endif // SEND_NEOCLIMA #if SEND_PANASONIC_AC void IRac::panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const int16_t clock) { ac->begin(); ac->setModel(model); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(ac->convertSwingV(swingv)); ac->setSwingHorizontal(ac->convertSwingH(swingh)); ac->setQuiet(quiet); ac->setPowerful(turbo); // No Light setting available. // No Econo setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. if (clock >= 0) ac->setClock(clock); ac->send(); } #endif // SEND_PANASONIC_AC #if SEND_SAMSUNG_AC void IRac::samsung(IRSamsungAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool quiet, const bool turbo, const bool clean, const bool beep, const bool prevpower, const bool forcepower) { ac->begin(); ac->stateReset(forcepower, prevpower); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(swingv != stdAc::swingv_t::kOff); // No Horizontal swing setting available. ac->setQuiet(quiet); ac->setPowerful(turbo); // No Light setting available. // No Econo setting available. // No Filter setting available. ac->setClean(clean); ac->setBeep(beep); // No Sleep setting available. // No Clock setting available. // Do setMode() again as it can affect fan speed. ac->setMode(ac->convertMode(mode)); ac->send(); } #endif // SEND_SAMSUNG_AC #if SEND_SHARP_AC void IRac::sharp(IRSharpAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); // No Vertical swing setting available. // No Horizontal swing setting available. // No Quiet setting available. // No Turbo setting available. // No Light setting available. // No Econo setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. // Do setMode() again as it can affect fan speed and temp. ac->setMode(ac->convertMode(mode)); ac->send(); } #endif // SEND_SHARP_AC #if SEND_TCL112AC void IRac::tcl112(IRTcl112Ac *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool turbo, const bool light, const bool econo, const bool filter) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(swingv != stdAc::swingv_t::kOff); ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff); // No Quiet setting available. ac->setTurbo(turbo); ac->setLight(light); ac->setEcono(econo); ac->setHealth(filter); // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_TCL112AC #if SEND_TECO void IRac::teco(IRTecoAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool light, const int16_t sleep) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(swingv != stdAc::swingv_t::kOff); // No Horizontal swing setting available. // No Quiet setting available. // No Turbo setting available. ac->setLight(light); // No Filter setting available. // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. // No Clock setting available. ac->send(); } #endif // SEND_TECO #if SEND_TOSHIBA_AC void IRac::toshiba(IRToshibaAC *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); // No Vertical swing setting available. // No Horizontal swing setting available. // No Quiet setting available. // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. // No Sleep setting available. // No Clock setting available. ac->send(); } #endif // SEND_TOSHIBA_AC #if SEND_TROTEC void IRac::trotec(IRTrotecESP *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const int16_t sleep) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setSpeed(ac->convertFan(fan)); // No Vertical swing setting available. // No Horizontal swing setting available. // No Quiet setting available. // No Turbo setting available. // No Light setting available. // No Filter setting available. // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. // No Clock setting available. ac->send(); } #endif // SEND_TROTEC #if SEND_VESTEL_AC void IRac::vestel(IRVestelAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool filter, const int16_t sleep, const int16_t clock, const bool sendNormal) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(swingv != stdAc::swingv_t::kOff); // No Horizontal swing setting available. // No Quiet setting available. ac->setTurbo(turbo); // No Light setting available. ac->setIon(filter); // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. if (sendNormal) ac->send(); // Send the normal message. if (clock >= 0) { ac->setTime(clock); ac->send(); // Setting the clock requires a different "timer" message. } } #endif // SEND_VESTEL_AC #if SEND_WHIRLPOOL_AC void IRac::whirlpool(IRWhirlpoolAc *ac, const whirlpool_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool turbo, const bool light, const int16_t sleep, const int16_t clock) { ac->begin(); ac->setModel(model); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(swingv != stdAc::swingv_t::kOff); // No Horizontal swing setting available. // No Quiet setting available. ac->setSuper(turbo); ac->setLight(light); // No Filter setting available // No Clean setting available. // No Beep setting available. ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. if (clock >= 0) ac->setClock(clock); ac->setPowerToggle(on); ac->send(); } #endif // SEND_WHIRLPOOL_AC // Create a new state base on desired & previous states but handle // any state changes for options that need to be toggled. // Args: // desired: The state_t structure describing the desired a/c state. // prev: Ptr to the previous state_t structure. // // Returns: // A stdAc::state_t with the needed settings. stdAc::state_t IRac::handleToggles(const stdAc::state_t desired, const stdAc::state_t *prev) { stdAc::state_t result = desired; // If we've been given a previous state AND the it's the same A/C basically. if (prev != NULL && desired.protocol == prev->protocol && desired.model == prev->model) { // Check if we have to handle toggle settings for specific A/C protocols. switch (desired.protocol) { case decode_type_t::COOLIX: if ((desired.swingv == stdAc::swingv_t::kOff) ^ (prev->swingv == stdAc::swingv_t::kOff)) // It changed, so toggle. result.swingv = stdAc::swingv_t::kAuto; else result.swingv = stdAc::swingv_t::kOff; // No change, so no toggle. result.turbo = desired.turbo ^ prev->turbo; result.light = desired.light ^ prev->light; result.clean = desired.clean ^ prev->clean; result.sleep = ((desired.sleep >= 0) ^ (prev->sleep >= 0)) ? 0 : -1; break; case decode_type_t::DAIKIN128: result.power = desired.power ^ prev->power; result.light = desired.light ^ prev->light; break; case decode_type_t::MIDEA: case decode_type_t::HITACHI_AC424: if ((desired.swingv == stdAc::swingv_t::kOff) ^ (prev->swingv == stdAc::swingv_t::kOff)) // It changed, so toggle. result.swingv = stdAc::swingv_t::kAuto; else result.swingv = stdAc::swingv_t::kOff; // No change, so no toggle. break; case decode_type_t::WHIRLPOOL_AC: result.power = desired.power ^ prev->power; break; case decode_type_t::PANASONIC_AC: // CKP models use a power mode toggle. if (desired.model == panasonic_ac_remote_model_t::kPanasonicCkp) result.power = desired.power ^ prev->power; break; default: {}; } } return result; } // Send A/C message for a given device using common A/C settings. // Args: // vendor: The type of A/C protocol to use. // model: The specific model of A/C if supported/applicable. // on: Should the unit be powered on? (or in some cases, toggled) // mode: What operating mode should the unit perform? e.g. Cool, Heat etc. // degrees: What temperature should the unit be set to? // celsius: Use degrees Celsius, otherwise Fahrenheit. // fan: Fan speed. // The following args are all "if supported" by the underlying A/C classes. // swingv: Control the vertical swing of the vanes. // swingh: Control the horizontal swing of the vanes. // quiet: Set the unit to quiet (fan) operation mode. // turbo: Set the unit to turbo operating mode. e.g. Max fan & cooling etc. // econo: Set the unit to economical operating mode. // light: Turn on the display/LEDs etc. // filter: Turn on any particle/ion/allergy filter etc. // clean: Turn on any settings to reduce mold etc. (Not self-clean mode.) // beep: Control if the unit beeps upon receiving commands. // sleep: Nr. of mins of sleep mode, or use sleep mode. (< 0 means off.) // clock: Nr. of mins past midnight to set the clock to. (< 0 means off.) // Returns: // boolean: True, if accepted/converted/attempted. False, if unsupported. bool IRac::sendAc(const decode_type_t vendor, const int16_t model, const bool power, const stdAc::opmode_t mode, const float degrees, const bool celsius, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool econo, const bool light, const bool filter, const bool clean, const bool beep, const int16_t sleep, const int16_t clock) { stdAc::state_t to_send; initState(&to_send, vendor, model, power, mode, degrees, celsius, fan, swingv, swingh, quiet, turbo, econo, light, filter, clean, beep, sleep, clock); return this->sendAc(to_send, &to_send); } // Send A/C message for a given device using state_t structures. // Args: // desired: The state_t structure describing the desired new a/c state. // prev: Ptr to the previous state_t structure. // // Returns: // boolean: True, if accepted/converted/attempted. False, if unsupported. bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { stdAc::state_t send = this->handleToggles(desired, prev); // Convert the temperature to Celsius. float degC; if (desired.celsius) degC = send.degrees; else degC = fahrenheitToCelsius(desired.degrees); bool on = desired.power; // A hack for Home Assistant, it appears to need/want an Off opmode. if (desired.mode == stdAc::opmode_t::kOff) on = false; // Per vendor settings & setup. switch (send.protocol) { #if SEND_AMCOR case AMCOR: { IRAmcorAc ac(_pin, _inverted, _modulation); amcor(&ac, on, send.mode, degC, send.fanspeed); break; } #endif // SEND_AMCOR #if SEND_ARGO case ARGO: { IRArgoAC ac(_pin, _inverted, _modulation); argo(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, send.sleep); break; } #endif // SEND_ARGO #if SEND_COOLIX case COOLIX: { IRCoolixAC ac(_pin, _inverted, _modulation); coolix(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.turbo, send.light, send.clean, send.sleep); break; } #endif // SEND_COOLIX #if SEND_DAIKIN case DAIKIN: { IRDaikinESP ac(_pin, _inverted, _modulation); daikin(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo, send.econo, send.clean); break; } #endif // SEND_DAIKIN #if SEND_DAIKIN128 case DAIKIN128: { IRDaikin128 ac(_pin, _inverted, _modulation); daikin128(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.quiet, send.turbo, send.light, send.econo, send.sleep, send.clock); break; } #endif // SEND_DAIKIN2 #if SEND_DAIKIN152 case DAIKIN152: { IRDaikin152 ac(_pin, _inverted, _modulation); daikin152(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.quiet, send.turbo, send.econo); break; } #endif // SEND_DAIKIN152 #if SEND_DAIKIN160 case DAIKIN160: { IRDaikin160 ac(_pin, _inverted, _modulation); daikin160(&ac, on, send.mode, degC, send.fanspeed, send.swingv); break; } #endif // SEND_DAIKIN160 #if SEND_DAIKIN176 case DAIKIN176: { IRDaikin176 ac(_pin, _inverted, _modulation); daikin176(&ac, on, send.mode, degC, send.fanspeed, send.swingh); break; } #endif // SEND_DAIKIN176 #if SEND_DAIKIN2 case DAIKIN2: { IRDaikin2 ac(_pin, _inverted, _modulation); daikin2(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo, send.light, send.econo, send.filter, send.clean, send.beep, send.sleep, send.clock); break; } #endif // SEND_DAIKIN2 #if SEND_DAIKIN216 case DAIKIN216: { IRDaikin216 ac(_pin, _inverted, _modulation); daikin216(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo); break; } #endif // SEND_DAIKIN216 #if SEND_ELECTRA_AC case ELECTRA_AC: { IRElectraAc ac(_pin, _inverted, _modulation); electra(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh); break; } #endif // SEND_ELECTRA_AC #if SEND_FUJITSU_AC case FUJITSU_AC: { IRFujitsuAC ac(_pin, (fujitsu_ac_remote_model_t)send.model, _inverted, _modulation); fujitsu(&ac, (fujitsu_ac_remote_model_t)send.model, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo, send.econo, send.filter, send.clean); break; } #endif // SEND_FUJITSU_AC #if SEND_GOODWEATHER case GOODWEATHER: { IRGoodweatherAc ac(_pin, _inverted, _modulation); goodweather(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, send.light, send.sleep); break; } #endif // SEND_GOODWEATHER #if SEND_GREE case GREE: { IRGreeAC ac(_pin, (gree_ac_remote_model_t)send.model, _inverted, _modulation); gree(&ac, (gree_ac_remote_model_t)send.model, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, send.light, send.clean, send.sleep); break; } #endif // SEND_GREE #if SEND_HAIER_AC case HAIER_AC: { IRHaierAC ac(_pin, _inverted, _modulation); haier(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.filter, send.sleep, send.clock); break; } #endif // SEND_HAIER_AC #if SEND_HAIER_AC_YRW02 case HAIER_AC_YRW02: { IRHaierACYRW02 ac(_pin, _inverted, _modulation); haierYrwo2(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, send.filter, send.sleep); break; } #endif // SEND_HAIER_AC_YRW02 #if SEND_HITACHI_AC case HITACHI_AC: { IRHitachiAc ac(_pin, _inverted, _modulation); hitachi(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh); break; } #endif // SEND_HITACHI_AC #if SEND_HITACHI_AC424 case HITACHI_AC424: { IRHitachiAc424 ac(_pin, _inverted, _modulation); hitachi424(&ac, on, send.mode, degC, send.fanspeed, send.swingv); break; } #endif // SEND_HITACHI_AC424 #if SEND_KELVINATOR case KELVINATOR: { IRKelvinatorAC ac(_pin, _inverted, _modulation); kelvinator(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo, send.light, send.filter, send.clean); break; } #endif // SEND_KELVINATOR #if SEND_MIDEA case MIDEA: { IRMideaAC ac(_pin, _inverted, _modulation); midea(&ac, on, send.mode, send.celsius, send.degrees, send.fanspeed, send.swingv, send.sleep); break; } #endif // SEND_MIDEA #if SEND_MITSUBISHI_AC case MITSUBISHI_AC: { IRMitsubishiAC ac(_pin, _inverted, _modulation); mitsubishi(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.clock); break; } #endif // SEND_MITSUBISHI_AC #if SEND_MITSUBISHI112 case MITSUBISHI112: { IRMitsubishi112 ac(_pin, _inverted, _modulation); mitsubishi112(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet); break; } #endif // SEND_MITSUBISHI112 #if SEND_MITSUBISHI136 case MITSUBISHI136: { IRMitsubishi136 ac(_pin, _inverted, _modulation); mitsubishi136(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.quiet); break; } #endif // SEND_MITSUBISHI136 #if SEND_MITSUBISHIHEAVY case MITSUBISHI_HEAVY_88: { IRMitsubishiHeavy88Ac ac(_pin, _inverted, _modulation); mitsubishiHeavy88(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.turbo, send.econo, send.clean); break; } case MITSUBISHI_HEAVY_152: { IRMitsubishiHeavy152Ac ac(_pin, _inverted, _modulation); mitsubishiHeavy152(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo, send.econo, send.filter, send.clean, send.sleep); break; } #endif // SEND_MITSUBISHIHEAVY #if SEND_NEOCLIMA case NEOCLIMA: { IRNeoclimaAc ac(_pin, _inverted, _modulation); neoclima(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.turbo, send.light, send.filter, send.sleep); break; } #endif // SEND_NEOCLIMA #if SEND_PANASONIC_AC case PANASONIC_AC: { IRPanasonicAc ac(_pin, _inverted, _modulation); panasonic(&ac, (panasonic_ac_remote_model_t)send.model, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.quiet, send.turbo, send.clock); break; } #endif // SEND_PANASONIC_AC #if SEND_SAMSUNG_AC case SAMSUNG_AC: { IRSamsungAc ac(_pin, _inverted, _modulation); samsung(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.quiet, send.turbo, send.clean, send.beep, prev->power); break; } #endif // SEND_SAMSUNG_AC #if SEND_SHARP_AC case SHARP_AC: { IRSharpAc ac(_pin, _inverted, _modulation); sharp(&ac, on, send.mode, degC, send.fanspeed); break; } #endif // SEND_SHARP_AC #if SEND_TCL112AC case TCL112AC: { IRTcl112Ac ac(_pin, _inverted, _modulation); tcl112(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.swingh, send.turbo, send.light, send.econo, send.filter); break; } #endif // SEND_TCL112AC #if SEND_TECO case TECO: { IRTecoAc ac(_pin, _inverted, _modulation); teco(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.light, send.sleep); break; } #endif // SEND_TECO #if SEND_TOSHIBA_AC case TOSHIBA_AC: { IRToshibaAC ac(_pin, _inverted, _modulation); toshiba(&ac, on, send.mode, degC, send.fanspeed); break; } #endif // SEND_TOSHIBA_AC #if SEND_TROTEC case TROTEC: { IRTrotecESP ac(_pin, _inverted, _modulation); trotec(&ac, on, send.mode, degC, send.fanspeed, send.sleep); break; } #endif // SEND_TROTEC #if SEND_VESTEL_AC case VESTEL_AC: { IRVestelAc ac(_pin, _inverted, _modulation); vestel(&ac, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, send.filter, send.sleep, send.clock); break; } #endif // SEND_VESTEL_AC #if SEND_WHIRLPOOL_AC case WHIRLPOOL_AC: { IRWhirlpoolAc ac(_pin, _inverted, _modulation); whirlpool(&ac, (whirlpool_ac_remote_model_t)send.model, on, send.mode, degC, send.fanspeed, send.swingv, send.turbo, send.light, send.sleep, send.clock); break; } #endif // SEND_WHIRLPOOL_AC default: return false; // Fail, didn't match anything. } return true; // Success. } // Send an A/C message based soley on our internal state. // // Returns: // boolean: True, if accepted/converted/attempted. False, if unsupported. bool IRac::sendAc(void) { bool success = this->sendAc(next, &_prev); _prev = next; return success; } // Compare two AirCon states. // Returns: True if they differ, False if they don't. // Note: Excludes clock. bool IRac::cmpStates(const stdAc::state_t a, const stdAc::state_t b) { return a.protocol != b.protocol || a.model != b.model || a.power != b.power || a.mode != b.mode || a.degrees != b.degrees || a.celsius != b.celsius || a.fanspeed != b.fanspeed || a.swingv != b.swingv || a.swingh != b.swingh || a.quiet != b.quiet || a.turbo != b.turbo || a.econo != b.econo || a.light != b.light || a.filter != b.filter || a.clean != b.clean || a.beep != b.beep || a.sleep != b.sleep; } bool IRac::hasStateChanged(void) { return cmpStates(next, _prev); } stdAc::opmode_t IRac::strToOpmode(const char *str, const stdAc::opmode_t def) { if (!strcasecmp(str, kAutoStr) || !strcasecmp(str, kAutomaticStr)) return stdAc::opmode_t::kAuto; else if (!strcasecmp(str, kOffStr) || !strcasecmp(str, kStopStr)) return stdAc::opmode_t::kOff; else if (!strcasecmp(str, kCoolStr) || !strcasecmp(str, "COOLING")) return stdAc::opmode_t::kCool; else if (!strcasecmp(str, kHeatStr) || !strcasecmp(str, "HEATING")) return stdAc::opmode_t::kHeat; else if (!strcasecmp(str, kDryStr) || !strcasecmp(str, "DRYING") || !strcasecmp(str, "DEHUMIDIFY")) return stdAc::opmode_t::kDry; else if (!strcasecmp(str, kFanStr) || !strcasecmp(str, "FANONLY") || !strcasecmp(str, kFanOnlyStr)) return stdAc::opmode_t::kFan; else return def; } stdAc::fanspeed_t IRac::strToFanspeed(const char *str, const stdAc::fanspeed_t def) { if (!strcasecmp(str, kAutoStr) || !strcasecmp(str, kAutomaticStr)) return stdAc::fanspeed_t::kAuto; else if (!strcasecmp(str, kMinStr) || !strcasecmp(str, kMinimumStr) || !strcasecmp(str, kLowestStr)) return stdAc::fanspeed_t::kMin; else if (!strcasecmp(str, kLowStr) || !strcasecmp(str, kLoStr)) return stdAc::fanspeed_t::kLow; else if (!strcasecmp(str, kMedStr) || !strcasecmp(str, kMediumStr) || !strcasecmp(str, kMidStr)) return stdAc::fanspeed_t::kMedium; else if (!strcasecmp(str, kHighStr) || !strcasecmp(str, kHiStr)) return stdAc::fanspeed_t::kHigh; else if (!strcasecmp(str, kMaxStr) || !strcasecmp(str, kMaximumStr) || !strcasecmp(str, kHighestStr)) return stdAc::fanspeed_t::kMax; else return def; } stdAc::swingv_t IRac::strToSwingV(const char *str, const stdAc::swingv_t def) { if (!strcasecmp(str, kAutoStr) || !strcasecmp(str, kAutomaticStr) || !strcasecmp(str, kOnStr) || !strcasecmp(str, kSwingStr)) return stdAc::swingv_t::kAuto; else if (!strcasecmp(str, kOffStr) || !strcasecmp(str, kStopStr)) return stdAc::swingv_t::kOff; else if (!strcasecmp(str, kMinStr) || !strcasecmp(str, kMinimumStr) || !strcasecmp(str, kLowestStr) || !strcasecmp(str, kBottomStr) || !strcasecmp(str, kDownStr)) return stdAc::swingv_t::kLowest; else if (!strcasecmp(str, kLowStr)) return stdAc::swingv_t::kLow; else if (!strcasecmp(str, kMidStr) || !strcasecmp(str, kMiddleStr) || !strcasecmp(str, kMedStr) || !strcasecmp(str, kMediumStr) || !strcasecmp(str, kCentreStr)) return stdAc::swingv_t::kMiddle; else if (!strcasecmp(str, kHighStr) || !strcasecmp(str, kHiStr)) return stdAc::swingv_t::kHigh; else if (!strcasecmp(str, kHighestStr) || !strcasecmp(str, kMaxStr) || !strcasecmp(str, kMaximumStr) || !strcasecmp(str, kTopStr) || !strcasecmp(str, kUpStr)) return stdAc::swingv_t::kHighest; else return def; } stdAc::swingh_t IRac::strToSwingH(const char *str, const stdAc::swingh_t def) { if (!strcasecmp(str, kAutoStr) || !strcasecmp(str, kAutomaticStr) || !strcasecmp(str, kOnStr) || !strcasecmp(str, kSwingStr)) return stdAc::swingh_t::kAuto; else if (!strcasecmp(str, kOffStr) || !strcasecmp(str, kStopStr)) return stdAc::swingh_t::kOff; else if (!strcasecmp(str, kLeftMaxStr) || !strcasecmp(str, D_STR_LEFT " " D_STR_MAX) || !strcasecmp(str, D_STR_MAX D_STR_LEFT) || !strcasecmp(str, kMaxLeftStr)) return stdAc::swingh_t::kLeftMax; else if (!strcasecmp(str, kLeftStr)) return stdAc::swingh_t::kLeft; else if (!strcasecmp(str, kMidStr) || !strcasecmp(str, kMiddleStr) || !strcasecmp(str, kMedStr) || !strcasecmp(str, kMediumStr) || !strcasecmp(str, kCentreStr)) return stdAc::swingh_t::kMiddle; else if (!strcasecmp(str, kRightStr)) return stdAc::swingh_t::kRight; else if (!strcasecmp(str, kRightMaxStr) || !strcasecmp(str, D_STR_MAX " " D_STR_RIGHT) || !strcasecmp(str, D_STR_MAX D_STR_RIGHT) || !strcasecmp(str, kMaxRightStr)) return stdAc::swingh_t::kRightMax; else if (!strcasecmp(str, kWideStr)) return stdAc::swingh_t::kWide; else return def; } // Assumes str is the model code or an integer >= 1. int16_t IRac::strToModel(const char *str, const int16_t def) { // Gree if (!strcasecmp(str, "YAW1F")) { return gree_ac_remote_model_t::YAW1F; } else if (!strcasecmp(str, "YBOFB")) { return gree_ac_remote_model_t::YBOFB; // Fujitsu A/C models } else if (!strcasecmp(str, "ARRAH2E")) { return fujitsu_ac_remote_model_t::ARRAH2E; } else if (!strcasecmp(str, "ARDB1")) { return fujitsu_ac_remote_model_t::ARDB1; } else if (!strcasecmp(str, "ARREB1E")) { return fujitsu_ac_remote_model_t::ARREB1E; } else if (!strcasecmp(str, "ARJW2")) { return fujitsu_ac_remote_model_t::ARJW2; } else if (!strcasecmp(str, "ARRY4")) { return fujitsu_ac_remote_model_t::ARRY4; // Panasonic A/C families } else if (!strcasecmp(str, "LKE") || !strcasecmp(str, "PANASONICLKE")) { return panasonic_ac_remote_model_t::kPanasonicLke; } else if (!strcasecmp(str, "NKE") || !strcasecmp(str, "PANASONICNKE")) { return panasonic_ac_remote_model_t::kPanasonicNke; } else if (!strcasecmp(str, "DKE") || !strcasecmp(str, "PANASONICDKE")) { return panasonic_ac_remote_model_t::kPanasonicDke; } else if (!strcasecmp(str, "JKE") || !strcasecmp(str, "PANASONICJKE")) { return panasonic_ac_remote_model_t::kPanasonicJke; } else if (!strcasecmp(str, "CKP") || !strcasecmp(str, "PANASONICCKP")) { return panasonic_ac_remote_model_t::kPanasonicCkp; } else if (!strcasecmp(str, "RKR") || !strcasecmp(str, "PANASONICRKR")) { return panasonic_ac_remote_model_t::kPanasonicRkr; // Whirlpool A/C models } else if (!strcasecmp(str, "DG11J13A") || !strcasecmp(str, "DG11J104") || !strcasecmp(str, "DG11J1-04")) { return whirlpool_ac_remote_model_t::DG11J13A; } else if (!strcasecmp(str, "DG11J191")) { return whirlpool_ac_remote_model_t::DG11J191; } else { int16_t number = atoi(str); if (number > 0) return number; else return def; } } bool IRac::strToBool(const char *str, const bool def) { if (!strcasecmp(str, kOnStr) || !strcasecmp(str, "1") || !strcasecmp(str, kYesStr) || !strcasecmp(str, kTrueStr)) return true; else if (!strcasecmp(str, kOffStr) || !strcasecmp(str, "0") || !strcasecmp(str, kNoStr) || !strcasecmp(str, kFalseStr)) return false; else return def; } String IRac::boolToString(const bool value) { return value ? kOnStr : kOffStr; } String IRac::opmodeToString(const stdAc::opmode_t mode) { switch (mode) { case stdAc::opmode_t::kOff: return kOffStr; case stdAc::opmode_t::kAuto: return kAutoStr; case stdAc::opmode_t::kCool: return kCoolStr; case stdAc::opmode_t::kHeat: return kHeatStr; case stdAc::opmode_t::kDry: return kDryStr; case stdAc::opmode_t::kFan: return kFanOnlyStr; default: return kUnknownStr; } } String IRac::fanspeedToString(const stdAc::fanspeed_t speed) { switch (speed) { case stdAc::fanspeed_t::kAuto: return kAutoStr; case stdAc::fanspeed_t::kMax: return kMaxStr; case stdAc::fanspeed_t::kHigh: return kHighStr; case stdAc::fanspeed_t::kMedium: return kMediumStr; case stdAc::fanspeed_t::kLow: return kLowStr; case stdAc::fanspeed_t::kMin: return kMinStr; default: return kUnknownStr; } } String IRac::swingvToString(const stdAc::swingv_t swingv) { switch (swingv) { case stdAc::swingv_t::kOff: return kOffStr; case stdAc::swingv_t::kAuto: return kAutoStr; case stdAc::swingv_t::kHighest: return kHighestStr; case stdAc::swingv_t::kHigh: return kHighStr; case stdAc::swingv_t::kMiddle: return kMiddleStr; case stdAc::swingv_t::kLow: return kLowStr; case stdAc::swingv_t::kLowest: return kLowestStr; default: return kUnknownStr; } } String IRac::swinghToString(const stdAc::swingh_t swingh) { switch (swingh) { case stdAc::swingh_t::kOff: return kOffStr; case stdAc::swingh_t::kAuto: return kAutoStr; case stdAc::swingh_t::kLeftMax: return kLeftMaxStr; case stdAc::swingh_t::kLeft: return kLeftStr; case stdAc::swingh_t::kMiddle: return kMiddleStr; case stdAc::swingh_t::kRight: return kRightStr; case stdAc::swingh_t::kRightMax: return kRightMaxStr; case stdAc::swingh_t::kWide: return kWideStr; default: return kUnknownStr; } } namespace IRAcUtils { // Display the human readable state of an A/C message if we can. // Args: // result: A Ptr to the captured `decode_results` that contains an A/C mesg. // Returns: // A string with the human description of the A/C message. "" if we can't. String resultAcToString(const decode_results * const result) { switch (result->decode_type) { #if DECODE_AMCOR case decode_type_t::AMCOR: { IRAmcorAc ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_AMCOR #if DECODE_ARGO case decode_type_t::ARGO: { IRArgoAC ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_ARGO #if DECODE_DAIKIN case decode_type_t::DAIKIN: { IRDaikinESP ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_DAIKIN #if DECODE_DAIKIN128 case decode_type_t::DAIKIN128: { IRDaikin128 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_DAIKIN128 #if DECODE_DAIKIN152 case decode_type_t::DAIKIN152: { IRDaikin152 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_DAIKIN152 #if DECODE_DAIKIN160 case decode_type_t::DAIKIN160: { IRDaikin160 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_DAIKIN160 #if DECODE_DAIKIN176 case decode_type_t::DAIKIN176: { IRDaikin176 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_DAIKIN160 #if DECODE_DAIKIN2 case decode_type_t::DAIKIN2: { IRDaikin2 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_DAIKIN2 #if DECODE_DAIKIN216 case decode_type_t::DAIKIN216: { IRDaikin216 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_DAIKIN216 #if DECODE_ELECTRA_AC case decode_type_t::ELECTRA_AC: { IRElectraAc ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_ELECTRA_AC #if DECODE_FUJITSU_AC case decode_type_t::FUJITSU_AC: { IRFujitsuAC ac(0); ac.setRaw(result->state, result->bits / 8); return ac.toString(); } #endif // DECODE_FUJITSU_AC #if DECODE_KELVINATOR case decode_type_t::KELVINATOR: { IRKelvinatorAC ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_KELVINATOR #if DECODE_MITSUBISHI_AC case decode_type_t::MITSUBISHI_AC: { IRMitsubishiAC ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_MITSUBISHI_AC #if DECODE_MITSUBISHI112 case decode_type_t::MITSUBISHI112: { IRMitsubishi112 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_MITSUBISHI112 #if DECODE_MITSUBISHI136 case decode_type_t::MITSUBISHI136: { IRMitsubishi136 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_MITSUBISHI136 #if DECODE_MITSUBISHIHEAVY case decode_type_t::MITSUBISHI_HEAVY_88: { IRMitsubishiHeavy88Ac ac(0); ac.setRaw(result->state); return ac.toString(); } case decode_type_t::MITSUBISHI_HEAVY_152: { IRMitsubishiHeavy152Ac ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_MITSUBISHIHEAVY #if DECODE_NEOCLIMA case decode_type_t::NEOCLIMA: { IRNeoclimaAc ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_NEOCLIMA #if DECODE_TOSHIBA_AC case decode_type_t::TOSHIBA_AC: { IRToshibaAC ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_TOSHIBA_AC #if DECODE_TROTEC case decode_type_t::TROTEC: { IRTrotecESP ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_TROTEC #if DECODE_GOODWEATHER case decode_type_t::GOODWEATHER: { IRGoodweatherAc ac(0); ac.setRaw(result->value); // Goodweather uses value instead of state. return ac.toString(); } #endif // DECODE_GOODWEATHER #if DECODE_GREE case decode_type_t::GREE: { IRGreeAC ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_GREE #if DECODE_MIDEA case decode_type_t::MIDEA: { IRMideaAC ac(0); ac.setRaw(result->value); // Midea uses value instead of state. return ac.toString(); } #endif // DECODE_MIDEA #if DECODE_HAIER_AC case decode_type_t::HAIER_AC: { IRHaierAC ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_HAIER_AC #if DECODE_HAIER_AC_YRW02 case decode_type_t::HAIER_AC_YRW02: { IRHaierACYRW02 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_HAIER_AC_YRW02 #if DECODE_SAMSUNG_AC case decode_type_t::SAMSUNG_AC: { IRSamsungAc ac(0); ac.setRaw(result->state, result->bits / 8); return ac.toString(); } #endif // DECODE_SAMSUNG_AC #if DECODE_SHARP_AC case decode_type_t::SHARP_AC: { IRSharpAc ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_SHARP_AC #if DECODE_COOLIX case decode_type_t::COOLIX: { IRCoolixAC ac(0); ac.on(); ac.setRaw(result->value); // Coolix uses value instead of state. return ac.toString(); } #endif // DECODE_COOLIX #if DECODE_PANASONIC_AC case decode_type_t::PANASONIC_AC: { if (result->bits > kPanasonicAcShortBits) { IRPanasonicAc ac(0); ac.setRaw(result->state); return ac.toString(); } return ""; } #endif // DECODE_PANASONIC_AC #if DECODE_HITACHI_AC case decode_type_t::HITACHI_AC: { IRHitachiAc ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_HITACHI_AC #if DECODE_HITACHI_AC424 case decode_type_t::HITACHI_AC424: { IRHitachiAc424 ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_HITACHI_AC424 #if DECODE_WHIRLPOOL_AC case decode_type_t::WHIRLPOOL_AC: { IRWhirlpoolAc ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_WHIRLPOOL_AC #if DECODE_VESTEL_AC case decode_type_t::VESTEL_AC: { IRVestelAc ac(0); ac.setRaw(result->value); // Like Coolix, use value instead of state. return ac.toString(); } #endif // DECODE_VESTEL_AC #if DECODE_TECO case decode_type_t::TECO: { IRTecoAc ac(0); ac.setRaw(result->value); // Like Coolix, use value instead of state. return ac.toString(); } #endif // DECODE_TECO #if DECODE_TCL112AC case decode_type_t::TCL112AC: { IRTcl112Ac ac(0); ac.setRaw(result->state); return ac.toString(); } #endif // DECODE_TCL112AC default: return ""; } } // Convert a valid IR A/C remote message that we understand enough into a // Common A/C state. // // Args: // decode: A PTR to a successful raw IR decode object. // result: A PTR to a state structure to store the result in. // prev: A PTR to a state structure which has the prev. state. (optional) // Returns: // A boolean indicating success or failure. bool decodeToState(const decode_results *decode, stdAc::state_t *result, const stdAc::state_t *prev) { if (decode == NULL || result == NULL) return false; // Safety check. switch (decode->decode_type) { #if DECODE_AMCOR case decode_type_t::AMCOR: { IRAmcorAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_AMCOR #if DECODE_ARGO case decode_type_t::ARGO: { IRArgoAC ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_ARGO #if DECODE_COOLIX case decode_type_t::COOLIX: { IRCoolixAC ac(kGpioUnused); ac.setRaw(decode->value); // Uses value instead of state. *result = ac.toCommon(prev); break; } #endif // DECODE_COOLIX #if DECODE_DAIKIN case decode_type_t::DAIKIN: { IRDaikinESP ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_DAIKIN #if DECODE_DAIKIN128 case decode_type_t::DAIKIN128: { IRDaikin128 ac(0); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_DAIKIN128 #if DECODE_DAIKIN152 case decode_type_t::DAIKIN152: { IRDaikin152 ac(0); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_DAIKIN152 #if DECODE_DAIKIN160 case decode_type_t::DAIKIN160: { IRDaikin160 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_DAIKIN160 #if DECODE_DAIKIN176 case decode_type_t::DAIKIN176: { IRDaikin176 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_DAIKIN160 #if DECODE_DAIKIN2 case decode_type_t::DAIKIN2: { IRDaikin2 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_DAIKIN2 #if DECODE_DAIKIN216 case decode_type_t::DAIKIN216: { IRDaikin216 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_DAIKIN216 #if DECODE_ELECTRA_AC case decode_type_t::ELECTRA_AC: { IRElectraAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_ELECTRA_AC #if DECODE_FUJITSU_AC case decode_type_t::FUJITSU_AC: { IRFujitsuAC ac(kGpioUnused); ac.setRaw(decode->state, decode->bits / 8); *result = ac.toCommon(); break; } #endif // DECODE_FUJITSU_AC #if DECODE_GOODWEATHER case decode_type_t::GOODWEATHER: { IRGoodweatherAc ac(kGpioUnused); ac.setRaw(decode->value); // Uses value instead of state. *result = ac.toCommon(); break; } #endif // DECODE_GOODWEATHER #if DECODE_GREE case decode_type_t::GREE: { IRGreeAC ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_GREE #if DECODE_HAIER_AC case decode_type_t::HAIER_AC: { IRHaierAC ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_HAIER_AC #if DECODE_HAIER_AC_YRW02 case decode_type_t::HAIER_AC_YRW02: { IRHaierACYRW02 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_HAIER_AC_YRW02 #if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2) case decode_type_t::HITACHI_AC: { IRHitachiAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC2) #if DECODE_HITACHI_AC424 case decode_type_t::HITACHI_AC424: { IRHitachiAc424 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_HITACHI_AC424 #if DECODE_KELVINATOR case decode_type_t::KELVINATOR: { IRKelvinatorAC ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_KELVINATOR #if DECODE_MIDEA case decode_type_t::MIDEA: { IRMideaAC ac(kGpioUnused); ac.setRaw(decode->value); // Uses value instead of state. *result = ac.toCommon(prev); break; } #endif // DECODE_MIDEA #if DECODE_MITSUBISHI_AC case decode_type_t::MITSUBISHI_AC: { IRMitsubishiAC ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_MITSUBISHI_AC #if DECODE_MITSUBISHI112 case decode_type_t::MITSUBISHI112: { IRMitsubishi112 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_MITSUBISHI112 #if DECODE_MITSUBISHI136 case decode_type_t::MITSUBISHI136: { IRMitsubishi136 ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_MITSUBISHI136 #if DECODE_MITSUBISHIHEAVY case decode_type_t::MITSUBISHI_HEAVY_88: { IRMitsubishiHeavy88Ac ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } case decode_type_t::MITSUBISHI_HEAVY_152: { IRMitsubishiHeavy152Ac ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_MITSUBISHIHEAVY #if DECODE_NEOCLIMA case decode_type_t::NEOCLIMA: { IRNeoclimaAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_NEOCLIMA #if DECODE_PANASONIC_AC case decode_type_t::PANASONIC_AC: { IRPanasonicAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_PANASONIC_AC #if DECODE_SAMSUNG_AC case decode_type_t::SAMSUNG_AC: { IRSamsungAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_SAMSUNG_AC #if DECODE_SHARP_AC case decode_type_t::SHARP_AC: { IRSharpAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_SHARP_AC #if DECODE_TCL112AC case decode_type_t::TCL112AC: { IRTcl112Ac ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_TCL112AC #if DECODE_TECO case decode_type_t::TECO: { IRTecoAc ac(kGpioUnused); ac.setRaw(decode->value); // Uses value instead of state. *result = ac.toCommon(); break; } #endif // DECODE_TECO #if DECODE_TOSHIBA_AC case decode_type_t::TOSHIBA_AC: { IRToshibaAC ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_TOSHIBA_AC #if DECODE_TROTEC case decode_type_t::TROTEC: { IRTrotecESP ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_TROTEC #if DECODE_VESTEL_AC case decode_type_t::VESTEL_AC: { IRVestelAc ac(kGpioUnused); ac.setRaw(decode->value); // Uses value instead of state. *result = ac.toCommon(); break; } #endif // DECODE_VESTEL_AC #if DECODE_WHIRLPOOL_AC case decode_type_t::WHIRLPOOL_AC: { IRWhirlpoolAc ac(kGpioUnused); ac.setRaw(decode->state); *result = ac.toCommon(); break; } #endif // DECODE_WHIRLPOOL_AC default: return false; } return true; } } // namespace IRAcUtils