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

[EXPERIMENTAL] Argo WREM2 - changed proto msg size: 96->90 bits #2136

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4563,7 +4563,8 @@ namespace IRAcUtils {
#endif // DECODE_AMCOR
#if DECODE_ARGO
case decode_type_t::ARGO: {
const uint16_t length = decode->bits / 8;
const uint16_t length = static_cast<uint16_t>(
ceil(static_cast<float>(decode->bits) / 8.0));
if (IRArgoAC_WREM3::isValidWrem3Message(decode->state,
decode->bits, true)) {
IRArgoAC_WREM3 ac(kGpioUnused);
Expand Down
35 changes: 22 additions & 13 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1583,8 +1583,6 @@ uint16_t IRrecv::_matchGeneric(volatile uint16_t *data_ptr,
const uint8_t tolerance,
const int16_t excess,
const bool MSBfirst) {
// If we are expecting byte sizes, check it's a factor of 8 or fail.
if (!use_bits && nbits % 8 != 0) return 0;
// Calculate if we expect a trailing space in the data section.
const bool kexpectspace = footermark || (onespace != zerospace);
// Calculate how much remaining buffer is required.
Expand All @@ -1607,23 +1605,34 @@ uint16_t IRrecv::_matchGeneric(volatile uint16_t *data_ptr,
return 0;

// Data
if (use_bits) { // Bits.
match_result_t result = IRrecv::matchData(data_ptr + offset, nbits,
if (!use_bits) { // Bytes.
uint16_t data_used = IRrecv::matchBytes(data_ptr + offset, result_bytes_ptr,
remaining - offset, nbits / 8,
onemark, onespace,
zeromark, zerospace, tolerance,
excess, MSBfirst, kexpectspace);
if (!data_used) return 0;
offset += data_used;
}

// Only using bits,
// -or- using *bytes*, but number of bits was not a multiple of 8
if (use_bits || nbits % 8 != 0) {
uint16_t target_bit_cnt = (use_bits)? nbits : nbits % 8;
match_result_t result = IRrecv::matchData(data_ptr + offset, target_bit_cnt,
onemark, onespace,
zeromark, zerospace, tolerance,
excess, MSBfirst, kexpectspace);
if (!result.success) return 0;
*result_bits_ptr = result.data;
if (use_bits) {
*result_bits_ptr = result.data;
} else {
// Fill in last (non-full) byte
result_bytes_ptr[nbits / 8] = static_cast<uint8_t>(result.data);
}
offset += result.used;
} else { // bytes
uint16_t data_used = IRrecv::matchBytes(data_ptr + offset, result_bytes_ptr,
remaining - offset, nbits / 8,
onemark, onespace,
zeromark, zerospace, tolerance,
excess, MSBfirst, kexpectspace);
if (!data_used) return 0;
offset += data_used;
}

// Footer
if (footermark && !matchMark(*(data_ptr + offset++), footermark, tolerance,
excess))
Expand Down
3 changes: 2 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,8 @@ const uint16_t kAmcorBits = kAmcorStateLength * 8;
const uint16_t kAmcorDefaultRepeat = kSingleRepeat;
const uint16_t kArgoStateLength = 12;
const uint16_t kArgoShortStateLength = 4;
const uint16_t kArgoBits = kArgoStateLength * 8;
const uint16_t kArgoBits = 90; // The protocol bit length
// is NOT full byte aligned
const uint16_t kArgoShortBits = kArgoShortStateLength * 8;
const uint16_t kArgo3AcControlStateLength = 6; // Bytes
const uint16_t kArgo3iFeelReportStateLength = 2; // Bytes
Expand Down
8 changes: 6 additions & 2 deletions test/IRrecv_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ TEST(TestMatchGeneric, UsingBytes) {
EXPECT_GT(irsend.capture.rawlen - kStartOffset, entries_used);
EXPECT_EQ(16, entries_used);

// Asking for non mod-8 size should fail.
// Asking for non mod-8 size should SUCCEED and fill-in next byte.
entries_used = irrecv.matchGeneric(
irsend.capture.rawbuf + offset, result_data,
irsend.capture.rawlen - offset,
Expand All @@ -1302,7 +1302,11 @@ TEST(TestMatchGeneric, UsingBytes) {
1, // 1% Tolerance
0, // No excess margin
true); // MSB first.
ASSERT_EQ(0, entries_used);
ASSERT_NE(0, entries_used);
EXPECT_EQ(0b10101010, result_data[0]);
EXPECT_EQ(0b1, result_data[1]);
EXPECT_GT(irsend.capture.rawlen - kStartOffset, entries_used);
EXPECT_EQ(18, entries_used);

// Expecting different timings should fail.
entries_used = irrecv.matchGeneric(
Expand Down
236 changes: 223 additions & 13 deletions test/ir_Argo_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ TEST(TestArgoACClass, MessageConstructon) {
auto expected = std::vector<uint8_t>({
0xAC, 0xF5, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD6, 0x01});
auto actual = ac.getRaw();
EXPECT_THAT(std::vector<uint8_t>(actual, actual + kArgoBits / 8),
EXPECT_THAT(std::vector<uint8_t>(actual, actual + static_cast<uint8_t>(
ceil(static_cast<float>(kArgoBits) / 8.0))),
::testing::ElementsAreArray(expected));
EXPECT_EQ(
"Model: 1 (WREM2), Power: On, Mode: 0 (Cool), Fan: 0 (Auto), Temp: 20C, "
Expand Down Expand Up @@ -1461,25 +1462,87 @@ TEST(TestDecodeArgo, RealShortDecode) {
EXPECT_EQ(28, r.sensorTemperature);
}

TEST(TestDecodeArgo, Issue2133_90bit_message) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

// Full Argo command message (90 bits)
const uint16_t command_90bit[193] = {
6422, 3190, 408, 872, 428, 848, 428, 2126, 402, 2150, 408, 872, 404, 2152,
402, 874, 402, 2152, 402, 2154, 406, 872, 428, 2126, 404, 876, 404, 2150,
430, 2124, 432, 2122, 432, 2124, 404, 874, 404, 874, 426, 852, 428, 850,
412, 864, 406, 872, 404, 874, 400, 2154, 428, 2128, 402, 876, 402, 874, 400,
2154, 404, 2150, 406, 2150, 400, 878, 400, 876, 402, 874, 416, 2136, 404,
2152, 402, 876, 402, 874, 402, 874, 428, 852, 402, 874, 404, 872, 400, 876,
402, 876, 404, 872, 430, 846, 402, 2152, 406, 2150, 406, 2150, 404, 874,
432, 846, 426, 850, 428, 850, 400, 878, 398, 876, 404, 874, 404, 874, 400,
2152, 432, 2124, 428, 2128, 432, 846, 426, 852, 400, 2154, 404, 874, 426,
2128, 428, 2128, 404, 872, 430, 848, 426, 2128, 404, 872, 414, 2140, 432,
848, 400, 876, 426, 850, 404, 872, 402, 876, 400, 876, 430, 848, 404, 872,
404, 874, 402, 2154, 402, 876, 428, 2126, 406, 872, 426, 2128, 426, 852,
404, 872, 430, 2124, 404, 874, 430, 846, 426, 2128, 400
}; // ARGO WREM2 (off command)

irsend.reset();
uint8_t expectedState[kArgoStateLength] = {
0xAC, 0xF5, 0x80, 0x39, 0x06, 0xE0, 0x00, 0xA7, 0x29, 0x80, 0x4A, 0x02 };
irsend.sendRaw(command_90bit, sizeof(command_90bit) /
sizeof(command_90bit[0]), 38);
irsend.makeDecodeResult();
EXPECT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::ARGO, irsend.capture.decode_type);
EXPECT_EQ(kArgoBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Model: 1 (WREM2), Power: Off, Mode: 0 (Cool), Fan: 3 (Max), Temp: 10C, "
"Sensor Temp: 21C, Max: Off, IFeel: On, Night: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
EXPECT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
EXPECT_EQ(stdAc::ac_command_t::kControlCommand, r.command);

EXPECT_EQ(21, r.sensorTemperature);
EXPECT_TRUE(r.iFeel);
EXPECT_FALSE(r.power);
EXPECT_EQ(10, r.degrees);
EXPECT_EQ(stdAc::opmode_t::kCool, r.mode);
}


///
/// @brief Test Fixture for recorded tests
///
struct ArgoE2ETestParam {
const std::vector<uint16_t> rawDataInput;
const uint8_t expectedEncodedSizeBytes;
const uint8_t expectedEncodedSizeBits;
const std::vector<uint8_t> expectedEncodedValue;
const std::string expectedString;
const argo_ac_remote_model_t expectedModel;

ArgoE2ETestParam(std::vector<uint16_t> _raw, uint8_t _encSizeBits,
std::vector<uint8_t> _encValue, std::string _str,
argo_ac_remote_model_t _model)
: rawDataInput(_raw), expectedEncodedSizeBits(_encSizeBits),
expectedEncodedValue(_encValue), expectedString(_str),
expectedModel(_model) {}

ArgoE2ETestParam(std::vector<uint16_t> _raw, uint8_t _encSize,
ArgoE2ETestParam(std::vector<uint16_t> _raw, uint8_t _encSizeBytes,
std::vector<uint8_t> _encValue, std::string _str)
: rawDataInput(_raw), expectedEncodedSizeBytes(_encSize),
expectedEncodedValue(_encValue), expectedString(_str) {}
: ArgoE2ETestParam(_raw, _encSizeBytes * 8, _encValue, _str,
argo_ac_remote_model_t::SAC_WREM3) {}

inline uint16_t getExpectedEncodedSizeBytes() const {
return static_cast<int>(ceil(static_cast<float>(
expectedEncodedSizeBits) / 8.0));
}

friend std::ostream& operator<<(std::ostream& os, const ArgoE2ETestParam& v) {
return os << "rawDataInput: " << ::testing::PrintToString(v.rawDataInput)
<< "\n\texpectedEncodedSize: "
<< static_cast<int>(v.expectedEncodedSizeBytes)
<< "[B]" << "\n\texpectedEncodedValue: 0x"
<< static_cast<int>(v.expectedEncodedSizeBits)
<< "[b] (" << v.getExpectedEncodedSizeBytes() << "[B])"
<< "\n\texpectedEncodedValue: 0x"
<< bytesToHexString(v.expectedEncodedValue) << "\n\texpectedString: "
<< v.expectedString;
}
Expand All @@ -1503,13 +1566,20 @@ TEST_P(TestArgoE2E, RealExampleCommands) {

ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::ARGO, irsend.capture.decode_type);
ASSERT_TRUE(IRArgoAC_WREM3::isValidWrem3Message(irsend.capture.state,
irsend.capture.bits, true));

EXPECT_EQ(GetParam().expectedEncodedSizeBytes * 8, irsend.capture.bits);
if (GetParam().expectedModel == argo_ac_remote_model_t::SAC_WREM3) {
ASSERT_TRUE(IRArgoAC_WREM3::isValidWrem3Message(irsend.capture.state,
irsend.capture.bits, true));
} else if (GetParam().expectedEncodedSizeBits != kArgoShortBits) {
ASSERT_TRUE(IRArgoAC::validChecksum(irsend.capture.state,
ceil(static_cast<float>(
irsend.capture.bits) / 8.0)));
}

EXPECT_EQ(GetParam().expectedEncodedSizeBits, irsend.capture.bits);

std::vector<uint8_t> stateActual(irsend.capture.state, irsend.capture.state
+ GetParam().expectedEncodedSizeBytes);
+ GetParam().getExpectedEncodedSizeBytes());
EXPECT_THAT(stateActual, ::testing::ElementsAreArray(
GetParam().expectedEncodedValue));

Expand All @@ -1524,6 +1594,9 @@ INSTANTIATE_TEST_CASE_P(
TestDecodeArgo,
TestArgoE2E,
::testing::Values(
//////
// WREM3 test cases (capture source: issue #1912)
//////
ArgoE2ETestParam(
std::vector<uint16_t> {
6468, 3150, 456, 2154, 428, 2152, 462, 874, 422, 2158, 424, 882,
Expand Down Expand Up @@ -1601,8 +1674,145 @@ INSTANTIATE_TEST_CASE_P(
},
kArgo3ConfigStateLength,
std::vector<uint8_t> { 0xCB, 0x0C, 0x4A, 0x21 },
"Config[CH#0]: Model: 2 (WREM3), Key: 12, Value: 74")),
"Config[CH#0]: Model: 2 (WREM3), Key: 12, Value: 74"),


//////
// WREM2 test cases (capture source: issue #2133)
//////
ArgoE2ETestParam(
std::vector<uint16_t> {
6390, 3192, 430, 848, 424, 852, 432, 2124, 424, 2132, 426, 850, 422,
2134, 424, 852, 432, 2124, 424, 2132, 426, 852, 432, 2122, 424, 852,
432, 2124, 424, 2132, 426, 2130, 428, 2126, 432, 846, 426, 850, 422,
854, 430, 848, 426, 850, 432, 844, 428, 850, 424, 2130, 426, 2128, 430,
848, 426, 852, 432, 2122, 424, 2132, 426, 850, 422, 854, 430, 2126, 432,
844, 430, 2126, 432, 2124, 424, 852, 430, 848, 426, 850, 424, 854, 428,
848, 424, 852, 432, 844, 430, 848, 424, 852, 432, 846, 428, 2128, 430,
2124, 434, 2122, 424, 852, 432, 846, 428, 850, 424, 854, 430, 846, 426,
850, 422, 854, 430, 848, 426, 2130, 430, 2126, 430, 2124, 422, 2132,
426, 2130, 428, 2126, 430, 2124, 422, 2132, 426, 2128, 430, 2126, 432,
2124, 424, 2130, 426, 2128, 430, 848, 426, 852, 432, 844, 428, 848, 424,
852, 432, 846, 428, 850, 424, 854, 430, 846, 426, 850, 434, 844, 430,
848, 424, 2130, 428, 850, 424, 854, 430, 846, 426, 850, 422, 854, 430,
848, 426, 2128, 428, 2128, 430
},
kArgoBits,
std::vector<uint8_t> { 0xAC, 0xF5, 0x80, 0x99, 0x06, 0xE0, 0x00, 0xFF,
0x1F, 0x00, 0x02, 0x03 },
"Model: 1 (WREM2), Power: Off, Mode: 0 (Cool), Fan: 3 (Max), Temp: 10C, "
"Sensor Temp: 24C, Max: Off, IFeel: Off, Night: Off",
argo_ac_remote_model_t::SAC_WREM2),


ArgoE2ETestParam(
std::vector<uint16_t> {
6420, 3164, 426, 850, 422, 854, 462, 2092, 432, 2122, 424, 852, 432,
2124, 422, 854, 462, 2092, 434, 2122, 458, 820, 454, 2102, 424, 854,
430, 2126, 454, 2100, 458, 2096, 428, 2126, 432, 846, 460, 816, 424,
854, 464, 814, 426, 852, 432, 844, 430, 848, 490, 2066, 426, 2128, 452,
826, 458, 818, 454, 2100, 458, 2098, 462, 816, 422, 854, 452, 2102, 456,
822, 462, 2092, 454, 2100, 458, 820, 454, 824, 460, 816, 456, 820, 452,
824, 460, 818, 422, 854, 462, 814, 458, 818, 454, 822, 428, 2126, 454,
2102, 456, 2098, 458, 818, 432, 844, 462, 816, 458, 820, 454, 824, 460,
816, 458, 820, 452, 824, 426, 2128, 462, 2092, 454, 2102, 456, 2098,
458, 2096, 462, 2092, 454, 2102, 456, 2098, 426, 2128, 464, 2092, 456,
2100, 456, 2098, 460, 2094, 452, 824, 460, 818, 456, 820, 462, 814, 458,
818, 454, 824, 460, 816, 456, 820, 452, 2102, 456, 822, 462, 816, 458,
820, 454, 2102, 424, 854, 452, 824, 460, 818, 456, 822, 462, 814, 458,
2098, 460, 2094, 454, 2102, 424
},
kArgoBits,
std::vector<uint8_t> { 0xAC, 0xF5, 0x80, 0x99, 0x06, 0xE0, 0x00, 0xFF,
0x1F, 0x20, 0x82, 0x03 },
"Model: 1 (WREM2), Power: On, Mode: 0 (Cool), Fan: 3 (Max), Temp: 10C, "
"Sensor Temp: 24C, Max: Off, IFeel: Off, Night: Off",
argo_ac_remote_model_t::SAC_WREM2),


ArgoE2ETestParam(
std::vector<uint16_t> {
6388, 3196, 428, 850, 424, 852, 430, 2124, 424, 2132, 426, 852, 432,
2124, 424, 854, 430, 2124, 422, 2132, 426, 852, 434, 2122, 424, 852,
432, 2124, 422, 2134, 424, 2130, 428, 2126, 432, 846, 428, 850, 422,
854, 430, 848, 426, 852, 432, 844, 428, 848, 424, 2130, 428, 2128, 430,
848, 424, 852, 432, 2124, 424, 2132, 426, 850, 422, 854, 430, 2126, 432,
846, 428, 2128, 430, 2124, 422, 854, 428, 848, 424, 852, 432, 846, 428,
850, 424, 854, 430, 846, 426, 850, 422, 854, 430, 848, 426, 2130, 428,
2128, 430, 2124, 422, 854, 484, 794, 424, 852, 432, 844, 428, 850, 424,
852, 430, 846, 426, 850, 422, 2132, 426, 2130, 428, 2126, 430, 2124,
422, 2132, 426, 2130, 428, 2126, 430, 2124, 434, 2122, 426, 2130, 428,
2126, 430, 2124, 434, 2122, 424, 852, 432, 844, 428, 850, 422, 854, 430,
846, 426, 852, 432, 844, 428, 848, 424, 2130, 428, 848, 424, 2132, 426,
852, 432, 2122, 424, 852, 432, 846, 428, 850, 424, 854, 430, 846, 426,
2128, 430, 2126, 432, 846, 428
},
kArgoBits,
std::vector<uint8_t> { 0xAC, 0xF5, 0x80, 0x99, 0x06, 0xE0, 0x00, 0xFF,
0x1F, 0xA0, 0x82, 0x01 },
"Model: 1 (WREM2), Power: On, Mode: 0 (Cool), Fan: 3 (Max), Temp: 10C, "
"Sensor Temp: 24C, Max: Off, IFeel: On, Night: Off",
argo_ac_remote_model_t::SAC_WREM2),



ArgoE2ETestParam(
std::vector<uint16_t> {
6388, 3194, 430, 848, 426, 852, 432, 2122, 424, 2130, 428, 850, 424,
2132, 426, 850, 434, 2122, 424, 2130, 426, 850, 424, 2132, 426, 852,
422, 2132, 424, 2130, 428, 2128, 430, 2124, 422, 854, 430, 2126, 434,
844, 428, 2126, 432, 846, 426, 2128, 430, 846, 426, 2130, 428, 2126,
432, 2122, 424, 854, 432, 2124, 424, 854, 430, 846, 426, 2130, 428,
848, 424
},
kArgoShortBits,
std::vector<uint8_t> { 0xAC, 0xF5, 0xAA, 0x4B },
"Model: 1 (WREM2), Sensor Temp: 25C",
argo_ac_remote_model_t::SAC_WREM2),

//////
// WREM2 test cases (capture source: issue #1859)
//////
ArgoE2ETestParam(
std::vector<uint16_t> {
6420, 3168, 442, 834, 442, 834, 442, 2112, 442, 2114, 442, 834, 442,
2112, 444, 834, 442, 2114, 442, 2114, 440, 836, 442, 2112, 442, 836,
442, 2112, 442, 2114, 442, 2114, 442, 2114, 442, 836, 442, 2114, 442,
836, 442, 834, 442, 836, 442, 2114, 442, 2114, 442, 2114, 442, 2114,
442, 2114, 442, 834, 442, 836, 442, 836, 442, 836, 442, 836, 442, 2114,
442
},
kArgoShortBits,
std::vector<uint8_t> { 0xAC, 0xF5, 0xE2, 0x83 },
"Model: 1 (WREM2), Sensor Temp: 32C",
argo_ac_remote_model_t::SAC_WREM2),


ArgoE2ETestParam(
std::vector<uint16_t> {
6418, 3168, 442, 836, 442, 834, 442, 2114, 442, 2114, 442, 836, 442,
2114, 442, 836, 440, 2114, 442, 2114, 442, 836, 442, 2112, 442, 834,
442, 2112, 442, 2112, 444, 2112, 442, 2114, 442, 836, 442, 836, 442,
834, 442, 834, 442, 2112, 442, 836, 442, 834, 442, 836, 440, 2114,
442, 836, 440, 2114, 442, 836, 442, 836, 440, 836, 442, 2112, 442, 2114,
442, 836, 442, 2114, 442, 2114, 442, 836, 442, 836, 442, 836, 440, 836,
442, 836, 442, 836, 442, 836, 442, 836, 440, 836, 442, 836, 440, 2114,
442, 2114, 442, 2114, 442, 836, 440, 838, 440, 836, 442, 836, 440, 838,
440, 836, 440, 836, 440, 836, 442, 2114, 440, 2116, 440, 2114, 442,
2114, 440, 2114, 440, 2114, 442, 2114, 442, 836, 440, 2114, 440, 836,
442, 2114, 442, 836, 440, 836, 442, 836, 442, 836, 440, 836, 440, 836,
440, 836, 440, 836, 440, 836, 440, 836, 440, 2114, 442, 836, 440, 2114,
442, 836, 440, 2114, 442, 836, 440, 2116, 440, 836, 440, 836, 440, 836,
440, 836, 442, 836, 440, 2114, 442
},
kArgoBits,
std::vector<uint8_t> { 0xAC, 0xF5, 0x10, 0xC5, 0x06, 0xE0, 0x00, 0x7F,
0x05, 0xA0, 0x0A, 0x02 },
"Model: 1 (WREM2), Power: On, Mode: 2 (Auto), Fan: 0 (Auto), Temp: 24C, "
"Sensor Temp: 26C, Max: Off, IFeel: On, Night: Off",
argo_ac_remote_model_t::SAC_WREM2)),
[](const testing::TestParamInfo<ArgoE2ETestParam>& info) {
return bytesToHexString(info.param.expectedEncodedValue);
return irutils::modelToStr(decode_type_t::ARGO, info.param.expectedModel)
+ "_" + bytesToHexString(info.param.expectedEncodedValue);
}
);
Loading