Reverse Engnieering a 'Dumb' AC to work with Home Assistant

May 29, 2026 min read

Like most homes, mine also has a simple split AC. No smart shenanigans whatsoever. And that really bothered me. I wanted a way to make the AC support scenes.

And since this AC is dumb, emulating its remote is the only option.

What followed was a multi-day rollercoaster of signal captures, raw bit-banging, hexadecimal cryptography, and serial conflicts. It is a story of intense learning, frustration, and the ultimate realization that sometimes, the open-source community has already solved your problems.


Phase 1: The Misleading “UNKNOWN” Protocol

The plan seemed simple on paper. Grab an ESP32, an IR receiver module, and an IR LED. Write a quick sketch using the standard IRremoteESP8266 library, look at the serial output, copy the hex codes, and replay them.

I set up my sniffing rig and pointed the physical remote at the receiver. I pressed a button. The serial monitor spit back:

Protocol: UNKNOWN
Bits: 130
Hex Bytes: 0B BB 11 71 00 00 00 00 00 00 00 00 00 00 00 00

My AC is from Fujitsu-General so i was expecting to see something like this:

Protocol: FUJITSU_AC
Bits: 128
Hex Bytes: 14 63 00 10 10 FE 09 30 80 02 00 00 00 00 20 2E

I pressed another button. UNKNOWN. I kept trying until, finally, I pressed the Power On button. Suddenly, the library recognized it! But for every other button, it failed to decode and threw an UNKNOWN error.

Because only the “On” signal worked and the rest did not, I jumped to a logical (but ultimately incorrect) conclusion: My AC must use a proprietary, undocumented code system.


Phase 2: Going Raw & The Line-of-Sight Illusion

Believing the library was useless for my specific remote, I bypassed it. I decided to capture the raw, clean hex codes directly, bypassing the library’s decoding attempts so I could avoid the noise and garbage.

I started small. I captured exactly three signals: ON, OFF, and one temperature change.

When I played these raw signals back to the AC, it worked… sometimes. It was incredibly inconsistent. I assumed that because my IR LED was just sitting flat on my desk, it wasn’t getting a proper line-of-sight to the AC unit, and me holding it in the air close to the AC didn’t fix it either, causing the occasional failures.

Assuming the captures were fine and I just needed better placement later, I spent hours painstakingly capturing all possible button combinations: timer, fan speeds, modes, and every single temperature step. Everything.


Phase 3: Cracking the Hexadecimal Cryptography

Now sitting on a massive pile of raw hex data, I started analyzing the packets to figure out how they were constructed.

By holding constants down and modifying a single variable at a time, the matrix began to reveal itself.

The Byte-by-Byte Mapping

18°C -> 14 63 00 10 10 FE 09 30 20 01 02 00 00 00 20 8D
24°C -> 14 63 00 10 10 FE 09 30 80 01 02 00 00 00 20 2D
30°C -> 14 63 00 10 10 FE 09 30 E0 01 02 00 00 00 20 CD
  • Bytes 0–4: 14 63 00 10 10 — The immutable manufacturer vendor ID.
  • Byte 5: FE — Denotes a long-frame execution packet.
  • Byte 8 (The Temperature Enigma): I observed that \(18^\circ\text{C} = \mathtt{0x20}\), \(24^\circ\text{C} = \mathtt{0x80}\), and \(30^\circ\text{C} = \mathtt{0xE0}\). The mathematical relationship clicked:

$$ \text{Byte 8} = (\text{Temp} - 16) \ll 4 $$

Cracking the Checksum

The final boss of the hex structure was Byte 15: the checksum. Standard checksum calculations weren’t matching. By summing the bytes of verified valid packets, I found the pattern. The remote used a strict Target Sum validation.

The true algorithm was:

$$ \text{Checksum} = (0\text{x}9E - (\sum_{i=0}^{14} \text{Byte}_i \pmod{0\text{x}100})) \pmod{0\text{x}100} $$


Phase 4: The Streamlit Dashboard & The 130-Bit Mystery

Having reverse-engineered the packet construction, I implemented this logic in Python using Streamlit to build a beautiful dashboard. The plan was to generate the hex codes in Python, send them over a serial connection to the ESP32, and have the ESP32 send them to the AC.

Ironically, when I fed my perfectly constructed, clean hex packets back into the IRremoteESP8266 library, it correctly identified the protocol as Fujitsu! This was a massive facepalm moment. It meant the library was completely fine all along, my remote wasn’t proprietary, and the initial UNKNOWN errors were likely just due to environmental noise or receiver issues.

But the hurdles weren’t over. When I tested my new Streamlit setup, the AC stayed completely silent. No response to any button presses.

I hooked up my sniffer to capture what the ESP32 was actually transmitting. The culprit? It was sending 130 bits instead of the required 128 bits. The timing on the ESP32 was drifting, adding garbage bits at the end of the payload.

After tweaking the transmission logic to stabilize the output, I finally got it to send exactly 128 bits consistently. I was now able to control my AC flawlessly using the Streamlit dashboard on my phone and PC!


Phase 5: The Home Assistant Plot Twist

Since the system was finally working, my grand plan was to move it into Home Assistant. I had heard it was possible to make ESP32s communicate with HA, so I dove in.

To my surprise, the Home Assistant ecosystem was totally different from what I expected. I discovered a tool called ESPHome. I installed it, flashed it to my ESP32, and realized that configuring it was just a matter of writing simple YAML files instead of C.

And then came the ultimate plot twist.

While looking through the ESPHome documentation, I found that some incredible developer had already created a native fujitsu_ac climate component. I added it to my YAML file, flashed the board, and… it worked on the first try.

Final Thoughts

All those hours of manual capturing, writing embedded C code, cracking checksums, and building the Streamlit dashboard? Technically, it was a complete waste of time. I could have just flashed ESPHome and been done in 10 minutes.

But in the end, I don’t regret it. I consider it an amazing learning opportunity. I dove deep into hardware signals, bitwise operations, serial communication, and reverse engineering.