Skip to content

Commit

Permalink
Airton: Add detailed A/C support. (#1688)
Browse files Browse the repository at this point in the history
* Add checksum verification to `decodeAirton()`.
* Add detailed support for Airton AC's via `IRAirtonAc` class.
  - Power
  - Temp
  - Mode
  - Fan Speed
  - SwingV
  - LED/Light/Display
  - Health/Filter
  - Turbo
  - Econo/Eco
  - Sleep
* Add `AIRTON` to `IRac` common API.
* Add unit test coverage for new changes.

H/T to @PtilopsisLeucotis for working out the checksum alg. Kudos!

Fixes #1670
  • Loading branch information
crankyoldgit committed Nov 22, 2021
1 parent 7b13d24 commit c657b27
Show file tree
Hide file tree
Showing 8 changed files with 823 additions and 7 deletions.
69 changes: 68 additions & 1 deletion src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "IRremoteESP8266.h"
#include "IRtext.h"
#include "IRutils.h"
#include "ir_Airton.h"
#include "ir_Airwell.h"
#include "ir_Amcor.h"
#include "ir_Argo.h"
Expand Down Expand Up @@ -152,9 +153,12 @@ stdAc::state_t IRac::getStatePrev(void) { return _prev; }
/// @return true if the protocol is supported by this class, otherwise false.
bool IRac::isProtocolSupported(const decode_type_t protocol) {
switch (protocol) {
#if SEND_AIRTON
case decode_type_t::AIRTON:
#endif // SEND_AIRTON
#if SEND_AIRWELL
case decode_type_t::AIRWELL:
#endif
#endif // SEND_AIRWELL
#if SEND_AMCOR
case decode_type_t::AMCOR:
#endif
Expand Down Expand Up @@ -326,6 +330,44 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
}
}

#if SEND_AIRTON
/// Send an Airton 56-bit A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRAirtonAc object to use.
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @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] turbo Run the device in turbo/powerful mode.
/// @param[in] light Turn on the LED/Display mode.
/// @param[in] econo Run the device in economical mode.
/// @param[in] filter Turn on the (ion/pollen/health/etc) filter mode.
/// @param[in] sleep Nr. of minutes for sleep mode.
/// @note -1 is Off, >= 0 is on.
void IRac::airton(IRAirtonAc *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 bool light, const bool econo, const bool filter,
const int16_t sleep) {
ac->begin();
ac->setPower(on);
ac->setMode(ac->convertMode(mode));
ac->setTemp(degrees);
ac->setFan(ac->convertFan(fan));
ac->setSwingV(swingv != stdAc::swingv_t::kOff);
// No Quiet setting available.
ac->setLight(light);
ac->setHealth(filter);
ac->setTurbo(turbo);
ac->setEcono(econo);
// No Clean setting available.
// No Beep setting available.
ac->setSleep(sleep >= 0); // Convert to a boolean.
ac->send();
}
#endif // SEND_AIRTON

#if SEND_AIRWELL
/// Send an Airwell A/C message with the supplied settings.
/// @param[in, out] ac A Ptr to an IRAirwellAc object to use.
Expand Down Expand Up @@ -2603,6 +2645,16 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
#endif // (SEND_LG || SEND_SHARP_AC)
// Per vendor settings & setup.
switch (send.protocol) {
#if SEND_AIRTON
case AIRTON:
{
IRAirtonAc ac(_pin, _inverted, _modulation);
airton(&ac, send.power, send.mode, degC, send.fanspeed,
send.swingv, send.turbo, send.light, send.econo, send.filter,
send.sleep);
break;
}
#endif // SEND_AIRTON
#if SEND_AIRWELL
case AIRWELL:
{
Expand Down Expand Up @@ -3507,6 +3559,13 @@ namespace IRAcUtils {
/// An empty string if we can't.
String resultAcToString(const decode_results * const result) {
switch (result->decode_type) {
#if DECODE_AIRTON
case decode_type_t::AIRTON: {
IRAirtonAc ac(kGpioUnused);
ac.setRaw(result->value); // AIRTON uses value instead of state.
return ac.toString();
}
#endif // DECODE_AIRTON
#if DECODE_AIRWELL
case decode_type_t::AIRWELL: {
IRAirwellAc ac(kGpioUnused);
Expand Down Expand Up @@ -3931,6 +3990,14 @@ namespace IRAcUtils {
) {
if (decode == NULL || result == NULL) return false; // Safety check.
switch (decode->decode_type) {
#if DECODE_AIRTON
case decode_type_t::AIRTON: {
IRAirtonAc ac(kGpioUnused);
ac.setRaw(decode->value); // Uses value instead of state.
*result = ac.toCommon();
break;
}
#endif // DECODE_AIRTON
#if DECODE_AIRWELL
case decode_type_t::AIRWELL: {
IRAirwellAc ac(kGpioUnused);
Expand Down
9 changes: 9 additions & 0 deletions src/IRac.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Arduino.h>
#endif
#include "IRremoteESP8266.h"
#include "ir_Airton.h"
#include "ir_Airwell.h"
#include "ir_Amcor.h"
#include "ir_Argo.h"
Expand Down Expand Up @@ -109,6 +110,14 @@ class IRac {
bool _inverted; ///< IR LED is lit when GPIO is LOW (true) or HIGH (false)?
bool _modulation; ///< Is frequency modulation to be used?
stdAc::state_t _prev; ///< The state we expect the device to currently be in.
#if SEND_AIRTON
void airton(IRAirtonAc *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 bool light, const bool econo, const bool filter,
const int16_t sleep = -1);
#endif // SEND_AIRTON
#if SEND_AIRWELL
void airwell(IRAirwellAc *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
Expand Down
15 changes: 15 additions & 0 deletions src/IRutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,21 @@ namespace irutils {
return nibbleonly ? sum & 0xF : sum;
}

/// Sum all the bytes together in an integer.
/// @param[in] data The integer to be summed.
/// @param[in] count The number of bytes to sum. Starts from LSB. Max of 8.
/// @param[in] init Starting value of the calculation to use. (Default is 0)
/// @param[in] byteonly true, the result is 8 bits. false, it's 16 bits.
/// @return The 8/16-bit calculated result of all the bytes and init value.
uint16_t sumBytes(const uint64_t data, const uint8_t count,
const uint8_t init, const bool byteonly) {
uint16_t sum = init;
uint64_t copy = data;
const uint8_t nrofbytes = (count < 8) ? count : (64 / 8);
for (uint8_t i = 0; i < nrofbytes; i++, copy >>= 8) sum += (copy & 0xFF);
return byteonly ? sum & 0xFF : sum;
}

/// Convert a byte of Binary Coded Decimal(BCD) into an Integer.
/// @param[in] bcd The BCD value.
/// @return A normal Integer value.
Expand Down
2 changes: 2 additions & 0 deletions src/IRutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ namespace irutils {
const uint8_t init = 0);
uint8_t sumNibbles(const uint64_t data, const uint8_t count = 16,
const uint8_t init = 0, const bool nibbleonly = true);
uint16_t sumBytes(const uint64_t data, const uint8_t count = 8,
const uint8_t init = 0, const bool byteonly = true);
uint8_t bcdToUint8(const uint8_t bcd);
uint8_t uint8ToBcd(const uint8_t integer);
bool getBit(const uint64_t data, const uint8_t position,
Expand Down
Loading

0 comments on commit c657b27

Please sign in to comment.