Skip to content
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
54 changes: 27 additions & 27 deletions src/ir_Samsung.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ IRSamsungAc::IRSamsungAc(const uint16_t pin, const bool inverted,
/// @param[in] initialPower Set the initial power state. True, on. False, off.
void IRSamsungAc::stateReset(const bool forcepower, const bool initialPower) {
static const uint8_t kReset[kSamsungAcExtendedStateLength] = {
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x02, 0xAE, 0x71, 0x00,
0x15, 0xF0};
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
0x01, 0x02, 0xAE, 0x71, 0x00, 0x15, 0xF0};
std::memcpy(_.raw, kReset, kSamsungAcExtendedStateLength);
_forcepower = forcepower;
_lastsentpowerstate = initialPower;
Expand Down Expand Up @@ -355,18 +355,14 @@ void IRSamsungAc::checksum(void) {
/// @note Use for most function/mode/settings changes to the unit.
/// i.e. When the device is already running.
void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) {
if (calcchecksum) checksum();
// Do we need to send a the special power on/off message?
if (getPower() != _lastsentpowerstate || _forcepower) {
_forcepower = false; // It will now been sent, so clear the flag if set.
if (getPower()) {
sendOn(repeat);
} else {
sendOff(repeat);
return; // No point sending anything else if we are turning the unit off.
}
// Do we need to send a the special power on/off message? i.e. An Extended Msg
if (getPower() != _lastsentpowerstate || _forcepower) { // We do.
sendExtended(repeat, calcchecksum);
_forcepower = false; // It has now been sent, so clear the flag if set.
} else { // No, it's just a normal message.
if (calcchecksum) checksum();
_irsend.sendSamsungAC(_.raw, kSamsungAcStateLength, repeat);
}
_irsend.sendSamsungAC(_.raw, kSamsungAcStateLength, repeat);
}

/// Send the extended current internal state as an IR message.
Expand All @@ -376,28 +372,32 @@ void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) {
/// Samsung A/C requires an extended length message when you want to
/// change the power operating mode of the A/C unit.
void IRSamsungAc::sendExtended(const uint16_t repeat, const bool calcchecksum) {
static const uint8_t extended_middle_section[kSamsungAcSectionLength] = {
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00};
if (calcchecksum) checksum();
uint8_t extended_state[kSamsungAcExtendedStateLength] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// Copy/convert the internal state to an extended state.
for (uint16_t i = 0; i < kSamsungAcSectionLength; i++)
extended_state[i] = _.raw[i];
for (uint16_t i = kSamsungAcSectionLength; i < kSamsungAcStateLength; i++)
extended_state[i + kSamsungAcSectionLength] = _.raw[i];
// extended_state[8] seems special. This is a guess on how to calculate it.
extended_state[8] = (extended_state[1] & 0x9F) | 0x40;
// Copy/convert the internal state to an extended state by
// copying the second section to the third section, and inserting the extended
// middle (second) section.
std::memcpy(_.raw + 2 * kSamsungAcSectionLength,
_.raw + kSamsungAcSectionLength,
kSamsungAcSectionLength);
std::memcpy(_.raw + kSamsungAcSectionLength, extended_middle_section,
kSamsungAcSectionLength);
// Send it.
_irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength, repeat);
_irsend.sendSamsungAC(_.raw, kSamsungAcExtendedStateLength, repeat);
// Now revert it by copying the third section over the second section.
std::memcpy(_.raw + kSamsungAcSectionLength,
_.raw + 2* kSamsungAcSectionLength,
kSamsungAcSectionLength);
_lastsentpowerstate = getPower(); // Remember the last power state sent.
}

/// Send the special extended "On" message as the library can't seem to
/// reproduce this message automatically.
/// @param[in] repeat Nr. of times the message will be repeated.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/604#issuecomment-475020036
void IRSamsungAc::sendOn(const uint16_t repeat) {
const uint8_t extended_state[21] = {
const uint8_t extended_state[kSamsungAcExtendedStateLength] = {
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00,
0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0};
Expand All @@ -410,7 +410,7 @@ void IRSamsungAc::sendOn(const uint16_t repeat) {
/// @param[in] repeat Nr. of times the message will be repeated.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/604#issuecomment-475020036
void IRSamsungAc::sendOff(const uint16_t repeat) {
const uint8_t extended_state[21] = {
const uint8_t extended_state[kSamsungAcExtendedStateLength] = {
0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0,
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00,
0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0};
Expand Down
9 changes: 2 additions & 7 deletions test/IRac_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1514,14 +1514,9 @@ TEST(TestIRac, Samsung) {
ac._irsend.makeDecodeResult();
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type);
// We expect an extended state because of `dopower`.
ASSERT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits);
// However, we expect a plain "on" state as it should be sent before the
// desired state.
char expected_on[] =
"Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, "
"Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, "
"Light: On, Ion: Off";
ASSERT_EQ(expected_on, IRAcUtils::resultAcToString(&ac._irsend.capture));
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
}

Expand Down
65 changes: 28 additions & 37 deletions test/ir_Samsung_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1270,14 +1270,16 @@ TEST(TestDecodeSamsung36, SyntheticExample) {
}

// https://github.com/crankyoldgit/IRremoteESP8266/issues/604
// This has been superceeded in a way by the ability to calculate extended msg
// checksums correctly. See #1484, #1538, & #1554
TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
IRSamsungAc ac(0);
ac.begin();
ac.stateReset(false); // Disable the initial forced sending of a power mesg.

std::string freqduty = "f38000d50";

std::string poweron =
std::string settings_section1 =
"m690s17844"
"m3086s8864"
"m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436"
Expand All @@ -1287,45 +1289,27 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
"m586s2886"
"m586s2886";
std::string settings_section2 =
"m3086s8864"
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
"m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s2886"
"m3086s8864"
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432"
"m586s436m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432"
"m586s436m586s1432m586s1432m586s1432m586s436m586s1432m586s436m586s1432"
"m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s1432"
"m586s1432m586s436m586s436m586s436m586s1432m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
"m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
"m586s100000";
std::string settings =
"m690s17844"
std::string extended_section =
"m3086s8864"
"m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s436m586s1432"
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
"m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
"m586s2886"
"m3086s8864"
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
"m586s436m586s1432m586s1432m586s1432m586s436m586s1432m586s436m586s1432"
"m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
"m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s436m586s436"
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
"m586s100000";
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
"m586s2886";
std::string text = "Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 4 (Med), "
"Swing: On, Beep: Off, Clean: Off, Quiet: Off, "
"Powerful: Off, Breeze: Off, Light: On, Ion: Off";
Expand All @@ -1336,33 +1320,38 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
ac.setFan(kSamsungAcFanMed);
ac.send();
EXPECT_EQ(text, ac.toString());
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
ac._irsend.outputStr());
// Ensure the power state is changed by changing it and sending it.
ac.off();
ac.send();
ac._irsend.reset(); // Clear the capture buffer.
// Now trigger a special power message by using a power method.
ac.on();
ac.send(); // This should result in two messages. 1 x extended + 1 x normal.
ac.send(); // This should result in an extended message.
EXPECT_EQ(text, ac.toString());
EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr());
EXPECT_EQ(freqduty + settings_section1 + extended_section + settings_section2,
ac._irsend.outputStr());
ac._irsend.reset(); // Clear the capture buffer.
// Subsequent sending should be just the "settings" message.
ac.send();
EXPECT_EQ(text, ac.toString());
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
ac._irsend.outputStr());
ac._irsend.reset(); // Clear the capture buffer.
ac.setPower(true); // Note: The power state hasn't changed from previous.
ac.send(); // This should result in a normal setting message.
EXPECT_EQ(text, ac.toString());
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
ac._irsend.outputStr());

ac._irsend.reset(); // Clear the capture buffer.
ac.setPower(false);
ac.setPower(true); // Note: The power state hasn't changed from the last sent
ac.send(); // This should result in a normal setting message.
EXPECT_EQ(text, ac.toString());
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
ac._irsend.outputStr());

ac.stateReset(); // Normal `stateReset` defaults to send the power message
// on first send.
Expand All @@ -1372,11 +1361,13 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
ac.setFan(kSamsungAcFanMed);
ac.send();
EXPECT_EQ(text, ac.toString());
EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr());
EXPECT_EQ(freqduty + settings_section1 + extended_section + settings_section2,
ac._irsend.outputStr());
ac._irsend.reset(); // Clear the capture buffer.
ac.send(); // Subsequent send() should just be a settings message.
EXPECT_EQ(text, ac.toString());
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
ac._irsend.outputStr());
}

TEST(TestIRSamsungAcClass, toCommon) {
Expand Down