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

Samsung AC - send "clean" on power off #1484

Closed
bogd opened this issue May 25, 2021 · 19 comments · Fixed by #1562
Closed

Samsung AC - send "clean" on power off #1484

bogd opened this issue May 25, 2021 · 19 comments · Fixed by #1562
Assignees
Labels
bug more info Pending Confirmation Waiting for confirmation from user

Comments

@bogd
Copy link

bogd commented May 25, 2021

Describe the bug

"Clean" flag should be honored and sent during power off - right now, the code only sends a "standard" power off message, and ignores anything else when powering off the unit.

For my type of unit, "clean" simply means that it keeps the fan running for about 15 minutes after power off, to dry the inside of the system. As far as I can tell, this flag is sent by the original remote as part of the "off" sequence (this might be wrong - I am attaching captures from the original remote below, if it would help troubleshooting).

To Reproduce

Originally discovered this while troubleshooting a different issue with Tasmota ( see here ).

Example code used

Include all relevant code snippets or links to the actual code files. Tip: How to quote your code so it is still readable in the report.

Expected behaviour

The "clean" flag should be sent as part of the power off sequence - however, as far as I can tell, it is not.

Output of raw data from [IRrecvDumpV2.ino]

Sequence from the original remote :

[ Powered on unit, 26 degrees C, cool mode ]

Protocol : UNKNOWN
Code : 0x8165DDF8 (178 Bits)
uint16_t rawData[355] = {70, 49496, 74, 3862, 70, 29350, 614, 16654, 3000, 8900, 530, 462, 530, 1454, 530, 464, 526, 464, 528, 464, 526, 466, 500, 512, 504, 488, 458, 532, 488, 1494, 496, 498, 524, 466, 526, 1454, 530, 462, 504, 486, 532, 1450, 532, 1454, 530, 1452, 504, 1480, 502, 1504, 504, 488, 458, 532, 460, 530, 490, 502, 494, 496, 498, 492, 502, 490, 530, 460, 504, 488, 504, 486, 532, 460, 528, 464, 528, 462, 528, 464, 528, 466, 524, 466, 526, 464, 526, 488, 502, 490, 434, 556, 486, 506, 462, 528, 492, 498, 496, 494, 528, 464, 528, 462, 528, 464, 530, 460, 528, 462, 530, 462, 528, 464, 528, 466, 528, 1454, 528, 1454, 528, 1478, 436, 1546, 532, 2928, 3000, 8924, 498, 1486, 534, 458, 532, 460, 530, 460, 530, 460, 532, 460, 530, 460, 530, 462, 530, 462, 528, 1452, 530, 464, 528, 486, 502, 1478, 460, 530, 488, 1494, 496, 1486, 530, 1452, 532, 1452, 530, 1452, 532, 1450, 530, 464, 528, 464, 524, 466, 526, 466, 526, 486, 506, 484, 502, 488, 460, 532, 486, 504, 490, 502, 496, 496, 524, 466, 530, 460, 530, 462, 530, 460, 532, 458, 530, 462, 532, 460, 530, 464, 528, 462, 528, 464, 526, 466, 528, 486, 504, 488, 460, 530, 460, 532, 462, 530, 490, 500, 498, 494, 528, 462, 530, 460, 530, 460, 528, 464, 502, 488, 530, 460, 502, 490, 530, 2952, 2998, 8904, 500, 1482, 530, 466, 526, 486, 502, 490, 458, 532, 484, 508, 462, 528, 520, 470, 524, 466, 530, 1452, 530, 462, 502, 488, 530, 1452, 530, 462, 526, 1458, 528, 1454, 526, 468, 526, 1478, 502, 1482, 486, 1496, 492, 1492, 526, 1458, 532, 1450, 532, 1452, 530, 1454, 530, 464, 524, 466, 526, 464, 524, 1458, 526, 1480, 462, 1520, 462, 530, 462, 528, 492, 500, 522, 468, 500, 490, 526, 464, 528, 1454, 526, 466, 528, 1454, 528, 1456, 500, 496, 496, 492, 522, 470, 520, 1484, 458, 532, 460, 532, 462, 530, 492, 500, 494, 496, 528, 464, 528, 462, 500, 1482, 526, 1456, 526, 1458, 526, 1458, 484}; // UNKNOWN 8165DDF8

[ Pressed the "clean" button to activate the feature ]

Timestamp : 000160.168
Library : v2.7.18

Protocol : UNKNOWN
Code : 0x9EBC58F0 (118 Bits)
uint16_t rawData[235] = {68, 28018, 612, 17422, 3026, 8898, 496, 494, 528, 1454, 532, 460, 530, 462, 528, 462, 532, 462, 528, 460, 530, 462, 526, 466, 526, 1454, 528, 468, 524, 488, 504, 1476, 460, 532, 488, 500, 494, 1488, 528, 1454, 506, 1476, 530, 1454, 532, 1452, 530, 462, 528, 464, 526, 464, 528, 464, 526, 466, 526, 486, 502, 490, 458, 532, 486, 504, 488, 502, 492, 498, 522, 470, 530, 396, 534, 452, 598, 460, 532, 356, 632, 462, 530, 460, 530, 462, 530, 462, 526, 466, 528, 464, 526, 466, 500, 514, 504, 488, 458, 532, 486, 504, 488, 504, 490, 500, 522, 468, 530, 460, 532, 462, 528, 1450, 534, 1448, 532, 1450, 528, 1456, 484, 2996, 2932, 8970, 500, 1506, 504, 488, 458, 532, 486, 506, 490, 502, 496, 494, 526, 466, 532, 460, 532, 460, 532, 1450, 532, 460, 530, 462, 530, 1454, 528, 1454, 528, 464, 528, 1476, 504, 490, 458, 1524, 486, 1496, 496, 1486, 530, 1452, 532, 1456, 526, 1452, 530, 1452, 532, 1452, 530, 464, 500, 490, 526, 466, 526, 1478, 460, 1522, 462, 1520, 494, 1488, 502, 490, 530, 1452, 532, 460, 530, 460, 530, 462, 530, 1454, 528, 464, 530, 1454, 528, 1478, 506, 488, 502, 488, 460, 532, 462, 1520, 494, 498, 524, 468, 530, 462, 502, 488, 530, 462, 530, 460, 528, 462, 676, 1306, 530, 1454, 528, 1456, 528, 1478, 524}; // UNKNOWN 9EBC58F0

[ Powered off unit with "clean" mode on ]

Timestamp : 000161.382
Library : v2.7.18

Protocol : UNKNOWN
Code : 0x4F9DA954 (183 Bits)
uint16_t rawData[365] = {68, 334, 610, 17784, 2958, 8946, 528, 488, 504, 1476, 486, 506, 490, 502, 496, 496, 524, 468, 530, 460, 530, 462, 528, 460, 532, 1450, 530, 462, 530, 462, 530, 1452, 530, 1452, 528, 466, 524, 1478, 438, 1546, 488, 1496, 494, 1488, 506, 1478, 504, 488, 530, 460, 528, 462, 530, 460, 532, 462, 528, 464, 526, 466, 528, 464, 524, 466, 500, 492, 524, 488, 502, 490, 458, 532, 488, 504, 488, 502, 524, 468, 500, 490, 530, 462, 528, 462, 532, 460, 528, 460, 530, 462, 528, 462, 530, 462, 528, 464, 526, 464, 526, 464, 528, 466, 526, 488, 460, 530, 460, 530, 462, 530, 488, 502, 524, 468, 526, 1456, 532, 1450, 528, 2954, 3000, 4432, 66, 4402, 530, 1454, 528, 466, 524, 466, 526, 464, 526, 466, 498, 494, 524, 488, 502, 488, 460, 530, 460, 1520, 496, 496, 498, 494, 530, 1452, 530, 462, 526, 1456, 528, 1456, 530, 1454, 500, 1482, 524, 1458, 524, 1480, 460, 532, 460, 530, 486, 506, 492, 500, 494, 498, 526, 466, 526, 466, 526, 464, 526, 464, 526, 466, 528, 464, 528, 464, 526, 466, 522, 470, 524, 466, 524, 468, 524, 490, 472, 518, 458, 532, 462, 530, 486, 504, 490, 502, 492, 498, 498, 492, 526, 464, 526, 464, 526, 466, 526, 464, 500, 490, 526, 466, 522, 470, 524, 466, 524, 468, 522, 468, 522, 492, 498, 492, 498, 2958, 2992, 8934, 462, 1520, 496, 498, 496, 494, 524, 466, 500, 492, 524, 466, 524, 466, 526, 466, 500, 492, 500, 1482, 524, 472, 494, 498, 520, 1482, 500, 1482, 460, 1522, 464, 1518, 496, 496, 496, 1484, 502, 1482, 524, 1458, 526, 1458, 500, 1484, 498, 1484, 498, 1486, 496, 1510, 460, 532, 460, 530, 490, 502, 492, 1490, 498, 1484, 502, 1482, 500, 492, 524, 466, 498, 492, 498, 496, 496, 496, 494, 496, 496, 1486, 498, 518, 470, 1510, 460, 1522, 464, 528, 490, 500, 494, 496, 496, 1484, 502, 492, 498, 492, 524, 466, 498, 494, 496, 496, 496, 496, 496, 496, 494, 498, 494, 496, 494, 1510, 502, 1480, 500, 14606, 68, 20020, 66, 19912, 62, 7344, 108, 14804, 68, 18518, 110}; // UNKNOWN 4F9DA954

Note: Output from Tasmota is not acceptable. We can't easily use their raw format.

What brand/model IR demodulator are you using?

N/A . Captures above are from a Lolin IR shield, but for sending the signals I am using tasmota on a variety of devices (mainly YTF/Eachen IR ones).

Circuit diagram and hardware used (if applicable)

N/A

Link to an image of the circuit diagram used. Part number of the IR receiver module etc. ESP8266 or ESP32 board type.

Has this library/code previously worked as expected for you?

No

Other useful information

As mentioned above, I believe (but please do not take my word on it, my understanding of the full IR protocol for the unit is quite limited!) that the "clean" flag is also sent as part of the "off" sequence. In which case, the library code should do the same, and honor that flag when sending a power off command.

@NiKiZe
Copy link
Collaborator

NiKiZe commented May 25, 2021

What is the full model number of AC and remote?

Notice that there is no protocol detected, this indicates that your device is not actually supported (could be temporary random timing issues)
Also which protocol have you been using?

@bogd
Copy link
Author

bogd commented May 25, 2021

The device is a samsung AR09HSFSBWKN, and I am using the SAMSUNG_AC protocol. As for the remote, I had no idea they even had model numbers... the only label on it says "DB93-14195A, OHSUNG ELECTRONICS CO, LTD".

The device is definitely supported - commands send via tasmota (from YTF/Eachen devices) are recognized correctly, and commands from the original remote are also generally correctly decoded by Tasmota (with some exceptions, see the issue I linked above).

Most likely, the lack of decoding on IRRecvDump is due to the lower quality of the IR receiver on the Lolin shield.

@bogd
Copy link
Author

bogd commented May 25, 2021

I finally managed to get some decodes (unfortunately, this only happens about 1 in 10 tries....):

[ Power on, 25 degrees ]
Protocol : SAMSUNG_AC
Code : 0x02920F000000F001D20F0000000001C2FE71900DF0 (168 Bits)
Mesg Desc.: Power: On, Mode: 0 (Auto), Temp: 25C, Fan: 6 (Auto), Swing: Off, Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, Light: On, Ion: Off
uint16_t rawData[349] = {612, 18464, 2964, 8934, 496, 498, 492, 1490, 492, 502, 490, 502, 488, 524, 468, 440, 542, 532, 458, 530, 460, 532, 462, 1518, 494, 498, 492, 498, 494, 1488, 520, 470, 494, 498, 494, 1490, 494, 1488, 492, 1490, 492, 1514, 468, 1514, 460, 532, 484, 508, 484, 506, 490, 500, 492, 498, 494, 498, 492, 498, 494, 498, 492, 498, 494, 496, 494, 498, 494, 498, 490, 502, 490, 502, 464, 526, 490, 524, 468, 522, 468, 522, 460, 530, 460, 532, 462, 528, 488, 502, 492, 500, 492, 500, 494, 496, 494, 496, 494, 498, 494, 498, 492, 498, 494, 498, 492, 500, 492, 500, 490, 1514, 468, 1514, 468, 1514, 462, 1522, 496, 2964, 2988, 8934, 494, 1488, 494, 496, 494, 496, 496, 496, 494, 496, 494, 498, 494, 498, 492, 500, 490, 500, 490, 1496, 486, 522, 468, 524, 458, 1522, 462, 530, 462, 1518, 494, 1490, 494, 1486, 496, 1486, 496, 1486, 494, 1490, 520, 474, 490, 500, 490, 502, 488, 522, 468, 524, 460, 530, 484, 506, 462, 530, 488, 502, 488, 502, 492, 498, 494, 498, 494, 498, 494, 498, 494, 496, 494, 496, 494, 500, 492, 500, 490, 500, 492, 502, 488, 502, 488, 526, 466, 524, 462, 528, 484, 508, 486, 504, 486, 506, 492, 500, 494, 496, 494, 498, 494, 496, 494, 498, 494, 496, 494, 498, 492, 500, 492, 500, 462, 3016, 2966, 8940, 492, 1512, 468, 524, 462, 528, 460, 470, 520, 530, 462, 528, 490, 502, 494, 498, 492, 498, 496, 1486, 494, 498, 496, 496, 494, 496, 494, 500, 492, 1490, 492, 1492, 490, 524, 466, 1514, 460, 1522, 462, 1520, 492, 1490, 496, 1488, 496, 1486, 496, 1486, 496, 1488, 494, 500, 492, 500, 490, 500, 490, 1514, 468, 1516, 460, 1522, 462, 530, 488, 502, 492, 500, 494, 498, 494, 498, 492, 1488, 496, 496, 492, 498, 494, 1490, 494, 1490, 490, 502, 490, 1514, 468, 1516, 460, 532, 460, 530, 460, 530, 488, 502, 490, 502, 494, 496, 494, 496, 496, 496, 494, 1488, 496, 1488, 492, 1492, 490, 1492, 510}; // SAMSUNG_AC
uint8_t state[21] = {0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC2, 0xFE, 0x71, 0x90, 0x0D, 0xF0};

[ Clean on - this seems to be using a short version of the IR protocol ]

Timestamp : 000259.820
Library : v2.7.18

Protocol : SAMSUNG_AC
Code : 0x02920F000000F001A2FEF1920DF0 (112 Bits)
Mesg Desc.: Power: On, Mode: 0 (Auto), Temp: 25C, Fan: 6 (Auto), Swing: Off, Beep: Off, Clean: On, Quiet: Off, Powerful: Off, Breeze: Off, Light: On, Ion: Off
uint16_t rawData[233] = {586, 17450, 3022, 8900, 526, 466, 528, 1452, 530, 462, 528, 462, 504, 486, 530, 462, 528, 462, 526, 466, 502, 490, 500, 1482, 528, 466, 524, 490, 502, 1478, 486, 506, 462, 530, 494, 1488, 526, 1456, 532, 1450, 530, 1454, 530, 1452, 532, 462, 526, 464, 528, 462, 528, 464, 526, 466, 524, 488, 502, 488, 458, 534, 460, 530, 490, 502, 490, 500, 498, 492, 530, 462, 502, 488, 530, 462, 528, 462, 528, 462, 528, 464, 528, 464, 524, 466, 528, 466, 498, 492, 526, 466, 524, 488, 500, 490, 460, 530, 462, 530, 488, 500, 494, 498, 522, 468, 526, 464, 528, 462, 530, 1452, 530, 1454, 502, 1480, 528, 1454, 486, 2996, 2956, 8946, 526, 1478, 500, 492, 460, 530, 462, 530, 490, 502, 494, 498, 498, 494, 526, 464, 524, 466, 524, 1456, 528, 464, 526, 464, 526, 392, 608, 1450, 524, 470, 522, 1482, 500, 492, 460, 1522, 460, 1522, 492, 1490, 526, 1458, 528, 1454, 530, 1454, 528, 1456, 528, 1456, 526, 468, 524, 468, 520, 470, 522, 1482, 500, 1482, 486, 1496, 490, 1492, 500, 492, 524, 1456, 526, 466, 526, 464, 526, 1456, 528, 466, 526, 466, 522, 1456, 524, 1460, 496, 518, 472, 1508, 460, 1522, 490, 502, 494, 498, 498, 492, 498, 492, 526, 464, 498, 494, 522, 468, 524, 466, 498, 1484, 522, 1462, 498, 1484, 522, 1484, 496}; // SAMSUNG_AC
uint8_t state[14] = {0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xA2, 0xFE, 0xF1, 0x92, 0x0D, 0xF0};

[ Power off ]
Timestamp : 000478.446
Library : v2.7.18

Protocol : SAMSUNG_AC
Code : 0x02B20F000000C001D20F0000000001F2FE719011C0 (168 Bits)
Mesg Desc.: Power: Off, Mode: 1 (Cool), Temp: 25C, Fan: 0 (Auto), Swing: Off, Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, Light: On, Ion: Off
uint16_t rawData[349] = {580, 17792, 2994, 8932, 464, 526, 492, 1490, 498, 494, 496, 494, 496, 496, 496, 494, 496, 496, 496, 496, 496, 496, 494, 1488, 492, 500, 492, 498, 492, 1512, 470, 1514, 488, 504, 462, 1520, 468, 1516, 498, 1484, 498, 1484, 498, 1486, 498, 496, 496, 496, 494, 498, 492, 498, 492, 500, 492, 522, 470, 520, 470, 520, 462, 530, 488, 504, 488, 502, 490, 500, 496, 496, 496, 496, 496, 494, 496, 496, 494, 496, 496, 496, 494, 496, 496, 496, 494, 498, 494, 498, 492, 500, 490, 522, 468, 522, 470, 522, 458, 532, 462, 530, 488, 504, 490, 500, 494, 496, 498, 494, 494, 496, 496, 496, 496, 1486, 496, 1488, 496, 2986, 2966, 8936, 494, 1488, 494, 522, 468, 522, 468, 522, 458, 532, 462, 528, 464, 526, 492, 500, 494, 496, 496, 1486, 496, 496, 496, 494, 494, 1486, 498, 496, 494, 1488, 494, 1490, 492, 1514, 470, 1514, 460, 1520, 490, 1494, 494, 500, 494, 496, 494, 496, 494, 496, 496, 494, 496, 496, 496, 494, 496, 496, 494, 500, 492, 500, 492, 498, 492, 524, 468, 522, 468, 522, 466, 524, 460, 530, 464, 528, 490, 502, 490, 500, 496, 496, 494, 496, 496, 496, 494, 496, 496, 494, 496, 496, 494, 496, 494, 498, 494, 498, 490, 502, 492, 522, 468, 522, 470, 522, 468, 524, 462, 530, 490, 500, 466, 526, 496, 2962, 2988, 8936, 496, 1382, 600, 494, 494, 496, 494, 496, 496, 496, 494, 498, 494, 498, 494, 498, 490, 500, 492, 1512, 468, 524, 466, 526, 462, 1518, 466, 1518, 494, 1488, 496, 1486, 498, 494, 496, 1486, 498, 1486, 496, 1488, 494, 1490, 492, 1514, 468, 1514, 462, 1520, 490, 1492, 494, 498, 496, 496, 496, 494, 496, 1486, 496, 1486, 496, 1488, 496, 498, 492, 500, 494, 498, 492, 524, 468, 520, 470, 1512, 464, 528, 464, 528, 488, 1492, 494, 1488, 496, 496, 496, 496, 496, 496, 494, 1486, 496, 496, 494, 498, 492, 500, 492, 500, 492, 500, 490, 522, 470, 520, 468, 522, 462, 528, 490, 1492, 492, 1490, 498}; // SAMSUNG_AC
uint8_t state[21] = {0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF2, 0xFE, 0x71, 0x90, 0x11, 0xC0};

Hmmm.... I might actually be wrong in my understanding of the IR protocol. Judging from the decode, the "clean" flag is not sent in the"off" message. If that is the case, I might just get it to work by toggling the flag before powering off. I have to run some additional tests :)

@NiKiZe
Copy link
Collaborator

NiKiZe commented May 25, 2021

Thanks for the additional information. (don't have time to deep dive into this right now, just trying to make sure that all information is available once someone does have that time)
yep clearly timing issues ;), a "seems to be working" is not the same thing as actually supported (as in a device being tested)

I can understand your frustration.
It is great that we have base to work with.
As you said, with that additional data it seems that there is no flag set in the off message of your original remote?
If it turns out somethings needs a change here, we must also make sure to not risk breaking other working devices. (I have not double checked this either)

One other thing to have in mind, The goal of the lib is to "make the devices usable, not to emulate every detail of a remote"
We try to avoid unnecessary emulation in the lib itself. Again as you said, by sending Cleaning which you seem to do on the real remote to activate this feature?

@NiKiZe NiKiZe added bug more info Pending Confirmation Waiting for confirmation from user labels May 25, 2021
@bogd
Copy link
Author

bogd commented May 25, 2021

Once again, thank you for taking the time to work on this. To answer your question/remarks:

  • based on my previous work trying to decode the IR protocol, and the fact that most commands are correctly recognized by the unit, I still believe that SAMSUNG_AC is the correct protocol for my unit (even though the exact model number is not listed as "supported"). And I am confident enough that I would even suggest adding it to the list of supported models (together with the 12K BTU model, which uses an identical remote and protocol)
  • there is no frustration - I am just trying to get to the bottom of this issue, which I originally (and wrongly) believed was due to the way the library implements the power off function. My apologies if my previous messages suggested otherwise!
  • I was not requesting any additional emulation, just something that I believed (again, wrongly!) was necessary for a specific function to work correctly.

Anyway - after additional testing, it appears that this ("clean") is a very strange flag on my unit. It appears to be a main unit-side toggle, and all the remote does when setting the bit on is toggle the setting on the main unit.

So a power on / toggle flag / power off sequence should work correctly for my use case.

I am closing this issue now, because the problem seems to be on my end. Thank you for your help, and my apologies for taking up your time with this!

@bogd bogd closed this as completed May 25, 2021
@crankyoldgit
Copy link
Owner

"Clean" flag should be honored and sent during power off - right now, the code only sends a "standard" power off message, and ignores anything else when powering off the unit.

For my type of unit, "clean" simply means that it keeps the fan running for about 15 minutes after power off, to dry the inside of the system. As far as I can tell, this flag is sent by the original remote as part of the "off" sequence (this might be wrong - I am attaching captures from the original remote below, if it would help troubleshooting).

FYI, The support of Samsung A/Cs is a tad "special". Yes, sending an "Off" message via this library involves sending a canned "Off" message. We have been unable to replicate the message integrity check for the longer special Samsung messages. e.g. "Off". Thus, we can't construct customised long/special messages. If you care to work out how the check digits are calculated, please do so and let us know. For the shorter messages, it's the total/count of all the 1 bits in the binary of the code. I'm willing to look at any data/analysis you collect/perform for it because it has alluded me for years. It's driving me (more) crazy.

If you want to send a custom "off" message, for now, you will need to capture it and send it via sendSamsungAC(your_state_code_here) or via sendRaw(). Sorry.

I finally managed to get some decodes (unfortunately, this only happens about 1 in 10 tries....):

I had a look at those failed matches, it is mostly IR noise in the capture buffer prior to the real message arriving. ie. Could be a poor sensor module, circuit, or environment for IR receiver.

You could work-around that in software by setting the max_skip parameter to IRrecv::decode() to something like 2, or 4.

See: https://crankyoldgit.github.io/IRremoteESP8266/doxygen/html/classIRrecv.html#aeaa5c07a8b46f8fbb982f996cc1f9f4b for more details, and the costs involved in doing so.

based on my previous work trying to decode the IR protocol, and the fact that most commands are correctly recognized by the unit, I still believe that SAMSUNG_AC is the correct protocol for my unit (even though the exact model number is not listed as "supported"). And I am confident enough that I would even suggest adding it to the list of supported models (together with the 12K BTU model, which uses an identical remote and protocol)

Thanks. I'll add in that info to the supported models for Samsung.

@bogd
Copy link
Author

bogd commented May 26, 2021

@crankyoldgit - yeah, that protocol is... "special"... And I know exactly what you mean about the checksums. Years ago, I spent several months trying to figure out the protocol. And while I could figure out the bits for temperature, fan, etc, the (multiple!) checksum blocks always eluded me.

Looking at my notes from back then, I see something like "4-bit checksum, number of all 0 bits in this set (the longer messages seem to consist of 3 "sets", separated by special "break" messages - 550/3100/3100/8900), modulo 15. If modulo equals 0, set to 15". Each set seems to have its own 4-bit checksum. But then again, this was a long time ago, and I am pretty sure it is not 100% correct.

I will try to look over my captures once again, and see if I can derive a little bit more meaning from them :)

I would also like to say a big thank you! for this library. As mentioned above, I know from personal experience how much work is involved with trying to capture and decode the various IR protocols - so thank you for taking the time to do that, and making it available to the rest of us!

@bogd
Copy link
Author

bogd commented May 26, 2021

I have posted my old notes from attempting to decode the protocol here . I can also provide various captures from the original remote, if needed - maybe together we can finally crack that annoying protocol! :)

@crankyoldgit
Copy link
Owner

I will try to look over my captures once again, and see if I can derive a little bit more meaning from them :)

That would be fabulous! I had a quick look at what you had documented, but I'm confused on the "sets". I'ff you can describe what each "set" is by the byte ranges of this library's state[] array, that would be good. Saves me having to go back to the raw stream to see what you mean.

The idea of multiple "checksums" for the sets (and their ignored bytes) may be a big help cracking the extended message construction.

@bogd
Copy link
Author

bogd commented May 26, 2021

@crankyoldgit - I will do my best to explain. When capturing the long IR messages from the remote, I noticed that they are sent in 3 "sets" of 7 bytes each. The sets are separated by what appears to be a special "break" sequence ( 550 3100 3100 8900 - notation used is LIRC-style: time on/time off).

As far as I can tell, each of these 56-bit "sets" has its own 4-bit CRC. The last set, however, seems to have a "global" CRC (one that takes into account all of the bits sent so far). Which does actually kind of make sense :)

[ Edited to add: in the gist , lines 13 to 57 are in fact one long signal captured by me, with the BREAKs and notes added for the bits that I was able to identify ]

@crankyoldgit
Copy link
Owner

X-Ref: #1538 & #1554

crankyoldgit added a commit that referenced this issue Aug 12, 2021
* 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
crankyoldgit added a commit that referenced this issue Aug 12, 2021
* 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
@crankyoldgit
Copy link
Owner

@bogd Can you please download and try out branch https://github.com/crankyoldgit/IRremoteESP8266/tree/samsung_clean / PR #1562 and let me know if it fixes your clean issue.

As we've finally worked out the Samsung A/C checksum properly, we can now create arbitrary extended messages. Thus it should construct a "Power Off" message with the clean bit set with the code in that branch. Also, it will only beep once, not twice! ;-)

@crankyoldgit crankyoldgit reopened this Aug 12, 2021
@bogd
Copy link
Author

bogd commented Aug 12, 2021

Wow, that is great!! Is the correct calculation documented anywhere? (I am curious to see if I got at least a little bit close to the correct answer with my assumptions above :) ).

I will try out the new version, but it will take a while - unfortunately, real life got in the way, and I had to put my IoT tinkering on hold for a little bit :|

@crankyoldgit
Copy link
Owner

Wow, that is great!! Is the correct calculation documented anywhere?

Yes: See #1538 (comment)
and code:

/// Get the existing checksum for a given state section.
/// @param[in] section The array to extract the checksum from.
/// @return The existing checksum value.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1538#issuecomment-894645947
uint8_t IRSamsungAc::getSectionChecksum(const uint8_t *section) {
return ((GETBITS8(*(section + 2), kLowNibble, kNibbleSize) << kNibbleSize) +
GETBITS8(*(section + 1), kHighNibble, kNibbleSize));
}
/// Calculate the checksum for a given state section.
/// @param[in] section The array to calc the checksum of.
/// @return The calculated checksum value.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1538#issuecomment-894645947
uint8_t IRSamsungAc::calcSectionChecksum(const uint8_t *section) {
uint8_t sum = 0;
sum += countBits(*section, 8); // Include the entire first byte
// The lower half of the second byte.
sum += countBits(GETBITS8(*(section + 1), kLowNibble, kNibbleSize), 8);
// The upper half of the third byte.
sum += countBits(GETBITS8(*(section + 2), kHighNibble, kNibbleSize), 8);
// The next 4 bytes.
sum += countBits(section + 3, 4);
// Bitwise invert the result.
return sum ^ UINT8_MAX;
}
/// Verify the checksum is valid for a given state.
/// @param[in] state The array to verify the checksum of.
/// @param[in] length The length/size of the array.
/// @return true, if the state has a valid checksum. Otherwise, false.
bool IRSamsungAc::validChecksum(const uint8_t state[], const uint16_t length) {
bool result = true;
const uint16_t maxlength =
(length > kSamsungAcExtendedStateLength) ? kSamsungAcExtendedStateLength
: length;
for (uint16_t offset = 0;
offset + kSamsungAcSectionLength <= maxlength;
offset += kSamsungAcSectionLength)
result &= (getSectionChecksum(state + offset) ==
calcSectionChecksum(state + offset));
return result;
}
/// Update the checksum for the internal state.
void IRSamsungAc::checksum(void) {
uint8_t sectionsum = calcSectionChecksum(_.raw);
_.Sum1Upper = GETBITS8(sectionsum, kHighNibble, kNibbleSize);
_.Sum1Lower = GETBITS8(sectionsum, kLowNibble, kNibbleSize);
sectionsum = calcSectionChecksum(_.raw + kSamsungAcSectionLength);
_.Sum2Upper = GETBITS8(sectionsum, kHighNibble, kNibbleSize);
_.Sum2Lower = GETBITS8(sectionsum, kLowNibble, kNibbleSize);
sectionsum = calcSectionChecksum(_.raw + kSamsungAcSectionLength * 2);
_.Sum3Upper = GETBITS8(sectionsum, kHighNibble, kNibbleSize);
_.Sum3Lower = GETBITS8(sectionsum, kLowNibble, kNibbleSize);
}

(I am curious to see if I got at least a little bit close to the correct answer with my assumptions above :) ).

You and me both! What we got wrong was thinking:

  1. it was only a 4 bit check value. Turns out it was 8 bits, and those two nibbles were in different byte locations.
  2. That it was ever calculated across more than 7 byte section of the message, it was one per each of the 7 byte sections.

@bogd
Copy link
Author

bogd commented Aug 12, 2021

Damn... I am both happy and frustrated. I got part of it right (different checksums for for different sections, or what I called "sets" above), but never figured out the 8-bit part. Because through an incredible stroke of bad luck, all my captures were modifying only 4 of the bits in the checksum :)

Nevertheless, I am incredibly happy that this was fixed - thank you once again to you @crankyoldgit and to @thermseekr for all your hard work on this!

Now I have to see when tasmota will integrate the new version of the library... :D

@crankyoldgit
Copy link
Owner

Now I have to see when tasmota will integrate the new version of the library... :D

They are pretty good at including the lastest released version of this library. I'll probably make a new official release when a few of the protocols currently under development are finished. In the meantime, it's fairly trivial to update the library in Tasmota and build it yourself.

@crankyoldgit crankyoldgit self-assigned this Aug 13, 2021
@thermseekr
Copy link

As far as I can tell, each of these 56-bit "sets" has its own 4-bit CRC.

This is interesting. I haven't noticed it as I didn't worry for any special functions, which I don't use. Does it still make sense to try to figure this out?

@bogd
Copy link
Author

bogd commented Aug 14, 2021

@thermseekr - the only such function I can think of is the scheduled on/off function. If you are interested and can take a look, I have posted my own attempts at decoding the protocol above .

However, take those with a grain of salt - you have already proven me wrong once :) (the CRCs are not actually 4-bit, they are 8-bit - but I never noticed that :) ).

crankyoldgit added a commit that referenced this issue Aug 14, 2021
* 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
crankyoldgit added a commit that referenced this issue Aug 28, 2021
_v2.7.20 (20210828)_

**[Bug Fixes]**
- Make `strToSwingH()` match "Right Max" (#1550 #1551)

**[Features]**
- Experimental Bose remote support (#1579)
- Added MitsubishiAC VaneLeft (#1572 #1576)
- HAIER_AC176: Add experimental detailed support (#1480 #1571)
- Detailed support for Tornado/Sanyo 88-bit A/C protocol (#1503 #1568)
- Add support for new `TROTEC_3550` A/C protocol (#1563 #1566 #1507)
- SamsungAc: Use `sendExtended()` going forward. (#1484 #1562)
- SamsungAc: Redo/fix checksum calculations. (#1538 #1554)
- LG: Add support for `AKB73757604` model (#1531 #1545)
- Daikin176: Add support for Unit Id. (#1543 #1544)
- Daikin2: Add support for Humidity setting/operation. (#1535 #1540)
- TCL112AC: Add support for quiet/mute setting. (#1528 #1529)
- LG2: Add Fan speed, Swing, & Light support for new `AKB74955603` model (#1513 #1530)
- Add Mitsubishi AC "fan only" mode (#1527)

**[Misc]**
- Fix pylint issues due to pylint update. (#1569 #1570)
- DAIKIN216: Update supported models. (#1552 #1567)
- IRMQTTServer: Build a minimal OTA image via PlatformIO. (#1513 #1541)
- Reduce memory fragmentation cause by String usage. (#1493 #1536)
- Refactor `decodeMitsubishiAC()` (#1523 #1532)
- Fix incorrect comment.
- Migrate from Travis to GitHub Actions (#1522 #1526)
- Documentation update with additional supported Panasonic AC models (#1525)
crankyoldgit added a commit that referenced this issue Aug 28, 2021
_v2.7.20 (20210828)_

**[Bug Fixes]**
- Make `strToSwingH()` match "Right Max" (#1550 #1551)

**[Features]**
- Experimental Bose remote support (#1579)
- Added MitsubishiAC VaneLeft (#1572 #1576)
- HAIER_AC176: Add experimental detailed support (#1480 #1571)
- Detailed support for Tornado/Sanyo 88-bit A/C protocol (#1503 #1568)
- Add support for new `TROTEC_3550` A/C protocol (#1563 #1566 #1507)
- SamsungAc: Use `sendExtended()` going forward. (#1484 #1562)
- SamsungAc: Redo/fix checksum calculations. (#1538 #1554)
- LG: Add support for `AKB73757604` model (#1531 #1545)
- Daikin176: Add support for Unit Id. (#1543 #1544)
- Daikin2: Add support for Humidity setting/operation. (#1535 #1540)
- TCL112AC: Add support for quiet/mute setting. (#1528 #1529)
- LG2: Add Fan speed, Swing, & Light support for new `AKB74955603` model (#1513 #1530)
- Add Mitsubishi AC "fan only" mode (#1527)

**[Misc]**
- Change when some github workflows run (#1583)
- Add/update supported device info (#1580 #1581 #1585)
- Fix pylint issues due to pylint update. (#1569 #1570)
- DAIKIN216: Update supported models. (#1552 #1567)
- IRMQTTServer: Build a minimal OTA image via PlatformIO. (#1513 #1541)
- Reduce memory fragmentation cause by String usage. (#1493 #1536)
- Refactor `decodeMitsubishiAC()` (#1523 #1532)
- Fix incorrect comment.
- Migrate from Travis to GitHub Actions (#1522 #1526)
- Documentation update with additional supported Panasonic AC models (#1525)
crankyoldgit added a commit that referenced this issue Aug 28, 2021
## _v2.7.20 (20210828)_

**[Bug Fixes]**
- Make `strToSwingH()` match "Right Max" (#1550 #1551)

**[Features]**
- Experimental Bose remote support (#1579)
- Added MitsubishiAC VaneLeft (#1572 #1576)
- HAIER_AC176: Add experimental detailed support (#1480 #1571)
- Detailed support for Tornado/Sanyo 88-bit A/C protocol (#1503 #1568)
- Add support for new `TROTEC_3550` A/C protocol (#1563 #1566 #1507)
- SamsungAc: Use `sendExtended()` going forward. (#1484 #1562)
- SamsungAc: Redo/fix checksum calculations. (#1538 #1554)
- LG: Add support for `AKB73757604` model (#1531 #1545)
- Daikin176: Add support for Unit Id. (#1543 #1544)
- Daikin2: Add support for Humidity setting/operation. (#1535 #1540)
- TCL112AC: Add support for quiet/mute setting. (#1528 #1529)
- LG2: Add Fan speed, Swing, & Light support for new `AKB74955603` model (#1513 #1530)
- Add Mitsubishi AC "fan only" mode (#1527)

**[Misc]**
- Change when some github workflows run (#1583)
- Add/update supported device info (#1580 #1581 #1585)
- Fix pylint issues due to pylint update. (#1569 #1570)
- DAIKIN216: Update supported models. (#1552 #1567)
- IRMQTTServer: Build a minimal OTA image via PlatformIO. (#1513 #1541)
- Reduce memory fragmentation cause by String usage. (#1493 #1536)
- Refactor `decodeMitsubishiAC()` (#1523 #1532)
- Fix incorrect comment.
- Migrate from Travis to GitHub Actions (#1522 #1526)
- Documentation update with additional supported Panasonic AC models (#1525)
@crankyoldgit
Copy link
Owner

FYI, the changes mentioned above have been included in the just released v2.7.20 of the library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug more info Pending Confirmation Waiting for confirmation from user
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants