Fujitsu: Add support for ARREW4E model. (#1456)

* All Models:
  - Add `setId()` & `getId()` for controlling multiple A/C units in the same area. (`IRFujitsuAC` class only)
  - Relax tests in `decodeFujitsu()` to match different IDs.
  - Tweak timing tolerance for `decodeFujitsu()` to improve matching.
* `ARREW4E` models
  - Support new temperature setting style.
    * Half degrees (Celsius) e.g. `25.5`
    * Native Fahrenheit support.
    * Allow _Outside Quiet_, _Powerful_, & _Economy_ settings.
    * Add support for _10C Heat_ setting. (`IRFujitsuAC` class only)
* Improve header messages in generated `IRtext.h`

Fixes #1455
This commit is contained in:
David Conran
2021-04-18 08:08:09 +10:00
committed by GitHub
parent 02c76513a1
commit 635ec85164
12 changed files with 562 additions and 162 deletions

View File

@@ -893,6 +893,7 @@ void IRac::electra(IRElectraAc *ac,
/// @param[in] model The A/C model to use.
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
@@ -905,6 +906,7 @@ void IRac::electra(IRElectraAc *ac,
/// @param[in] sleep Nr. of minutes for sleep mode. <= 0 is Off, > 0 is on.
void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model,
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 stdAc::swingh_t swingh,
const bool quiet, const bool turbo, const bool econo,
@@ -933,7 +935,7 @@ void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model,
}
// Normal operation.
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setTemp(degrees, celsius);
ac->setFanSpeed(ac->convertFan(fan));
uint8_t swing = kFujitsuAcSwingOff;
if (swingv > stdAc::swingv_t::kOff) swing |= kFujitsuAcSwingVert;
@@ -2485,7 +2487,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
IRFujitsuAC ac(_pin, (fujitsu_ac_remote_model_t)send.model, _inverted,
_modulation);
fujitsu(&ac, (fujitsu_ac_remote_model_t)send.model, send.power, send.mode,
degC, send.fanspeed, send.swingv, send.swingh, send.quiet,
send.celsius, send.degrees, send.fanspeed,
send.swingv, send.swingh, send.quiet,
send.turbo, send.econo, send.filter, send.clean);
break;
}

View File

@@ -224,7 +224,8 @@ void electra(IRElectraAc *ac,
#endif // SEND_ELECTRA_AC
#if SEND_FUJITSU_AC
void fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model,
const bool on, const stdAc::opmode_t mode, const float degrees,
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 stdAc::swingh_t swingh,
const bool quiet, const bool turbo, const bool econo,

View File

@@ -127,6 +127,7 @@ enum fujitsu_ac_remote_model_t {
///< control)
ARJW2, ///< (4) AR-JW2 (Same as ARDB1 but with horiz control)
ARRY4, ///< (5) AR-RY4 (Same as AR-RAH2E but with clean & filter)
ARREW4E, ///< (6) Similar to ARRAH2E, but with different temp config.
};
/// Gree A/C model numbers

View File

@@ -56,7 +56,8 @@ const PROGMEM char* kIonStr = D_STR_ION; ///< "Ion"
const PROGMEM char* kFreshStr = D_STR_FRESH; ///< "Fresh"
const PROGMEM char* kHoldStr = D_STR_HOLD; ///< "Hold"
const PROGMEM char* kButtonStr = D_STR_BUTTON; ///< "Button"
const PROGMEM char* k8CHeatStr = D_STR_8C_HEAT; ///< "8CHeat"
const PROGMEM char* k8CHeatStr = D_STR_8C_HEAT; ///< "8C Heat"
const PROGMEM char* k10CHeatStr = D_STR_10C_HEAT; ///< "10C Heat"
const PROGMEM char* kNightStr = D_STR_NIGHT; ///< "Night"
const PROGMEM char* kSilentStr = D_STR_SILENT; ///< "Silent"
const PROGMEM char* kFilterStr = D_STR_FILTER; ///< "Filter"
@@ -97,6 +98,7 @@ const PROGMEM char* kRoomStr = D_STR_ROOM; ///< "Room"
const PROGMEM char* k6thSenseStr = D_STR_6THSENSE; ///< "6th Sense"
const PROGMEM char* kTypeStr = D_STR_TYPE; ///< "Type"
const PROGMEM char* kSpecialStr = D_STR_SPECIAL; ///< "Special"
const PROGMEM char* kIdStr = D_STR_ID; ///< "Id" / Device Identifier
const PROGMEM char* kAutoStr = D_STR_AUTO; ///< "Auto"
const PROGMEM char* kAutomaticStr = D_STR_AUTOMATIC; ///< "Automatic"

View File

@@ -1,8 +1,8 @@
// Copyright 2019 - David Conran (@crankyoldgit)
// Copyright 2019-2021 - David Conran (@crankyoldgit)
// This header file is to be included in files **other than** 'IRtext.cpp'.
//
// WARNING: Do not edit this file! This file is automatically generated by
// 'tools/generate_irtext_h.sh'.
// '../tools/generate_irtext_h.sh'.
#ifndef IRTEXT_H_
#define IRTEXT_H_
@@ -13,6 +13,7 @@
// This means there is only one copy of the character/string/text etc.
extern char kTimeSep;
extern const char* k10CHeatStr;
extern const char* k3DStr;
extern const char* k6thSenseStr;
extern const char* k8CHeatStr;
@@ -66,6 +67,7 @@ extern const char* kHoldStr;
extern const char* kHoursStr;
extern const char* kHourStr;
extern const char* kHumidStr;
extern const char* kIdStr;
extern const char* kIFeelStr;
extern const char* kInsideStr;
extern const char* kIonStr;

View File

@@ -507,6 +507,7 @@ namespace irutils {
case fujitsu_ac_remote_model_t::ARREB1E: return F("ARREB1E");
case fujitsu_ac_remote_model_t::ARJW2: return F("ARJW2");
case fujitsu_ac_remote_model_t::ARRY4: return F("ARRY4");
case fujitsu_ac_remote_model_t::ARREW4E: return F("ARREW4E");
default: return kUnknownStr;
}
break;

View File

@@ -1,5 +1,5 @@
// Copyright 2017 Jonny Graham
// Copyright 2017-2019 David Conran
// Copyright 2017-2021 David Conran
// Copyright 2021 siriuslzx
/// @file
@@ -28,6 +28,7 @@ const uint16_t kFujitsuAcBitMark = 448;
const uint16_t kFujitsuAcOneSpace = 1182;
const uint16_t kFujitsuAcZeroSpace = 390;
const uint16_t kFujitsuAcMinGap = 8100;
const uint8_t kFujitsuAcExtraTolerance = 5; // Extra tolerance percentage.
using irutils::addBoolToString;
using irutils::addIntToString;
@@ -35,7 +36,7 @@ using irutils::addLabeledString;
using irutils::addModeToString;
using irutils::addModelToString;
using irutils::addFanToString;
using irutils::addTempToString;
using irutils::addTempFloatToString;
using irutils::minsToString;
#if SEND_FUJITSU_AC
@@ -147,6 +148,7 @@ bool IRFujitsuAC::updateUseLongOrShort(void) {
case fujitsu_ac_remote_model_t::ARRY4:
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARREW4E:
_.Cmd = 0xFE;
break;
case fujitsu_ac_remote_model_t::ARDB1:
@@ -165,19 +167,20 @@ void IRFujitsuAC::checkSum(void) {
if (updateUseLongOrShort()) { // Is it a long code?
// Nr. of bytes in the message after this byte.
_.RestLength = _state_length - 7;
_.longcode[7] = 0x30;
_.Power = (_cmd == kFujitsuAcCmdTurnOn);
_.Protocol = (_model == fujitsu_ac_remote_model_t::ARREW4E) ? 0x31 : 0x30;
_.Power = (_cmd == kFujitsuAcCmdTurnOn) || get10CHeat();
// These values depend on model
if (_model != fujitsu_ac_remote_model_t::ARREB1E) {
if (_model != fujitsu_ac_remote_model_t::ARREB1E &&
_model != fujitsu_ac_remote_model_t::ARREW4E) {
_.OutsideQuiet = 0;
if (_model != fujitsu_ac_remote_model_t::ARRAH2E) {
_.TimerType = kFujitsuAcStopTimers;
}
}
if (_model != fujitsu_ac_remote_model_t::ARRY4) {
_.Clean = 0;
_.Filter = 0;
if (_model != fujitsu_ac_remote_model_t::ARREW4E) _.Clean = false;
_.Filter = false;
}
// Set the On/Off/Sleep timer Nr of mins.
_.OffTimer = getOffSleepTimer();
@@ -215,6 +218,7 @@ void IRFujitsuAC::checkSum(void) {
case fujitsu_ac_remote_model_t::ARRY4:
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARREW4E:
// The last byte is the inverse of penultimate byte
_.shortcode[_state_length_short - 1] =
~_.shortcode[_state_length_short - 2];
@@ -278,9 +282,9 @@ void IRFujitsuAC::buildFromState(const uint16_t length) {
// Currently the only way we know how to tell ARRAH2E & ARRY4 apart is if
// either the raw Filter or Clean setting is on.
if (_model == fujitsu_ac_remote_model_t::ARRAH2E && (_.Filter || _.Clean))
setModel(fujitsu_ac_remote_model_t::ARRY4);
setModel(fujitsu_ac_remote_model_t::ARRY4);
if (_state_length == kFujitsuAcStateLength && _.OutsideQuiet)
setModel(fujitsu_ac_remote_model_t::ARREB1E);
setModel(fujitsu_ac_remote_model_t::ARREB1E);
switch (_.Cmd) {
case kFujitsuAcCmdTurnOff:
case kFujitsuAcCmdStepHoriz:
@@ -292,6 +296,7 @@ void IRFujitsuAC::buildFromState(const uint16_t length) {
setCmd(_.Cmd);
break;
}
if (_.Protocol == 0x31) setModel(fujitsu_ac_remote_model_t::ARREW4E);
}
/// Set the internal state from a valid code for this protocol.
@@ -362,6 +367,7 @@ void IRFujitsuAC::setCmd(const uint8_t cmd) {
switch (_model) {
// Only these remotes have these commands.
case ARREB1E:
case ARREW4E:
_cmd = cmd;
break;
default:
@@ -406,24 +412,70 @@ void IRFujitsuAC::setOutsideQuiet(const bool on) {
/// @return true, the setting is on. false, the setting is off.
bool IRFujitsuAC::getOutsideQuiet(void) const {
switch (_model) {
// Only ARREB1E seems to have this mode.
case fujitsu_ac_remote_model_t::ARREB1E: return _.OutsideQuiet;
// Only ARREB1E & ARREW4E seems to have this mode.
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARREW4E:
return _.OutsideQuiet;
default: return false;
}
}
/// Set the temperature.
/// @param[in] temp The temperature in degrees celsius.
void IRFujitsuAC::setTemp(const uint8_t temp) {
uint8_t t = std::max((uint8_t)kFujitsuAcMinTemp, temp);
t = std::min((uint8_t)kFujitsuAcMaxTemp, t);
_.Temp = t - kFujitsuAcMinTemp;
/// @param[in] temp The temperature in degrees.
/// @param[in] useCelsius Use Celsius or Fahrenheit?
void IRFujitsuAC::setTemp(const float temp, const bool useCelsius) {
float mintemp;
float maxtemp;
uint8_t offset;
bool _useCelsius;
float _temp;
switch (_model) {
// These models have native Fahrenheit & Celsius upport.
case fujitsu_ac_remote_model_t::ARREW4E:
_useCelsius = useCelsius;
_temp = temp;
break;
// Make sure everything else uses Celsius.
default:
_useCelsius = true;
_temp = useCelsius ? temp : fahrenheitToCelsius(temp);
}
setCelsius(_useCelsius);
if (_useCelsius) {
mintemp = kFujitsuAcMinTemp;
maxtemp = kFujitsuAcMaxTemp;
offset = kFujitsuAcTempOffsetC;
} else {
mintemp = kFujitsuAcMinTempF;
maxtemp = kFujitsuAcMaxTempF;
offset = kFujitsuAcTempOffsetF;
}
_temp = std::max(mintemp, _temp);
_temp = std::min(maxtemp, _temp);
if (_useCelsius) {
if (_model == fujitsu_ac_remote_model_t::ARREW4E)
_.Temp = (_temp - (offset / 2)) * 2;
else
_.Temp = (_temp - offset) * 4;
} else {
_.Temp = _temp - offset;
}
setCmd(kFujitsuAcCmdStayOn); // No special command involved.
}
/// Get the current temperature setting.
/// @return The current setting for temp. in degrees celsius.
uint8_t IRFujitsuAC::getTemp(void) const { return _.Temp + kFujitsuAcMinTemp; }
/// @return The current setting for temp. in degrees of the currently set units.
float IRFujitsuAC::getTemp(void) const {
if (_model == fujitsu_ac_remote_model_t::ARREW4E) {
if (_.Fahrenheit) // Currently only ARREW4E supports native Fahrenheit.
return _.Temp + kFujitsuAcTempOffsetF;
else
return (_.Temp / 2.0) + (kFujitsuAcMinTemp / 2);
} else {
return _.Temp / 4 + kFujitsuAcMinTemp;
}
}
/// Set the speed of the fan.
/// @param[in] fanSpeed The desired setting.
@@ -515,6 +567,35 @@ bool IRFujitsuAC::getFilter(void) const {
}
}
/// Set the 10C heat status of the A/C.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRFujitsuAC::set10CHeat(const bool on) {
switch (_model) {
// Only selected models support this.
case fujitsu_ac_remote_model_t::ARREW4E:
setClean(on); // 10C Heat uses the same bit as Clean
if (on) {
_.Mode = kFujitsuAcModeFan;
_.Power = true;
_.Fan = kFujitsuAcFanAuto;
_.Swing = kFujitsuAcSwingOff;
}
default:
break;
}
}
/// Get the 10C heat status of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRFujitsuAC::get10CHeat(void) const {
switch (_model) {
case fujitsu_ac_remote_model_t::ARREW4E:
return (_.Clean && _.Power && _.Mode == kFujitsuAcModeFan &&
_.Fan == kFujitsuAcFanAuto && _.Swing == kFujitsuAcSwingOff);
default: return false;
}
}
/// Get the Timer type of the A/C message.
/// @return The current timer type in numeric form.
uint8_t IRFujitsuAC::getTimerType(void) const {
@@ -623,6 +704,22 @@ bool IRFujitsuAC::validChecksum(uint8_t state[], const uint16_t length) {
return checksum == (uint8_t)(sum_complement - sum); // Does it match?
}
/// Set the device's remote ID number.
/// @param[in] num The ID for the remote. Valid number range is 0 to 3.
void IRFujitsuAC::setId(const uint8_t num) { _.Id = num; }
/// Get the current device's remote ID number.
/// @return The current device's remote ID number.
uint8_t IRFujitsuAC::getId(void) const { return _.Id; }
/// Set the Temperature units for the A/C.
/// @param[in] on true, use Celsius. false, use Fahrenheit.
void IRFujitsuAC::setCelsius(const bool on) { _.Fahrenheit = !on; }
/// Get the Clean mode status of the A/C.
/// @return true, the setting is on. false, the setting is off.
bool IRFujitsuAC::getCelsius(void) const { return !_.Fahrenheit; }
/// Convert a stdAc::opmode_t enum into its native mode.
/// @param[in] mode The enum to be converted.
/// @return The native equivalent of the enum.
@@ -684,7 +781,7 @@ stdAc::state_t IRFujitsuAC::toCommon(void) const {
result.model = _model;
result.power = getPower();
result.mode = toCommonMode(_.Mode);
result.celsius = true;
result.celsius = getCelsius();
result.degrees = getTemp();
result.fanspeed = toCommonFanSpeed(_.Fan);
uint8_t swing = _.Swing;
@@ -726,11 +823,12 @@ String IRFujitsuAC::toString(void) const {
result.reserve(100); // Reserve some heap for the string to reduce fragging.
fujitsu_ac_remote_model_t model = _model;
result += addModelToString(decode_type_t::FUJITSU_AC, model, false);
result += addIntToString(_.Id, kIdStr);
result += addBoolToString(getPower(), kPowerStr);
result += addModeToString(_.Mode, kFujitsuAcModeAuto, kFujitsuAcModeCool,
kFujitsuAcModeHeat, kFujitsuAcModeDry,
kFujitsuAcModeFan);
result += addTempToString(getTemp());
result += addTempFloatToString(getTemp(), getCelsius());
result += addFanToString(_.Fan, kFujitsuAcFanHigh, kFujitsuAcFanLow,
kFujitsuAcFanAuto, kFujitsuAcFanQuiet,
kFujitsuAcFanMed);
@@ -739,9 +837,16 @@ String IRFujitsuAC::toString(void) const {
case fujitsu_ac_remote_model_t::ARDB1:
case fujitsu_ac_remote_model_t::ARJW2:
break;
default: // Assume everything else does.
// These models have Clean & Filter, plus Swing (via fall thru)
case fujitsu_ac_remote_model_t::ARRAH2E:
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARRY4:
result += addBoolToString(getClean(), kCleanStr);
result += addBoolToString(getFilter(), kFilterStr);
// FALL THRU
default: // e.g. ARREW4E
if (model == fujitsu_ac_remote_model_t::ARREW4E)
result += addBoolToString(get10CHeat(), k10CHeatStr);
result += addIntToString(_.Swing, kSwingStr);
result += kSpaceLBraceStr;
switch (_.Swing) {
@@ -801,6 +906,7 @@ String IRFujitsuAC::toString(void) const {
String type_str = kTimerStr;
switch (model) {
case fujitsu_ac_remote_model_t::ARREB1E:
case fujitsu_ac_remote_model_t::ARREW4E:
result += addBoolToString(getOutsideQuiet(), kOutsideQuietStr);
// FALL THRU
// These models seem to have timer support.
@@ -858,32 +964,30 @@ bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t offset,
}
}
// Header
if (!matchMark(results->rawbuf[offset++], kFujitsuAcHdrMark)) return false;
if (!matchSpace(results->rawbuf[offset++], kFujitsuAcHdrSpace)) return false;
// Data (Fixed signature)
match_result_t data_result =
matchData(&(results->rawbuf[offset]), kFujitsuAcMinBits - 8,
kFujitsuAcBitMark, kFujitsuAcOneSpace, kFujitsuAcBitMark,
kFujitsuAcZeroSpace, _tolerance, kMarkExcess, false);
if (data_result.success == false) return false; // Fail
if (data_result.data != 0x1010006314) return false; // Signature failed.
// Header / Some of the Data
uint16_t used = matchGeneric(results->rawbuf + offset, results->state,
results->rawlen - offset, kFujitsuAcMinBits - 8,
kFujitsuAcHdrMark, kFujitsuAcHdrSpace, // Header
kFujitsuAcBitMark, kFujitsuAcOneSpace, // Data
kFujitsuAcBitMark, kFujitsuAcZeroSpace,
0, 0, // No Footer (yet)
false, _tolerance + kFujitsuAcExtraTolerance, 0,
false); // LSBF
if (!used) return false;
offset += used;
// Check we have the typical data header.
if (results->state[0] != 0x14 || results->state[1] != 0x63) return false;
dataBitsSoFar += kFujitsuAcMinBits - 8;
offset += data_result.used;
results->state[0] = 0x14;
results->state[1] = 0x63;
results->state[2] = 0x00;
results->state[3] = 0x10;
results->state[4] = 0x10;
// Keep reading bytes until we either run out of message or state to fill.
match_result_t data_result;
for (uint16_t i = 5;
offset <= results->rawlen - 16 && i < kFujitsuAcStateLength;
i++, dataBitsSoFar += 8, offset += data_result.used) {
data_result = matchData(
&(results->rawbuf[offset]), 8, kFujitsuAcBitMark, kFujitsuAcOneSpace,
kFujitsuAcBitMark, kFujitsuAcZeroSpace, _tolerance, kMarkExcess, false);
kFujitsuAcBitMark, kFujitsuAcZeroSpace,
_tolerance + kFujitsuAcExtraTolerance, 0, false);
if (data_result.success == false) break; // Fail
results->state[i] = data_result.data;
}

View File

@@ -1,5 +1,5 @@
// Copyright 2017 Jonny Graham
// Copyright 2018-2019 David Conran
// Copyright 2018-2021 David Conran
// Copyright 2021 siriuslzx
/// @file
@@ -31,6 +31,8 @@
// Brand: Fujitsu, Model: ASU30C1 A/C (ARDB1)
// Brand: Fujitsu, Model: AR-RAH1U remote (ARREB1E)
// Brand: Fujitsu, Model: ASU12RLF A/C (ARREB1E)
// Brand: Fujitsu, Model: AR-REW4E remote (ARREW4E)
// Brand: Fujitsu, Model: ASYG09KETA-B A/C (ARREW4E)
#ifndef IR_FUJITSU_H_
#define IR_FUJITSU_H_
@@ -54,21 +56,27 @@ union FujitsuProtocol {
uint8_t shortcode[kFujitsuAcStateLengthShort];
};
struct {
// Byte 0~4
uint64_t :40;
// Byte 0~1
uint64_t :16; // Fixed header
// Byte 2
uint64_t :4;
uint64_t Id :2; // Device Number/Identifier
uint64_t :2;
// Byte 3-4
uint64_t :16;
// Byte 5
uint64_t Cmd :8; // short codes:cmd; long codes:fixed value
uint64_t Cmd :8; // short codes:cmd; long codes:fixed value
// Byte 6
uint64_t RestLength :8; // Nr. of bytes in the message after this byte.
// Byte 7
uint64_t :8;
uint64_t Protocol :8; // Seems like a protocol version number. Not sure.
// Byte 8
uint64_t Power :1;
uint64_t :3;
uint64_t Temp :4;
uint64_t Power :1;
uint64_t Fahrenheit :1;
uint64_t Temp :6; // Internal representation varies between models.
// Byte 9
uint64_t Mode :3;
uint64_t Clean :1;
uint64_t Clean :1; // Also 10C Heat in ARREW4E.
uint64_t TimerType :2;
uint64_t :2;
// Byte 10
@@ -89,16 +97,16 @@ union FujitsuProtocol {
uint64_t :1;
uint64_t OutsideQuiet :1;
// Byte 15
uint64_t :0;
uint64_t :0; // Checksum
};
};
// Constants
const uint8_t kFujitsuAcModeAuto = 0x00;
const uint8_t kFujitsuAcModeCool = 0x01;
const uint8_t kFujitsuAcModeDry = 0x02;
const uint8_t kFujitsuAcModeFan = 0x03;
const uint8_t kFujitsuAcModeHeat = 0x04;
const uint8_t kFujitsuAcModeAuto = 0x0; // 0b000
const uint8_t kFujitsuAcModeCool = 0x1; // 0b001
const uint8_t kFujitsuAcModeDry = 0x2; // 0b010
const uint8_t kFujitsuAcModeFan = 0x3; // 0b011
const uint8_t kFujitsuAcModeHeat = 0x4; // 0b100
const uint8_t kFujitsuAcCmdStayOn = 0x00; // b00000000
const uint8_t kFujitsuAcCmdTurnOn = 0x01; // b00000001
@@ -116,8 +124,12 @@ const uint8_t kFujitsuAcFanMed = 0x02;
const uint8_t kFujitsuAcFanLow = 0x03;
const uint8_t kFujitsuAcFanQuiet = 0x04;
const uint8_t kFujitsuAcMinTemp = 16; // 16C
const uint8_t kFujitsuAcMaxTemp = 30; // 30C
const float kFujitsuAcMinTemp = 16; // 16C
const float kFujitsuAcMaxTemp = 30; // 30C
const uint8_t kFujitsuAcTempOffsetC = kFujitsuAcMinTemp;
const float kFujitsuAcMinTempF = 60; // 60F
const float kFujitsuAcMaxTempF = 88; // 88F
const uint8_t kFujitsuAcTempOffsetF = 44;
const uint8_t kFujitsuAcSwingOff = 0x00;
const uint8_t kFujitsuAcSwingVert = 0x01;
@@ -146,8 +158,8 @@ const uint16_t kFujitsuAcTimerMax = 12 * 60; ///< Minutes.
#define FUJITSU_AC_FAN_MED kFujitsuAcFanMed
#define FUJITSU_AC_FAN_LOW kFujitsuAcFanLow
#define FUJITSU_AC_FAN_QUIET kFujitsuAcFanQuiet
#define FUJITSU_AC_MIN_TEMP kFujitsuAcMinTemp
#define FUJITSU_AC_MAX_TEMP kFujitsuAcMaxTemp
#define FUJITSU_AC_MIN_TEMP kFujitsuAcMinTempC
#define FUJITSU_AC_MAX_TEMP kFujitsuAcMaxTempC
#define FUJITSU_AC_SWING_OFF kFujitsuAcSwingOff
#define FUJITSU_AC_SWING_VERT kFujitsuAcSwingVert
#define FUJITSU_AC_SWING_HORIZ kFujitsuAcSwingHoriz
@@ -178,8 +190,8 @@ class IRFujitsuAC {
void toggleSwingVert(const bool update = true);
void setCmd(const uint8_t cmd);
uint8_t getCmd(void) const;
void setTemp(const uint8_t temp);
uint8_t getTemp(void) const;
void setTemp(const float temp, const bool useCelsius = true);
float getTemp(void) const;
void setFanSpeed(const uint8_t fan);
uint8_t getFanSpeed(void) const;
void setMode(const uint8_t mode);
@@ -198,6 +210,8 @@ class IRFujitsuAC {
bool getClean(void) const;
void setFilter(const bool on);
bool getFilter(void) const;
void set10CHeat(const bool on);
bool get10CHeat(void) const;
void setOutsideQuiet(const bool on);
bool getOutsideQuiet(void) const;
uint8_t getTimerType(void) const;
@@ -207,6 +221,10 @@ class IRFujitsuAC {
uint16_t getOffSleepTimer(void) const;
void setOffTimer(const uint16_t nr_mins);
void setSleepTimer(const uint16_t nr_mins);
void setId(const uint8_t num);
uint8_t getId(void) const;
void setCelsius(const bool on);
bool getCelsius(void) const;
static uint8_t convertMode(const stdAc::opmode_t mode);
static uint8_t convertFan(stdAc::fanspeed_t speed);
static stdAc::opmode_t toCommonMode(const uint8_t mode);

View File

@@ -135,6 +135,9 @@
#ifndef D_STR_8C_HEAT
#define D_STR_8C_HEAT "8C " D_STR_HEAT // Set `D_STR_HEAT` first!
#endif // D_STR_8C_HEAT
#ifndef D_STR_10C_HEAT
#define D_STR_10C_HEAT "10C " D_STR_HEAT // Set `D_STR_HEAT` first!
#endif // D_STR_10C_HEAT
#ifndef D_STR_BUTTON
#define D_STR_BUTTON "Button"
#endif // D_STR_BUTTON
@@ -273,6 +276,9 @@
#ifndef D_STR_RECYCLE
#define D_STR_RECYCLE "Recycle"
#endif // D_STR_RECYCLE
#ifndef D_STR_ID
#define D_STR_ID "Id"
#endif // D_STR_ID
#ifndef D_STR_AUTO
#define D_STR_AUTO "Auto"

View File

@@ -585,21 +585,26 @@ TEST(TestIRac, Fujitsu) {
IRac irac(kGpioUnused);
IRrecv capture(kGpioUnused);
std::string ardb1_expected =
"Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 19C, "
"Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 2 (Medium), Command: N/A";
std::string arrah2e_expected =
"Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 19C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 2 (Medium), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Sleep Timer: 03:00";
std::string arry4_expected =
"Model: 5 (ARRY4), Power: On, Mode: 1 (Cool), Temp: 19C, "
"Model: 5 (ARRY4), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 2 (Medium), Clean: On, Filter: On, Swing: 0 (Off), Command: N/A";
std::string arrew4e_expected =
"Model: 6 (ARREW4E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 73F, "
"Fan: 1 (High), 10C Heat: Off, Swing: 0 (Off), Command: N/A, "
"Outside Quiet: Off, Timer: Off";
ac.begin();
irac.fujitsu(&ac,
ARDB1, // Model
true, // Power
stdAc::opmode_t::kCool, // Mode
19, // Celsius
true, // Celsius
19, // Degrees
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
@@ -622,7 +627,8 @@ TEST(TestIRac, Fujitsu) {
ARRAH2E, // Model
true, // Power
stdAc::opmode_t::kCool, // Mode
19, // Celsius
true, // Celsius
19, // Degrees
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
@@ -644,7 +650,8 @@ TEST(TestIRac, Fujitsu) {
fujitsu_ac_remote_model_t::ARRY4, // Model
true, // Power
stdAc::opmode_t::kCool, // Mode
19, // Celsius
true, // Celsius
19, // Degrees
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
@@ -660,6 +667,28 @@ TEST(TestIRac, Fujitsu) {
ASSERT_EQ(kFujitsuAcBits, ac._irsend.capture.bits);
ASSERT_EQ(arry4_expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
ac._irsend.reset();
irac.fujitsu(&ac,
ARREW4E, // Model
true, // Power
stdAc::opmode_t::kCool, // Mode
false, // Fahrenheit
73, // Degrees
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
false, // Turbo (Powerful)
false, // Econo
false, // Filter
false); // Clean
ASSERT_EQ(arrew4e_expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kFujitsuAcBits, ac._irsend.capture.bits);
ASSERT_EQ(arrew4e_expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
}
TEST(TestIRac, Goodweather) {

View File

@@ -10,7 +10,7 @@
// Test sending typical data only.
TEST(TestIRFujitsuACClass, GetRawDefault) {
IRFujitsuAC ac(0); // AR-RAH2E
IRFujitsuAC ac(kGpioUnused); // AR-RAH2E
ac.setSwing(kFujitsuAcSwingBoth);
ac.setMode(kFujitsuAcModeCool);
ac.setFanSpeed(kFujitsuAcFanHigh);
@@ -21,7 +21,7 @@ TEST(TestIRFujitsuACClass, GetRawDefault) {
0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD};
EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, "
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off",
ac.toString());
@@ -32,19 +32,19 @@ TEST(TestIRFujitsuACClass, GetRawDefault) {
ac.setModel(ARDB1);
EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 15 * 8);
EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 24C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Command: N/A",
ac.toString());
}
TEST(TestIRFujitsuACClass, GetRawTurnOff) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
ac.setModel(ARRAH2E);
ac.off();
uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD};
EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8);
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Power: Off, Mode: 1 (Cool), Temp: 24C, "
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: N/A, Timer: Off",
ac.toString());
@@ -53,33 +53,33 @@ TEST(TestIRFujitsuACClass, GetRawTurnOff) {
uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02};
EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 6 * 8);
EXPECT_EQ(kFujitsuAcStateLengthShort - 1, ac.getStateLength());
EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 1 (Cool), Temp: 24C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: Off, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Command: N/A",
ac.toString());
}
TEST(TestIRFujitsuACClass, GetRawStepHoriz) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
ac.stepHoriz();
uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x79, 0x86};
EXPECT_STATE_EQ(expected, ac.getRaw(), 7 * 8);
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), "
"Command: Step Swing(H), Timer: Off",
ac.toString());
}
TEST(TestIRFujitsuACClass, GetRawStepVert) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
ac.setModel(ARRAH2E);
ac.stepVert();
uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93};
EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 7 * 8);
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 3 (Swing(V)+Swing(H)), "
"Command: Step Swing(V), Timer: Off",
ac.toString());
@@ -90,13 +90,13 @@ TEST(TestIRFujitsuACClass, GetRawStepVert) {
EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), 6 * 8);
EXPECT_EQ(kFujitsuAcStateLengthShort - 1,
ac.getStateLength());
EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 24C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Command: Step Swing(V)",
ac.toString());
}
TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
ac.setCmd(kFujitsuAcCmdStayOn);
ac.setSwing(kFujitsuAcSwingHoriz);
ac.setMode(kFujitsuAcModeCool);
@@ -105,14 +105,14 @@ TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) {
uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30,
0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB};
EXPECT_STATE_EQ(expected, ac.getRaw(), 16 * 8);
EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 25C, "
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 25C, "
"Fan: 4 (Quiet), Clean: Off, Filter: Off, "
"Swing: 2 (Swing(H)), Command: N/A, Timer: Off",
ac.toString());
}
TEST(TestIRFujitsuACClass, GetRawWithFan) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
ac.setCmd(kFujitsuAcCmdStayOn);
ac.setSwing(kFujitsuAcSwingHoriz);
ac.setMode(kFujitsuAcModeFan);
@@ -125,7 +125,7 @@ TEST(TestIRFujitsuACClass, GetRawWithFan) {
0x40, 0x03, 0x22, 0x00, 0x00, 0x00, 0x20, 0x4B};
EXPECT_STATE_EQ(expected_arrah2e, ac.getRaw(), 16 * 8);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 3 (Fan), Temp: 20C, "
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 3 (Fan), Temp: 20C, "
"Fan: 2 (Medium), Clean: Off, Filter: Off, "
"Swing: 2 (Swing(H)), Command: N/A, Timer: Off",
ac.toString());
@@ -136,19 +136,19 @@ TEST(TestIRFujitsuACClass, GetRawWithFan) {
0x40, 0x03, 0x02, 0x00, 0x00, 0x00, 0x8B};
EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
EXPECT_STATE_EQ(expected_ardb1, ac.getRaw(), ac.getStateLength() * 8);
EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 3 (Fan), Temp: 20C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: On, Mode: 3 (Fan), Temp: 20C, "
"Fan: 2 (Medium), Command: N/A", ac.toString());
}
TEST(TestIRFujitsuACClass, SetRaw) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
uint8_t expected_default_arrah2e[kFujitsuAcStateLength] = {
0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30,
0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD};
EXPECT_STATE_EQ(expected_default_arrah2e, ac.getRaw(),
ac.getStateLength() * 8);
EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, "
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Clean: Off, Filter: Off, "
"Swing: 3 (Swing(V)+Swing(H)), Command: N/A, "
"Timer: Off",
@@ -161,13 +161,13 @@ TEST(TestIRFujitsuACClass, SetRaw) {
ac.setRaw(new_state1, kFujitsuAcStateLength - 1);
EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
EXPECT_STATE_EQ(new_state1, ac.getRaw(), ac.getStateLength() * 8);
EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 19C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 0 (Auto), Command: N/A", ac.toString());
}
TEST(TestSendFujitsuAC, GenerateMessage) {
IRFujitsuAC ac(0);
IRsendTest irsend(0);
IRFujitsuAC ac(kGpioUnused);
IRsendTest irsend(kGpioUnused);
ac.begin();
irsend.begin();
@@ -209,8 +209,8 @@ TEST(TestSendFujitsuAC, GenerateMessage) {
}
TEST(TestSendFujitsuAC, GenerateShortMessage) {
IRFujitsuAC ac(0);
IRsendTest irsend(0);
IRFujitsuAC ac(kGpioUnused);
IRsendTest irsend(kGpioUnused);
ac.begin();
irsend.begin();
@@ -234,8 +234,8 @@ TEST(TestSendFujitsuAC, GenerateShortMessage) {
// Issue #275
TEST(TestSendFujitsuAC, Issue275) {
IRFujitsuAC ac(0);
IRsendTest irsend(0);
IRFujitsuAC ac(kGpioUnused);
IRsendTest irsend(kGpioUnused);
ac.begin();
irsend.begin();
irsend.reset();
@@ -301,9 +301,9 @@ TEST(TestSendFujitsuAC, Issue275) {
}
TEST(TestDecodeFujitsuAC, SyntheticShortMessages) {
IRsendTest irsend(0);
IRFujitsuAC ac(0);
IRrecv irrecv(0);
IRsendTest irsend(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
@@ -318,7 +318,7 @@ TEST(TestDecodeFujitsuAC, SyntheticShortMessages) {
uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD};
EXPECT_STATE_EQ(expected_arrah2e, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: Off, Mode: 0 (Auto), Temp: 16C, "
"Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 0 (Auto), Temp: 16C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
IRAcUtils::resultAcToString(&irsend.capture));
@@ -339,9 +339,9 @@ TEST(TestDecodeFujitsuAC, SyntheticShortMessages) {
}
TEST(TestDecodeFujitsuAC, SyntheticLongMessages) {
IRsendTest irsend(0);
IRFujitsuAC ac(0);
IRrecv irrecv(0);
IRsendTest irsend(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
@@ -364,7 +364,7 @@ TEST(TestDecodeFujitsuAC, SyntheticLongMessages) {
EXPECT_STATE_EQ(expected_arrah2e, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ("Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 18C, "
EXPECT_EQ("Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 18C, "
"Fan: 4 (Quiet), Clean: Off, Filter: Off, "
"Swing: 1 (Swing(V)), Command: N/A, "
"Timer: Off",
@@ -384,14 +384,14 @@ TEST(TestDecodeFujitsuAC, SyntheticLongMessages) {
EXPECT_STATE_EQ(expected_ardb1, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 18C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 18C, "
"Fan: 4 (Quiet), Command: N/A", ac.toString());
}
TEST(TestDecodeFujitsuAC, RealShortARDB1OffExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRFujitsuAC ac(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
irsend.begin();
@@ -416,14 +416,14 @@ TEST(TestDecodeFujitsuAC, RealShortARDB1OffExample) {
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(kFujitsuAcStateLengthShort - 1, ac.getStateLength());
EXPECT_EQ("Model: 2 (ARDB1), Power: Off, Mode: 0 (Auto), Temp: 16C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: Off, Mode: 0 (Auto), Temp: 16C, "
"Fan: 0 (Auto), Command: N/A", ac.toString());
}
TEST(TestDecodeFujitsuAC, RealLongARDB1Example) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRFujitsuAC ac(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
irsend.begin();
irsend.reset();
@@ -460,7 +460,7 @@ TEST(TestDecodeFujitsuAC, RealLongARDB1Example) {
EXPECT_STATE_EQ(expected1, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 18C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 18C, "
"Fan: 4 (Quiet), Command: N/A", ac.toString());
irsend.reset();
@@ -497,14 +497,14 @@ TEST(TestDecodeFujitsuAC, RealLongARDB1Example) {
EXPECT_STATE_EQ(expected2, irsend.capture.state, irsend.capture.bits);
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(kFujitsuAcStateLength - 1, ac.getStateLength());
EXPECT_EQ("Model: 2 (ARDB1), Power: On, Mode: 1 (Cool), Temp: 19C, "
EXPECT_EQ("Model: 2 (ARDB1), Id: 0, Power: On, Mode: 1 (Cool), Temp: 19C, "
"Fan: 0 (Auto), Command: N/A", ac.toString());
}
TEST(TestDecodeFujitsuAC, Issue414) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRFujitsuAC ac(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
// Capture as supplied by arpmota
uint16_t rawData[259] = {3352, 1574, 480, 350, 480, 346, 480, 1190, 458, 346,
@@ -540,7 +540,7 @@ TEST(TestDecodeFujitsuAC, Issue414) {
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 4 (Heat), Temp: 24C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 4 (Heat), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
ac.toString());
@@ -576,7 +576,7 @@ TEST(TestDecodeFujitsuAC, Issue414) {
}
TEST(TestIRFujitsuACClass, toCommon) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
ac.setMode(kFujitsuAcModeCool);
ac.setTemp(20);
ac.setFanSpeed(kFujitsuAcFanQuiet);
@@ -609,7 +609,7 @@ TEST(TestIRFujitsuACClass, toCommon) {
ASSERT_FALSE(ac.toCommon().power);
ac.send();
ac.stateReset();
IRrecv irrecv(0);
IRrecv irrecv(kGpioUnused);
ac._irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&ac._irsend.capture));
ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type);
@@ -617,7 +617,7 @@ TEST(TestIRFujitsuACClass, toCommon) {
// Now test it.
EXPECT_EQ( // Off mode technically has no temp, mode, fan, etc.
"Model: 1 (ARRAH2E), Power: Off, Mode: 0 (Auto), Temp: 16C, "
"Model: 1 (ARRAH2E), Id: 0, Power: Off, Mode: 0 (Auto), Temp: 16C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
ac.toString());
@@ -644,9 +644,9 @@ TEST(TestIRFujitsuACClass, toCommon) {
}
TEST(TestDecodeFujitsuAC, Issue716) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRFujitsuAC ac(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
// Powerful command from a raw data capture.
// Capture as supplied by u4mzu4
@@ -673,7 +673,7 @@ TEST(TestDecodeFujitsuAC, Issue716) {
ac.setRaw(irsend.capture.state, irsend.capture.bits / 8);
EXPECT_EQ(fujitsu_ac_remote_model_t::ARREB1E, ac.getModel());
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (Auto), Temp: 16C, "
EXPECT_EQ("Model: 3 (ARREB1E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 16C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), "
"Command: Powerful, Outside Quiet: Off, "
"Timer: Off",
@@ -689,7 +689,7 @@ TEST(TestDecodeFujitsuAC, Issue716) {
ac.setRaw(econo, kFujitsuAcStateLengthShort);
EXPECT_EQ(fujitsu_ac_remote_model_t::ARREB1E, ac.getModel());
EXPECT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_EQ("Model: 3 (ARREB1E), Power: On, Mode: 0 (Auto), Temp: 16C, "
EXPECT_EQ("Model: 3 (ARREB1E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 16C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), "
"Command: Econo, Outside Quiet: Off, "
"Timer: Off",
@@ -697,9 +697,9 @@ TEST(TestDecodeFujitsuAC, Issue716) {
}
TEST(TestIRFujitsuACClass, OutsideQuiet) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRFujitsuAC ac(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
ASSERT_NE(fujitsu_ac_remote_model_t::ARDB1,
fujitsu_ac_remote_model_t::ARREB1E);
@@ -722,12 +722,12 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) {
// We can really only tell the difference between ARRAH2E & ARREB1E if
// the option is set. Otheriwse they appear the same.
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 1 (Cool), Temp: 24C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), "
"Command: N/A, Timer: Off", ac.toString());
ac.setModel(fujitsu_ac_remote_model_t::ARREB1E);
EXPECT_EQ(
"Model: 3 (ARREB1E), Power: On, Mode: 1 (Cool), Temp: 24C, "
"Model: 3 (ARREB1E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), "
"Command: N/A, Outside Quiet: Off, Timer: Off",
ac.toString());
@@ -739,7 +739,7 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) {
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_TRUE(ac.getOutsideQuiet());
EXPECT_EQ(
"Model: 3 (ARREB1E), Power: On, Mode: 1 (Cool), Temp: 24C, "
"Model: 3 (ARREB1E), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), "
"Command: N/A, Outside Quiet: On, Timer: Off",
ac.toString());
@@ -753,9 +753,9 @@ TEST(TestIRFujitsuACClass, OutsideQuiet) {
}
TEST(TestIRFujitsuACClass, toggleSwing) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRFujitsuAC ac(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
ac.begin();
ac.setModel(ARJW2);
@@ -788,8 +788,8 @@ TEST(TestIRFujitsuACClass, toggleSwing) {
EXPECT_EQ(kFujitsuAcSwingBoth, ac.getSwing());
EXPECT_EQ(
"Model: 4 (ARJW2), Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 1 (High), "
"Command: Toggle Swing(H)",
"Model: 4 (ARJW2), Id: 0, Power: On, Mode: 1 (Cool), Temp: 24C, "
"Fan: 1 (High), Command: Toggle Swing(H)",
ac.toString());
// Test without the update set.
@@ -802,9 +802,9 @@ TEST(TestIRFujitsuACClass, toggleSwing) {
}
TEST(TestDecodeFujitsuAC, Issue726) {
IRsendTest irsend(0);
IRrecv irrecv(0);
IRFujitsuAC ac(0);
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
IRFujitsuAC ac(kGpioUnused);
// fan:auto mode:auto temp:24 poweron
// Capture as supplied by huexpub
@@ -825,14 +825,14 @@ TEST(TestDecodeFujitsuAC, Issue726) {
EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 24C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 24C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
ac.toString());
}
TEST(TestIRFujitsuACClass, Clean) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
// Data from:
// https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=646887633&range=A27:B30
uint8_t clean_off[kFujitsuAcStateLength] = {
@@ -845,7 +845,7 @@ TEST(TestIRFujitsuACClass, Clean) {
EXPECT_TRUE(ac.getClean());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 5 (ARRY4), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: On, Filter: Off, Swing: 0 (Off), Command: N/A",
ac.toString());
ac.setClean(false);
@@ -858,7 +858,7 @@ TEST(TestIRFujitsuACClass, Clean) {
EXPECT_FALSE(ac.getClean());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
ac.toString());
@@ -866,7 +866,7 @@ TEST(TestIRFujitsuACClass, Clean) {
ac.setClean(true);
EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, ac.getModel());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
ac.toString());
@@ -874,13 +874,13 @@ TEST(TestIRFujitsuACClass, Clean) {
ac.setModel(fujitsu_ac_remote_model_t::ARRY4);
EXPECT_TRUE(ac.getClean());
EXPECT_EQ(
"Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 5 (ARRY4), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: On, Filter: Off, Swing: 0 (Off), Command: N/A",
ac.toString());
}
TEST(TestIRFujitsuACClass, Filter) {
IRFujitsuAC ac(0);
IRFujitsuAC ac(kGpioUnused);
// Data from:
// https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit#gid=646887633&range=A27:B30
uint8_t filter_on[kFujitsuAcStateLength] = {
@@ -893,7 +893,7 @@ TEST(TestIRFujitsuACClass, Filter) {
EXPECT_TRUE(ac.getFilter());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 5 (ARRY4), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: On, Swing: 0 (Off), Command: N/A",
ac.toString());
ac.setFilter(false);
@@ -904,7 +904,7 @@ TEST(TestIRFujitsuACClass, Filter) {
EXPECT_FALSE(ac.getFilter());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Timer: Off",
ac.toString());
@@ -915,7 +915,7 @@ TEST(TestIRFujitsuACClass, Filter) {
ac.setModel(fujitsu_ac_remote_model_t::ARRY4);
EXPECT_TRUE(ac.getFilter());
EXPECT_EQ(
"Model: 5 (ARRY4), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 5 (ARRY4), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 0 (Auto), Clean: Off, Filter: On, Swing: 0 (Off), Command: N/A",
ac.toString());
}
@@ -933,7 +933,7 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(12 * 60, ac.getOnTimer());
EXPECT_EQ(0, ac.getOffSleepTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"On Timer: 12:00",
ac.toString());
@@ -947,7 +947,7 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(8 * 60 + 30, ac.getOnTimer());
EXPECT_EQ(0, ac.getOffSleepTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"On Timer: 08:30",
ac.toString());
@@ -962,7 +962,7 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(11 * 60, ac.getOffSleepTimer());
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Off Timer: 11:00",
ac.toString());
@@ -977,7 +977,7 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(30, ac.getOffSleepTimer());
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Off Timer: 00:30",
ac.toString());
@@ -992,7 +992,7 @@ TEST(TestIRFujitsuACClass, Timers) {
EXPECT_EQ(3 * 60, ac.getOffSleepTimer());
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Sleep Timer: 03:00",
ac.toString());
@@ -1010,7 +1010,7 @@ TEST(TestIRFujitsuACClass, Timers) {
ac.setOffTimer(30);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Off Timer: 00:30",
ac.toString());
@@ -1019,7 +1019,7 @@ TEST(TestIRFujitsuACClass, Timers) {
ac.setOnTimer(12 * 60);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"On Timer: 12:00",
ac.toString());
@@ -1032,10 +1032,242 @@ TEST(TestIRFujitsuACClass, Timers) {
ac.setSleepTimer(3 * 60);
EXPECT_EQ(
"Model: 1 (ARRAH2E), Power: On, Mode: 0 (Auto), Temp: 26C, "
"Model: 1 (ARRAH2E), Id: 0, Power: On, Mode: 0 (Auto), Temp: 26C, "
"Fan: 1 (High), Clean: Off, Filter: Off, Swing: 0 (Off), Command: N/A, "
"Sleep Timer: 03:00",
ac.toString());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
EXPECT_STATE_EQ(timer_sleep_3h, ac.getRaw(), ac.getStateLength() * 8);
}
TEST(TestIRFujitsuACClass, ARREW4E) {
IRFujitsuAC ac(kGpioUnused);
uint8_t on_18_cool_auto[kFujitsuAcStateLength] = {
0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x31,
0x50, 0x01, 0x00, 0x21, 0x03, 0x20, 0x20, 0x1A};
EXPECT_TRUE(ac.validChecksum(on_18_cool_auto, kFujitsuAcStateLength));
ac.setRaw(on_18_cool_auto, kFujitsuAcStateLength);
EXPECT_EQ(0, ac.getId());
EXPECT_EQ(fujitsu_ac_remote_model_t::ARREW4E, ac.getModel());
EXPECT_EQ(18, ac.getTemp());
uint8_t mode_C_power_on_18[kFujitsuAcStateLength] = {
0x14, 0x63, 0x20, 0x10, 0x10, 0xFE, 0x09, 0x31,
0x51, 0x01, 0x00, 0x17, 0x07, 0x54, 0x20, 0xEB};
EXPECT_TRUE(ac.validChecksum(mode_C_power_on_18, kFujitsuAcStateLength));
ac.setRaw(mode_C_power_on_18, kFujitsuAcStateLength);
EXPECT_EQ(2, ac.getId());
EXPECT_EQ(fujitsu_ac_remote_model_t::ARREW4E, ac.getModel());
EXPECT_EQ(18, ac.getTemp());
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
irsend.sendFujitsuAC(mode_C_power_on_18, kFujitsuAcStateLength);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
ASSERT_EQ(kFujitsuAcStateLength * 8, irsend.capture.bits);
EXPECT_STATE_EQ(mode_C_power_on_18, irsend.capture.state,
irsend.capture.bits);
}
TEST(TestDecodeFujitsuAC, Issue1455) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
uint16_t rawData[259] = {
3220, 1700, 354, 446, 380, 448, 380, 1296, 352, 446, 382, 1296, 354, 448,
380, 448, 378, 446, 382, 1296, 352, 1296, 354, 448, 378, 446, 380, 446,
382, 1294, 354, 1270, 380, 448, 380, 446, 380, 448, 380, 446, 380, 450,
378, 448, 380, 446, 380, 448, 380, 448, 380, 448, 380, 450, 376, 450, 380,
448, 378, 1298, 352, 448, 378, 448, 380, 448, 380, 448, 378, 450, 378,
450, 378, 448, 378, 1296, 354, 446, 382, 446, 380, 448, 378, 448, 380,
1296, 352, 1296, 354, 1296, 354, 1272, 376, 1272, 378, 1296, 354, 1294,
354, 1296, 354, 446, 380, 448, 378, 1296, 354, 448, 378, 448, 378, 448,
380, 446, 380, 1272, 378, 446, 380, 450, 378, 448, 378, 1296, 354, 1296,
354, 446, 380, 448, 378, 448, 378, 446, 382, 446, 380, 1296, 354, 1296,
354, 446, 380, 1296, 354, 446, 380, 446, 380, 446, 380, 1294, 354, 448,
380, 448, 380, 448, 380, 448, 380, 446, 380, 448, 380, 446, 380, 448,
380, 446, 380, 446, 380, 448, 380, 446, 380, 448, 380, 448, 380, 446, 380,
1296, 352, 446, 380, 1296, 354, 446, 380, 448, 380, 448, 380, 1296, 354,
448, 378, 448, 380, 446, 380, 446, 382, 446, 380, 446, 382, 446, 380,
1272, 378, 446, 380, 446, 382, 1294, 354, 446, 382, 1294, 354, 446, 382,
446, 382, 446, 380, 448, 380, 448, 380, 448, 380, 448, 378, 1296, 354,
446, 382, 446, 380, 1296, 354, 446, 382, 1296, 354, 446, 382, 1294, 354,
446, 382, 446, 380, 446, 382}; // UNKNOWN 8383D7DE
irsend.sendRaw(rawData, 259, 38);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type);
ASSERT_EQ(kFujitsuAcStateLength * 8, irsend.capture.bits);
EXPECT_EQ(
"Model: 6 (ARREW4E), Id: 0, Power: On, Mode: 4 (Heat), Temp: 19C, "
"Fan: 0 (Auto), 10C Heat: Off, Swing: 0 (Off), Command: N/A, "
"Outside Quiet: Off, Timer: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
}
TEST(TestIRFujitsuACClass, Heat10Deg) {
IRFujitsuAC ac(kGpioUnused);
const uint8_t heat_on[kFujitsuAcStateLength] = {
0x14, 0x63, 0x10, 0x10, 0x10, 0xFE, 0x09, 0x31,
0x69, 0x0B, 0x00, 0x23, 0x06, 0x23, 0x20, 0xEF};
ac.setRaw(heat_on, kFujitsuAcStateLength);
EXPECT_EQ(
"Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, "
"Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, "
"Outside Quiet: Off, Timer: Off",
ac.toString());
ac.stateReset();
ac.setModel(fujitsu_ac_remote_model_t::ARREW4E);
ac.setId(1);
ac.setMode(kFujitsuAcModeFan);
ac.setTemp(21);
ac.setFanSpeed(kFujitsuAcFanAuto);
ac.setSwing(0);
ac.setOutsideQuiet(false);
ac.setPower(true);
ac.set10CHeat(true);
EXPECT_TRUE(ac.get10CHeat());
EXPECT_EQ(
"Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, "
"Fan: 0 (Auto), 10C Heat: On, Swing: 0 (Off), Command: N/A, "
"Outside Quiet: Off, Timer: Off",
ac.toString());
EXPECT_EQ(kFujitsuAcStateLength, ac.getStateLength());
ac.set10CHeat(false);
EXPECT_FALSE(ac.get10CHeat());
EXPECT_EQ(
"Model: 6 (ARREW4E), Id: 1, Power: On, Mode: 3 (Fan), Temp: 21C, "
"Fan: 0 (Auto), 10C Heat: Off, Swing: 0 (Off), Command: N/A, "
"Outside Quiet: Off, Timer: Off",
ac.toString());
// For https://github.com/crankyoldgit/IRremoteESP8266/issues/1455#issuecomment-817339816
ac.set10CHeat(true);
EXPECT_TRUE(ac.get10CHeat());
ac.setFanSpeed(kFujitsuAcFanHigh);
ac.setSwing(kFujitsuAcSwingVert);
EXPECT_FALSE(ac.get10CHeat());
ac.set10CHeat(false);
EXPECT_EQ(kFujitsuAcFanHigh, ac.getFanSpeed());
EXPECT_EQ(kFujitsuAcSwingVert, ac.getSwing());
EXPECT_FALSE(ac.get10CHeat());
ac.set10CHeat(true);
EXPECT_TRUE(ac.get10CHeat());
EXPECT_EQ(kFujitsuAcFanAuto, ac.getFanSpeed());
EXPECT_EQ(kFujitsuAcSwingOff, ac.getSwing());
}
TEST(TestUtils, Housekeeping) {
ASSERT_EQ("FUJITSU_AC", typeToString(decode_type_t::FUJITSU_AC));
ASSERT_EQ(decode_type_t::FUJITSU_AC, strToDecodeType("FUJITSU_AC"));
ASSERT_TRUE(hasACState(decode_type_t::FUJITSU_AC));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::FUJITSU_AC));
ASSERT_EQ(0, IRsend::defaultBits(decode_type_t::FUJITSU_AC)); // No default
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::FUJITSU_AC));
}
TEST(TestIRFujitsuACClass, Temperature) {
IRFujitsuAC ac(kGpioUnused);
// Most models
// Celsius
ac.setModel(fujitsu_ac_remote_model_t::ARRAH2E);
ac.setTemp(kFujitsuAcMinTemp);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(kFujitsuAcMinTemp, ac.getTemp());
ac.setTemp(kFujitsuAcMaxTemp);
EXPECT_EQ(kFujitsuAcMaxTemp, ac.getTemp());
ac.setTemp(kFujitsuAcMinTemp - 1);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(kFujitsuAcMinTemp, ac.getTemp());
ac.setTemp(kFujitsuAcMaxTemp + 1);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(kFujitsuAcMaxTemp, ac.getTemp());
// Fahrenheit (can't be used by most model, check it converts correctly)
ac.setTemp(77, false); // 77F is 25C
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(25, ac.getTemp());
// ARREW4E is different.
ac.setModel(fujitsu_ac_remote_model_t::ARREW4E);
ac.setTemp(kFujitsuAcMinTemp);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(kFujitsuAcMinTemp, ac.getTemp());
ac.setTemp(kFujitsuAcMaxTemp);
EXPECT_EQ(kFujitsuAcMaxTemp, ac.getTemp());
ac.setTemp(kFujitsuAcMinTemp - 1);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(kFujitsuAcMinTemp, ac.getTemp());
ac.setTemp(kFujitsuAcMaxTemp + 1);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(kFujitsuAcMaxTemp, ac.getTemp());
ac.setTemp(22.5);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(22.5, ac.getTemp());
// Fahrenheit
ac.setTemp(77, false);
EXPECT_FALSE(ac.getCelsius());
EXPECT_EQ(77, ac.getTemp());
// Real example
const uint8_t arrew4e_22c[16] = {
0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x31,
0x70, 0x01, 0x00, 0x20, 0x03, 0x58, 0x20, 0xC3};
ac.setRaw(arrew4e_22c, 16);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(22, ac.getTemp());
const uint8_t arrew4e_25_5c[16] = {
0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x31,
0x8C, 0x01, 0x00, 0x21, 0x03, 0x12, 0x20, 0xEC};
ac.setRaw(arrew4e_25_5c, 16);
EXPECT_TRUE(ac.getCelsius());
EXPECT_EQ(25.5, ac.getTemp());
const uint8_t arrew4e_69f[16] = {
0x14, 0x63, 0x20, 0x10, 0x10, 0xFE, 0x09, 0x31,
0x66, 0x04, 0x00, 0x16, 0x01, 0x32, 0x20, 0xFC};
ac.setRaw(arrew4e_69f, 16);
EXPECT_EQ(fujitsu_ac_remote_model_t::ARREW4E, ac.getModel());
EXPECT_FALSE(ac.getCelsius());
EXPECT_EQ(69, ac.getTemp());
}
TEST(TestIRFujitsuACClass, ARREW4EShortCodes) {
// ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1455#issuecomment-817339816
IRFujitsuAC ac(kGpioUnused);
ac.setId(3);
ac.setModel(fujitsu_ac_remote_model_t::ARREW4E);
const uint8_t off[kFujitsuAcStateLengthShort] = {
0x14, 0x63, 0x30, 0x10, 0x10, 0x02, 0xFD};
ac.off();
ASSERT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_STATE_EQ(off, ac.getRaw(), kFujitsuAcStateLengthShort * 8);
const uint8_t econo[kFujitsuAcStateLengthShort] = {
0x14, 0x63, 0x30, 0x10, 0x10, 0x09, 0xF6};
ac.setCmd(kFujitsuAcCmdEcono);
ASSERT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_STATE_EQ(econo, ac.getRaw(), kFujitsuAcStateLengthShort * 8);
const uint8_t powerful[kFujitsuAcStateLengthShort] = {
0x14, 0x63, 0x30, 0x10, 0x10, 0x39, 0xC6};
ac.setCmd(kFujitsuAcCmdPowerful);
ASSERT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_STATE_EQ(powerful, ac.getRaw(), kFujitsuAcStateLengthShort * 8);
const uint8_t stepvert[kFujitsuAcStateLengthShort] = {
0x14, 0x63, 0x30, 0x10, 0x10, 0x6C, 0x93};
ac.setCmd(kFujitsuAcCmdStepVert);
ASSERT_EQ(kFujitsuAcStateLengthShort, ac.getStateLength());
EXPECT_STATE_EQ(stepvert, ac.getRaw(), kFujitsuAcStateLengthShort * 8);
}

View File

@@ -6,14 +6,15 @@ if [[ ! -f ${INPUT} ]]; then
echo "Can't read file '${INPUT}'. Aborting!"
exit 1
fi
# Current year
export YEAR=$(date "+%Y")
# Header
cat >${OUTPUT} << EOF
// Copyright 2019 - David Conran (@crankyoldgit)
// Copyright 2019-${YEAR} - David Conran (@crankyoldgit)
// This header file is to be included in files **other than** 'IRtext.cpp'.
//
// WARNING: Do not edit this file! This file is automatically generated by
// 'tools/generate_irtext_h.sh'.
// '../tools/generate_irtext_h.sh'.
#ifndef IRTEXT_H_
#define IRTEXT_H_