Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic support for Airton Protocol #1681

Merged
merged 1 commit into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Rhoss decode");
if (decodeRhoss(results, offset)) return true;
#endif // DECODE_RHOSS
#if DECODE_AIRTON
DPRINTLN("Attempting Airton decode");
if (decodeAirton(results, offset)) return true;
#endif // DECODE_AIRTON
// Typically new protocols are added above this line.
}
#if DECODE_HASH
Expand Down
5 changes: 5 additions & 0 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,11 @@ class IRrecv {
bool decodeRhoss(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kRhossBits, const bool strict = true);
#endif // DECODE_RHOSS
#if DECODE_AIRTON
bool decodeAirton(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kAirtonBits,
const bool strict = true);
#endif // DECODE_AIRTON
};

#endif // IRRECV_H_
16 changes: 13 additions & 3 deletions src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -798,12 +798,19 @@
#endif // SEND_ARRIS

#ifndef DECODE_RHOSS
#define DECODE_RHOSS _IR_ENABLE_DEFAULT_
#define DECODE_RHOSS _IR_ENABLE_DEFAULT_
#endif // DECODE_RHOSS
#ifndef SEND_RHOSS
#define SEND_RHOSS _IR_ENABLE_DEFAULT_
#define SEND_RHOSS _IR_ENABLE_DEFAULT_
#endif // SEND_RHOSS

#ifndef DECODE_AIRTON
#define DECODE_AIRTON _IR_ENABLE_DEFAULT_
#endif // DECODE_AIRTON
#ifndef SEND_AIRTON
#define SEND_AIRTON _IR_ENABLE_DEFAULT_
#endif // SEND_AIRTON

#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
Expand Down Expand Up @@ -967,14 +974,17 @@ enum decode_type_t {
BOSE,
ARRIS,
RHOSS,
AIRTON,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = RHOSS,
kLastDecodeType = AIRTON,
};

// Message lengths & required repeat values
const uint16_t kNoRepeat = 0;
const uint16_t kSingleRepeat = 1;

const uint16_t kAirtonBits = 56;
const uint16_t kAirtonDefaultRepeat = kNoRepeat;
const uint16_t kAirwellBits = 34;
const uint16_t kAirwellMinRepeats = 2;
const uint16_t kAiwaRcT501Bits = 15;
Expand Down
6 changes: 6 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
case MIDEA:
case PANASONIC:
return 48;
case AIRTON:
case ECOCLIM:
case MAGIQUEST:
case VESTEL_AC:
Expand Down Expand Up @@ -784,6 +785,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
uint16_t min_repeat __attribute__((unused)) =
std::max(IRsend::minRepeats(type), repeat);
switch (type) {
#if SEND_AIRTON
case AIRTON:
sendAirton(data, nbits, min_repeat);
break;
#endif // SEND_AIRTON
#if SEND_AIRWELL
case AIRWELL:
sendAirwell(data, nbits, min_repeat);
Expand Down
4 changes: 4 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,10 @@ class IRsend {
const uint16_t nbytes = kRhossStateLength,
const uint16_t repeat = kRhossDefaultRepeat);
#endif // SEND_RHOSS
#if SEND_AIRTON
void sendAirton(const uint64_t data, const uint16_t nbits = kAirtonBits,
const uint16_t repeat = kAirtonDefaultRepeat);
#endif // SEND_AIRTON

protected:
#ifdef UNIT_TEST
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_BOSE "\x0"
D_STR_ARRIS "\x0"
D_STR_RHOSS "\x0"
D_STR_AIRTON "\x0"
///< New protocol strings should be added just above this line.
"\x0" ///< This string requires double null termination.
};
Expand Down
70 changes: 70 additions & 0 deletions src/ir_Airton.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2021 David Conran (crankyoldgit)
/// @file
/// @brief Support for Airton protocol
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1670

// Supports:
// Brand: Airton, Model: SMVH09B-2A2A3NH ref. 409730 A/C
// Brand: Airton, Model: RD1A1 remote

#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"

const uint16_t kAirtonHdrMark = 6630;
const uint16_t kAirtonBitMark = 400;
const uint16_t kAirtonHdrSpace = 3350;
const uint16_t kAirtonOneSpace = 1260;
const uint16_t kAirtonZeroSpace = 430;
const uint16_t kAirtonFreq = 38000; // Hz. (Just a guess)

#if SEND_AIRTON
// Function should be safe up to 64 bits.
/// Send a Airton formatted message.
/// Status: BETA / Probably works. Needs to be tested with a real device.
/// @param[in] data containing the IR command.
/// @param[in] nbits Nr. of bits to send. usually kAirtonBits
/// @param[in] repeat Nr. of times the message is to be repeated.
void IRsend::sendAirton(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
sendGeneric(kAirtonHdrMark, kAirtonHdrSpace,
kAirtonBitMark, kAirtonOneSpace,
kAirtonBitMark, kAirtonZeroSpace,
kAirtonBitMark, kDefaultMessageGap,
data, nbits, kAirtonFreq, false, repeat, kDutyDefault);
}
#endif // SEND_AIRTON

#if DECODE_AIRTON
/// Decode the supplied Airton message.
/// Status: STABLE / Expected to work. LSBF ordering confirmed via temperature.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeAirton(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * nbits + kHeader + kFooter - offset)
return false; // Too short a message to match.
if (strict && nbits != kAirtonBits)
return false;

// Header + Data + Footer
if (!matchGeneric(&(results->rawbuf[offset]), &(results->value),
results->rawlen - offset, nbits,
kAirtonHdrMark, kAirtonHdrSpace,
kAirtonBitMark, kAirtonOneSpace,
kAirtonBitMark, kAirtonZeroSpace,
kAirtonBitMark, kDefaultMessageGap,
true, kUseDefTol, kMarkExcess, false)) return false;

// Success
results->decode_type = decode_type_t::AIRTON;
results->bits = nbits;
results->command = 0;
results->address = 0;
return true;
}
#endif // DECODE_AIRTON
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,9 @@
#endif // D_STR_DG11J191

// Protocols Names
#ifndef D_STR_AIRTON
#define D_STR_AIRTON "AIRTON"
#endif // D_STR_AIRTON
#ifndef D_STR_AIRWELL
#define D_STR_AIRWELL "AIRWELL"
#endif // D_STR_AIRWELL
Expand Down
62 changes: 62 additions & 0 deletions test/ir_Airton_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2021 crankyoldgit

#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"

// Tests for decodeAirton().

TEST(TestDecodeAirton, RealExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
const uint16_t rawData[115] = {
6632, 3352,
404, 1266, 404, 1264, 406, 430, 406, 430, 400, 1264, 406, 430, 402, 1264,
408, 1262, 406, 1264, 404, 430, 402, 434, 402, 432, 402, 1264, 406, 430,
404, 432, 400, 456, 376, 432, 402, 430, 402, 1264, 404, 1264, 404, 432,
402, 434, 398, 434, 402, 430, 404, 1264, 404, 432, 402, 430, 404, 1264,
406, 430, 402, 432, 400, 434, 402, 430, 402, 430, 404, 432, 402, 430,
402, 432, 402, 432, 402, 430, 402, 432, 402, 430, 402, 434, 400, 432,
402, 1264, 404, 430, 404, 1264, 404, 432, 402, 454, 378, 432, 402, 430,
404, 1264, 404, 1264, 404, 1264, 378, 1292, 404, 432, 402, 1264, 404, 432,
402};
irsend.begin();
irsend.reset();
irsend.sendRaw(rawData, 115, 38);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(decode_type_t::AIRTON, irsend.capture.decode_type);
ASSERT_EQ(kAirtonBits, irsend.capture.bits);
EXPECT_EQ(0x5E1400090C11D3, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
}

TEST(TestDecodeAirton, SyntheticExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();
irsend.reset();
irsend.sendAirton(0x5E1400090C11D3);
irsend.makeDecodeResult();

ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(decode_type_t::AIRTON, irsend.capture.decode_type);
ASSERT_EQ(kAirtonBits, irsend.capture.bits);
EXPECT_EQ(0x5E1400090C11D3, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
}

TEST(TestUtils, Housekeeping) {
ASSERT_EQ("AIRTON", typeToString(decode_type_t::AIRTON));
ASSERT_EQ(decode_type_t::AIRTON, strToDecodeType("AIRTON"));
ASSERT_FALSE(hasACState(decode_type_t::AIRTON));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::AIRTON));
ASSERT_EQ(kAirtonBits, IRsend::defaultBits(decode_type_t::AIRTON));
ASSERT_EQ(kAirtonDefaultRepeat, IRsend::minRepeats(decode_type_t::AIRTON));
}