Skip to content

Commit

Permalink
KKG29AC1 model improvements.
Browse files Browse the repository at this point in the history
* Tweak model detection in `getModel(state)`
* Various improvements/fixes found in testing.
* Update unit tests for `KKG29AC1` model.
  - Clock
  - Sleep
  - Light
  - Turbo
  - Power
  - SwingV

* New unit tests for `KKG29AC1`
  - SwingH
  - Filter
  - Quiet
  - CleanToggle
  - Timers
  - IFeel & SensorTemp

For #1573
  • Loading branch information
crankyoldgit committed Nov 2, 2021
1 parent 23acd95 commit 5b85d02
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 13 deletions.
38 changes: 25 additions & 13 deletions src/ir_Mirage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ void IRMirageAc::begin(void) { _irsend.begin(); }
/// @param[in] repeat Nr. of times the message will be repeated.
void IRMirageAc::send(const uint16_t repeat) {
_irsend.sendMirage(getRaw(), kMirageStateLength, repeat);
setCleanToggle(false); // Clean Toggle is reset after each send.
}
#endif // SEND_MITSUBISHI_AC

Expand All @@ -138,17 +139,19 @@ void IRMirageAc::setRaw(const uint8_t *data) {
/// @param[in] state A valid state code for this protocol.
/// @return The model code.
mirage_ac_remote_model_t IRMirageAc::getModel(const uint8_t *state) {
Mirage120Protocol prot;
std::memcpy(prot.raw, state, kMirageStateLength);
// If the minutes or seconds or raw[10] are set, it's a KKG9AC1
if (prot.Minutes || prot.Seconds || prot.raw[10])
Mirage120Protocol p;
std::memcpy(p.raw, state, kMirageStateLength);
// Check for things specific to KKG9AC1
if ((p.Minutes || p.Seconds) && // Is part of the clock set?
// Are the timer times set, but not enabled?
(!p.OffTimerEnable && (p.OffTimerHours || p.OffTimerMins)) &&
(!p.OnTimerEnable && (p.OnTimerHours || p.OnTimerMins)))
return mirage_ac_remote_model_t::KKG9AC1;
// Check for KKG29AC1 specific settings.
if (prot.RecycleHeat || prot.Filter || prot.Sleep_Kkg29ac1 ||
prot.CleanToggle || prot.IFeel)
if (p.RecycleHeat || p.Filter || p.Sleep_Kkg29ac1 || p.CleanToggle ||
p.IFeel || p.OffTimerEnable || p.OnTimerEnable)
return mirage_ac_remote_model_t::KKG29AC1;
else
return mirage_ac_remote_model_t::KKG9AC1;
return mirage_ac_remote_model_t::KKG9AC1; // Default.
}

/// Get the model code of the interal message state.
Expand All @@ -163,9 +166,11 @@ mirage_ac_remote_model_t IRMirageAc::getModel(const bool useRaw) const {
void IRMirageAc::setModel(mirage_ac_remote_model_t model) {
if (model != _model) { // Only change things if we need to.
// Save the old settings.
stdAc::state_t old = toCommon();
uint16_t ontimer = getOnTimer();
uint16_t offtimer = getOffTimer();
const stdAc::state_t old = toCommon();
const uint16_t ontimer = getOnTimer();
const uint16_t offtimer = getOffTimer();
const bool ifeel = getIFeel();
const uint8_t sensor = getSensorTemp();
// Change the model.
_model = model;
// Restore/Convert the settings.
Expand All @@ -184,6 +189,8 @@ void IRMirageAc::setModel(mirage_ac_remote_model_t model) {
setClock(old.clock * 60); // setClock() expects seconds, not minutes.
setOnTimer(ontimer);
setOffTimer(offtimer);
setIFeel(ifeel);
setSensorTemp(sensor);
}
}

Expand Down Expand Up @@ -417,7 +424,7 @@ void IRMirageAc::setSwingV(const uint8_t position) {
uint8_t IRMirageAc::getSwingV(void) const {
switch (_model) {
case mirage_ac_remote_model_t::KKG29AC1:
return _.SwingV;
return _.SwingV ? kMirageAcSwingVAuto : kMirageAcSwingVOff;
default:
return _.SwingAndPower - (getPower() ? 0 : kMirageAcPowerOff);
}
Expand Down Expand Up @@ -513,7 +520,12 @@ void IRMirageAc::setIFeel(const bool on) {
switch (_model) {
case mirage_ac_remote_model_t::KKG29AC1:
_.IFeel = on;
if (!on) _.SensorTemp = 0;
if (on) {
// If no previous sensor temp, default to currently desired temp.
if (!_.SensorTemp) _.SensorTemp = getTemp();
} else {
_.SensorTemp = 0; // When turning it off, clear the Sensor Temp.
}
break;
default:
break;
Expand Down
213 changes: 213 additions & 0 deletions test/ir_Mirage_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ TEST(TestMirageAcClass, Power) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1);
ac.on();
EXPECT_TRUE(ac.getPower());
ac.on();
Expand All @@ -159,6 +160,16 @@ TEST(TestMirageAcClass, Power) {
0x0C, 0x00, 0x0C, 0x2C, 0x23, 0x01, 0x61};
ac.setRaw(off);
EXPECT_FALSE(ac.getPower());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1);
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(TestMirageAcClass, OperatingMode) {
Expand Down Expand Up @@ -278,6 +289,15 @@ TEST(TestMirageAcClass, Turbo) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1);
ac.setTurbo(true);
EXPECT_TRUE(ac.getTurbo());
ac.setTurbo(false);
EXPECT_FALSE(ac.getTurbo());
ac.setTurbo(true);
EXPECT_TRUE(ac.getTurbo());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1);
ac.setTurbo(true);
EXPECT_TRUE(ac.getTurbo());
ac.setTurbo(false);
Expand All @@ -290,6 +310,15 @@ TEST(TestMirageAcClass, Light) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1);
ac.setLight(true);
EXPECT_TRUE(ac.getLight());
ac.setLight(false);
EXPECT_FALSE(ac.getLight());
ac.setLight(true);
EXPECT_TRUE(ac.getLight());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1);
ac.setLight(true);
EXPECT_TRUE(ac.getLight());
ac.setLight(false);
Expand All @@ -302,6 +331,15 @@ TEST(TestMirageAcClass, Sleep) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1);
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());
ac.setSleep(false);
EXPECT_FALSE(ac.getSleep());
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1);
ac.setSleep(true);
EXPECT_TRUE(ac.getSleep());
ac.setSleep(false);
Expand All @@ -314,6 +352,7 @@ TEST(TestMirageAcClass, Clock) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // This model supports time.
ac.setClock(0);
EXPECT_EQ(0, ac.getClock());
ac.setClock(12 * 60 * 60 + 30 * 60 + 59); // aka. 12:30:59
Expand All @@ -322,6 +361,11 @@ TEST(TestMirageAcClass, Clock) {
EXPECT_EQ(23 * 60 * 60 + 59 * 60 + 59, ac.getClock());
ac.setClock(24 * 60 * 60); // aka. 24:00:00
EXPECT_EQ(23 * 60 * 60 + 59 * 60 + 59, ac.getClock()); // aka. 23:59:59

ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // This model has no clock.
EXPECT_EQ(0, ac.getClock());
ac.setClock(12 * 60 * 60 + 30 * 60 + 59); // aka. 12:30:59
EXPECT_EQ(0, ac.getClock());
}

TEST(TestMirageAcClass, Checksums) {
Expand All @@ -339,6 +383,9 @@ TEST(TestMirageAcClass, SwingV) {
IRMirageAc ac(kGpioUnused);
ac.begin();

// Set the model to one with full swingv support.
ac.setModel(mirage_ac_remote_model_t::KKG9AC1);

ac.setSwingV(kMirageAcSwingVAuto);
EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV());

Expand All @@ -353,6 +400,172 @@ TEST(TestMirageAcClass, SwingV) {

ac.setSwingV(kMirageAcSwingVLowest - 1);
EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV());

// Set the model to one with limited swingv support.
ac.setModel(mirage_ac_remote_model_t::KKG29AC1);

ac.setSwingV(kMirageAcSwingVAuto);
EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV());
ac.setSwingV(kMirageAcSwingVOff);
EXPECT_EQ(kMirageAcSwingVOff, ac.getSwingV());
ac.setSwingV(kMirageAcSwingVHigh);
EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV());
ac.setSwingV(0xFF);
EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV());
ac.setSwingV(kMirageAcSwingVOff);
EXPECT_EQ(kMirageAcSwingVOff, ac.getSwingV());
}

TEST(TestMirageAcClass, SwingH) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1);
ac.setSwingH(true);
EXPECT_FALSE(ac.getSwingH());
ac.setSwingH(false);
EXPECT_FALSE(ac.getSwingH());
ac.setSwingH(true);
EXPECT_FALSE(ac.getSwingH());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1);
ac.setSwingH(true);
EXPECT_TRUE(ac.getSwingH());
ac.setSwingH(false);
EXPECT_FALSE(ac.getSwingH());
ac.setSwingH(true);
EXPECT_TRUE(ac.getSwingH());
}

TEST(TestMirageAcClass, Filter) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No Support
ac.setFilter(true);
EXPECT_FALSE(ac.getFilter());
ac.setFilter(false);
EXPECT_FALSE(ac.getFilter());
ac.setFilter(true);
EXPECT_FALSE(ac.getFilter());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Supported
ac.setFilter(true);
EXPECT_TRUE(ac.getFilter());
ac.setFilter(false);
EXPECT_FALSE(ac.getFilter());
ac.setFilter(true);
EXPECT_TRUE(ac.getFilter());
}

TEST(TestMirageAcClass, Quiet) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No Support
ac.setQuiet(true);
EXPECT_FALSE(ac.getQuiet());
ac.setQuiet(false);
EXPECT_FALSE(ac.getQuiet());
ac.setQuiet(true);
EXPECT_FALSE(ac.getQuiet());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Supported
ac.setQuiet(true);
EXPECT_TRUE(ac.getQuiet());
ac.setQuiet(false);
EXPECT_FALSE(ac.getQuiet());
ac.setQuiet(true);
EXPECT_TRUE(ac.getQuiet());
}

TEST(TestMirageAcClass, CleanToggle) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1);
ac.setCleanToggle(true);
EXPECT_FALSE(ac.getCleanToggle());
ac.setCleanToggle(false);
EXPECT_FALSE(ac.getCleanToggle());
ac.setCleanToggle(true);
EXPECT_FALSE(ac.getCleanToggle());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1);
ac.setCleanToggle(true);
EXPECT_TRUE(ac.getCleanToggle());
ac.setCleanToggle(false);
EXPECT_FALSE(ac.getCleanToggle());
ac.setCleanToggle(true);
EXPECT_TRUE(ac.getCleanToggle());
ac.send(); // Should be reset when sent.
EXPECT_FALSE(ac.getCleanToggle());
}

TEST(TestMirageAcClass, Timers) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No timer support
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(0, ac.getOffTimer());
ac.setOnTimer(12 * 60 + 37); // 12:37
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(0, ac.getOffTimer());
ac.setOffTimer(17 * 60 + 5); // 17:05
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(0, ac.getOffTimer());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Timer supported
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(0, ac.getOffTimer());

ac.setOnTimer(12 * 60 + 37); // 12:37
EXPECT_EQ(12 * 60 + 37, ac.getOnTimer());
EXPECT_EQ(0, ac.getOffTimer());

ac.setOffTimer(17 * 60 + 5); // 17:05
EXPECT_EQ(17 * 60 + 5, ac.getOffTimer());
EXPECT_EQ(12 * 60 + 37, ac.getOnTimer());
ac.setOnTimer(0); // Off/Disabled
EXPECT_EQ(0, ac.getOnTimer());
EXPECT_EQ(17 * 60 + 5, ac.getOffTimer());
ac.setOffTimer(0); // Off/Disabled
EXPECT_EQ(0, ac.getOffTimer());
EXPECT_EQ(0, ac.getOnTimer());

ac.setOnTimer(12 * 60 + 37); // 12:37
ac.setOffTimer(17 * 60 + 5); // 17:05
ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No timer support
EXPECT_EQ(0, ac.getOffTimer());
EXPECT_EQ(0, ac.getOnTimer());
}

TEST(TestMirageAcClass, IFeelAndSensorTemp) {
IRMirageAc ac(kGpioUnused);
ac.begin();

ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No support
EXPECT_FALSE(ac.getIFeel());
EXPECT_EQ(0, ac.getSensorTemp());
ac.setIFeel(true);
EXPECT_FALSE(ac.getIFeel());
EXPECT_EQ(0, ac.getSensorTemp());
ac.setSensorTemp(20); // 20C
EXPECT_FALSE(ac.getIFeel());
EXPECT_EQ(0, ac.getSensorTemp());

ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Supported
EXPECT_FALSE(ac.getIFeel());
EXPECT_EQ(0, ac.getSensorTemp());
ac.setIFeel(true);
EXPECT_TRUE(ac.getIFeel());
EXPECT_EQ(0, ac.getSensorTemp());
ac.setSensorTemp(25); // 25C
EXPECT_TRUE(ac.getIFeel());
EXPECT_EQ(25, ac.getSensorTemp());
ac.setIFeel(false);
EXPECT_FALSE(ac.getIFeel());
}

TEST(TestMirageAcClass, getModel) {
Expand Down

0 comments on commit 5b85d02

Please sign in to comment.