Skip to content

Commit

Permalink
Argo WREM2 - changed proto msg size: 96->90 bits
Browse files Browse the repository at this point in the history
Includes `matchBytes()` change to be able to work with non-byte-aligned bit lengths.

Signed-off-by: Mateusz Bronk <[email protected]>
  • Loading branch information
mbronk committed Aug 30, 2024
1 parent 850a45f commit 31808d8
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
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
46 changes: 45 additions & 1 deletion test/ir_Argo_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ 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,6 +1461,50 @@ 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); // Note: This may be off by 1 per the report in #2133
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
///
Expand Down

0 comments on commit 31808d8

Please sign in to comment.