Skip to content

Commit c657b27

Browse files
authored
Airton: Add detailed A/C support. (#1688)
* 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
1 parent 7b13d24 commit c657b27

File tree

8 files changed

+823
-7
lines changed

8 files changed

+823
-7
lines changed

src/IRac.cpp

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "IRremoteESP8266.h"
1717
#include "IRtext.h"
1818
#include "IRutils.h"
19+
#include "ir_Airton.h"
1920
#include "ir_Airwell.h"
2021
#include "ir_Amcor.h"
2122
#include "ir_Argo.h"
@@ -152,9 +153,12 @@ stdAc::state_t IRac::getStatePrev(void) { return _prev; }
152153
/// @return true if the protocol is supported by this class, otherwise false.
153154
bool IRac::isProtocolSupported(const decode_type_t protocol) {
154155
switch (protocol) {
156+
#if SEND_AIRTON
157+
case decode_type_t::AIRTON:
158+
#endif // SEND_AIRTON
155159
#if SEND_AIRWELL
156160
case decode_type_t::AIRWELL:
157-
#endif
161+
#endif // SEND_AIRWELL
158162
#if SEND_AMCOR
159163
case decode_type_t::AMCOR:
160164
#endif
@@ -326,6 +330,44 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) {
326330
}
327331
}
328332

333+
#if SEND_AIRTON
334+
/// Send an Airton 56-bit A/C message with the supplied settings.
335+
/// @param[in, out] ac A Ptr to an IRAirtonAc object to use.
336+
/// @param[in] on The power setting.
337+
/// @param[in] mode The operation mode setting.
338+
/// @param[in] degrees The temperature setting in degrees.
339+
/// @param[in] fan The speed setting for the fan.
340+
/// @param[in] swingv The vertical swing setting.
341+
/// @param[in] turbo Run the device in turbo/powerful mode.
342+
/// @param[in] light Turn on the LED/Display mode.
343+
/// @param[in] econo Run the device in economical mode.
344+
/// @param[in] filter Turn on the (ion/pollen/health/etc) filter mode.
345+
/// @param[in] sleep Nr. of minutes for sleep mode.
346+
/// @note -1 is Off, >= 0 is on.
347+
void IRac::airton(IRAirtonAc *ac,
348+
const bool on, const stdAc::opmode_t mode,
349+
const float degrees, const stdAc::fanspeed_t fan,
350+
const stdAc::swingv_t swingv, const bool turbo,
351+
const bool light, const bool econo, const bool filter,
352+
const int16_t sleep) {
353+
ac->begin();
354+
ac->setPower(on);
355+
ac->setMode(ac->convertMode(mode));
356+
ac->setTemp(degrees);
357+
ac->setFan(ac->convertFan(fan));
358+
ac->setSwingV(swingv != stdAc::swingv_t::kOff);
359+
// No Quiet setting available.
360+
ac->setLight(light);
361+
ac->setHealth(filter);
362+
ac->setTurbo(turbo);
363+
ac->setEcono(econo);
364+
// No Clean setting available.
365+
// No Beep setting available.
366+
ac->setSleep(sleep >= 0); // Convert to a boolean.
367+
ac->send();
368+
}
369+
#endif // SEND_AIRTON
370+
329371
#if SEND_AIRWELL
330372
/// Send an Airwell A/C message with the supplied settings.
331373
/// @param[in, out] ac A Ptr to an IRAirwellAc object to use.
@@ -2603,6 +2645,16 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
26032645
#endif // (SEND_LG || SEND_SHARP_AC)
26042646
// Per vendor settings & setup.
26052647
switch (send.protocol) {
2648+
#if SEND_AIRTON
2649+
case AIRTON:
2650+
{
2651+
IRAirtonAc ac(_pin, _inverted, _modulation);
2652+
airton(&ac, send.power, send.mode, degC, send.fanspeed,
2653+
send.swingv, send.turbo, send.light, send.econo, send.filter,
2654+
send.sleep);
2655+
break;
2656+
}
2657+
#endif // SEND_AIRTON
26062658
#if SEND_AIRWELL
26072659
case AIRWELL:
26082660
{
@@ -3507,6 +3559,13 @@ namespace IRAcUtils {
35073559
/// An empty string if we can't.
35083560
String resultAcToString(const decode_results * const result) {
35093561
switch (result->decode_type) {
3562+
#if DECODE_AIRTON
3563+
case decode_type_t::AIRTON: {
3564+
IRAirtonAc ac(kGpioUnused);
3565+
ac.setRaw(result->value); // AIRTON uses value instead of state.
3566+
return ac.toString();
3567+
}
3568+
#endif // DECODE_AIRTON
35103569
#if DECODE_AIRWELL
35113570
case decode_type_t::AIRWELL: {
35123571
IRAirwellAc ac(kGpioUnused);
@@ -3931,6 +3990,14 @@ namespace IRAcUtils {
39313990
) {
39323991
if (decode == NULL || result == NULL) return false; // Safety check.
39333992
switch (decode->decode_type) {
3993+
#if DECODE_AIRTON
3994+
case decode_type_t::AIRTON: {
3995+
IRAirtonAc ac(kGpioUnused);
3996+
ac.setRaw(decode->value); // Uses value instead of state.
3997+
*result = ac.toCommon();
3998+
break;
3999+
}
4000+
#endif // DECODE_AIRTON
39344001
#if DECODE_AIRWELL
39354002
case decode_type_t::AIRWELL: {
39364003
IRAirwellAc ac(kGpioUnused);

src/IRac.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <Arduino.h>
88
#endif
99
#include "IRremoteESP8266.h"
10+
#include "ir_Airton.h"
1011
#include "ir_Airwell.h"
1112
#include "ir_Amcor.h"
1213
#include "ir_Argo.h"
@@ -109,6 +110,14 @@ class IRac {
109110
bool _inverted; ///< IR LED is lit when GPIO is LOW (true) or HIGH (false)?
110111
bool _modulation; ///< Is frequency modulation to be used?
111112
stdAc::state_t _prev; ///< The state we expect the device to currently be in.
113+
#if SEND_AIRTON
114+
void airton(IRAirtonAc *ac,
115+
const bool on, const stdAc::opmode_t mode,
116+
const float degrees, const stdAc::fanspeed_t fan,
117+
const stdAc::swingv_t swingv, const bool turbo,
118+
const bool light, const bool econo, const bool filter,
119+
const int16_t sleep = -1);
120+
#endif // SEND_AIRTON
112121
#if SEND_AIRWELL
113122
void airwell(IRAirwellAc *ac,
114123
const bool on, const stdAc::opmode_t mode, const float degrees,

src/IRutils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,21 @@ namespace irutils {
10491049
return nibbleonly ? sum & 0xF : sum;
10501050
}
10511051

1052+
/// Sum all the bytes together in an integer.
1053+
/// @param[in] data The integer to be summed.
1054+
/// @param[in] count The number of bytes to sum. Starts from LSB. Max of 8.
1055+
/// @param[in] init Starting value of the calculation to use. (Default is 0)
1056+
/// @param[in] byteonly true, the result is 8 bits. false, it's 16 bits.
1057+
/// @return The 8/16-bit calculated result of all the bytes and init value.
1058+
uint16_t sumBytes(const uint64_t data, const uint8_t count,
1059+
const uint8_t init, const bool byteonly) {
1060+
uint16_t sum = init;
1061+
uint64_t copy = data;
1062+
const uint8_t nrofbytes = (count < 8) ? count : (64 / 8);
1063+
for (uint8_t i = 0; i < nrofbytes; i++, copy >>= 8) sum += (copy & 0xFF);
1064+
return byteonly ? sum & 0xFF : sum;
1065+
}
1066+
10521067
/// Convert a byte of Binary Coded Decimal(BCD) into an Integer.
10531068
/// @param[in] bcd The BCD value.
10541069
/// @return A normal Integer value.

src/IRutils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ namespace irutils {
9494
const uint8_t init = 0);
9595
uint8_t sumNibbles(const uint64_t data, const uint8_t count = 16,
9696
const uint8_t init = 0, const bool nibbleonly = true);
97+
uint16_t sumBytes(const uint64_t data, const uint8_t count = 8,
98+
const uint8_t init = 0, const bool byteonly = true);
9799
uint8_t bcdToUint8(const uint8_t bcd);
98100
uint8_t uint8ToBcd(const uint8_t integer);
99101
bool getBit(const uint64_t data, const uint8_t position,

0 commit comments

Comments
 (0)