Skip to content

Commit ee7cd5c

Browse files
authored
SamsungAc: Use sendExtended() going forward. (#1562)
* As the `checksum()` calculation for extended states has been fixed in #1554, use `sendExtended()` to calculate & send the extended state instead of the `sendOn()` & `sendOff()`. - This should allow for custom off messages. e.g. clean. - It should also reduce the number of messages sent, and the beeps generated by the A/C on receiving the message. - And make the intended transaction quicker. * Update/adjust unit tests accordingly. * Refactored `sendExtended()` - Use `memcpy()`. - Use less stack space / memory. For #1484
1 parent 0ec49ff commit ee7cd5c

File tree

3 files changed

+57
-71
lines changed

3 files changed

+57
-71
lines changed

src/ir_Samsung.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ IRSamsungAc::IRSamsungAc(const uint16_t pin, const bool inverted,
280280
/// @param[in] initialPower Set the initial power state. True, on. False, off.
281281
void IRSamsungAc::stateReset(const bool forcepower, const bool initialPower) {
282282
static const uint8_t kReset[kSamsungAcExtendedStateLength] = {
283-
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x02, 0xAE, 0x71, 0x00,
284-
0x15, 0xF0};
283+
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
284+
0x01, 0x02, 0xAE, 0x71, 0x00, 0x15, 0xF0};
285285
std::memcpy(_.raw, kReset, kSamsungAcExtendedStateLength);
286286
_forcepower = forcepower;
287287
_lastsentpowerstate = initialPower;
@@ -355,18 +355,14 @@ void IRSamsungAc::checksum(void) {
355355
/// @note Use for most function/mode/settings changes to the unit.
356356
/// i.e. When the device is already running.
357357
void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) {
358-
if (calcchecksum) checksum();
359-
// Do we need to send a the special power on/off message?
360-
if (getPower() != _lastsentpowerstate || _forcepower) {
361-
_forcepower = false; // It will now been sent, so clear the flag if set.
362-
if (getPower()) {
363-
sendOn(repeat);
364-
} else {
365-
sendOff(repeat);
366-
return; // No point sending anything else if we are turning the unit off.
367-
}
358+
// Do we need to send a the special power on/off message? i.e. An Extended Msg
359+
if (getPower() != _lastsentpowerstate || _forcepower) { // We do.
360+
sendExtended(repeat, calcchecksum);
361+
_forcepower = false; // It has now been sent, so clear the flag if set.
362+
} else { // No, it's just a normal message.
363+
if (calcchecksum) checksum();
364+
_irsend.sendSamsungAC(_.raw, kSamsungAcStateLength, repeat);
368365
}
369-
_irsend.sendSamsungAC(_.raw, kSamsungAcStateLength, repeat);
370366
}
371367

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

395395
/// Send the special extended "On" message as the library can't seem to
396396
/// reproduce this message automatically.
397397
/// @param[in] repeat Nr. of times the message will be repeated.
398398
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/604#issuecomment-475020036
399399
void IRSamsungAc::sendOn(const uint16_t repeat) {
400-
const uint8_t extended_state[21] = {
400+
const uint8_t extended_state[kSamsungAcExtendedStateLength] = {
401401
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
402402
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00,
403403
0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0};
@@ -410,7 +410,7 @@ void IRSamsungAc::sendOn(const uint16_t repeat) {
410410
/// @param[in] repeat Nr. of times the message will be repeated.
411411
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/604#issuecomment-475020036
412412
void IRSamsungAc::sendOff(const uint16_t repeat) {
413-
const uint8_t extended_state[21] = {
413+
const uint8_t extended_state[kSamsungAcExtendedStateLength] = {
414414
0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0,
415415
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00,
416416
0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0};

test/IRac_test.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,14 +1514,9 @@ TEST(TestIRac, Samsung) {
15141514
ac._irsend.makeDecodeResult();
15151515
EXPECT_TRUE(capture.decode(&ac._irsend.capture));
15161516
ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type);
1517+
// We expect an extended state because of `dopower`.
15171518
ASSERT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits);
1518-
// However, we expect a plain "on" state as it should be sent before the
1519-
// desired state.
1520-
char expected_on[] =
1521-
"Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, "
1522-
"Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, "
1523-
"Light: On, Ion: Off";
1524-
ASSERT_EQ(expected_on, IRAcUtils::resultAcToString(&ac._irsend.capture));
1519+
ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture));
15251520
ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p));
15261521
}
15271522

test/ir_Samsung_test.cpp

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,14 +1270,16 @@ TEST(TestDecodeSamsung36, SyntheticExample) {
12701270
}
12711271

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

12781280
std::string freqduty = "f38000d50";
12791281

1280-
std::string poweron =
1282+
std::string settings_section1 =
12811283
"m690s17844"
12821284
"m3086s8864"
12831285
"m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436"
@@ -1287,45 +1289,27 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
12871289
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
12881290
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
12891291
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
1290-
"m586s2886"
1292+
"m586s2886";
1293+
std::string settings_section2 =
12911294
"m3086s8864"
12921295
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
12931296
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
1294-
"m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436"
1295-
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1296-
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1297-
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1298-
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1299-
"m586s2886"
1300-
"m3086s8864"
1301-
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1302-
"m586s436m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432"
1303-
"m586s436m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432"
1297+
"m586s436m586s1432m586s1432m586s1432m586s436m586s1432m586s436m586s1432"
13041298
"m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
1305-
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s1432"
1306-
"m586s1432m586s436m586s436m586s436m586s1432m586s436m586s436m586s436"
1299+
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
1300+
"m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s436m586s436"
13071301
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
13081302
"m586s100000";
1309-
std::string settings =
1310-
"m690s17844"
1303+
std::string extended_section =
13111304
"m3086s8864"
1312-
"m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436"
1313-
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s436m586s1432"
1305+
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1306+
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
13141307
"m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436"
13151308
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
13161309
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
13171310
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1318-
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
1319-
"m586s2886"
1320-
"m3086s8864"
1321-
"m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1322-
"m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432"
1323-
"m586s436m586s1432m586s1432m586s1432m586s436m586s1432m586s436m586s1432"
1324-
"m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
1325-
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436"
1326-
"m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s436m586s436"
1327-
"m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432"
1328-
"m586s100000";
1311+
"m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436"
1312+
"m586s2886";
13291313
std::string text = "Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 4 (Med), "
13301314
"Swing: On, Beep: Off, Clean: Off, Quiet: Off, "
13311315
"Powerful: Off, Breeze: Off, Light: On, Ion: Off";
@@ -1336,33 +1320,38 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
13361320
ac.setFan(kSamsungAcFanMed);
13371321
ac.send();
13381322
EXPECT_EQ(text, ac.toString());
1339-
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
1323+
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
1324+
ac._irsend.outputStr());
13401325
// Ensure the power state is changed by changing it and sending it.
13411326
ac.off();
13421327
ac.send();
13431328
ac._irsend.reset(); // Clear the capture buffer.
13441329
// Now trigger a special power message by using a power method.
13451330
ac.on();
1346-
ac.send(); // This should result in two messages. 1 x extended + 1 x normal.
1331+
ac.send(); // This should result in an extended message.
13471332
EXPECT_EQ(text, ac.toString());
1348-
EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr());
1333+
EXPECT_EQ(freqduty + settings_section1 + extended_section + settings_section2,
1334+
ac._irsend.outputStr());
13491335
ac._irsend.reset(); // Clear the capture buffer.
13501336
// Subsequent sending should be just the "settings" message.
13511337
ac.send();
13521338
EXPECT_EQ(text, ac.toString());
1353-
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
1339+
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
1340+
ac._irsend.outputStr());
13541341
ac._irsend.reset(); // Clear the capture buffer.
13551342
ac.setPower(true); // Note: The power state hasn't changed from previous.
13561343
ac.send(); // This should result in a normal setting message.
13571344
EXPECT_EQ(text, ac.toString());
1358-
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
1345+
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
1346+
ac._irsend.outputStr());
13591347

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

13671356
ac.stateReset(); // Normal `stateReset` defaults to send the power message
13681357
// on first send.
@@ -1372,11 +1361,13 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) {
13721361
ac.setFan(kSamsungAcFanMed);
13731362
ac.send();
13741363
EXPECT_EQ(text, ac.toString());
1375-
EXPECT_EQ(freqduty + poweron + settings, ac._irsend.outputStr());
1364+
EXPECT_EQ(freqduty + settings_section1 + extended_section + settings_section2,
1365+
ac._irsend.outputStr());
13761366
ac._irsend.reset(); // Clear the capture buffer.
13771367
ac.send(); // Subsequent send() should just be a settings message.
13781368
EXPECT_EQ(text, ac.toString());
1379-
EXPECT_EQ(freqduty + settings, ac._irsend.outputStr());
1369+
EXPECT_EQ(freqduty + settings_section1 + settings_section2,
1370+
ac._irsend.outputStr());
13801371
}
13811372

13821373
TEST(TestIRSamsungAcClass, toCommon) {

0 commit comments

Comments
 (0)