Added 'sensorTemperature' and 'iFeel' to IRac (common) (#1928)

* Added sensor temp. support to IRac (common)

Incl. impl. for Argo A/C

Signed-off-by: Mateusz Bronk <bronk.m+gh@gmail.com>

* Added common sensor temp. support to all protos exposing iFeel already

Signed-off-by: Mateusz Bronk <bronk.m+gh@gmail.com>

Signed-off-by: Mateusz Bronk <bronk.m+gh@gmail.com>
Co-authored-by: Mateusz Bronk <bronk.m+gh@gmail.com>
This commit is contained in:
Mateusz Bronk
2022-12-25 09:17:00 +01:00
committed by GitHub
parent f19ab879c7
commit e6ec73c3b9
14 changed files with 228 additions and 81 deletions

View File

@@ -12,6 +12,7 @@
#ifndef ARDUINO
#include <string>
#endif
#include <cmath>
#include "IRsend.h"
#include "IRremoteESP8266.h"
#include "IRtext.h"
@@ -469,19 +470,27 @@ void IRac::amcor(IRAmcorAc *ac,
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] sensorTemp The room (iFeel) temperature sensor reading in degrees
/// Celsius.
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] iFeel Whether to enable iFeel (remote temp) mode on the A/C unit.
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] sleep Nr. of minutes for sleep mode.
/// @note -1 is Off, >= 0 is on.
void IRac::argo(IRArgoAC *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const float sensorTemp, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const bool iFeel,
const bool turbo, const int16_t sleep) {
ac->begin();
ac->setPower(on);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setTemp(static_cast<uint8_t>(std::round(degrees)));
if (sensorTemp != kNoTempValue) {
ac->setSensorTemp(static_cast<uint8_t>(std::round(sensorTemp)));
}
ac->setiFeel(iFeel);
ac->setFan(ac->convertFan(fan));
ac->setFlap(ac->convertSwingV(swingv));
// No Quiet setting available.
@@ -500,16 +509,23 @@ void IRac::argo(IRArgoAC *ac,
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The set temperature setting in degrees Celsius.
/// @param[in] sensorTemp The room (iFeel) temperature sensor reading in degrees
/// Celsius.
/// @warning The @c sensorTemp param is assumed to be in 0..255 range (uint8_t)
/// The overflow is *not* checked, though.
/// @note The value is rounded to nearest integer, rounding halfway cases
/// away from zero. E.g. 1.5 [C] becomes 2 [C].
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] iFeel Whether to enable iFeel (remote temp) mode on the A/C unit.
/// @param[in] night Enable night mode (raises temp by +1*C after 1h).
/// @param[in] econo Enable eco mode (limits power consumed).
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] filter Enable filter mode
/// @param[in] light Enable device display/LEDs
void IRac::argoWrem3_ACCommand(IRArgoAC_WREM3 *ac, const bool on,
const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const stdAc::opmode_t mode, const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const bool iFeel,
const bool night, const bool econo, const bool turbo, const bool filter,
const bool light) {
ac->begin();
@@ -517,6 +533,10 @@ void IRac::argoWrem3_ACCommand(IRArgoAC_WREM3 *ac, const bool on,
ac->setPower(on);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
if (sensorTemp != kNoTempValue) {
ac->setSensorTemp(static_cast<uint8_t>(std::round(sensorTemp)));
}
ac->setiFeel(iFeel);
ac->setFan(ac->convertFan(fan));
ac->setFlap(ac->convertSwingV(swingv));
ac->setNight(night);
@@ -524,7 +544,6 @@ void IRac::argoWrem3_ACCommand(IRArgoAC_WREM3 *ac, const bool on,
ac->setMax(turbo);
ac->setFilter(filter);
ac->setLight(light);
// No "sensorTemp" mode/value support in common (yet)
// No Clean setting available.
// No Beep setting available - always beeps in this mode :)
ac->send();
@@ -534,10 +553,14 @@ void IRac::argoWrem3_ACCommand(IRArgoAC_WREM3 *ac, const bool on,
/// @param[in, out] ac A Ptr to an IRArgoAC_WREM3 object to use.
/// @param[in] sensorTemp The room (iFeel) temperature setting
/// in degrees Celsius.
/// @warning The @c sensorTemp param is assumed to be in 0..255 range (uint8_t)
/// The overflow is *not* checked, though.
/// @note The value is rounded to nearest integer, rounding halfway cases
/// away from zero. E.g. 1.5 [C] becomes 2 [C].
void IRac::argoWrem3_iFeelReport(IRArgoAC_WREM3 *ac, const float sensorTemp) {
ac->begin();
ac->setMessageType(argoIrMessageType_t::IFEEL_TEMP_REPORT);
ac->setSensorTemp(sensorTemp);
ac->setSensorTemp(static_cast<uint8_t>(std::round(sensorTemp)));
ac->send();
}
@@ -677,9 +700,12 @@ void IRac::carrier64(IRCarrierAc64 *ac,
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] sensorTemp The room (iFeel) temperature sensor reading in degrees
/// Celsius.
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] swingh The horizontal swing setting.
/// @param[in] iFeel Whether to enable iFeel (remote temp) mode on the A/C unit.
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] light Turn on the LED/Display mode.
/// @param[in] clean Turn on the self-cleaning mode. e.g. Mould, dry filters etc
@@ -687,10 +713,11 @@ void IRac::carrier64(IRCarrierAc64 *ac,
/// @note -1 is Off, >= 0 is on.
void IRac::coolix(IRCoolixAC *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
const bool turbo, const bool light, const bool clean,
const int16_t sleep) {
const bool iFeel, const bool turbo, const bool light,
const bool clean, const int16_t sleep) {
ac->begin();
ac->setPower(on);
if (!on) {
@@ -707,6 +734,12 @@ void IRac::coolix(IRCoolixAC *ac,
// No Clock setting available.
// No Econo setting available.
// No Quiet setting available.
if (sensorTemp != kNoTempValue) {
ac->setSensorTemp(static_cast<uint8_t>(std::round(sensorTemp)));
} else {
ac->clearSensorTemp();
}
ac->setZoneFollow(iFeel);
ac->send(); // Send the state, which will also power on the unit.
// The following are all options/settings that create their own special
// messages. Often they only make sense to be sent after the unit is turned
@@ -1071,13 +1104,16 @@ void IRac::delonghiac(IRDelonghiAc *ac,
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] sensorTemp The room (iFeel) temperature sensor reading in degrees
/// Celsius.
/// @param[in] fan The speed setting for the fan.
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
/// @param[in] clock The time in Nr. of mins since midnight. < 0 is ignore.
void IRac::ecoclim(IREcoclimAc *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const int16_t sleep, const int16_t clock) {
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const int16_t sleep,
const int16_t clock) {
ac->begin();
ac->setPower(on);
uint8_t new_mode;
@@ -1087,8 +1123,13 @@ void IRac::ecoclim(IREcoclimAc *ac,
new_mode = ac->convertMode(mode); // Not Sleep, so use the supplied mode.
ac->setMode(new_mode);
ac->setTemp(degrees);
ac->setSensorTemp(degrees); //< Set to the desired temp until we cab disable.
ac->setFan(ac->convertFan(fan));
if (sensorTemp != kNoTempValue) {
ac->setSensorTemp(static_cast<uint8_t>(std::round(sensorTemp)));
} else {
ac->setSensorTemp(degrees); //< Set to the desired temp
// until we can disable.
}
// No SwingV setting available
// No SwingH setting available
// No Quiet setting available.
@@ -1110,22 +1151,28 @@ void IRac::ecoclim(IREcoclimAc *ac,
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] sensorTemp The room (iFeel) temperature sensor reading in degrees
/// Celsius.
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] swingh The horizontal swing setting.
/// @param[in] iFeel Whether to enable iFeel (remote temp) mode on the A/C unit.
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] lighttoggle Should we toggle the LED/Display?
/// @param[in] clean Turn on the self-cleaning mode. e.g. Mould, dry filters etc
void IRac::electra(IRElectraAc *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv,
const stdAc::swingh_t swingh, const bool turbo,
const bool lighttoggle, const bool clean) {
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const stdAc::swingh_t swingh, const bool iFeel,
const bool turbo, const bool lighttoggle, const bool clean) {
ac->begin();
ac->setPower(on);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
if (sensorTemp != kNoTempValue) {
ac->setSensorTemp(static_cast<uint8_t>(std::round(sensorTemp)));
}
ac->setFan(ac->convertFan(fan));
ac->setSwingV(swingv != stdAc::swingv_t::kOff);
ac->setSwingH(swingh != stdAc::swingh_t::kOff);
@@ -1138,6 +1185,7 @@ void IRac::electra(IRElectraAc *ac,
// No Beep setting available.
// No Sleep setting available.
// No Clock setting available.
ac->setIFeel(iFeel);
ac->send();
}
#endif // SEND_ELECTRA_AC
@@ -1263,6 +1311,7 @@ void IRac::goodweather(IRGoodweatherAc *ac,
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] swingh The horizontal swing setting.
/// @param[in] iFeel Whether to enable iFeel (remote temp) mode on the A/C unit.
/// @param[in] turbo Run the device in turbo/powerful mode.
/// @param[in] econo Toggle the device's economical mode.
/// @param[in] light Turn on the LED/Display mode.
@@ -1272,8 +1321,8 @@ void IRac::gree(IRGreeAC *ac, const gree_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 turbo, const bool econo, const bool light,
const bool clean, const int16_t sleep) {
const bool iFeel, const bool turbo, const bool econo,
const bool light, const bool clean, const int16_t sleep) {
ac->begin();
ac->setModel(model);
ac->setPower(on);
@@ -1283,6 +1332,7 @@ void IRac::gree(IRGreeAC *ac, const gree_ac_remote_model_t model,
ac->setSwingVertical(swingv == stdAc::swingv_t::kAuto, // Set auto flag.
ac->convertSwingV(swingv));
ac->setSwingHorizontal(ac->convertSwingH(swingh));
ac->setIFeel(iFeel);
ac->setLight(light);
ac->setTurbo(turbo);
ac->setEcono(econo);
@@ -1792,8 +1842,11 @@ void IRac::lg(IRLgAc *ac, const lg_ac_remote_model_t model,
/// @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] sensorTemp The room (iFeel) temperature sensor reading
/// in degrees.
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] iFeel Whether to enable iFeel (remote temp) mode on the A/C unit.
/// @param[in] quiet Run the device in quiet/silent mode.
/// @param[in] quiet_prev The device's previous quiet/silent mode.
/// @param[in] turbo Toggle the device's turbo/powerful mode.
@@ -1804,9 +1857,9 @@ void IRac::lg(IRLgAc *ac, const lg_ac_remote_model_t model,
/// @note On Danby A/C units, swingv controls the Ion Filter instead.
void IRac::midea(IRMideaAC *ac,
const bool on, const stdAc::opmode_t mode, const bool celsius,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv,
const bool quiet, const bool quiet_prev,
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool iFeel, const bool quiet, const bool quiet_prev,
const bool turbo, const bool econo, const bool light,
const bool clean, const int16_t sleep) {
ac->begin();
@@ -1814,6 +1867,10 @@ void IRac::midea(IRMideaAC *ac,
ac->setMode(ac->convertMode(mode));
ac->setUseCelsius(celsius);
ac->setTemp(degrees, celsius);
if (sensorTemp != kNoTempValue) {
ac->setSensorTemp(sensorTemp, celsius);
}
ac->setEnableSensorTemp(iFeel);
ac->setFan(ac->convertFan(fan));
ac->setSwingVToggle(swingv != stdAc::swingv_t::kOff);
// No Horizontal swing setting available.
@@ -2211,19 +2268,29 @@ void IRac::samsung(IRSamsungAc *ac,
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] sensorTemp The room (iFeel) temperature sensor reading in degrees
/// Celsius.
/// @param[in] fan The speed setting for the fan.
/// @param[in] swingv The vertical swing setting.
/// @param[in] iFeel Whether to enable iFeel (remote temp) mode on the A/C unit.
/// @param[in] beep Enable/Disable beeps when receiving IR messages.
/// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on.
void IRac::sanyo(IRSanyoAc *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const bool beep,
const int16_t sleep) {
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool iFeel, const bool beep, const int16_t sleep) {
ac->begin();
ac->setPower(on);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
if (sensorTemp != kNoTempValue) {
ac->setSensorTemp(static_cast<uint8_t>(std::round(sensorTemp)));
} else {
ac->setSensorTemp(degrees); // Set the sensor temp to the desired
// (normal) temp.
}
ac->setSensor(!iFeel);
ac->setFan(ac->convertFan(fan));
ac->setSwingV(ac->convertSwingV(swingv));
// No Horizontal swing setting available.
@@ -2236,10 +2303,6 @@ void IRac::sanyo(IRSanyoAc *ac,
ac->setBeep(beep);
ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean.
// No Clock setting available.
// Extra
ac->setSensor(true); // Set the A/C to use the temp sensor in the Unit/Wall.
ac->setSensorTemp(degrees); // Set the sensor temp to the desired temp.
ac->send();
}
#endif // SEND_SANYO_AC
@@ -2932,6 +2995,11 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
// Convert the temp from Fahrenheit to Celsius if we are not in Celsius mode.
float degC __attribute__((unused)) =
desired.celsius ? desired.degrees : fahrenheitToCelsius(desired.degrees);
// Convert the sensorTemp from Fahrenheit to Celsius if we are not in Celsius
// mode.
float sensorTempC __attribute__((unused)) =
desired.sensorTemperature ? desired.sensorTemperature
: fahrenheitToCelsius(desired.sensorTemperature);
// special `state_t` that is required to be sent based on that.
stdAc::state_t send = this->handleToggles(this->cleanState(desired), prev);
// Some protocols expect a previous state for power.
@@ -2985,8 +3053,7 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
IRArgoAC_WREM3 ac(_pin, _inverted, _modulation);
switch (send.command) {
case stdAc::ac_command_t::kSensorTempReport:
argoWrem3_iFeelReport(&ac, send.degrees); // Uses "degrees"
// as roomTemp
argoWrem3_iFeelReport(&ac, sensorTempC);
break;
case stdAc::ac_command_t::kConfigCommand:
/// @warning: this is ABUSING current **common** parameters:
@@ -3000,16 +3067,16 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
break;
case stdAc::ac_command_t::kControlCommand:
default:
argoWrem3_ACCommand(&ac, send.power, send.mode, send.degrees,
send.fanspeed, send.swingv, send.quiet, send.econo, send.turbo,
send.filter, send.light);
argoWrem3_ACCommand(&ac, send.power, send.mode, degC, sensorTempC,
send.fanspeed, send.swingv, send.iFeel, send.quiet, send.econo,
send.turbo, send.filter, send.light);
break;
}
OUTPUT_DECODE_RESULTS_FOR_UT(ac);
} else {
IRArgoAC ac(_pin, _inverted, _modulation);
argo(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
send.turbo, send.sleep);
argo(&ac, send.power, send.mode, degC, sensorTempC, send.fanspeed,
send.swingv, send.iFeel, send.turbo, send.sleep);
OUTPUT_DECODE_RESULTS_FOR_UT(ac);
}
break;
@@ -3036,8 +3103,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
case COOLIX:
{
IRCoolixAC ac(_pin, _inverted, _modulation);
coolix(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
send.swingh, send.turbo, send.light, send.clean, send.sleep);
coolix(&ac, send.power, send.mode, degC, sensorTempC, send.fanspeed,
send.swingv, send.swingh, send.iFeel, send.turbo, send.light,
send.clean, send.sleep);
break;
}
#endif // SEND_COOLIX
@@ -3135,7 +3203,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
case ECOCLIM:
{
IREcoclimAc ac(_pin, _inverted, _modulation);
ecoclim(&ac, send.power, send.mode, degC, send.fanspeed, send.clock);
ecoclim(&ac, send.power, send.mode, degC, sensorTempC, send.fanspeed,
send.iFeel, send.clock);
break;
}
#endif // SEND_ECOCLIM
@@ -3143,8 +3212,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
case ELECTRA_AC:
{
IRElectraAc ac(_pin, _inverted, _modulation);
electra(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
send.swingh, send.turbo, send.light, send.clean);
electra(&ac, send.power, send.mode, degC, sensorTempC, send.fanspeed,
send.swingv, send.swingh, send.iFeel, send.turbo, send.light,
send.clean);
break;
}
#endif // SEND_ELECTRA_AC
@@ -3312,8 +3382,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
{
IRMideaAC ac(_pin, _inverted, _modulation);
midea(&ac, send.power, send.mode, send.celsius, send.degrees,
send.fanspeed, send.swingv, send.quiet, prev_quiet, send.turbo,
send.econo, send.light, send.sleep);
send.sensorTemperature, send.fanspeed, send.swingv, send.iFeel,
send.quiet, prev_quiet, send.turbo, send.econo, send.light,
send.sleep);
break;
}
#endif // SEND_MIDEA
@@ -3422,8 +3493,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
case SANYO_AC:
{
IRSanyoAc ac(_pin, _inverted, _modulation);
sanyo(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv,
send.beep, send.sleep);
sanyo(&ac, send.power, send.mode, degC, sensorTempC, send.fanspeed,
send.swingv, send.iFeel, send.beep, send.sleep);
break;
}
#endif // SEND_SANYO_AC
@@ -3581,7 +3652,8 @@ bool IRac::cmpStates(const stdAc::state_t a, const stdAc::state_t b) {
a.swingh != b.swingh || a.quiet != b.quiet || a.turbo != b.turbo ||
a.econo != b.econo || a.light != b.light || a.filter != b.filter ||
a.clean != b.clean || a.beep != b.beep || a.sleep != b.sleep ||
a.command != b.command;
a.command != b.command || a.sensorTemperature != b.sensorTemperature ||
a.iFeel != b.iFeel;
}
/// Check if the internal state has changed from what was previously sent.

View File

@@ -144,13 +144,14 @@ class IRac {
#if SEND_ARGO
void argo(IRArgoAC *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool turbo, const int16_t sleep = -1);
const float sensorTemp, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const bool iFeel, const bool turbo,
const int16_t sleep = -1);
void argoWrem3_ACCommand(IRArgoAC_WREM3 *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool night, const bool econo, const bool turbo, const bool filter,
const bool light);
const float sensorTemp, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const bool iFeel, const bool night,
const bool econo, const bool turbo, const bool filter, const bool light);
void argoWrem3_iFeelReport(IRArgoAC_WREM3 *ac, const float sensorTemp);
void argoWrem3_ConfigSet(IRArgoAC_WREM3 *ac, const uint8_t param,
const uint8_t value, bool safe = true);
@@ -162,7 +163,7 @@ class IRac {
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan,
const bool quiet);
#endif // SEND_COOLIX
#endif // SEND_BOSCH144
#if SEND_CARRIER_AC64
void carrier64(IRCarrierAc64 *ac,
const bool on, const stdAc::opmode_t mode,
@@ -172,10 +173,10 @@ void carrier64(IRCarrierAc64 *ac,
#if SEND_COOLIX
void coolix(IRCoolixAC *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan,
const float sensorTemp, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
const bool turbo, const bool light, const bool clean,
const int16_t sleep = -1);
const bool iFeel, const bool turbo, const bool light,
const bool clean, const int16_t sleep = -1);
#endif // SEND_COOLIX
#if SEND_CORONA_AC
void corona(IRCoronaAc *ac,
@@ -253,15 +254,16 @@ void daikin216(IRDaikin216 *ac,
#if SEND_ECOCLIM
void ecoclim(IREcoclimAc *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const int16_t sleep = -1, const int16_t clock = -1);
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const int16_t sleep = -1,
const int16_t clock = -1);
#endif // SEND_ECOCLIM
#if SEND_ELECTRA_AC
void electra(IRElectraAc *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv,
const stdAc::swingh_t swingh, const bool turbo,
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const stdAc::swingh_t swingh, const bool iFeel, const bool turbo,
const bool lighttoggle, const bool clean);
#endif // SEND_ELECTRA_AC
#if SEND_FUJITSU_AC
@@ -287,8 +289,8 @@ void electra(IRElectraAc *ac,
const bool on, const stdAc::opmode_t mode, const bool celsius,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const stdAc::swingh_t swingh,
const bool turbo, const bool econo, const bool light,
const bool clean, const int16_t sleep = -1);
const bool iFeel, const bool turbo, const bool econo,
const bool light, const bool clean, const int16_t sleep = -1);
#endif // SEND_GREE
#if SEND_HAIER_AC
void haier(IRHaierAC *ac,
@@ -385,11 +387,11 @@ void electra(IRElectraAc *ac,
#if SEND_MIDEA
void midea(IRMideaAC *ac,
const bool on, const stdAc::opmode_t mode, const bool celsius,
const float degrees, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv,
const bool quiet, const bool quiet_prev, const bool turbo,
const bool econo, const bool light, const bool clean,
const int16_t sleep = -1);
const float degrees, const float sensorTemp,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool iFeel, const bool quiet, const bool quiet_prev,
const bool turbo, const bool econo, const bool light,
const bool clean, const int16_t sleep = -1);
#endif // SEND_MIDEA
#if SEND_MIRAGE
void mirage(IRMirageAc *ac, const stdAc::state_t state);
@@ -473,8 +475,9 @@ void electra(IRElectraAc *ac,
#if SEND_SANYO_AC
void sanyo(IRSanyoAc *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv,
const bool beep, const int16_t sleep = -1);
const float sensorTemp, const stdAc::fanspeed_t fan,
const stdAc::swingv_t swingv, const bool iFeel, const bool beep,
const int16_t sleep = -1);
#endif // SEND_SANYO_AC
#if SEND_SANYO_AC88
void sanyo88(IRSanyoAc88 *ac,

View File

@@ -39,6 +39,9 @@ const uint8_t kDutyMax = 100; // Percentage
const uint16_t kMaxAccurateUsecDelay = 16383;
// Usecs to wait between messages we don't know the proper gap time.
const uint32_t kDefaultMessageGap = 100000;
/// Placeholder for missing sensor temp value
/// @note Not using "-1" as it may be a valid external temp
const float kNoTempValue = -100.0;
/// Enumerators and Structures for the Common A/C API.
namespace stdAc {
@@ -128,6 +131,8 @@ struct state_t {
int16_t sleep = -1; // `-1` means off.
int16_t clock = -1; // `-1` means not set.
stdAc::ac_command_t command = stdAc::ac_command_t::kControlCommand;
bool iFeel = false;
float sensorTemperature = kNoTempValue; // `kNoTempValue` means not set.
};
}; // namespace stdAc

View File

@@ -1253,8 +1253,9 @@ stdAc::state_t IRArgoAC::toCommon(void) const {
result.power = _.Power;
result.mode = toCommonMode(getModeEx());
result.celsius = true;
result.degrees = (_messageType != argoIrMessageType_t::IFEEL_TEMP_REPORT)?
getTemp() : getSensorTemp();
result.degrees = getTemp();
result.sensorTemperature = getSensorTemp();
result.iFeel = getiFeel();
result.fanspeed = toCommonFanSpeed(getFanEx());
result.turbo = _.Max;
result.sleep = _.Night ? 0 : -1;
@@ -1268,7 +1269,6 @@ stdAc::state_t IRArgoAC::toCommon(void) const {
result.clean = false;
result.beep = false;
result.clock = -1;
// Common does not (yet?) support commandType / iFeel / roomTemp
return result;
}
@@ -1282,8 +1282,9 @@ stdAc::state_t IRArgoAC_WREM3::toCommon(void) const {
result.power = getPower();
result.mode = toCommonMode(getModeEx());
result.celsius = true;
result.degrees = (_messageType != argoIrMessageType_t::IFEEL_TEMP_REPORT)?
getTemp() : getSensorTemp();
result.degrees = getTemp();
result.sensorTemperature = getSensorTemp();
result.iFeel = getiFeel();
result.fanspeed = toCommonFanSpeed(getFanEx());
result.turbo = _.Max;
result.swingv = toCommonSwingV(_.Flap);
@@ -1304,7 +1305,6 @@ stdAc::state_t IRArgoAC_WREM3::toCommon(void) const {
result.swingh = stdAc::swingh_t::kOff;
result.clean = false;
// Common does not (yet?) support commandType / iFeel / roomTemp
return result;
}

View File

@@ -548,6 +548,8 @@ stdAc::state_t IRCoolixAC::toCommon(const stdAc::state_t *prev) const {
// Back to "normal" stateful messages.
result.mode = toCommonMode(getMode());
result.degrees = getTemp();
result.sensorTemperature = getSensorTemp();
result.iFeel = getZoneFollow();
result.fanspeed = toCommonFanSpeed(getFan());
return result;
}

View File

@@ -165,6 +165,7 @@ class IRCoolixAC {
static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed);
stdAc::state_t toCommon(const stdAc::state_t *prev = NULL) const;
String toString(void) const;
void setZoneFollow(const bool on);
#ifndef UNIT_TEST
private:
@@ -189,7 +190,6 @@ class IRCoolixAC {
void setTempRaw(const uint8_t code);
uint8_t getTempRaw(void) const;
void setSensorTempRaw(const uint8_t code);
void setZoneFollow(const bool on);
bool isSpecialState(void) const;
bool handleSpecialState(const uint32_t data);
void updateAndSaveState(const uint32_t raw_state);

View File

@@ -365,6 +365,7 @@ stdAc::state_t IREcoclimAc::toCommon(void) const {
result.mode = toCommonMode(getMode());
result.celsius = true;
result.degrees = getTemp();
result.sensorTemperature = getSensorTemp();
result.fanspeed = toCommonFanSpeed(_.Fan);
result.sleep = (getMode() == kEcoclimSleep) ? 0 : -1;
result.clock = getClock();

View File

@@ -365,6 +365,7 @@ stdAc::state_t IRElectraAc::toCommon(void) const {
result.mode = toCommonMode(_.Mode);
result.celsius = true;
result.degrees = getTemp();
result.sensorTemperature = getSensorTemp();
result.fanspeed = toCommonFanSpeed(_.Fan);
result.swingv = getSwingV() ? stdAc::swingv_t::kAuto
: stdAc::swingv_t::kOff;
@@ -373,6 +374,7 @@ stdAc::state_t IRElectraAc::toCommon(void) const {
result.light = getLightToggle();
result.turbo = _.Turbo;
result.clean = _.Clean;
result.iFeel = getIFeel();
// Not supported.
result.model = -1; // No models used.
result.quiet = false;

View File

@@ -591,6 +591,8 @@ stdAc::state_t IRGreeAC::toCommon(void) {
result.mode = toCommonMode(_.Mode);
result.celsius = !_.UseFahrenheit;
result.degrees = getTemp();
// no support for Sensor temp.
result.iFeel = getIFeel();
result.fanspeed = toCommonFanSpeed(_.Fan);
if (_.SwingAuto)
result.swingv = stdAc::swingv_t::kAuto;

View File

@@ -679,6 +679,7 @@ stdAc::state_t IRMideaAC::toCommon(const stdAc::state_t *prev) {
result.mode = toCommonMode(_.Mode);
result.celsius = !_.useFahrenheit;
result.degrees = getTemp(result.celsius);
result.sensorTemperature = getSensorTemp(result.celsius);
result.fanspeed = toCommonFanSpeed(_.Fan);
result.sleep = _.Sleep ? 0 : -1;
result.econo = getEconoToggle();

View File

@@ -740,6 +740,7 @@ stdAc::state_t IRMirageAc::toCommon(void) const {
result.mode = toCommonMode(_.Mode);
result.celsius = true;
result.degrees = getTemp();
result.sensorTemperature = getSensorTemp();
result.fanspeed = toCommonFanSpeed(getFan(), _model);
result.swingv = toCommonSwingV(getSwingV());
result.swingh = getSwingH() ? stdAc::swingh_t::kAuto : stdAc::swingh_t::kOff;
@@ -750,6 +751,7 @@ stdAc::state_t IRMirageAc::toCommon(void) const {
result.sleep = getSleep() ? 0 : -1;
result.quiet = getQuiet();
result.clock = getClock() / 60;
result.iFeel = getIFeel();
// Not supported.
result.econo = false;
result.beep = false;
@@ -775,10 +777,14 @@ void IRMirageAc::fromCommon(const stdAc::state_t state) {
setFilter(state.filter);
// setClock() expects seconds, not minutes.
setClock((state.clock > 0) ? state.clock * 60 : 0);
setIFeel(state.iFeel);
if (state.sensorTemperature != kNoTempValue) {
setSensorTemp(state.celsius ? state.sensorTemperature
: fahrenheitToCelsius(state.sensorTemperature));
}
// Non-common settings.
setOnTimer(0);
setOffTimer(0);
setIFeel(false);
}
/// Convert the internal state into a human readable string.

View File

@@ -622,10 +622,12 @@ stdAc::state_t IRSanyoAc::toCommon(void) const {
result.mode = toCommonMode(_.Mode);
result.celsius = true;
result.degrees = getTemp();
result.sensorTemperature = getSensorTemp();
result.fanspeed = toCommonFanSpeed(_.Fan);
result.sleep = _.Sleep ? 0 : -1;
result.swingv = toCommonSwingV(_.SwingV);
result.beep = _.Beep;
result.iFeel = !getSensor();
// Not supported.
result.swingh = stdAc::swingh_t::kOff;
result.turbo = false;

View File

@@ -133,8 +133,10 @@ TEST(TestIRac, Argo) {
true, // Power
stdAc::opmode_t::kHeat, // Mode
21, // Celsius
22, // Sensor Temp.
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kOff, // Vertical swing
false, // iFeel
false, // Turbo
-1); // Sleep
EXPECT_TRUE(ac.getPower());
@@ -194,9 +196,11 @@ TEST(TestIRac, Coolix) {
true, // Power
stdAc::opmode_t::kHeat, // Mode
21, // Celsius
kNoTempValue, // Sensor Temp
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kOff, // Vertical swing
stdAc::swingh_t::kOff, // Horizontal swing
false, // iFeel
false, // Turbo
false, // Light
false, // Clean
@@ -562,7 +566,7 @@ TEST(TestIRac, Ecoclim) {
IRac irac(kGpioUnused);
IRrecv capture(kGpioUnused);
char expected[] =
"Power: On, Mode: 1 (Cool), Temp: 26C, SensorTemp: 26C, Fan: 2 (High), "
"Power: On, Mode: 1 (Cool), Temp: 26C, SensorTemp: 27C, Fan: 2 (High), "
"Clock: 12:34, On Timer: Off, Off Timer: Off, Type: 0";
ac.begin();
@@ -570,6 +574,7 @@ TEST(TestIRac, Ecoclim) {
true, // Power
stdAc::opmode_t::kCool, // Mode
26, // Celsius
27, // Sensor Temp.
stdAc::fanspeed_t::kHigh, // Fan speed
-1, // Sleep
12 * 60 + 34); // Clock
@@ -581,7 +586,7 @@ TEST(TestIRac, Ecoclim) {
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
char expected_sleep[] =
"Power: On, Mode: 7 (Sleep), Temp: 21C, SensorTemp: 21C, Fan: 0 (Low), "
"Power: On, Mode: 7 (Sleep), Temp: 21C, SensorTemp: 22C, Fan: 0 (Low), "
"Clock: 17:17, On Timer: Off, Off Timer: Off, Type: 0";
ac._irsend.reset();
@@ -589,6 +594,7 @@ TEST(TestIRac, Ecoclim) {
true, // Power
stdAc::opmode_t::kCool, // Mode
21, // Celsius
22, // Sensor Temp.
stdAc::fanspeed_t::kLow, // Fan speed
8 * 60, // Sleep
17 * 60 + 17); // Clock
@@ -614,9 +620,11 @@ TEST(TestIRac, Electra) {
true, // Power
stdAc::opmode_t::kFan, // Mode
26, // Celsius
27, // Sensor Temp.
stdAc::fanspeed_t::kHigh, // Fan speed
stdAc::swingv_t::kAuto, // Vertical swing
stdAc::swingh_t::kLeft, // Horizontal swing
false, // iFeel
true, // Turbo
true, // Light (toggle)
true); // Clean
@@ -779,7 +787,7 @@ TEST(TestIRac, Gree) {
IRrecv capture(kGpioUnused);
char expected[] =
"Model: 1 (YAW1F), Power: On, Mode: 1 (Cool), Temp: 71F, "
"Fan: 2 (Medium), Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, "
"Fan: 2 (Medium), Turbo: Off, Econo: Off, IFeel: On, WiFi: Off, "
"XFan: On, Light: On, Sleep: On, Swing(V) Mode: Manual, "
"Swing(V): 3 (UNKNOWN), Swing(H): 5 (Right), Timer: Off, "
"Display Temp: 0 (Off)";
@@ -794,6 +802,7 @@ TEST(TestIRac, Gree) {
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kHigh, // Vertical swing
stdAc::swingh_t::kRight, // Horizontal swing
true, // iFeel
false, // Turbo
false, // Econo
true, // Light
@@ -1496,8 +1505,10 @@ TEST(TestIRac, Midea) {
stdAc::opmode_t::kDry, // Mode
true, // Celsius
27, // Degrees
28, // Sensor Temp.
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kOff, // Swing(V)
false, // iFeel
false, // Silent/Quiet
false, // Previous Silent/Quiet setting
false, // Turbo
@@ -1939,8 +1950,10 @@ TEST(TestIRac, Sanyo) {
true, // Power
stdAc::opmode_t::kCool, // Mode
28, // Celsius
kNoTempValue, // SensorTemp
stdAc::fanspeed_t::kMedium, // Fan speed
stdAc::swingv_t::kHighest, // Vertical Swing
false, // iFeel
true, // Beep
17); // Sleep
ASSERT_EQ(expected, ac.toString());
@@ -2576,6 +2589,16 @@ TEST(TestIRac, cmpStates) {
ASSERT_FALSE(IRac::cmpStates(a, b));
b.command = stdAc::ac_command_t::kTimerCommand;
ASSERT_TRUE(IRac::cmpStates(a, b));
b = a;
ASSERT_FALSE(IRac::cmpStates(a, b));
b.iFeel = true;
ASSERT_TRUE(IRac::cmpStates(a, b));
b = a;
ASSERT_FALSE(IRac::cmpStates(a, b));
b.sensorTemperature = 12.5;
ASSERT_TRUE(IRac::cmpStates(a, b));
}
TEST(TestIRac, handleToggles) {
@@ -2872,9 +2895,11 @@ TEST(TestIRac, Issue821) {
result.power, // Power
result.mode, // Mode
result.degrees, // Celsius
kNoTempValue, // Sensor Temp
result.fanspeed, // Fan speed
result.swingv, // Vertical swing
result.swingh, // Horizontal swing
result.iFeel, // iFeel
result.turbo, // Turbo
result.light, // Light
result.clean, // Clean
@@ -3253,4 +3278,25 @@ TEST(TestIRac, initState) {
EXPECT_EQ(stdAc::swingv_t::kOff, builtin_init.swingv);
EXPECT_EQ(decode_type_t::UNKNOWN, no_init.protocol);
EXPECT_EQ(stdAc::ac_command_t::kControlCommand, no_init.command);
EXPECT_FALSE(no_init.iFeel);
EXPECT_EQ(kNoTempValue, no_init.sensorTemperature);
}
TEST(TestIRac, cleanState) {
IRac irac(kGpioUnused);
stdAc::state_t s = {};
s.mode = stdAc::opmode_t::kFan;
s.power = true;
s.sensorTemperature = 20.5;
s.degrees = 22.3;
auto clean = irac.cleanState(s);
EXPECT_TRUE(clean.power);
EXPECT_EQ(s.mode, clean.mode);
EXPECT_EQ(s.sensorTemperature, clean.sensorTemperature);
EXPECT_EQ(s.degrees, clean.degrees);
s.mode = stdAc::opmode_t::kOff;
clean = irac.cleanState(s);
EXPECT_FALSE(clean.power);
}

View File

@@ -44,6 +44,8 @@ TEST(TestArgoACClass, toCommon) {
ASSERT_FALSE(ac.toCommon().beep);
ASSERT_FALSE(ac.toCommon().quiet);
ASSERT_EQ(-1, ac.toCommon().clock);
ASSERT_FALSE(ac.toCommon().iFeel);
ASSERT_EQ(25, ac.toCommon().sensorTemperature);
}
TEST(TestArgoAC_WREM3Class, toCommon) {
@@ -79,6 +81,8 @@ TEST(TestArgoAC_WREM3Class, toCommon) {
ASSERT_TRUE(ac.toCommon().econo);
ASSERT_TRUE(ac.toCommon().light);
ASSERT_TRUE(ac.toCommon().filter);
ASSERT_TRUE(ac.toCommon().iFeel);
ASSERT_EQ(25, ac.toCommon().sensorTemperature);
}
/******************************************************************************/
@@ -409,7 +413,7 @@ TEST(TestIrAc, ArgoWrem3_SyntheticSendAndDecode_iFeelReport) {
state.protocol = ARGO;
state.model = argo_ac_remote_model_t::SAC_WREM3;
state.command = stdAc::ac_command_t::kSensorTempReport;
state.degrees = 19;
state.sensorTemperature = 18.9; // expected to be rounded up
irac.sendAc(state, nullptr);
@@ -424,7 +428,7 @@ TEST(TestIrAc, ArgoWrem3_SyntheticSendAndDecode_iFeelReport) {
EXPECT_EQ(ARGO, r.protocol);
EXPECT_EQ(state.model, r.model);
EXPECT_EQ(state.command, r.command);
EXPECT_EQ(state.degrees, r.degrees);
EXPECT_EQ(19, r.sensorTemperature);
}
TEST(TestIrAc, ArgoWrem3_SyntheticSendAndDecode_Timer) {
@@ -1454,6 +1458,7 @@ TEST(TestDecodeArgo, RealShortDecode) {
// These short messages do result in a valid state (w/ room temperature only)
EXPECT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
EXPECT_EQ(stdAc::ac_command_t::kSensorTempReport, r.command);
EXPECT_EQ(28, r.sensorTemperature);
}
///