Tasmota/lib/lib_basic/IRremoteESP8266/test/ir_Voltas_test.cpp

426 lines
13 KiB
C++

// Copyright 2020 crankyoldgit
#include "ir_Voltas.h"
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"
// Tests for decodeVoltas().
TEST(TestDecodeVoltas, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
const uint16_t rawData[161] = {
1002, 584, 1000, 586, 1000, 2568, 1002, 2570, 1002, 586, 998, 588, 1000,
2568, 1002, 2570, 1002, 2572, 1002, 584, 1002, 586, 1000, 584, 1000, 586,
1002, 2568, 1004, 584, 1000, 586, 1002, 2568, 1002, 584, 1002, 584, 1004,
584, 1000, 2568, 1002, 586, 1000, 586, 998, 590, 998, 584, 1002, 584,
1000, 586, 1000, 2570, 1002, 2568, 1004, 584, 1000, 584, 1002, 584, 1002,
582, 1004, 584, 1002, 2568, 1002, 2570, 1004, 2570, 1000, 586, 1002, 2568,
1004, 2568, 1006, 584, 1000, 584, 1002, 2568, 1002, 2570, 1002, 2568,
1002, 586, 1002, 2570, 1000, 2570, 1002, 588, 998, 586, 1000, 2568, 1004,
2568, 1004, 2568, 1002, 588, 998, 2570, 1002, 2568, 1004, 586, 1002, 584,
1000, 586, 1000, 2570, 1000, 586, 1000, 584, 1002, 586, 1000, 2568, 1004,
584, 1000, 586, 1000, 586, 1002, 584, 1002, 586, 1000, 586, 1000, 586,
1000, 586, 1000, 2568, 1002, 2568, 1002, 2568, 1004, 586, 1000, 584,
1000, 2570, 1004, 2568, 1004, 584, 1002};
const uint8_t expected[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0xE6};
irsend.begin();
irsend.reset();
irsend.sendRaw(rawData, 161, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(decode_type_t::VOLTAS, irsend.capture.decode_type);
ASSERT_EQ(kVoltasBits, irsend.capture.bits);
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 4 (Dry), Temp: 24C, Fan: 4 (Low), "
"Swing(V): Off, Swing(H): N/A, "
"Turbo: Off, Econo: Off, WiFi: On, Light: Off, Sleep: Off, "
"On Timer: Off, Off Timer: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
}
TEST(TestDecodeVoltas, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
const uint8_t expected[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0xE6};
// power
irsend.sendVoltas(expected);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::VOLTAS, irsend.capture.decode_type);
EXPECT_EQ(kVoltasBits, irsend.capture.bits);
EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits);
}
TEST(TestUtils, Housekeeping) {
ASSERT_EQ("VOLTAS", typeToString(decode_type_t::VOLTAS));
ASSERT_EQ(decode_type_t::VOLTAS, strToDecodeType("VOLTAS"));
ASSERT_TRUE(hasACState(decode_type_t::VOLTAS));
ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::VOLTAS));
ASSERT_EQ(kVoltasBits, IRsend::defaultBits(decode_type_t::VOLTAS));
ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::VOLTAS));
}
TEST(TestIRVoltasClass, Checksums) {
const uint8_t valid[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0xE6};
EXPECT_TRUE(IRVoltas::validChecksum(valid));
EXPECT_FALSE(IRVoltas::validChecksum(valid, kVoltasStateLength - 1));
EXPECT_EQ(0xE6, IRVoltas::calcChecksum(valid));
const uint8_t badchecksum[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0x00};
EXPECT_FALSE(IRVoltas::validChecksum(badchecksum));
EXPECT_EQ(0xE6, IRVoltas::calcChecksum(badchecksum));
const uint8_t kReset[kVoltasStateLength] = {
0x33, 0x28, 0x00, 0x17, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0xCB};
EXPECT_TRUE(IRVoltas::validChecksum(kReset));
EXPECT_EQ(0xCB, IRVoltas::calcChecksum(kReset));
}
TEST(TestIRVoltasClass, SetandGetRaw) {
const uint8_t valid[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0xE6};
const uint8_t badchecksum[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0x00};
IRVoltas ac(kGpioUnused);
ac.setRaw(valid);
EXPECT_STATE_EQ(valid, ac.getRaw(), kVoltasBits);
ac.setRaw(badchecksum);
EXPECT_STATE_EQ(valid, ac.getRaw(), kVoltasBits);
}
TEST(TestIRVoltasClass, Power) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.on();
EXPECT_TRUE(ac.getPower());
ac.off();
EXPECT_FALSE(ac.getPower());
ac.setPower(true);
EXPECT_TRUE(ac.getPower());
ac.setPower(false);
EXPECT_FALSE(ac.getPower());
}
TEST(TestIRVoltasClass, Wifi) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setWifi(false);
EXPECT_FALSE(ac.getWifi());
ac.setWifi(true);
EXPECT_TRUE(ac.getWifi());
ac.setWifi(false);
EXPECT_FALSE(ac.getWifi());
}
TEST(TestIRVoltasClass, Turbo) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setTurbo(false);
EXPECT_FALSE(ac.getTurbo());
ac.setTurbo(true);
EXPECT_TRUE(ac.getTurbo());
ac.setTurbo(false);
EXPECT_FALSE(ac.getTurbo());
}
TEST(TestIRVoltasClass, Sleep) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setSleep(false);
EXPECT_FALSE(ac.getSleep());
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());
ac.setSleep(false);
EXPECT_FALSE(ac.getSleep());
}
TEST(TestIRVoltasClass, Econo) {
IRVoltas ac(kGpioUnused);
ac.begin();
// Control of econo mode is only available in cool.
ac.setMode(kVoltasCool);
ac.setEcono(false);
EXPECT_FALSE(ac.getEcono());
ac.setEcono(true);
EXPECT_TRUE(ac.getEcono());
ac.setEcono(false);
EXPECT_FALSE(ac.getEcono());
ac.setEcono(true);
ac.setMode(kVoltasHeat); // Control of econo mode should now be disabled.
EXPECT_FALSE(ac.getEcono());
ac.setEcono(true);
EXPECT_FALSE(ac.getEcono());
}
TEST(TestIRVoltasClass, Light) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setLight(false);
EXPECT_FALSE(ac.getLight());
ac.setLight(true);
EXPECT_TRUE(ac.getLight());
ac.setLight(false);
EXPECT_FALSE(ac.getLight());
const uint8_t light_off[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x00, 0xE6};
ac.setRaw(light_off);
EXPECT_FALSE(ac.getLight());
const uint8_t light_on[kVoltasStateLength] = {
0x33, 0x84, 0x88, 0x18, 0x3B, 0x3B, 0x3B, 0x11, 0x20, 0xC6};
ac.setRaw(light_on);
EXPECT_TRUE(ac.getLight());
ac.setLight(false);
EXPECT_STATE_EQ(light_off, ac.getRaw(), kVoltasBits);
ac.setLight(true);
EXPECT_STATE_EQ(light_on, ac.getRaw(), kVoltasBits);
}
TEST(TestVoltasClass, OperatingMode) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setMode(kVoltasCool);
EXPECT_EQ(kVoltasCool, ac.getMode());
ac.setMode(kVoltasFan);
EXPECT_EQ(kVoltasFan, ac.getMode());
ac.setMode(kVoltasDry);
EXPECT_EQ(kVoltasDry, ac.getMode());
ac.setMode(kVoltasHeat);
EXPECT_EQ(kVoltasHeat, ac.getMode());
ac.setMode(kVoltasCool - 1);
EXPECT_EQ(kVoltasCool, ac.getMode());
ac.setMode(kVoltasCool + 1);
EXPECT_EQ(kVoltasCool, ac.getMode());
ac.setMode(255);
EXPECT_EQ(kVoltasCool, ac.getMode());
}
TEST(TestVoltasClass, Temperature) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setTemp(kVoltasMinTemp);
EXPECT_EQ(kVoltasMinTemp, ac.getTemp());
ac.setTemp(kVoltasMinTemp + 1);
EXPECT_EQ(kVoltasMinTemp + 1, ac.getTemp());
ac.setTemp(kVoltasMaxTemp);
EXPECT_EQ(kVoltasMaxTemp, ac.getTemp());
ac.setTemp(kVoltasMinTemp - 1);
EXPECT_EQ(kVoltasMinTemp, ac.getTemp());
ac.setTemp(kVoltasMaxTemp + 1);
EXPECT_EQ(kVoltasMaxTemp, ac.getTemp());
ac.setTemp(23);
EXPECT_EQ(23, ac.getTemp());
ac.setTemp(0);
EXPECT_EQ(kVoltasMinTemp, ac.getTemp());
ac.setTemp(255);
EXPECT_EQ(kVoltasMaxTemp, ac.getTemp());
}
TEST(TestVoltasClass, FanSpeed) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setMode(kVoltasCool); // All fan speeds are allowed in cool mode.
ac.setFan(kVoltasFanLow);
ac.setFan(kVoltasFanAuto);
EXPECT_EQ(kVoltasFanAuto, ac.getFan());
ac.setFan(kVoltasFanLow);
EXPECT_EQ(kVoltasFanLow, ac.getFan());
ac.setFan(kVoltasFanMed);
EXPECT_EQ(kVoltasFanMed, ac.getFan());
ac.setFan(kVoltasFanHigh);
EXPECT_EQ(kVoltasFanHigh, ac.getFan());
ac.setFan(0);
EXPECT_EQ(kVoltasFanAuto, ac.getFan());
ac.setFan(255);
EXPECT_EQ(kVoltasFanAuto, ac.getFan());
// Confirm auto speed isn't operable in Fan mode.
ac.setMode(kVoltasFan);
EXPECT_NE(kVoltasFanAuto, ac.getFan());
ac.setFan(kVoltasFanLow);
EXPECT_EQ(kVoltasFanLow, ac.getFan());
ac.setFan(kVoltasFanMed);
EXPECT_EQ(kVoltasFanMed, ac.getFan());
ac.setFan(kVoltasFanHigh);
EXPECT_EQ(kVoltasFanHigh, ac.getFan());
ac.setFan(kVoltasFanAuto);
EXPECT_NE(kVoltasFanAuto, ac.getFan());
}
TEST(TestVoltasClass, SwingV) {
IRVoltas ac(kGpioUnused);
ac.begin();
ac.setSwingV(true);
EXPECT_TRUE(ac.getSwingV());
ac.setSwingV(false);
EXPECT_EQ(false, ac.getSwingV());
ac.setSwingV(true);
EXPECT_TRUE(ac.getSwingV());
}
TEST(TestVoltasClass, SwingH) {
IRVoltas ac(kGpioUnused);
ac.begin();
// This model allows full control.
ac.setModel(voltas_ac_remote_model_t::kVoltasUnknown);
ac.setSwingHChange(false);
EXPECT_FALSE(ac.getSwingHChange());
ac.setSwingH(true);
EXPECT_TRUE(ac.getSwingH());
EXPECT_TRUE(ac.getSwingHChange());
ac.setSwingHChange(false);
ac.setSwingH(false);
EXPECT_FALSE(ac.getSwingH());
EXPECT_TRUE(ac.getSwingHChange());
ac.setSwingH(true);
EXPECT_TRUE(ac.getSwingH());
EXPECT_TRUE(ac.getSwingHChange());
// Switch to a model that does not allow SwingH control.
ac.setModel(voltas_ac_remote_model_t::kVoltas122LZF);
EXPECT_FALSE(ac.getSwingHChange());
EXPECT_FALSE(ac.getSwingH());
ac.setSwingH(true);
EXPECT_FALSE(ac.getSwingHChange());
EXPECT_FALSE(ac.getSwingH());
ac.setSwingH(false);
EXPECT_FALSE(ac.getSwingHChange());
EXPECT_FALSE(ac.getSwingH());
}
TEST(TestVoltasClass, HumanReadable) {
IRVoltas ac(kGpioUnused);
EXPECT_EQ(
"Model: 1 (122LZF), Power: Off, Mode: 8 (Cool), Temp: 23C, "
"Fan: 1 (High), Swing(V): Off, Swing(H): N/A, Turbo: Off, Econo: Off, "
"WiFi: Off, Light: Off, Sleep: Off, On Timer: Off, Off Timer: Off",
ac.toString());
ac.on();
ac.setTemp(21);
ac.setFan(kVoltasFanAuto);
ac.setSwingV(true);
ac.setWifi(true);
ac.setLight(true);
ac.setTurbo(true);
ac.setSleep(true);
ac.setEcono(true);
ac.setOnTime(2 * 60 + 17);
ac.setMode(kVoltasHeat); // Heat mode should cancel Sleep, Turbo, & Econo.
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 2 (Heat), Temp: 21C, "
"Fan: 7 (Auto), Swing(V): On, Swing(H): N/A, Turbo: Off, Econo: Off, "
"WiFi: On, Light: On, Sleep: Off, On Timer: 02:17, Off Timer: Off",
ac.toString());
ac.setOffTime(13 * 60 + 37);
ac.setMode(kVoltasCool);
ac.setTurbo(true);
ac.setSleep(true);
ac.setEcono(true);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 8 (Cool), Temp: 21C, "
"Fan: 7 (Auto), Swing(V): On, Swing(H): N/A, Turbo: On, Econo: On, "
"WiFi: On, Light: On, Sleep: On, On Timer: 02:17, Off Timer: 13:37",
ac.toString());
ac.setModel(voltas_ac_remote_model_t::kVoltasUnknown);
ac.setSwingH(true);
EXPECT_EQ(
"Model: 0 (UNKNOWN), Power: On, Mode: 8 (Cool), Temp: 21C, "
"Fan: 7 (Auto), Swing(V): On, Swing(H): On, Turbo: On, Econo: On, "
"WiFi: On, Light: On, Sleep: On, On Timer: 02:17, Off Timer: 13:37",
ac.toString());
ac.setModel(voltas_ac_remote_model_t::kVoltas122LZF);
ac.setOnTime(0);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 8 (Cool), Temp: 21C, "
"Fan: 7 (Auto), Swing(V): On, Swing(H): N/A, Turbo: On, Econo: On, "
"WiFi: On, Light: On, Sleep: On, On Timer: Off, Off Timer: 13:37",
ac.toString());
ac.setOffTime(0);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 8 (Cool), Temp: 21C, "
"Fan: 7 (Auto), Swing(V): On, Swing(H): N/A, Turbo: On, Econo: On, "
"WiFi: On, Light: On, Sleep: On, On Timer: Off, Off Timer: Off",
ac.toString());
}
TEST(TestVoltasClass, Timers) {
IRVoltas ac(kGpioUnused);
const uint8_t off_7hrs[10] = { // Real Data
0x33, 0x28, 0x80, 0x1B, 0x3B, 0x3B, 0x3B, 0x71, 0x40, 0xA7};
ac.setRaw(off_7hrs);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 8 (Cool), Temp: 27C, Fan: 1 (High), "
"Swing(V): Off, Swing(H): N/A, Turbo: Off, Econo: Off, WiFi: Off, "
"Light: Off, Sleep: Off, On Timer: Off, Off Timer: 06:59",
ac.toString());
const uint8_t off_16hrs[10] = { // Real Data
0x33, 0x28, 0x80, 0x1B, 0x3B, 0xBB, 0x3B, 0x41, 0x40, 0x57};
ac.setRaw(off_16hrs);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 8 (Cool), Temp: 27C, Fan: 1 (High), "
"Swing(V): Off, Swing(H): N/A, Turbo: Off, Econo: Off, WiFi: Off, "
"Light: Off, Sleep: Off, On Timer: Off, Off Timer: 15:59",
ac.toString());
ac.setOffTime(23 * 60 + 59);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 8 (Cool), Temp: 27C, Fan: 1 (High), "
"Swing(V): Off, Swing(H): N/A, Turbo: Off, Econo: Off, WiFi: Off, "
"Light: Off, Sleep: Off, On Timer: Off, Off Timer: 23:59",
ac.toString());
const uint8_t off_24hrs[10] = { // Real Data
0x33, 0x28, 0x80, 0x1B, 0x3A, 0x3A, 0x3B, 0x01, 0x40, 0x19};
ac.setRaw(off_24hrs);
EXPECT_EQ(
"Model: 1 (122LZF), Power: On, Mode: 8 (Cool), Temp: 27C, Fan: 1 (High), "
"Swing(V): Off, Swing(H): N/A, Turbo: Off, Econo: Off, WiFi: Off, "
"Light: Off, Sleep: Off, On Timer: Off, Off Timer: 23:58",
ac.toString());
}