Inconsistent Broadlink codes - Mitsubishi Heavy Industries

This topic seems to pop up every now and then, but I can’t really get to the bottom of it.
I have a Mitsubishi Heavy Industries AC (SRK 20 CSS-S6). The codes for this model aren’t available in any of the IR databases I can find; so looking elsewhere is not an option.
The problem with learning the codes in HA is that there are 11(h. fan direction) x 7(v. fan direction) x 13(temp) x 4(mode) x 4(fan speed) = 16016 unique remote states (not including the timer, and other stuff i don’t use). The best solution would be to generate the codes on the fly. In order to do that, I need to reverse engineer the code format.
I used the learn command in HA to capture a few commands, and transform them to raw data using irgen. However, the raw pulse timing generated is completely different for different captures of the same remote state. What’s more is that if I use IrScrutinizer to render the codes, I get results that make no sense. 18 degC-Cool-High looks nothing at all like 19 degC-Cool-Hi given every other setting is the same.
There’s a project on Github where MHI codes for a different AC are reverse engineered, but my codes look nothing like that.
Is there something I’m missing? Or am I approaching this problem from a completely wrong direction? Any help would be appreciated.
I’d be happy to provide any other necessary details.

My advice is to try and switch only one setting and record the IR codes.
Then convert the hex to binary, it’s probably something really simple in binary.
There would be no reason to for them to make it complex.

have you try smartir codes? Its for SRK25ZSX worth a try. Or browse through other model.

I did this. Stopped with the hex conversion tho, since there were way too many (small) variations. Broadlink gives me a 186 byte hex code.

For ex:

2600 b600 6635 0e0c 0e27 0e0c 0e0c 0e26 0e0d 0e26 0e0c 0e0c 0e27 0e26 0e26 0e0c 0e27 0e0c 0e26 0e27 0e26 0e0c 0e0c 0e0c 0e0d 0d27 0e26 0e0c 0e27 0e26 0e0c 0e0c 0e27 0e0c 0e0c 0e26 0e0c 0e0d 0e26 0e26 0e0c 0e27 0e26 0e26 0e27 0e0c 0e26 0e27 0e26 0e0c 0e26 0e0d 0e0c 0e26 0e0c 0e0c 0e0d 0d27 0e0c 0e26 0e27 0e26 0e26 0e0c 0e27 0e26 0e0c 0e0c 0e0d 0e0c 0e0c 0e26 0e0c 0e0d 0e26 0e0c 0e26 0e27 0e0c 0e0c 0e26 0e27 0e26 0e26 0e0d 0e0c 0e26 0e26 0e0d 0d0d 0e0c 0e00 0d05 0000

2600 b600 6635 0e0c 0e27 0e0c 0e0c 0e26 0e0d 0e26 0e0c 0e0c 0e27 0e26 0e26 0e0c 0e27 0e0c 0e26 0e27 0e26 0e0c 0e0c 0e0c 0e0d 0d27 0e26 0e0c 0e27 0e26 0e0c 0e0c 0e27 0e0c 0e0c 0e26 0e0c 0e0d 0e26 0e26 1605 0d27 0e26 0e26 0e27 0e0c 0e26 0e27 0e26 0e0c 0e27 0e0c 0e0c 0e26 0e0c 0e0d 0d0d 0e26 0e0c 0e26 0e27 0e26 0e26 0e0d 0e26 0e26 0e0c 0e0d 0d0d 0e0c 0e0c 0e26 0e0d 0e0c 0e26 0e0c 0e27 0e26 0e0c 0e26 0f0c 0d27 0e26 0e27 0e0c 0e0c 0d27 0e0c 0e27 0e0c 0e0c 0e00 0d05 0000

As you can see, there are multiple differences and a lot of bits are off by just 1. Should I just ignore those small variations?

I looked through smartir, but didn’t give it much thought since my model wasn’t listed. I’ll try it out to see if it works.
Although, it would be good to be able to control swing position too, and that is currently not in the smartir database.

Making it binary using this tool (remove spaces first):
Hex to Binary Converter (

Then comparing the string position by position shows there are areas that is different.
Online PHP editor | output for ggGtN (

I wouldn’t be surprised if it’s the same position that is changing between all temperatures.

That’s a nice tool! I’ll check with other temperatures and let you know how it goes.

Not really a tool.
It’s just a little thing I wrote to get the differences.

Ok… So I’m using smartir for now, but it’s not really ideal. Changing the temperature also changes the swing position. Not unusable, but not perfect.
In the meantime, I’m still working on the codes. I took inspiration from you and wrote a python script to compare the codes in the hex stage (since converting them to binary gives me too many - almost 1500 - variables). I just can’t see any pattern in it tho. I can’t upload csv, so I’m putting up a jpg of a csv here.
I’m gonna go insane at this rate.

I guess it wasn’t easy after all.
I’m surprised there is that much difference.

Had I designed the format then it would probably be something like [temp] [fan setting] [cooling/heating] or something.

Funnily enough, I just figured it out and was about to post here when I got your reply.
So, the idea is that the broadlink code is just the ir pulse timing directly encoded in hex. After delving deeper, I figured out that 0x0E0C or any similar codes equals to a logical 1, and 0x0000 and all anamolies equal to a logical 0. Not including the broadlink header and end codes, we have 88 encoded byte pairs which translate to 44 logical bits which in turn translate to a 11 byte code.
Bytepairs in NEC codes are supposed add up to 0xFF, so I assume the first 3 bytes are some sort of header. Now its pretty clear that the last 2 bytes are what control the temperature.

That was pretty exhausting. Now I need to write a script to generate broadlink codes from this on-the-go.

So this is interesting and I followed a link from another thread. I’m just curious… does 26 work for you?

I started to analyze the last 2 bytes to see if there was a pattern and I found one. But 26 does not fit the pattern. In binary, the last 4 bytes are:

temp ab cd
18 98 67
19 94 6b
20 9c 63
21 92 6d
22 9a 65
23 96 69
24 9e 61
25 91 6e
26 90 66
27 95 6a
28 9d 62
29 93 6c
30 9b 64
temp a b c d
18 1001 1000 0110 0111
19 1001 0100 0110 1011
20 1001 1100 0110 0011
21 1001 0010 0110 1101
22 1001 1010 0110 0101
23 1001 0110 0110 1001
24 1001 1110 0110 0001
25 1001 0001 0110 1110
26 1001 0000 0110 0110
27 1001 0101 0110 1010
28 1001 1101 0110 0010
29 1001 0011 0110 1100
30 1001 1011 0110 0100

Using the tables above, it seems byte a is the binary opposite of byte c, and byte b is the binary opposite of byte d.

I.e. when a is 1001, c is 0110.

The only set that doesn’t match that is temperature for 26. I would expect the bd pair to be 1001 0110 as it matches the pattern in the sequence.

I really wish we had what zero is. I would assume it would have a bd pair of 1111 0000.

At any rate, I see another pattern in the binary data. If we invert (read it backwards) the b and d, b counts up and d counts down. (aside from that blip in 26).

temp b b (int) b (bkwds) b (int-bkwds) d d(int) d (bkwds) d (int-bkwds)
18 1000 8 0001 1 0111 7 1110 14
19 0100 4 0010 2 1011 11 1101 13
20 1100 12 0011 3 0011 3 1100 12
21 0010 2 0100 4 1101 13 1011 11
22 1010 10 0101 5 0101 5 1010 10
23 0110 6 0110 6 1001 9 1001 9
24 1110 14 0111 7 0001 1 1000 8
25 0001 1 1000 8 1110 14 0111 7
26 0000 0 0000 0 0110 6 0110 6
27 0101 5 1010 10 1010 10 0101 5
28 1101 13 1011 11 0010 2 0100 4
29 0011 3 1100 12 1100 12 0011 3
30 1011 11 1101 13 0100 4 0010 2

Assuming your lowest temperature is 17 @ 0000, your highest setting would be 32 @ 1111. Are these temperatures in c?

Anyways, with what we know, it seems a and c are always 9 and 6. and if we calculate b, based on an input number… we can come up with an template that calculates it for you.

{% set temperature = 18 %}
{% set start = 17 %}
{% set i = temperature - start %}
{%- set j = 15 - i %}
{%- set b = '{0:04b}'.format(i)[::-1] %}
{%- set d = '{0:04b}'.format(j)[::-1] %}
{%- set ab = '1001{0}'.format(b) %}
{%- set cd = '0110{0}'.format(d) %}
{{ '{0:x} {1:x}'.format(int(ab, base=2), int(cd, base=2)) }}