Control a Dumb AC Unit with ESP32 and ESPHome
🤖 Researched and drafted automatically from the official docs, and reviewed before publishing. Commands are taken from the source projects — but always sanity-check before running anything on your own hardware.
Most window AC units have no network smarts—just an infrared remote or basic wall switch. You can add control by wiring an ESP32 microcontroller to the AC’s remote board, then expose it to Home Assistant or a simple HTTP API on your LAN. This guide shows you how to decode the AC remote, wire the ESP32, and configure ESPHome to toggle power and set temperature.
What You Need
- ESP32 dev board (~$8–12)
- Window AC unit with a removable remote or accessible control board
- Soldering iron, solder, and small wire
- Multimeter (to trace the remote circuit)
- USB cable to flash the ESP32
- Home Assistant instance or a way to send HTTP requests (optional; you can also toggle relays manually)
Step 1: Identify the AC Remote Signal Type
Most AC remotes use one of two methods:
- Infrared (IR): The remote sends IR pulses. You can capture these with an IR receiver on the ESP32.
- Direct relay contacts: Older units or wall-mounted controls have physical relay switches that close to trigger modes.
Open your AC unit’s remote or control panel. If you see an IR LED on the remote, you’ll need an IR receiver module (TSOP4838 or similar, ~$2). If you see a simple circuit board with switches, you can wire the ESP32 directly to those contact points.
Step 2: Set Up Your ESP32 with ESPHome
On a machine with Python 3.7+ and pip installed, install ESPHome:
pip install esphome
Create a new ESPHome device configuration:
esphome wizard my-ac-controller
Answer the prompts to set a device name, Wi-Fi SSID/password, and OTA password. ESPHome will create a YAML config file at my-ac-controller.yaml.
Step 3: Configure GPIO Pins for IR Reception or Relay Control
Edit your my-ac-controller.yaml. For infrared reception, add this section:
remote_receiver:
pin:
number: GPIO14
inverted: true
mode:
input: true
pullup: true
tolerance: 55%
filter: 25us
idle: 2ms
Replace GPIO14 with the pin you’re using. Connect your IR receiver module’s data line to that GPIO pin, power to 3.3V, and ground to GND.
For direct relay control (if your AC has physical switch contacts), add this:
switch:
- platform: gpio
pin: GPIO12
name: "AC Power"
id: ac_power
- platform: gpio
pin: GPIO13
name: "AC Mode"
id: ac_mode
Solder wires from GPIO12 and GPIO13 to the AC’s remote contact points. Test with a multimeter first to confirm which pins trigger which action.
Step 4: Capture IR Codes (If Using IR)
Flash the ESP32 with your config:
esphome run my-ac-controller.yaml
ESPHome will compile and upload the firmware. Once running, open the web dashboard (shown in the terminal output, usually http://192.168.x.x:3232) and check the logs.
Point your AC remote at the ESP32’s IR receiver and press buttons. You’ll see raw IR codes in the logs. Copy these codes—they look like data: [9024, -4512, 564, -564, ...].
Step 5: Create IR Transmitter Actions (If Using IR)
Add an IR transmitter to send those codes back to the AC:
remote_transmitter:
pin: GPIO15
carrier_duty_percent: 50%
switch:
- platform: template
name: "AC Power"
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
data: [9024, -4512, 564, -564, 564, -564, 564, -1692]
turn_off_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
data: [9024, -4512, 564, -564, 564, -564, 564, -1692]
Paste the actual IR codes you captured. Connect GPIO15 to an IR LED (with a current-limiting resistor, typically 220Ω).
Step 6: Add Temperature or Mode Selectors (Optional)
If your AC remote has temperature buttons, you can create a climate entity:
climate:
- platform: ir_climate
name: "Window AC"
receiver_id: remote_receiver
transmitter_id: remote_transmitter
supports_heat: false
supports_cool: true
supports_fan_only: true
supports_dry: true
min_temperature: 16
max_temperature: 30
temperature_step: 1
You’ll need to map each temperature level to its corresponding IR code.
Step 7: Expose via Home Assistant or HTTP
If you run Home Assistant, ESPHome devices auto-discover. Just add the device in Settings → Devices & Services, and all switches/climate entities appear as automatable entities.
For standalone HTTP control, ESPHome exposes a REST API. Once your device is on the network, you can toggle a switch with:
curl -X POST http://192.168.x.x/switch/ac_power/turn_on
curl -X POST http://192.168.x.x/switch/ac_power/turn_off
Replace the IP with your ESP32’s address (shown in ESPHome logs or your router’s DHCP table).
Step 8: Secure Your Network
ESPHome runs an unencrypted HTTP API by default. Keep it on your LAN only—never expose the device to the public internet. If you must access it remotely, use a VPN back into your home network or set up a reverse proxy with proper authentication.
Optionally, enable OTA password in your config (set during wizard) to prevent unauthorized firmware updates.
Wiring Checklist
- ESP32 GND → AC remote/receiver GND
- ESP32 3.3V → IR receiver power (if using IR)
- ESP32 GPIO14 (or your chosen pin) → IR receiver data line
- ESP32 GPIO15 (or your chosen pin) → IR LED anode (through 220Ω resistor); IR LED cathode to GND
- USB power → ESP32 micro-USB for programming and runtime power
For direct relay control, solder to the AC’s remote board switch contacts instead, being careful not to short 12V or 24V supplies.
Is It Worth It?
Yes, if you already have an ESP32 and soldering skills. The hardware cost is trivial; the real value is that you own the control logic—no cloud service, no subscription. Your AC stays on your network. The setup takes an afternoon of reverse-engineering IR codes or tracing relay circuits, but once running, it’s rock-solid. Pair it with Home Assistant and you’ve got scene-based automation: “Good Night” turns off the AC, “Summer” sets it to cool at 72°F. That’s worth $35.
Related video
New self-hosted AI & homelab shorts, daily.
Subscribe on YouTubeRelated guides
Self-host Kubernetes: escape the cloud tax
Run Kubernetes on your own hardware to replace managed cloud services. Deploy and scale containerized apps without paying AWS, Azure, or GCP monthly bills.
Run rust-analyzer on your homelab for 100x less RAM
Deploy a self-hosted Rust LSP server on cheap hardware. Get IDE features—completion, refactoring, diagnostics—without melting your machine. Keep it on your LAN.
Run Claude Code and Codex Locally with OtoDock
Deploy OtoDock on your server to get local code generation without cloud API costs. Self-hosted alternative to Claude Code and GitHub Copilot.