Technibel: Cleanup and code fixes/improvements. (#1266)

* Add Fahrenheit support to `IRac` for Technibel.
* Add checksum verification to `decodeTechnibelAc()`.
* Add unit tests for `IRac::technibel()`
* Fix old horrible typo.
* Add more Technibel Unit tests.
* Fix poor Technibel Unit test.
* [bug] Fix problem with `IRTechnibelAc` initial state not being initalised properly.
* [bug] Fix problem where "Auto" being returned for "Cool" mode. (Auto mode doesn't exist!)
* Lots of minor code style cleanups.
* Refactor some class methods to make them simpler/smaller etc.
* Fix/Add some Doxygen comments.

Ref #1259
This commit is contained in:
David Conran
2020-09-06 23:02:33 +10:00
committed by GitHub
parent 93f82923e2
commit d33297376a
6 changed files with 210 additions and 171 deletions

View File

@@ -1755,18 +1755,19 @@ void IRac::tcl112(IRTcl112Ac *ac,
/// @param[in, out] ac A Ptr to an IRTechnibelAc object 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.
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
void IRac::technibel(IRTechnibelAc *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const int16_t sleep) {
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->setTemp(degrees);
ac->setTemp(degrees, !celsius);
ac->setFan(ac->convertFan(fan));
ac->setSwing(swingv != stdAc::swingv_t::kOff);
// No Horizontal swing setting available.
@@ -2502,8 +2503,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
case TECHNIBEL_AC:
{
IRTechnibelAc ac(_pin, _inverted, _modulation);
technibel(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
send.sleep);
technibel(&ac, send.power, send.mode, send.celsius, send.degrees,
send.fanspeed, send.swingv, send.sleep);
break;
}
#endif // SEND_TECHNIBEL_AC

View File

@@ -384,9 +384,9 @@ void electra(IRElectraAc *ac,
#endif // SEND_TCL112AC
#if SEND_TECHNIBEL_AC
void technibel(IRTechnibelAc *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const int16_t sleep = -1);
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 = -1);
#endif // SEND_TECHNIBEL_AC
#if SEND_TECO
void teco(IRTecoAc *ac,

View File

@@ -26,7 +26,6 @@ const uint16_t kTechnibelAcOneSpace = 1696;;
const uint16_t kTechnibelAcZeroSpace = 564;;
const uint32_t kTechnibelAcGap = kDefaultMessageGap;
const uint16_t kTechnibelAcFreq = 38000;
const uint16_t kTechnibelAcOverhead = 3;
#if SEND_TECHNIBEL_AC
@@ -56,9 +55,7 @@ void IRsend::sendTechnibelAc(const uint64_t data, const uint16_t nbits,
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeTechnibelAc(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * nbits + kTechnibelAcOverhead - offset) {
return false; // Too short a message to match.
}
// Compliance
if (strict && nbits != kTechnibelAcBits) {
return false;
}
@@ -74,6 +71,9 @@ bool IRrecv::decodeTechnibelAc(decode_results *results, uint16_t offset,
kTechnibelAcBitMark, kTechnibelAcGap, true,
_tolerance, kMarkExcess, true)) return false;
// Compliance
if (strict && !IRTechnibelAc::validChecksum(data)) return false;
// Success
results->decode_type = decode_type_t::TECHNIBEL_AC;
results->bits = nbits;
@@ -103,19 +103,24 @@ void IRTechnibelAc::send(const uint16_t repeat) {
}
#endif // SEND_TECHNIBEL_AC
/// Compute the checksum of the internal state.
/// Compute the checksum of the supplied state.
/// @param[in] state A valid code for this protocol.
/// @return The checksum byte of the internal state.
/// @return The calculated checksum of the supplied state.
uint8_t IRTechnibelAc::calcChecksum(const uint64_t state) {
uint8_t sum = 0;
// Add up all the 8 bit data chunks.
for (uint8_t offset = kTechnibelAcTimerHoursOffset;
offset < kTechnibelAcHeaderOffset; offset += 8) {
offset < kTechnibelAcHeaderOffset; offset += 8)
sum += GETBITS64(state, offset, 8);
return ~sum + 1;
}
sum = invertBits(sum, 8);
sum += 1;
return sum;
/// Confirm the checksum of the supplied state is valid.
/// @param[in] state A valid code for this protocol.
/// @return `true` if the checksum is correct, otherwise `false`.
bool IRTechnibelAc::validChecksum(const uint64_t state) {
return calcChecksum(state) == GETBITS64(state, kTechnibelAcChecksumOffset,
kTechnibelAcChecksumSize);
}
/// Set the checksum of the internal state.
@@ -127,23 +132,14 @@ void IRTechnibelAc::checksum(void) {
/// Reset the internal state of the emulation.
/// @note Mode:Cool, Power:Off, fan:Low, temp:20, swing:Off, sleep:Off
void IRTechnibelAc::stateReset(void) {
remote_state = kTechnibelAcResetState;
_saved_temp = 20; // DegC (Random reasonable default value)
_saved_temp_units = 0; // Celsius
off();
setTemp(_saved_temp);
setTempUnit(_saved_temp_units);
setMode(kTechnibelAcCool);
setFan(kTechnibelAcFanLow);
setSwing(false);
setSleep(false);
}
/// Get a copy of the internal state/code for this protocol.
/// @return A code for this protocol based on the current internal state.
uint64_t IRTechnibelAc::getRaw(void) {
setBits(&remote_state, kTechnibelAcHeaderOffset, kTechnibelAcHeaderSize,
kTechnibelAcHeader);
checksum();
return remote_state;
}
@@ -175,6 +171,7 @@ bool IRTechnibelAc::getPower(void) {
/// Set the temperature unit setting.
/// @param[in] fahrenheit true, the unit is °F. false, the unit is °C.
void IRTechnibelAc::setTempUnit(const bool fahrenheit) {
_saved_temp_units = fahrenheit;
setBit(&remote_state, kTechnibelAcTempUnitBit, fahrenheit);
}
@@ -188,20 +185,12 @@ bool IRTechnibelAc::getTempUnit(void) {
/// @param[in] degrees The temperature in degrees.
/// @param[in] fahrenheit The temperature unit: true=°F, false(default)=°C.
void IRTechnibelAc::setTemp(const uint8_t degrees, const bool fahrenheit) {
uint8_t temp;
uint8_t temp_min = kTechnibelAcTempMinC;
uint8_t temp_max = kTechnibelAcTempMaxC;
setTempUnit(fahrenheit);
if (fahrenheit) {
temp_min = kTechnibelAcTempMinF;
temp_max = kTechnibelAcTempMaxF;
}
temp = std::max(temp_min, degrees);
temp = std::min(temp_max, temp);
_saved_temp = temp;
_saved_temp_units = fahrenheit;
setBits(&remote_state, kTechnibelAcTempOffset, kTechnibelAcTempSize, temp);
uint8_t temp_min = fahrenheit ? kTechnibelAcTempMinF : kTechnibelAcTempMinC;
uint8_t temp_max = fahrenheit ? kTechnibelAcTempMaxF : kTechnibelAcTempMaxC;
_saved_temp = std::min(temp_max, std::max(temp_min, degrees));
setBits(&remote_state, kTechnibelAcTempOffset, kTechnibelAcTempSize,
_saved_temp);
}
/// Get the current temperature setting.
@@ -218,13 +207,14 @@ void IRTechnibelAc::setFan(const uint8_t speed) {
setFan(kTechnibelAcFanLow);
return;
}
// Bounds check enforcement
if (speed > kTechnibelAcFanHigh) {
setFan(kTechnibelAcFanHigh);
} else if (speed < kTechnibelAcFanLow) {
setFan(kTechnibelAcFanLow);
} else {
switch (speed) {
case kTechnibelAcFanHigh:
case kTechnibelAcFanMedium:
case kTechnibelAcFanLow:
setBits(&remote_state, kTechnibelAcFanOffset, kTechnibelAcFanSize, speed);
break;
default:
setFan(kTechnibelAcFanLow);
}
}
@@ -240,15 +230,11 @@ uint8_t IRTechnibelAc::getFan(void) {
uint8_t IRTechnibelAc::convertFan(const stdAc::fanspeed_t speed) {
switch (speed) {
case stdAc::fanspeed_t::kMin:
case stdAc::fanspeed_t::kLow:
return kTechnibelAcFanLow;
case stdAc::fanspeed_t::kMedium:
return kTechnibelAcFanMedium;
case stdAc::fanspeed_t::kLow: return kTechnibelAcFanLow;
case stdAc::fanspeed_t::kMedium: return kTechnibelAcFanMedium;
case stdAc::fanspeed_t::kHigh:
case stdAc::fanspeed_t::kMax:
return kTechnibelAcFanHigh;
default:
return kTechnibelAcFanLow;
case stdAc::fanspeed_t::kMax: return kTechnibelAcFanHigh;
default: return kTechnibelAcFanLow;
}
}
@@ -259,7 +245,6 @@ stdAc::fanspeed_t IRTechnibelAc::toCommonFanSpeed(const uint8_t speed) {
switch (speed) {
case kTechnibelAcFanHigh: return stdAc::fanspeed_t::kHigh;
case kTechnibelAcFanMedium: return stdAc::fanspeed_t::kMedium;
case kTechnibelAcFanLow: return stdAc::fanspeed_t::kLow;
default: return stdAc::fanspeed_t::kLow;
}
}
@@ -267,8 +252,7 @@ stdAc::fanspeed_t IRTechnibelAc::toCommonFanSpeed(const uint8_t speed) {
/// Get the operating mode setting of the A/C.
/// @return The current operating mode setting.
uint8_t IRTechnibelAc::getMode(void) {
return GETBITS64(remote_state, kTechnibelAcModeOffset,
kTechnibelAcModeSize);
return GETBITS64(remote_state, kTechnibelAcModeOffset, kTechnibelAcModeSize);
}
/// Set the operating mode of the A/C.
@@ -295,16 +279,10 @@ void IRTechnibelAc::setMode(const uint8_t mode) {
/// @return The native equivilant of the enum.
uint8_t IRTechnibelAc::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
case stdAc::opmode_t::kCool:
return kTechnibelAcCool;
case stdAc::opmode_t::kHeat:
return kTechnibelAcHeat;
case stdAc::opmode_t::kDry:
return kTechnibelAcDry;
case stdAc::opmode_t::kFan:
return kTechnibelAcFan;
default:
return kTechnibelAcCool;
case stdAc::opmode_t::kHeat: return kTechnibelAcHeat;
case stdAc::opmode_t::kDry: return kTechnibelAcDry;
case stdAc::opmode_t::kFan: return kTechnibelAcFan;
default: return kTechnibelAcCool;
}
}
@@ -313,11 +291,10 @@ uint8_t IRTechnibelAc::convertMode(const stdAc::opmode_t mode) {
/// @return The stdAc equivilant of the native setting.
stdAc::opmode_t IRTechnibelAc::toCommonMode(const uint8_t mode) {
switch (mode) {
case kTechnibelAcCool: return stdAc::opmode_t::kCool;
case kTechnibelAcHeat: return stdAc::opmode_t::kHeat;
case kTechnibelAcDry: return stdAc::opmode_t::kDry;
case kTechnibelAcFan: return stdAc::opmode_t::kFan;
default: return stdAc::opmode_t::kAuto;
default: return stdAc::opmode_t::kCool;
}
}
@@ -337,22 +314,14 @@ bool IRTechnibelAc::getSwing(void) {
/// @param[in] swing The enum to be converted.
/// @return true, the swing is on. false, the swing is off.
bool IRTechnibelAc::convertSwing(const stdAc::swingv_t swing) {
switch (swing) {
case stdAc::swingv_t::kOff:
return false;
default:
return true;
}
return swing != stdAc::swingv_t::kOff;
}
/// Convert a native swing into its stdAc equivilant.
/// @param[in] swing true, the swing is on. false, the swing is off.
/// @return The stdAc equivilant of the native setting.
stdAc::swingv_t IRTechnibelAc::toCommonSwing(const bool swing) {
if (swing)
return stdAc::swingv_t::kAuto;
else
return stdAc::swingv_t::kOff;
return swing ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff;
}
/// Set the Sleep setting of the A/C.
@@ -367,8 +336,8 @@ bool IRTechnibelAc::getSleep(void) {
return GETBIT64(remote_state, kTechnibelAcSleepBit);
}
/// Is the timer function enabled?
/// @return true, the setting is on. false, the setting is off.
/// Set the enable timer setting.
/// @param[in] on true, the setting is on. false, the setting is off.
void IRTechnibelAc::setTimerEnabled(const bool on) {
setBit(&remote_state, kTechnibelAcTimerEnableBit, on);
}
@@ -384,23 +353,19 @@ bool IRTechnibelAc::getTimerEnabled(void) {
/// `0` will clear the timer. Max is 24 hrs (1440 mins).
/// @note Time is stored internaly in hours.
void IRTechnibelAc::setTimer(const uint16_t nr_of_mins) {
uint8_t hours = nr_of_mins / 60;
uint8_t value = std::min(kTechnibelAcTimerMax, hours);
const uint8_t hours = nr_of_mins / 60;
setBits(&remote_state, kTechnibelAcTimerHoursOffset, kTechnibelAcHoursSize,
value);
std::min(kTechnibelAcTimerMax, hours));
// Enable or not?
setTimerEnabled(value > 0);
setTimerEnabled(hours);
}
/// Get the timer time for when the A/C unit will switch power state.
/// @return The number of minutes left on the timer. `0` means off.
uint16_t IRTechnibelAc::getTimer(void) {
uint16_t mins = 0;
if (getTimerEnabled()) {
mins = GETBITS64(remote_state, kTechnibelAcTimerHoursOffset,
kTechnibelAcHoursSize) * 60;
}
return mins;
return getTimerEnabled() ? GETBITS64(remote_state,
kTechnibelAcTimerHoursOffset,
kTechnibelAcHoursSize) * 60 : 0;
}
/// Convert the current internal state into its stdAc::state_t equivilant.
@@ -435,8 +400,8 @@ String IRTechnibelAc::toString(void) {
String result = "";
result.reserve(100); // Reserve some heap for the string to reduce fragging.
result += addBoolToString(getPower(), kPowerStr, false);
result += addModeToString(getMode(), kTechnibelAcCool, kTechnibelAcCool,
kTechnibelAcHeat, kTechnibelAcDry,
result += addModeToString(getMode(), 255, // No Auto, so use impossible value
kTechnibelAcCool, kTechnibelAcHeat, kTechnibelAcDry,
kTechnibelAcFan);
result += addFanToString(getFan(), kTechnibelAcFanHigh, kTechnibelAcFanLow,
kTechnibelAcFanLow, kTechnibelAcFanLow,
@@ -444,10 +409,8 @@ String IRTechnibelAc::toString(void) {
result += addTempToString(getTemp(), !getTempUnit());
result += addBoolToString(getSleep(), kSleepStr);
result += addBoolToString(getSwing(), kSwingVStr);
if (getTimerEnabled())
result += addLabeledString(irutils::minsToString(getTimer()),
result += addLabeledString(getTimerEnabled() ? minsToString(getTimer())
: kOffStr,
kTimerStr);
else
result += addBoolToString(false, kTimerStr);
return result;
}

View File

@@ -18,13 +18,8 @@
#endif
// Supports:
// Brand: TECHNIBEL, Model: IRO PLUS
// Brand: Technibel, Model: IRO PLUS
// Ref:
//
// Kudos:
// : For the breakdown and mapping of the bit values.
/* State bit map:
@@ -50,17 +45,17 @@
const uint8_t kTechnibelAcChecksumOffset = 0;
const uint8_t kTechnibelAcChecksumSize = 8;
const uint8_t kTechnibelAcFooterOffset = kTechnibelAcChecksumOffset
+ kTechnibelAcChecksumSize;
const uint8_t kTechnibelAcFooterOffset = kTechnibelAcChecksumOffset +
kTechnibelAcChecksumSize;
const uint8_t kTechnibelAcFooterSize = 8;
const uint8_t kTechnibelAcTimerHoursOffset = kTechnibelAcFooterOffset
+ kTechnibelAcFooterSize;
const uint8_t kTechnibelAcTimerHoursOffset = kTechnibelAcFooterOffset +
kTechnibelAcFooterSize;
const uint8_t kTechnibelAcHoursSize = 8; // Max 24 hrs
const uint8_t kTechnibelAcTimerMax = 24;
const uint8_t kTechnibelAcTempOffset = kTechnibelAcTimerHoursOffset
+ kTechnibelAcHoursSize;
const uint8_t kTechnibelAcTempOffset = kTechnibelAcTimerHoursOffset +
kTechnibelAcHoursSize;
const uint8_t kTechnibelAcTempSize = 8;
const uint8_t kTechnibelAcTempMinC = 16; // Deg C
const uint8_t kTechnibelAcTempMaxC = 31; // Deg C
@@ -74,13 +69,13 @@ const uint8_t kTechnibelAcFanLow = 0b0001;
const uint8_t kTechnibelAcFanMedium = 0b0010;
const uint8_t kTechnibelAcFanHigh = 0b0100;
const uint8_t kTechnibelAcSleepBit = kTechnibelAcFanOffset
+ kTechnibelAcFanSize;
const uint8_t kTechnibelAcSleepBit = kTechnibelAcFanOffset +
kTechnibelAcFanSize;
const uint8_t kTechnibelAcSwingBit = kTechnibelAcSleepBit + 1;
const uint8_t kTechnibelAcTempUnitBit = kTechnibelAcSwingBit + 1;
// (0 = Celsius, 1 = Fahrenheit)
const uint8_t kTechnibelAcTempUnitBit = kTechnibelAcSwingBit + 1;
const uint8_t kTechnibelAcTimerEnableBit = kTechnibelAcTempUnitBit + 1;
@@ -91,8 +86,8 @@ const uint8_t kTechnibelAcDry = 0b0010;
const uint8_t kTechnibelAcFan = 0b0100;
const uint8_t kTechnibelAcHeat = 0b1000;
const uint8_t kTechnibelAcFanChangeBit = kTechnibelAcModeOffset
+ kTechnibelAcModeSize;
const uint8_t kTechnibelAcFanChangeBit = kTechnibelAcModeOffset +
kTechnibelAcModeSize;
const uint8_t kTechnibelAcTempChangeBit = kTechnibelAcFanChangeBit + 1;
@@ -104,15 +99,22 @@ const uint8_t kTechnibelAcHeaderOffset = kTechnibelAcPowerBit + 1;
const uint8_t kTechnibelAcHeaderSize = 8;
const uint8_t kTechnibelAcHeader = 0b00011000;
const uint64_t kTechnibelAcResetState = 0x180101140000EA; ///<
///< Mode:Cool, Power:Off, fan:Low, temp:20, swing:Off, sleep:Off
// Classes
class IRTechnibelAc {
public:
explicit IRTechnibelAc(const uint16_t pin, const bool inverted = false,
const bool use_modulation = true);
void stateReset();
#if SEND_TECHNIBEL_AC
void send(const uint16_t repeat = kTechnibelAcDefaultRepeat);
/// Run the calibration to calculate uSec timing offsets for this platform.
/// @return The uSec timing offset needed per modulation of the IR Led.
/// @note This will produce a 65ms IR signal pulse at 38kHz.
/// Only ever needs to be run once per object instantiation, if at all.
int8_t calibrate(void) { return _irsend.calibrate(); }
#endif // SEND_TECHNIBEL_AC
void begin();

View File

@@ -97,7 +97,7 @@ TEST(TestIRac, Argo) {
stdAc::opmode_t::kHeat, // Mode
21, // Celsius
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
false, // Turbo
-1); // Sleep
EXPECT_TRUE(ac.getPower());
@@ -123,7 +123,7 @@ TEST(TestIRac, Carrier64) {
stdAc::opmode_t::kHeat, // Mode
21, // Celsius
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
1); // Sleep
EXPECT_TRUE(ac.getPower()); // Power.
EXPECT_EQ(kCarrierAc64Heat, ac.getMode()); // Operating mode.
@@ -156,7 +156,7 @@ TEST(TestIRac, Coolix) {
stdAc::opmode_t::kHeat, // Mode
21, // Celsius
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Turbo
false, // Light
@@ -225,7 +225,7 @@ TEST(TestIRac, Corona) {
stdAc::opmode_t::kHeat, // Mode
21, // Celsius
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
true); // Econo (PowerSave)
EXPECT_TRUE(ac.getPower()); // Power.
EXPECT_TRUE(ac.getPowerButton()); // Power.button
@@ -262,7 +262,7 @@ TEST(TestIRac, Daikin) {
stdAc::opmode_t::kCool, // Mode
19, // Celsius
stdAc::fanspeed_t::kMax, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
false, // Turbo
@@ -294,7 +294,7 @@ TEST(TestIRac, Daikin128) {
stdAc::opmode_t::kHeat, // Mode
27, // Celsius
stdAc::fanspeed_t::kMin, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
true, // Quiet
false, // Turbo
true, // Light
@@ -325,7 +325,7 @@ TEST(TestIRac, Daikin152) {
stdAc::opmode_t::kCool, // Mode
27, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
false, // Quiet
false, // Turbo
true); // Econo
@@ -353,7 +353,7 @@ TEST(TestIRac, Daikin160) {
stdAc::opmode_t::kDry, // Mode
23, // Celsius
stdAc::fanspeed_t::kMin, // Fan speed
stdAc::swingv_t::kMiddle); // Veritcal swing
stdAc::swingv_t::kMiddle); // Vertical swing
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
@@ -405,7 +405,7 @@ TEST(TestIRac, Daikin2) {
stdAc::opmode_t::kCool, // Mode
19, // Celsius
stdAc::fanspeed_t::kLow, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kMiddle, // Horizontal swing
false, // Quiet
false, // Turbo
@@ -440,7 +440,7 @@ TEST(TestIRac, Daikin216) {
stdAc::opmode_t::kHeat, // Mode
31, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
stdAc::swingh_t::kLeft, // Horizontal swing
true, // Quiet
false); // Turbo (Powerful)
@@ -469,7 +469,7 @@ TEST(TestIRac, Daikin64) {
stdAc::opmode_t::kCool, // Mode
27, // Celsius
stdAc::fanspeed_t::kLow, // Fan Speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
false, // Quiet
false, // Turbo
360, // Sleep
@@ -521,7 +521,7 @@ TEST(TestIRac, Electra) {
stdAc::opmode_t::kFan, // Mode
26, // Celsius
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
stdAc::swingh_t::kLeft, // Horizontal swing
true, // Turbo
true, // Light (toggle)
@@ -555,7 +555,7 @@ TEST(TestIRac, Fujitsu) {
stdAc::opmode_t::kCool, // Mode
19, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
false, // Turbo (Powerful)
@@ -578,7 +578,7 @@ TEST(TestIRac, Fujitsu) {
stdAc::opmode_t::kCool, // Mode
19, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
false, // Turbo (Powerful)
@@ -599,7 +599,7 @@ TEST(TestIRac, Fujitsu) {
stdAc::opmode_t::kCool, // Mode
19, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
false, // Turbo (Powerful)
@@ -629,7 +629,7 @@ TEST(TestIRac, Goodweather) {
stdAc::opmode_t::kCool, // Mode
19, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
true, // Turbo
true, // Light
8 * 60 + 0); // Sleep time
@@ -661,7 +661,7 @@ TEST(TestIRac, Gree) {
false, // Celsius
71, // Degrees (F)
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
false, // Turbo
true, // Light
true, // Clean (aka Mold/XFan)
@@ -691,7 +691,7 @@ TEST(TestIRac, Haier) {
stdAc::opmode_t::kCool, // Mode
24, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
true, // Filter
8 * 60 + 0, // Sleep time
13 * 60 + 45); // Clock
@@ -721,7 +721,7 @@ TEST(TestIRac, HaierYrwo2) {
stdAc::opmode_t::kCool, // Mode
23, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
true, // Turbo
true, // Filter
8 * 60 + 0); // Sleep time
@@ -749,7 +749,7 @@ TEST(TestIRac, Hitachi) {
stdAc::opmode_t::kAuto, // Mode
22, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kAuto); // Horizontal swing
ASSERT_EQ(expected, ac.toString());
@@ -905,7 +905,7 @@ TEST(TestIRac, Kelvinator) {
stdAc::opmode_t::kCool, // Mode
19, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Quiet
false, // Turbo
@@ -993,7 +993,7 @@ TEST(TestIRac, Mitsubishi) {
stdAc::opmode_t::kCool, // Mode
20, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Silent
14 * 60 + 35); // Clock
@@ -1021,7 +1021,7 @@ TEST(TestIRac, Mitsubishi136) {
stdAc::opmode_t::kDry, // Mode
22, // Celsius
stdAc::fanspeed_t::kMax, // Fan speed
stdAc::swingv_t::kHighest, // Veritcal swing
stdAc::swingv_t::kHighest, // Vertical swing
false); // Quiet
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
@@ -1048,7 +1048,7 @@ TEST(TestIRac, MitsubishiHeavy88) {
stdAc::opmode_t::kCool, // Mode
21, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // Turbo
false, // Econo
@@ -1078,7 +1078,7 @@ TEST(TestIRac, MitsubishiHeavy152) {
stdAc::opmode_t::kCool, // Mode
20, // Celsius
stdAc::fanspeed_t::kLow, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kAuto, // Horizontal swing
true, // Silent
false, // Turbo
@@ -1112,7 +1112,7 @@ TEST(TestIRac, Neoclima) {
stdAc::opmode_t::kCool, // Mode
20, // Celsius
stdAc::fanspeed_t::kLow, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kAuto, // Horizontal swing
false, // Turbo
true, // Light
@@ -1144,7 +1144,7 @@ TEST(TestIRac, Panasonic) {
stdAc::opmode_t::kHeat, // Mode
28, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
stdAc::swingh_t::kLeft, // Horizontal swing
true, // Quiet
false, // Turbo
@@ -1171,7 +1171,7 @@ TEST(TestIRac, Panasonic) {
stdAc::opmode_t::kCool, // Mode
18, // Celsius
stdAc::fanspeed_t::kMax, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
stdAc::swingh_t::kMiddle, // Horizontal swing
false, // Quiet
true, // Turbo
@@ -1201,7 +1201,7 @@ TEST(TestIRac, Samsung) {
stdAc::opmode_t::kAuto, // Mode
28, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
true, // Quiet
false, // Turbo
true, // Light (Display)
@@ -1225,7 +1225,7 @@ TEST(TestIRac, Samsung) {
stdAc::opmode_t::kAuto, // Mode
28, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
true, // Quiet
false, // Turbo
true, // Light (Display)
@@ -1292,7 +1292,7 @@ TEST(TestIRac, Sharp) {
stdAc::opmode_t::kCool, // Mode
28, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
false, // Turbo
true, // Filter (Ion)
false); // Clean
@@ -1320,7 +1320,7 @@ TEST(TestIRac, Tcl112) {
stdAc::opmode_t::kCool, // Mode
20, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Veritcal swing
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kAuto, // Horizontal swing
false, // Turbo
true, // Light
@@ -1336,6 +1336,33 @@ TEST(TestIRac, Tcl112) {
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
}
TEST(TestIRac, Technibel) {
IRTechnibelAc ac(kGpioUnused);
IRac irac(kGpioUnused);
IRrecv capture(kGpioUnused);
char expected[] =
"Power: On, Mode: 8 (Heat), Fan: 2 (Medium), Temp: 72F, Sleep: On, "
"Swing(V): On, Timer: Off";
ac.begin();
irac.technibel(&ac,
true, // Power
stdAc::opmode_t::kHeat, // Mode
false, // Celsius
72, // Degrees
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Vertical swing
8 * 60 + 30); // Sleep
ASSERT_EQ(expected, ac.toString());
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(decode_type_t::TECHNIBEL_AC, ac._irsend.capture.decode_type);
ASSERT_EQ(kTechnibelAcBits, ac._irsend.capture.bits);
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
stdAc::state_t r, p;
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
}
TEST(TestIRac, Teco) {
IRTecoAc ac(kGpioUnused);
IRac irac(kGpioUnused);
@@ -1350,7 +1377,7 @@ TEST(TestIRac, Teco) {
stdAc::opmode_t::kAuto, // Mode
21, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
true, // Light
8 * 60 + 30); // Sleep
ASSERT_EQ(expected, ac.toString());
@@ -1479,7 +1506,7 @@ TEST(TestIRac, Vestel) {
stdAc::opmode_t::kAuto, // Mode
22, // Celsius
stdAc::fanspeed_t::kLow, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
false, // Turbo
true, // Filter
8 * 60 + 0); // Sleep time
@@ -1503,7 +1530,7 @@ TEST(TestIRac, Vestel) {
stdAc::opmode_t::kAuto, // Mode
22, // Celsius
stdAc::fanspeed_t::kLow, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
false, // Turbo
true, // Filter
8 * 60 + 0, // Sleep time
@@ -1527,7 +1554,7 @@ TEST(TestIRac, Vestel) {
stdAc::opmode_t::kAuto, // Mode
22, // Celsius
stdAc::fanspeed_t::kLow, // Fan speed
stdAc::swingv_t::kHigh, // Veritcal swing
stdAc::swingv_t::kHigh, // Vertical swing
false, // Turbo
true, // Filter
8 * 60 + 0, // Sleep time
@@ -1649,7 +1676,7 @@ TEST(TestIRac, Whirlpool) {
stdAc::opmode_t::kAuto, // Mode
21, // Celsius
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kAuto, // Veritcal swing
stdAc::swingv_t::kAuto, // Vertical swing
false, // Turbo
true, // Light
8 * 60 + 30, // Sleep
@@ -1951,7 +1978,7 @@ TEST(TestIRac, Issue821) {
result.mode, // Mode
result.degrees, // Celsius
result.fanspeed, // Fan speed
result.swingv, // Veritcal swing
result.swingv, // Vertical swing
result.swingh, // Horizontal swing
result.turbo, // Turbo
result.light, // Light
@@ -2043,7 +2070,7 @@ TEST(TestIRac, Issue1001) {
result.mode, // Mode
result.degrees, // Celsius
result.fanspeed, // Fan speed
result.swingv, // Veritcal swing
result.swingv, // Vertical swing
result.turbo, // Turbo
result.light, // Light
result.sleep); // Sleep
@@ -2074,7 +2101,7 @@ TEST(TestIRac, Issue1001) {
result.mode, // Mode
result.degrees, // Celsius
result.fanspeed, // Fan speed
result.swingv, // Veritcal swing
result.swingv, // Vertical swing
result.turbo, // Turbo
result.light, // Light
result.sleep); // Sleep

View File

@@ -25,12 +25,12 @@ TEST(TestDecodeTechnibelAc, SyntheticSelfDecode) {
irsend.begin();
irsend.reset();
irsend.sendTechnibelAc(0xD2000048448118);
irsend.sendTechnibelAc(0x1881221200004B);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(TECHNIBEL_AC, irsend.capture.decode_type);
EXPECT_EQ(kTechnibelAcBits, irsend.capture.bits);
EXPECT_EQ(0xD2000048448118, irsend.capture.value);
EXPECT_EQ(0x1881221200004B, irsend.capture.value);
EXPECT_EQ(0, irsend.capture.command);
EXPECT_EQ(0, irsend.capture.address);
}
@@ -62,7 +62,7 @@ TEST(TestDecodeTechnibelAc, RealExample) {
EXPECT_EQ(0, irsend.capture.command);
EXPECT_EQ(0, irsend.capture.address);
EXPECT_EQ(
"Power: On, Mode: 1 (Auto), Fan: 2 (Medium), Temp: 18C, "
"Power: On, Mode: 1 (Cool), Fan: 2 (Medium), Temp: 18C, "
"Sleep: Off, Swing(V): On, Timer: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
@@ -201,12 +201,6 @@ TEST(TestIRTechnibelAcClass, FanSpeed) {
ac.begin();
ac.setMode(kTechnibelAcCool); // All fan speeds available in this mode.
ac.setFan(0);
EXPECT_EQ(kTechnibelAcFanLow, ac.getFan());
ac.setFan(255);
EXPECT_EQ(kTechnibelAcFanHigh, ac.getFan());
ac.setFan(kTechnibelAcFanLow);
EXPECT_EQ(kTechnibelAcFanLow, ac.getFan());
@@ -215,6 +209,21 @@ TEST(TestIRTechnibelAcClass, FanSpeed) {
ac.setFan(kTechnibelAcFanHigh);
EXPECT_EQ(kTechnibelAcFanHigh, ac.getFan());
ac.setFan(0);
EXPECT_EQ(kTechnibelAcFanLow, ac.getFan());
ac.setFan(kTechnibelAcFanMedium);
ac.setFan(255);
EXPECT_EQ(kTechnibelAcFanLow, ac.getFan());
// Check fan speed enforcement for Dry mode.
ac.setFan(kTechnibelAcFanMedium);
ac.setMode(kTechnibelAcDry);
EXPECT_EQ(kTechnibelAcFanLow, ac.getFan());
EXPECT_EQ(kTechnibelAcDry, ac.getMode());
ac.setFan(kTechnibelAcFanHigh);
EXPECT_EQ(kTechnibelAcFanLow, ac.getFan());
}
TEST(TestIRTechnibelAcClass, Swing) {
@@ -274,3 +283,40 @@ TEST(TestIRTechnibelAcClass, Timer) {
EXPECT_TRUE(ac.getTimerEnabled());
EXPECT_EQ(1440, ac.getTimer());
}
TEST(TestIRTechnibelAcClass, ConstructKnownState) {
IRTechnibelAc ac(kGpioUnused);
EXPECT_EQ(kTechnibelAcResetState, ac.getRaw());
ac.on();
ac.setMode(kTechnibelAcCool);
ac.setFan(kTechnibelAcFanMedium);
ac.setTemp(18); // 18C
ac.setSleep(false); // Off
ac.setSwing(true); // On
EXPECT_EQ(0x1881221200004B, ac.getRaw());
EXPECT_EQ(
"Power: On, Mode: 1 (Cool), Fan: 2 (Medium), Temp: 18C, "
"Sleep: Off, Swing(V): On, Timer: Off",
ac.toString());
}
TEST(TestIRTechnibelAcClass, HumanReadable) {
IRTechnibelAc ac(kGpioUnused);
ac.begin();
EXPECT_EQ(
"Power: Off, Mode: 1 (Cool), Fan: 1 (Low), Temp: 20C, Sleep: Off, "
"Swing(V): Off, Timer: Off", ac.toString());
ac.setPower(true);
ac.setTemp(72, true); // 72F
ac.setFan(kTechnibelAcFanMedium);
ac.setSleep(true);
ac.setSwing(true);
EXPECT_EQ(
"Power: On, Mode: 1 (Cool), Fan: 2 (Medium), Temp: 72F, Sleep: On, "
"Swing(V): On, Timer: Off", ac.toString());
ac.setMode(kTechnibelAcHeat);
ac.setTimer(23 * 60);
EXPECT_EQ(
"Power: On, Mode: 8 (Heat), Fan: 2 (Medium), Temp: 72F, Sleep: On, "
"Swing(V): On, Timer: 23:00", ac.toString());
}