Tasmota/lib/IRremoteESP8266-2.7.8.10/test/ir_Panasonic_test.cpp

1253 lines
52 KiB
C++

// Copyright 2017, 2018 David Conran
#include "ir_Panasonic.h"
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "IRutils.h"
#include "gtest/gtest.h"
// Tests for encodePanasonic().
TEST(TestEncodePanasonic, General) {
IRsendTest irsend(4);
EXPECT_EQ(0x0, irsend.encodePanasonic(0, 0, 0, 0));
EXPECT_EQ(0x101010101, irsend.encodePanasonic(1, 1, 1, 1));
EXPECT_EQ(0xFFFF, irsend.encodePanasonic(0, 0, 0, 0xFF));
EXPECT_EQ(0xFF00FF, irsend.encodePanasonic(0, 0, 0xFF, 0));
EXPECT_EQ(0xFF0000FF, irsend.encodePanasonic(0, 0xFF, 0, 0));
EXPECT_EQ(0xFFFF00000000, irsend.encodePanasonic(0xFFFF, 0, 0, 0));
EXPECT_EQ(0xFFFFFFFFFFFF, irsend.encodePanasonic(0xFFFF, 0xFF, 0xFF, 0xFF));
EXPECT_EQ(0x40040190ED7C, irsend.encodePanasonic(0x4004, 0x01, 0x90, 0xED));
}
// Tests for sendPanasonic64().
// Test sending typical data only.
TEST(TestSendPanasonic64, SendDataOnly) {
IRsendTest irsend(4);
irsend.begin();
irsend.reset();
irsend.sendPanasonic64(0x0);
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s116208",
irsend.outputStr());
irsend.reset();
irsend.sendPanasonic64(0x40040190ED7C);
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
"m432s102384",
irsend.outputStr());
irsend.reset();
irsend.sendPanasonic64(0xFFFFFFFFFFFF);
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296"
"m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296"
"m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296"
"m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296"
"m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296"
"m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296"
"m432s74736",
irsend.outputStr());
}
// Test sending with different repeats.
TEST(TestSendPanasonic64, SendWithRepeats) {
IRsendTest irsend(4);
irsend.begin();
irsend.reset();
irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 0); // 0 repeats.
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
"m432s102384",
irsend.outputStr());
irsend.reset();
irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 1); // 1 repeat.
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
"m432s102384"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
"m432s102384",
irsend.outputStr());
irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2); // 2 repeats.
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
"m432s102384"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
"m432s102384"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432"
"m432s102384",
irsend.outputStr());
}
// Test sending an atypical data size.
TEST(TestSendPanasonic64, SendUnusualSize) {
IRsendTest irsend(4);
irsend.begin();
irsend.reset();
irsend.sendPanasonic64(0x0, 8);
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s150768",
irsend.outputStr());
irsend.reset();
irsend.sendPanasonic64(0x1234567890ABCDEF, 64);
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432"
"m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432"
"m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296m432s432"
"m432s432m432s1296m432s1296m432s1296m432s1296m432s432m432s432m432s432"
"m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432"
"m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296"
"m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296"
"m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296"
"m432s74736",
irsend.outputStr());
}
// Tests for sendPanasonic().
TEST(TestSendPanasonic, CompareToSendPanasonic64) {
IRsendTest panasonic(4);
IRsendTest panasonic64(0);
panasonic.begin();
panasonic64.begin();
panasonic.reset();
panasonic64.reset();
panasonic.sendPanasonic(0x4004, 0x0190ED7C);
panasonic64.sendPanasonic64(0x40040190ED7C);
EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr());
panasonic.sendPanasonic(0x0, 0x0);
panasonic64.sendPanasonic64(0x0);
EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr());
panasonic.sendPanasonic(0x0, 0x0, 8);
panasonic64.sendPanasonic64(0x0, 8);
EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr());
panasonic.sendPanasonic(0x1234, 0x567890AB, 64);
panasonic64.sendPanasonic64(0x1234567890AB, 64);
EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr());
panasonic.sendPanasonic(0x1234, 0x567890AB, kPanasonicBits, 2);
panasonic64.sendPanasonic64(0x1234567890AB, kPanasonicBits, 2);
EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr());
}
// Tests for decodePanasonic().
// Decode normal Panasonic messages.
TEST(TestDecodePanasonic, NormalDecodeWithStrict) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
// Normal Panasonic 48-bit message.
irsend.reset();
irsend.sendPanasonic64(0x40040190ED7C);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x0190ED7C, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
// Synthesised Normal Panasonic 48-bit message.
irsend.reset();
irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x12, 0x34, 0x56));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x400412345670, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x12345670, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
// Synthesised Normal Panasonic 48-bit message.
irsend.reset();
irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x1, 0x1, 0x1));
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x400401010101, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x1010101, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
}
// Decode normal repeated Panasonic messages.
TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
// Normal Panasonic 48-bit message with 2 repeats.
irsend.reset();
irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x190ED7C, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
irsend.makeDecodeResult(2 * kPanasonicBits + 4);
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
irsend.makeDecodeResult(2 * (2 * kPanasonicBits + 4));
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
}
// Decode Panasonic messages with unsupported values.
TEST(TestDecodePanasonic, DecodeWithNonStrictValues) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();
irsend.sendPanasonic64(0x0); // Illegal value Panasonic 48-bit message.
irsend.makeDecodeResult();
// Should fail with strict on.
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
// Should pass if strict off.
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, false));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x0, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x0, irsend.capture.command);
irsend.reset();
// Illegal address/Manufacturer code. The rest is legal.
irsend.sendPanasonic64(irsend.encodePanasonic(0, 1, 2, 3));
irsend.makeDecodeResult();
// Should fail with strict on.
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
// Should pass if strict off.
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, false));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x1020300, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x1020300, irsend.capture.command);
}
// Decode Panasonic messages with unsupported size/lengths.
TEST(TestDecodePanasonic, DecodeWithNonStrictSize) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();
irsend.sendPanasonic64(0x12345678, 32); // Illegal size Panasonic message.
irsend.makeDecodeResult();
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
irsend.makeDecodeResult();
// Should fail with strict when we ask for the wrong bit size.
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 32, true));
// Should pass if strict off.
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 32, false));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(32, irsend.capture.bits);
EXPECT_EQ(0x12345678, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.address);
EXPECT_EQ(0x12345678, irsend.capture.command);
// Illegal over length (56-bit) message.
irsend.reset();
irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 1, 2, 3), 56);
irsend.makeDecodeResult();
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
// Shouldn't pass if strict off and wrong bit size.
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, false));
// Re-decode with correct bit size.
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 56, true));
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 56, false));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(56, irsend.capture.bits);
EXPECT_EQ(0x400401020300, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x01020300, irsend.capture.command);
}
// Decode (non-standard) 64-bit messages.
TEST(TestDecodePanasonic, Decode64BitMessages) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();
// Illegal value & size Panasonic 64-bit message.
irsend.sendPanasonic64(0xFFFFFFFFFFFFFFFF, 64);
irsend.makeDecodeResult();
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 64, true));
// Should work with a 'normal' match (not strict)
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 64, false));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(64, irsend.capture.bits);
EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value);
EXPECT_EQ(0xFFFFFFFF, irsend.capture.address);
EXPECT_EQ(0xFFFFFFFF, irsend.capture.command);
}
// Decode a 'real' example via GlobalCache
TEST(TestDecodePanasonic, DecodeGlobalCacheExample) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();
// Panasonic code from Global Cache.
uint16_t gc_test[103] = {
37000, 1, 1, 126, 64, 16, 17, 16, 49, 15, 16, 16, 16, 16, 16,
16, 17, 15, 17, 15, 17, 15, 17, 15, 16, 16, 16, 16, 16, 16,
17, 15, 49, 16, 16, 16, 16, 16, 17, 15, 17, 15, 17, 15, 17,
15, 16, 16, 16, 16, 16, 16, 49, 15, 49, 16, 17, 15, 17, 15,
49, 16, 16, 16, 17, 16, 17, 15, 17, 15, 49, 16, 49, 15, 49,
16, 17, 16, 49, 15, 49, 16, 17, 15, 48, 16, 16, 16, 49, 15,
48, 16, 49, 15, 49, 16, 49, 15, 17, 15, 16, 16, 2721};
irsend.sendGC(gc_test, 103);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, true));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x0190ED7C, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040190ED7C, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x0190ED7C, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
}
// Fail to decode a non-Panasonic example via GlobalCache
TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();
// Modified a few entries to unexpected values, based on previous test case.
uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20,
20, 20, 20, 20, 20, 20, 127, 20, 61, 9,
20, 20, 61, 20, 20, 20, 61, 20, 61, 20,
61, 20, 20, 20, 20, 20, 20, 20, 884};
irsend.sendGC(gc_test, 39);
irsend.makeDecodeResult();
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture));
ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset,
kPanasonicBits, false));
}
// Failing to decode Panasonic in Issue #245
TEST(TestDecodePanasonic, DecodeIssue245) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();
uint16_t rawData[100] = {
3550, 1750, 500, 450, 500, 1300, 500, 450, 500, 450, 500, 450,
500, 450, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450,
500, 450, 500, 450, 500, 1300, 500, 450, 500, 450, 500, 450,
500, 450, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450,
500, 1300, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450,
500, 450, 500, 450, 500, 450, 500, 1300, 500, 450, 500, 1300,
500, 1300, 500, 1300, 500, 1300, 500, 450, 500, 450, 500, 1300,
500, 450, 500, 1300, 500, 1300, 500, 1300, 500, 1300, 500, 450,
500, 1300, 500, 5000};
irsend.sendRaw(rawData, 100, 37);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040100BCBD, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x100BCBD, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
irsend.reset();
irsend.sendRaw(rawData, 99, 37);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(PANASONIC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicBits, irsend.capture.bits);
EXPECT_EQ(0x40040100BCBD, irsend.capture.value);
EXPECT_EQ(0x4004, irsend.capture.address);
EXPECT_EQ(0x100BCBD, irsend.capture.command);
EXPECT_FALSE(irsend.capture.repeat);
}
// Tests for sendPanasonicAC().
// Test sending typical data only.
TEST(TestSendPanasonicAC, SendDataOnly) {
IRsendTest irsend(0);
irsend.begin();
irsend.reset();
uint8_t state[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83};
irsend.sendPanasonicAC(state);
EXPECT_EQ(
"f36700d50"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s1296"
"m432s432m432s432m432s1296m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432"
"m432s10000"
"m3456s1728"
"m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s1296"
"m432s432m432s432m432s1296m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s1296m432s1296m432s432m432s432"
"m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s1296m432s1296m432s1296m432s1296m432s432m432s1296m432s432m432s1296"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432"
"m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432"
"m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432m432s1296"
"m432s100000",
irsend.outputStr());
}
// Tests for the IRPanasonicAc class.
TEST(TestIRPanasonicAcClass, ChecksumCalculation) {
IRPanasonicAc pana(0);
const uint8_t originalstate[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83};
uint8_t examplestate[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83};
EXPECT_TRUE(IRPanasonicAc::validChecksum(examplestate));
EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate));
examplestate[kPanasonicAcStateLength - 1] = 0x0; // Set incorrect checksum.
EXPECT_FALSE(IRPanasonicAc::validChecksum(examplestate));
EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate));
pana.setRaw(examplestate);
// Extracting the state from the object should have a correct checksum.
EXPECT_TRUE(IRPanasonicAc::validChecksum(pana.getRaw()));
EXPECT_STATE_EQ(originalstate, pana.getRaw(), kPanasonicAcBits);
examplestate[kPanasonicAcStateLength - 1] = 0x83; // Restore old checksum.
// Change the state to force a different checksum.
examplestate[6] = 0x01; // Should increase checksum by 1.
EXPECT_FALSE(IRPanasonicAc::validChecksum(examplestate));
EXPECT_EQ(0x84, IRPanasonicAc::calcChecksum(examplestate));
}
TEST(TestIRPanasonicAcClass, SetAndGetPower) {
IRPanasonicAc pana(0);
pana.on();
EXPECT_TRUE(pana.getPower());
pana.off();
EXPECT_FALSE(pana.getPower());
pana.setPower(true);
EXPECT_TRUE(pana.getPower());
pana.setPower(false);
EXPECT_FALSE(pana.getPower());
}
TEST(TestIRPanasonicAcClass, SetAndGetModel) {
IRPanasonicAc pana(0);
EXPECT_EQ(kPanasonicJke, pana.getModel());
pana.setModel(kPanasonicDke);
EXPECT_EQ(kPanasonicDke, pana.getModel());
pana.setModel(kPanasonicLke);
EXPECT_EQ(kPanasonicLke, pana.getModel());
pana.setModel(kPanasonicNke);
EXPECT_EQ(kPanasonicNke, pana.getModel());
pana.setModel(kPanasonicUnknown); // shouldn't change.
EXPECT_EQ(kPanasonicNke, pana.getModel());
pana.setModel((panasonic_ac_remote_model_t)255); // shouldn't change.
EXPECT_EQ(kPanasonicNke, pana.getModel());
pana.setModel(kPanasonicJke);
EXPECT_EQ(kPanasonicJke, pana.getModel());
// This state tickled a bug in getModel(). Should read as a JKE.
uint8_t jkeState[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x32, 0x2E, 0x80, 0xA2, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x74};
pana.setModel(kPanasonicDke); // Make sure it isn't somehow set to JKE
pana.setRaw(jkeState);
EXPECT_EQ(kPanasonicJke, pana.getModel());
EXPECT_STATE_EQ(jkeState, pana.getRaw(), kPanasonicAcBits);
// This state tickled a bug in getModel(). Should read as CKP.
uint8_t ckpState[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x67, 0x2E, 0x80, 0xAF, 0x00,
0xC0, 0x6B, 0x98, 0x10, 0x00, 0x81, 0x64, 0x05, 0x87};
pana.setModel(kPanasonicDke); // Make sure it isn't somehow set to CKP
pana.setRaw(ckpState);
EXPECT_EQ(kPanasonicCkp, pana.getModel());
EXPECT_STATE_EQ(ckpState, pana.getRaw(), kPanasonicAcBits);
}
TEST(TestIRPanasonicAcClass, SetAndGetMode) {
IRPanasonicAc pana(0);
pana.setMode(kPanasonicAcCool);
pana.setTemp(21);
EXPECT_EQ(kPanasonicAcCool, pana.getMode());
pana.setMode(kPanasonicAcHeat);
EXPECT_EQ(kPanasonicAcHeat, pana.getMode());
pana.setMode(kPanasonicAcAuto);
EXPECT_EQ(kPanasonicAcAuto, pana.getMode());
pana.setMode(kPanasonicAcDry);
EXPECT_EQ(kPanasonicAcDry, pana.getMode());
EXPECT_EQ(21, pana.getTemp()); // Temp should be unchanged.
pana.setMode(kPanasonicAcFan);
EXPECT_EQ(kPanasonicAcFan, pana.getMode());
EXPECT_EQ(kPanasonicAcFanModeTemp, pana.getTemp()); // Temp should change.
pana.setMode(kPanasonicAcCool);
EXPECT_EQ(kPanasonicAcCool, pana.getMode());
// Temp should be unchanged from the last manual change.
EXPECT_EQ(21, pana.getTemp());
}
TEST(TestIRPanasonicAcClass, SetAndGetTemp) {
IRPanasonicAc pana(0);
pana.setTemp(25);
EXPECT_EQ(25, pana.getTemp());
pana.setTemp(kPanasonicAcMinTemp);
EXPECT_EQ(kPanasonicAcMinTemp, pana.getTemp());
pana.setTemp(kPanasonicAcMinTemp - 1);
EXPECT_EQ(kPanasonicAcMinTemp, pana.getTemp());
pana.setTemp(kPanasonicAcMaxTemp);
EXPECT_EQ(kPanasonicAcMaxTemp, pana.getTemp());
pana.setTemp(kPanasonicAcMaxTemp + 1);
EXPECT_EQ(kPanasonicAcMaxTemp, pana.getTemp());
}
TEST(TestIRPanasonicAcClass, SetAndGetFan) {
IRPanasonicAc pana(0);
pana.setFan(kPanasonicAcFanAuto);
EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan());
pana.setFan(kPanasonicAcFanMin);
EXPECT_EQ(kPanasonicAcFanMin, pana.getFan());
pana.setFan(kPanasonicAcFanMin - 1);
EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan());
pana.setFan(kPanasonicAcFanMed);
EXPECT_EQ(kPanasonicAcFanMed, pana.getFan());
pana.setFan(kPanasonicAcFanMin + 1);
EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan());
pana.setFan(kPanasonicAcFanMax);
EXPECT_EQ(kPanasonicAcFanMax, pana.getFan());
pana.setFan(kPanasonicAcFanMax + 1);
EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan());
pana.setFan(kPanasonicAcFanMax - 1);
EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan());
}
TEST(TestIRPanasonicAcClass, SetAndGetSwings) {
IRPanasonicAc pana(0);
// Vertical
pana.setSwingVertical(kPanasonicAcSwingVAuto);
EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical());
pana.setSwingVertical(kPanasonicAcSwingVHighest);
EXPECT_EQ(kPanasonicAcSwingVHighest, pana.getSwingVertical());
pana.setSwingVertical(kPanasonicAcSwingVHighest - 1);
EXPECT_EQ(kPanasonicAcSwingVHighest, pana.getSwingVertical());
pana.setSwingVertical(kPanasonicAcSwingVHighest + 1);
EXPECT_EQ(kPanasonicAcSwingVHighest + 1, pana.getSwingVertical());
pana.setSwingVertical(kPanasonicAcSwingVLowest);
EXPECT_EQ(kPanasonicAcSwingVLowest, pana.getSwingVertical());
pana.setSwingVertical(kPanasonicAcSwingVLowest + 1);
EXPECT_EQ(kPanasonicAcSwingVLowest, pana.getSwingVertical());
pana.setSwingVertical(kPanasonicAcSwingVLowest - 1);
EXPECT_EQ(kPanasonicAcSwingVLowest - 1, pana.getSwingVertical());
pana.setSwingVertical(kPanasonicAcSwingVAuto);
EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical());
// Horizontal is model dependant.
pana.setModel(kPanasonicNke); // NKE is always fixed in the middle.
EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal());
pana.setSwingHorizontal(kPanasonicAcSwingHAuto);
EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal());
pana.setModel(kPanasonicJke); // JKE has no H swing.
EXPECT_EQ(0, pana.getSwingHorizontal());
pana.setSwingHorizontal(kPanasonicAcSwingHMiddle);
EXPECT_EQ(0, pana.getSwingHorizontal());
pana.setModel(kPanasonicLke); // LKE is always fixed in the middle.
EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal());
pana.setSwingHorizontal(kPanasonicAcSwingHAuto);
EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal());
pana.setModel(kPanasonicDke); // DKE has full control.
ASSERT_EQ(kPanasonicDke, pana.getModel());
// Auto was last requested.
EXPECT_EQ(kPanasonicAcSwingHAuto, pana.getSwingHorizontal());
pana.setSwingHorizontal(kPanasonicAcSwingHLeft);
EXPECT_EQ(kPanasonicAcSwingHLeft, pana.getSwingHorizontal());
// Changing models from DKE to something else, then back should not change
// the intended swing.
pana.setModel(kPanasonicLke);
EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal());
pana.setModel(kPanasonicDke);
EXPECT_EQ(kPanasonicAcSwingHLeft, pana.getSwingHorizontal());
}
TEST(TestIRPanasonicAcClass, QuietAndPowerful) {
IRPanasonicAc pana(0);
pana.setQuiet(false);
EXPECT_FALSE(pana.getQuiet());
pana.setQuiet(true);
EXPECT_TRUE(pana.getQuiet());
EXPECT_FALSE(pana.getPowerful());
pana.setPowerful(false);
EXPECT_FALSE(pana.getPowerful());
EXPECT_TRUE(pana.getQuiet());
pana.setPowerful(true);
EXPECT_TRUE(pana.getPowerful());
EXPECT_FALSE(pana.getQuiet());
pana.setPowerful(false);
EXPECT_FALSE(pana.getPowerful());
EXPECT_FALSE(pana.getQuiet());
pana.setPowerful(true);
pana.setQuiet(true);
EXPECT_TRUE(pana.getQuiet());
EXPECT_FALSE(pana.getPowerful());
}
TEST(TestIRPanasonicAcClass, SetAndGetIon) {
IRPanasonicAc ac(0);
// Ion Filter only works for DKE.
ac.setModel(kPanasonicDke);
ac.setIon(true);
EXPECT_TRUE(ac.getIon());
ac.setIon(false);
EXPECT_FALSE(ac.getIon());
ac.setIon(true);
EXPECT_TRUE(ac.getIon());
// Now try a different (a guess at unsupported) model.
ac.setModel(kPanasonicRkr);
EXPECT_FALSE(ac.getIon());
ac.setIon(true);
EXPECT_FALSE(ac.getIon());
ac.setIon(false);
EXPECT_FALSE(ac.getIon());
}
TEST(TestIRPanasonicAcClass, HumanReadable) {
IRPanasonicAc pana(0);
EXPECT_EQ(
"Model: 4 (JKE), Power: Off, Mode: 0 (Auto), Temp: 0C, "
"Fan: 253 (UNKNOWN), Swing(V): 0 (UNKNOWN), Quiet: Off, "
"Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
pana.setPower(true);
pana.setTemp(kPanasonicAcMaxTemp);
pana.setMode(kPanasonicAcHeat);
pana.setFan(kPanasonicAcFanMax);
pana.setSwingVertical(kPanasonicAcSwingVAuto);
pana.setPowerful(true);
EXPECT_EQ(
"Model: 4 (JKE), Power: On, Mode: 4 (Heat), Temp: 30C, "
"Fan: 4 (High), Swing(V): 15 (Auto), Quiet: Off, "
"Powerful: On, Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
pana.setQuiet(true);
pana.setModel(kPanasonicLke);
EXPECT_EQ(
"Model: 1 (LKE), Power: Off, Mode: 4 (Heat), Temp: 30C, "
"Fan: 4 (High), Swing(V): 15 (Auto), "
"Swing(H): 6 (Middle), Quiet: On, Powerful: Off, "
"Clock: 00:00, On Timer: 00:00, Off Timer: Off",
pana.toString());
pana.setModel(kPanasonicDke);
pana.setSwingHorizontal(kPanasonicAcSwingHRight);
EXPECT_EQ(
"Model: 3 (DKE), Power: Off, Mode: 4 (Heat), Temp: 30C, "
"Fan: 4 (High), Swing(V): 15 (Auto), "
"Swing(H): 11 (Right), Quiet: On, Powerful: Off, Ion: Off, "
"Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
}
// Tests for decodePanasonicAC().
// Decode normal Panasonic AC messages.
TEST(TestDecodePanasonicAC, RealExample) {
IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
// Data from Issue #525
uint16_t rawData[439] = {
3582, 1686, 488, 378, 488, 1238, 488, 378, 488, 378, 488, 378,
488, 378, 488, 378, 488, 384, 488, 378, 488, 378, 488, 378,
488, 378, 488, 378, 488, 1242, 486, 378, 488, 384, 488, 378,
488, 378, 488, 380, 486, 382, 484, 382, 484, 1264, 464, 1266,
460, 1272, 462, 378, 488, 406, 460, 1266, 462, 380, 488, 382,
484, 388, 478, 406, 462, 410, 462, 404, 462, 406, 462, 396,
470, 406, 462, 404, 462, 406, 460, 404, 462, 410, 462, 404,
462, 404, 462, 406, 464, 406, 462, 404, 462, 406, 462, 404,
462, 410, 462, 404, 462, 406, 462, 404, 462, 404, 462, 404,
462, 406, 460, 406, 462, 410, 462, 404, 462, 1264, 484, 1244,
486, 382, 482, 382, 486, 382, 486, 378, 486, 382, 488, 9924,
3554, 1686, 488, 378, 490, 1240, 486, 378, 488, 378, 488, 378,
488, 378, 488, 382, 484, 386, 486, 378, 488, 382, 486, 378,
488, 382, 486, 382, 484, 1242, 486, 380, 488, 386, 484, 382,
486, 380, 486, 382, 486, 380, 486, 380, 486, 1242, 486, 1242,
484, 1248, 484, 380, 488, 382, 484, 1242, 486, 382, 484, 382,
484, 382, 484, 382, 486, 386, 484, 382, 486, 382, 484, 382,
486, 382, 486, 380, 484, 382, 486, 382, 488, 380, 486, 382,
484, 380, 462, 406, 488, 376, 484, 1246, 482, 1246, 460, 404,
480, 392, 484, 386, 482, 1244, 484, 382, 484, 382, 484, 1242,
482, 1244, 484, 382, 464, 410, 460, 404, 462, 406, 462, 404,
462, 404, 470, 396, 462, 406, 462, 404, 462, 1286, 460, 1268,
458, 1268, 460, 1266, 460, 1266, 460, 406, 460, 1266, 462, 406,
460, 1272, 462, 406, 460, 406, 460, 406, 460, 406, 462, 404,
462, 406, 460, 406, 462, 410, 462, 404, 462, 406, 460, 406,
460, 406, 462, 404, 462, 406, 460, 406, 460, 410, 462, 406,
460, 1268, 460, 1266, 460, 404, 460, 406, 462, 406, 460, 406,
460, 412, 456, 410, 460, 410, 438, 428, 460, 410, 456, 410,
456, 1272, 436, 1288, 438, 434, 438, 428, 438, 428, 438, 428,
438, 428, 438, 428, 438, 428, 438, 428, 438, 434, 438, 428,
438, 428, 438, 428, 438, 428, 438, 428, 440, 428, 438, 428,
438, 432, 438, 428, 438, 428, 438, 428, 438, 428, 438, 428,
438, 428, 438, 430, 438, 1294, 438, 428, 438, 428, 438, 428,
438, 428, 438, 428, 438, 428, 438, 428, 438, 434, 438, 428,
438, 1288, 438, 1290, 438, 428, 438, 428, 438, 428, 438, 428,
438, 432, 438, 1288, 438, 1290, 438, 430, 438, 428, 438, 428,
438, 428, 438, 428, 438, 1292, 438};
uint8_t expectedState[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83};
irsend.sendRaw(rawData, 439, kPanasonicFreq);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
}
// Decode synthetic Panasonic AC message.
TEST(TestDecodePanasonicAC, SyntheticExample) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Data from Issue #525
uint8_t expectedState[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00,
0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83};
irsend.sendPanasonicAC(expectedState);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
EXPECT_EQ(
"Model: 4 (JKE), Power: Off, Mode: 3 (Cool), Temp: 25C, "
"Fan: 7 (Auto), Swing(V): 15 (Auto), Quiet: Off, "
"Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t r, p;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p));
}
// Tests for general utility functions.
TEST(TestGeneralPanasonic, hasACState) {
EXPECT_TRUE(hasACState(PANASONIC_AC));
ASSERT_FALSE(hasACState(PANASONIC));
}
TEST(TestGeneralPanasonic, typeToString) {
EXPECT_EQ("PANASONIC_AC", typeToString(PANASONIC_AC));
EXPECT_EQ("PANASONIC", typeToString(PANASONIC));
}
// Decode a problematic Panasonic AC message
TEST(TestDecodePanasonicAC, Issue540) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Data from Issue #540
uint16_t rawData[439] = {
3512, 1714, 466, 408, 466, 1280, 470, 408, 466, 412, 466, 408,
466, 412, 462, 412, 466, 414, 466, 408, 466, 412, 462, 412,
466, 412, 466, 408, 466, 1280, 466, 412, 462, 416, 462, 412,
466, 408, 466, 412, 462, 416, 462, 412, 462, 1282, 462, 1284,
462, 1288, 466, 412, 462, 412, 462, 1284, 462, 416, 440, 438,
462, 412, 462, 412, 462, 416, 466, 412, 462, 412, 462, 412,
440, 442, 462, 412, 462, 412, 460, 418, 462, 416, 462, 412,
462, 418, 462, 412, 462, 416, 462, 412, 436, 442, 462, 412,
460, 418, 462, 416, 462, 412, 460, 412, 462, 420, 436, 438,
462, 412, 462, 416, 432, 448, 436, 438, 436, 1310, 436, 1310,
462, 420, 432, 442, 436, 438, 462, 416, 432, 444, 432, 10008,
3480, 1744, 492, 382, 492, 1254, 492, 386, 488, 390, 492, 382,
492, 386, 488, 386, 492, 386, 492, 386, 488, 386, 488, 386,
492, 386, 492, 382, 492, 1258, 488, 386, 488, 390, 492, 386,
488, 386, 488, 386, 492, 390, 488, 386, 488, 1256, 488, 1258,
488, 1262, 488, 390, 488, 386, 488, 1258, 488, 390, 488, 392,
488, 386, 488, 386, 488, 394, 488, 386, 488, 386, 488, 390,
488, 390, 488, 386, 488, 390, 462, 412, 488, 390, 462, 1282,
488, 390, 456, 416, 458, 1292, 456, 1288, 488, 1258, 488, 392,
456, 422, 488, 390, 484, 392, 484, 1262, 458, 420, 484, 1262,
482, 1262, 488, 392, 484, 394, 484, 416, 436, 442, 458, 416,
458, 422, 430, 448, 432, 442, 458, 416, 458, 1296, 432, 1314,
458, 1288, 432, 1312, 432, 1322, 428, 446, 428, 1318, 432, 442,
432, 1318, 432, 1318, 428, 446, 428, 1318, 428, 1322, 430, 448,
426, 448, 428, 452, 426, 452, 426, 448, 428, 472, 400, 478,
402, 478, 402, 472, 402, 476, 402, 472, 402, 478, 402, 472,
402, 1348, 398, 1348, 398, 1352, 398, 508, 370, 478, 398, 476,
398, 512, 366, 508, 370, 502, 372, 508, 340, 538, 372, 504,
344, 1400, 344, 1400, 346, 1434, 314, 560, 316, 588, 290, 560,
314, 564, 396, 400, 474, 400, 480, 394, 480, 404, 474, 400,
454, 446, 454, 426, 448, 430, 424, 450, 428, 452, 448, 426,
426, 452, 424, 1322, 454, 426, 450, 424, 426, 452, 428, 452,
450, 424, 428, 446, 426, 1322, 454, 426, 422, 450, 454, 426,
448, 430, 454, 426, 448, 426, 428, 446, 454, 430, 454, 422,
452, 424, 424, 452, 452, 430, 424, 452, 452, 426, 448, 426,
426, 456, 448, 426, 448, 1296, 424, 1322, 426, 1326, 450, 1270,
478, 422, 454, 424, 424, 450, 454};
uint8_t expectedState[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x39, 0x34, 0x80, 0xAF, 0x0D,
0x00, 0x0E, 0xE0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x1E};
irsend.sendRaw(rawData, 439, kPanasonicFreq);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
IRPanasonicAc pana(0);
pana.setRaw(irsend.capture.state);
// TODO(crankyoldgit): Try to figure out what model this should be.
EXPECT_EQ(
"Model: 0 (UNKNOWN), Power: On, Mode: 3 (Cool), Temp: 26C, "
"Fan: 7 (Auto), Swing(V): 15 (Auto), "
"Swing(H): 13 (Auto), Quiet: Off, Powerful: Off, "
"Clock: 00:00, On Timer: Off, Off Timer: Off",
pana.toString());
}
TEST(TestIRPanasonicAcClass, TimeBasics) {
EXPECT_EQ(0x186, IRPanasonicAc::encodeTime(6, 30));
EXPECT_EQ(0x3CA, IRPanasonicAc::encodeTime(16, 10));
EXPECT_EQ(0x448, IRPanasonicAc::encodeTime(18, 16));
EXPECT_EQ(0, IRPanasonicAc::encodeTime(0, 0));
EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59));
EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59));
EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(25, 72));
EXPECT_EQ(59, IRPanasonicAc::encodeTime(0, 72));
EXPECT_EQ(23 * 60, IRPanasonicAc::encodeTime(27, 0));
}
TEST(TestIRPanasonicAcClass, TimersAndClock) {
IRPanasonicAc pana(0);
// Data from Issue #544
uint8_t state[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00,
0xCA, 0x6B, 0x98, 0x10, 0x00, 0x01, 0x48, 0x04, 0xDB};
pana.setRaw(state);
EXPECT_TRUE(pana.isOnTimerEnabled());
EXPECT_EQ(0x3CA, pana.getOnTimer());
EXPECT_TRUE(pana.isOffTimerEnabled());
EXPECT_EQ(0x186, pana.getOffTimer());
EXPECT_EQ(0x448, pana.getClock());
pana.cancelOnTimer();
EXPECT_FALSE(pana.isOnTimerEnabled());
EXPECT_EQ(0, pana.getOnTimer());
EXPECT_TRUE(pana.isOffTimerEnabled());
EXPECT_EQ(0x186, pana.getOffTimer());
EXPECT_EQ(0x448, pana.getClock());
pana.cancelOffTimer();
EXPECT_FALSE(pana.isOnTimerEnabled());
EXPECT_EQ(0, pana.getOnTimer());
EXPECT_FALSE(pana.isOffTimerEnabled());
EXPECT_EQ(0, pana.getOffTimer());
EXPECT_EQ(0x448, pana.getClock());
pana.setOnTimer(7 * 60 + 50);
EXPECT_TRUE(pana.isOnTimerEnabled());
EXPECT_EQ(7 * 60 + 50, pana.getOnTimer());
EXPECT_FALSE(pana.isOffTimerEnabled());
EXPECT_EQ(0, pana.getOffTimer());
EXPECT_EQ(0x448, pana.getClock());
pana.setOnTimer(7 * 60 + 57); // It should round down.
EXPECT_EQ(7 * 60 + 50, pana.getOnTimer());
pana.setOnTimer(28 * 60); // It should round down.
EXPECT_EQ(kPanasonicAcTimeMax - 9, pana.getOnTimer());
pana.setOnTimer(kPanasonicAcTimeSpecial);
EXPECT_EQ(0, pana.getOnTimer());
pana.setOnTimer(7 * 60 + 50);
pana.setOffTimer(19 * 60 + 30);
EXPECT_TRUE(pana.isOnTimerEnabled());
EXPECT_EQ(7 * 60 + 50, pana.getOnTimer());
EXPECT_TRUE(pana.isOffTimerEnabled());
EXPECT_EQ(19 * 60 + 30, pana.getOffTimer());
EXPECT_EQ(0x448, pana.getClock());
pana.setOffTimer(19 * 60 + 57); // It should round down.
EXPECT_EQ(19 * 60 + 50, pana.getOffTimer());
pana.setOffTimer(28 * 60); // It should round down.
EXPECT_EQ(kPanasonicAcTimeMax - 9, pana.getOffTimer());
pana.setOffTimer(kPanasonicAcTimeSpecial);
EXPECT_EQ(0, pana.getOffTimer());
pana.setClock(0);
EXPECT_EQ(0, pana.getClock());
pana.setClock(kPanasonicAcTimeMax);
EXPECT_EQ(kPanasonicAcTimeMax, pana.getClock());
pana.setClock(kPanasonicAcTimeMax - 1);
EXPECT_EQ(kPanasonicAcTimeMax - 1, pana.getClock());
pana.setClock(kPanasonicAcTimeMax + 1);
EXPECT_EQ(kPanasonicAcTimeMax, pana.getClock());
pana.setClock(kPanasonicAcTimeSpecial);
EXPECT_EQ(0, pana.getClock());
}
// Decode a real short Panasonic AC message
TEST(TestDecodePanasonicAC, RealExampleOfShortMessage) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Data from Issue #544 (Odour Wash)
uint16_t rawData[263] = {
3496, 1734, 506, 366, 448, 1294, 504, 368, 498, 374, 452, 418,
448, 424, 444, 428, 450, 422, 446, 426, 450, 420, 448, 424,
452, 418, 448, 422, 444, 1300, 498, 374, 504, 368, 448, 424,
452, 418, 448, 424, 444, 428, 450, 422, 446, 1296, 500, 1242,
502, 1242, 504, 368, 498, 374, 452, 1292, 504, 366, 450, 422,
444, 426, 450, 420, 446, 424, 452, 418, 448, 424, 444, 428,
450, 422, 444, 426, 450, 420, 446, 424, 452, 418, 448, 422,
444, 428, 450, 422, 446, 426, 452, 420, 446, 426, 452, 418,
448, 424, 442, 428, 448, 422, 444, 426, 450, 420, 446, 426,
452, 418, 448, 424, 444, 428, 450, 422, 444, 1298, 500, 1244,
500, 372, 444, 428, 450, 422, 446, 426, 452, 418, 448, 10020,
3500, 1732, 498, 372, 452, 1290, 506, 366, 450, 422, 446, 426,
452, 420, 448, 424, 452, 418, 448, 422, 444, 426, 450, 420,
446, 426, 452, 420, 446, 1296, 500, 370, 444, 428, 450, 422,
446, 426, 452, 420, 446, 424, 442, 428, 448, 1294, 502, 1240,
504, 1238, 506, 366, 448, 422, 444, 1298, 498, 374, 452, 418,
448, 424, 444, 428, 450, 422, 446, 426, 450, 420, 446, 424,
452, 418, 448, 422, 444, 428, 450, 420, 446, 1298, 498, 1244,
500, 1242, 502, 368, 446, 1298, 500, 1244, 500, 372, 444, 428,
450, 1292, 504, 368, 446, 1296, 502, 370, 444, 426, 452, 1290,
504, 1238, 506, 366, 450, 422, 446, 1298, 498, 1246, 500, 372,
444, 428, 450, 1294, 452, 420, 446, 1296, 448, 422, 444}; // UNKNOWN
// 1FB51F79
uint8_t expectedState[kPanasonicAcStateShortLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06,
0x02, 0x20, 0xE0, 0x04, 0x80, 0x9B, 0x32, 0x53};
irsend.sendRaw(rawData, 263, kPanasonicFreq);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicAcShortBits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
}
// Create and decode a short Panasonic AC message
TEST(TestDecodePanasonicAC, SyntheticShortMessage) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
uint8_t odourWash[kPanasonicAcStateShortLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06,
0x02, 0x20, 0xE0, 0x04, 0x80, 0x9B, 0x32, 0x53};
irsend.sendPanasonicAC(odourWash, kPanasonicAcStateShortLength);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicAcShortBits, irsend.capture.bits);
EXPECT_STATE_EQ(odourWash, irsend.capture.state, irsend.capture.bits);
}
//
// Test for CKP model / see issue #544
TEST(TestDecodePanasonicAC, CkpModelSpecifics) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Data from Issue #544
uint8_t ckpPowerfulOn[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00,
0x00, 0x0E, 0xE0, 0x11, 0x00, 0x01, 0x00, 0x06, 0xB7};
uint8_t ckpQuietOn[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00,
0x00, 0x0E, 0xE0, 0x30, 0x00, 0x01, 0x00, 0x06, 0xD6};
irsend.sendPanasonicAC(ckpPowerfulOn);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type);
EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits);
EXPECT_STATE_EQ(ckpPowerfulOn, irsend.capture.state, irsend.capture.bits);
EXPECT_FALSE(irsend.capture.repeat);
IRPanasonicAc pana(0);
pana.setRaw(irsend.capture.state);
EXPECT_EQ(
"Model: 5 (CKP), Power: Off, Mode: 4 (Heat), Temp: 23C, "
"Fan: 7 (Auto), Swing(V): 15 (Auto), Quiet: Off, "
"Powerful: On, Clock: 00:00, On Timer: 00:00, Off Timer: 00:00",
pana.toString());
pana.setQuiet(true);
EXPECT_FALSE(pana.getPowerful());
EXPECT_TRUE(pana.getQuiet());
EXPECT_EQ(kPanasonicCkp, pana.getModel());
EXPECT_STATE_EQ(ckpQuietOn, pana.getRaw(), kPanasonicAcBits);
pana.setPowerful(true);
EXPECT_TRUE(pana.getPowerful());
EXPECT_FALSE(pana.getQuiet());
EXPECT_EQ(kPanasonicCkp, pana.getModel());
EXPECT_STATE_EQ(ckpPowerfulOn, pana.getRaw(), kPanasonicAcBits);
}
TEST(TestIRPanasonicAcClass, toCommon) {
IRPanasonicAc ac(0);
ac.setModel(panasonic_ac_remote_model_t::kPanasonicDke);
ac.setPower(true);
ac.setMode(kPanasonicAcCool);
ac.setTemp(20);
ac.setFan(kPanasonicAcFanMax);
ac.setSwingVertical(kPanasonicAcSwingVAuto);
ac.setSwingHorizontal(kPanasonicAcSwingHMiddle);
ac.setPowerful(true);
ac.setQuiet(false);
// Now test it.
ASSERT_EQ(decode_type_t::PANASONIC_AC, ac.toCommon().protocol);
ASSERT_EQ(panasonic_ac_remote_model_t::kPanasonicDke, ac.toCommon().model);
ASSERT_TRUE(ac.toCommon().power);
ASSERT_TRUE(ac.toCommon().celsius);
ASSERT_EQ(20, ac.toCommon().degrees);
ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode);
ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed);
ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv);
ASSERT_EQ(stdAc::swingh_t::kMiddle, ac.toCommon().swingh);
ASSERT_TRUE(ac.toCommon().turbo);
ASSERT_FALSE(ac.toCommon().quiet);
// Unsupported.
ASSERT_FALSE(ac.toCommon().econo);
ASSERT_FALSE(ac.toCommon().clean);
ASSERT_FALSE(ac.toCommon().light);
ASSERT_FALSE(ac.toCommon().filter);
ASSERT_FALSE(ac.toCommon().beep);
ASSERT_EQ(-1, ac.toCommon().sleep);
ASSERT_EQ(-1, ac.toCommon().clock);
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/921#issuecomment-532267240
ac.setSwingVertical(kPanasonicAcSwingVLow);
ASSERT_EQ(stdAc::swingv_t::kLow, ac.toCommon().swingv);
// Real data.
uint8_t swingVMiddle[27] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, 0x20, 0xE0, 0x04,
0x00, 0x39, 0x32, 0x80, 0x73, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x89,
0x00, 0x00, 0xDB};
ac.setRaw(swingVMiddle);
ASSERT_EQ(stdAc::swingv_t::kMiddle, ac.toCommon().swingv);
ASSERT_EQ(kPanasonicAcSwingVMiddle,
IRPanasonicAc::convertSwingV(stdAc::swingv_t::kMiddle));
}
//
// Test for DKE/DKW model / see issue #1024
TEST(TestDecodePanasonicAC, DkeIonRealMessages) {
IRsendTest irsend(0);
IRrecv irrecv(0);
irsend.begin();
// Data from Issue #1024
// 0x0220E004000000060220E004004F3280AF0D000660000001000630
uint8_t dkeIonOff[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x4F, 0x32, 0x80, 0xAF, 0x0D,
0x00, 0x06, 0x60, 0x00, 0x00, 0x01, 0x00, 0x06, 0x30};
// 0x0220E004000000060220E004004F3280AF0D000660000101000631
uint8_t dkeIonOn[kPanasonicAcStateLength] = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02,
0x20, 0xE0, 0x04, 0x00, 0x4F, 0x32, 0x80, 0xAF, 0x0D,
0x00, 0x06, 0x60, 0x00, 0x01, 0x01, 0x00, 0x06, 0x31};
IRPanasonicAc ac(0);
ac.setRaw(dkeIonOff);
EXPECT_EQ(
"Model: 3 (DKE), Power: On, Mode: 4 (Heat), Temp: 25C, Fan: 7 (Auto), "
"Swing(V): 15 (Auto), Swing(H): 13 (Auto), Quiet: Off, Powerful: Off, "
"Ion: Off, Clock: 00:00, On Timer: 00:00, Off Timer: 00:00",
ac.toString());
ac.setRaw(dkeIonOn);
EXPECT_EQ(
"Model: 3 (DKE), Power: On, Mode: 4 (Heat), Temp: 25C, Fan: 7 (Auto), "
"Swing(V): 15 (Auto), Swing(H): 13 (Auto), Quiet: Off, Powerful: Off, "
"Ion: On, Clock: 00:00, On Timer: 00:00, Off Timer: 00:00",
ac.toString());
}