Enigma: Air conditioner protocol reverse engineering

In my previous post I created new version of IR transmitter for air conditioner but didn’t explain the process of reverse engineering chinese IR remote for air conditioner.

First of all I captured a lot of IR commands from remote control using Raspberry PI and LIRC library, then using Excel sheet found patterns.

So, the transmission itself using 38 KHz frequency with next lengths (pulse/space):

  • header 9000/4500
  • logical ONE 700/1600
  • logical ZERO 700/500
  • ptrail 700
  • gap 19900
  • repeat gap 39900

During transmission IR remote sends two 67 bit commands divided by repeat gap. I determined that second part is not mandatory and looks like contains timers settings which is not useful for home automation project.

The 67 bit command consists from two 32 bit command divided by three bits of post_data (0x2), so my resulted pattern is “header|command1|post_data|ptrail|gap|command2|ptrail”

Based on captured results from original IR remote control I determined that each byte (8 bit) should be reversed first to correct reading (big endian system).  Below the enigma of protocol:

COMMAND1

BYTE 1

  • BIT 7: sleep flag (0 for me)
  • BIT 6: move shutters (for some modes should be enabled )
  • BIT 5&4: fan speed (00 AUTO; 01 LOW; 10 MED; 11 HIGH)
  • BIT 3: ON/OFF (1 ON; 0 OFF)
  • BIT 2: heat mode enabled
  • BIT 1&0:  mode (00 heat/antifreeze/auto; 01 cold; 10 dry; 11 fan)

BYTE 2

  • BIT 7&6&5&4: timer setting (0000)
  • BIT 3&2&1&0: temperature – lowest value is 16 (0000), highest is 30 (1111)

BYTE 3

  • BIT 7: always 0 for me
  • BIT 6: cold plasma (1 ON; 0 OFF)
  • BIT 5: LCD screens which shows temperature (1 ON; 0 OFF)
  • BIT 4: turbo fan mode (0 for me)
  • BIT 3&2&1&0: timer setting (0000)

BYTE 4

  • BIT 7&6&5&4: message number (0101 for first command always)
  • BIT 3&2&1: unrecognized due always 0 (000)
  • BIT 0: external ventilation (0 for me)

COMMAND2

BYTE 1

  • BIT 7&6&5&4: horizontal shutters position (0000 OFF; 0001 FULL; 0010 LEFT; 0011 LEFT CENTER; 0100 CENTER; 0101 RIGHT CENTER; 0110 RIGHT; 1100 LEFT RIGHT; 1101 LEFT TO RIGHT )
  • BIT 3&2&1&0: vertical shutters position (0000 OFF; 0001 FULL; 0010 UP; 0011 MID UP; 0100 MID; 0101 MID DOWN; 0110 DONW; 0111 DOWN TO MID; 1001 MID DOWN TO MID UP; 1011 MID TO UP)

BYTE 2

  • BIT 7&6&5&4: message number (0100 for first command always)
  • BIT 3: always 0 for me
  • BIT 2: iFeel mode (0)
  • BIT 1&0: 00 (ability to show on LCD display the temperature – 01 wish temperature; 10 room temperature; 11 outside temperature)

BYTE 3

All bits are 0

BYTE 4

BIT 7&6&5&4: checksum (hardest part, will be described below)

BIT 3: always 0 for me

BIT 2: antifreeze mode, +8C (1 ON; 0 OFF)

BIT 1&0: always 0 for me

The hardest part were to unravel CheckSum algorithm. Many different captures of IR messages helped me determine that only specific parts (half-bytes converted to integer) of the whole command are affecting CheckSum, below is the formula that summarizes and explains calculation:

HALF BYTES FROM COMMAND1

INT(BYTE1(3;2;1;0)) + INT(BYTE2(3;2;1;0)) + INT(BYTE4(7;6;5;4)) + INT(BYTE4(3;2;1;0)) +

HALF BYTES FROM COMMAND2

INT(BYTE1(7;6;5;4)) + INT(BYTE2(7;6;5;4)) + 5

From that integer value you need to keep only one half byte of the result and ignore overflow.

The full code of implementation described above for ESP controller and Openhab project available on GitHub:

Leave a Reply

Your email address will not be published. Required fields are marked *