I have a Mitsubishi ducted air conditioning unit installed in my ceiling. No remote access, no scheduling, no way to tell it to start cooling before I get home. Mitsubishi offers MELCloud — their cloud service — but it requires a proprietary WiFi adapter that costs around €100, depends on their servers staying online, and gives you only what they decide to expose. I wanted something different.
I didn't want a full home automation system. No Home Assistant, no Zigbee coordinator, no always-on server. Just the AC, an ESP8266, and enough control to manage it properly from my phone — locally and remotely.
Mitsubishi indoor units have a small 5-pin JST connector on the control board called CN105. It carries 5V, GND, and a serial UART running at 2400 baud with even parity. The protocol is proprietary and undocumented by Mitsubishi, but the community reverse-engineered it years ago. SwiCago's HeatPump Arduino library implements it cleanly and has become the standard starting point for DIY projects of this type.
The hardware is straightforward: a NodeMCU ESP-12E/F, a bidirectional level shifter (the AC side runs at 5V, the ESP at 3.3V), and a meter or so of UTP cable to reach from the unit's control board to wherever you mount the ESP. The NodeMCU is powered by its own USB supply — not from the AC — to avoid ground loops.
One detail worth noting: the TX and RX lines cross intentionally. The AC's TX connects to the ESP's RX and vice versa. It's correct, not a mistake.
UTP cable is used specifically because each signal travels twisted with its own dedicated return ground wire — this reduces electromagnetic noise on a low-speed serial line running a meter through or near equipment that generates significant interference.
The hardware is straightforward: a NodeMCU ESP-12E/F, a bidirectional level shifter (the AC side runs at 5V, the ESP at 3.3V), and a meter or so of UTP cable to reach from the unit's control board to wherever you mount the ESP. The NodeMCU is powered by its own USB supply — not from the AC — to avoid ground loops.
One detail worth noting: the TX and RX lines cross intentionally. The AC's TX connects to the ESP's RX and vice versa. It's correct, not a mistake.
UTP cable is used specifically because each signal travels twisted with its own dedicated return ground wire — this reduces electromagnetic noise on a low-speed serial line running a meter through or near equipment that generates significant interference.
The CN105 connector itself deserves a special mention. It's a 5-pin JST PA 2.0mm — (it houses a PAP-05V-S), not the easiest component to find. In my case, the PAP-05V-S I bought required a small mechanical adjustment to fit correctly. If you replicate this, set aside some time for that part. Everything else — NodeMCU, shifter, UTP cable — is generic and cheap, and probably already sitting in a components drawer from other projects. The total hardware cost is around €10–15 as a rough guide, though it can be less if you repurpose parts from electronic scrap.
There are solid projects built on SwiCago's library — ESPHome components, Home Assistant integrations, Tasmota forks... If you already have a home automation platform running, that's the right answer. But I don't, and setting one up just to control an air conditioner felt like buying a van to carry a backpack.
What I needed was simpler: a standalone device with a web interface accessible from any browser on the local network, MQTT for remote access and logging, and scheduling that works autonomously even if the phone or server is off.
The ESP8266 runs custom firmware, built using SwiCago's library among others, that serves the compressed web interface directly from PROGMEM — no SD card, no filesystem access for the HTML. This was a deliberate decision after finding that serving pages from LittleFS significantly fragmented the ESP8266's heap within its limited 80KB of RAM. Moving everything to PROGMEM brought the free heap from around 9KB to a stable 22KB.
The web interface covers everything: power, mode, target temperature, fan speed, and a timer manager. The physical wall remote continues to work normally — the ESP coexists with it without interference. MQTT handles the same controls remotely, and also publishes state — ambient temperature, compressor frequency, operating status — with retain flags so the broker always has the current or last known state. OTA firmware updates are also available directly from the interface.
One design detail that required some thought: the ESP8266's serial port is synchronous and blocking. The HeatPump library's sync cycle cannot coexist with the web server and MQTT loop in a naïve main loop. The solution was a `loopCallback` — HTTP and MQTT processing happens inside the library's sync cycle rather than in parallel, eliminating re-entrancy issues without needing threads or interrupts.
The most interesting part of the firmware is the custom scheduler. Three types of profiles:
Type A — time-based, runs automatically at configured hours on selected weekdays
Type B — immediate timer with duration, starts now and runs for N minutes
Type C — poweroff countdown, triggered manually
All three support independent ramp sequences for both temperature and fan speed. Temperature is defined as a sequence of accumulated deltas relative to the initial value — for example +1, +1, +2 raises the setpoint by 1°C, then another degree, then two more, with a configurable interval between each step. Fan speed is defined as an independent sequence of absolute values — AUTO, 1, 2, 3 — separate from the temperature sequence.
The timers run autonomously and reliably without any phone interaction, even across ESP restarts — Type A profiles resume automatically if the device reboots within their scheduled window.
In addition to the web interface, the firmware exposes a complete HTTP JSON API that allows integration with any tool or script. Through it you can query the full device and AC status, send control commands, manage timer profiles — create, edit, delete and start them — export the configuration, and access system performance metrics.
For remote access, MQTT is the right protocol — lightweight, works through NAT without port forwarding, and has a good ecosystem of free brokers. Options for a single hobbyist device include HiveMQ Cloud, EMQX Cloud, Adafruit IO, CloudMQTT and others — all offer free tiers with TLS support sufficient for this use case.
From outside the home, the same MQTT connection the ESP uses for publishing is also how commands arrive — no VPN, no dynamic DNS, no port forwarding required.
The status topic publishes room temperature and compressor frequency with a configurable minimum interval to avoid flooding the broker during the inverter compressor's normal hunting behavior. Without rate limiting, the continuously varying compressor frequency on an inverter unit would generate a new message every few seconds.
The topic paths are configurable on the configuration page.
One of the most useful day-to-day integrations is an iOS Shortcut that manages the AC directly from the iPhone Control Center.
The shortcut automatically detects which WiFi network the phone is connected to: if it matches the home network, it uses the web API directly — faster, with no broker latency; if away from home, it uses MQTT. In both cases the experience is identical for the user.
The menu header shows the current AC state in real time — power, mode, setpoint temperature, ambient temperature, compressor status and frequency — before touching any button. From there you can change power state, mode, temperature and fan speed, or open the web interface directly for full access. The menu itself shows the modified settings just above the option to send them to the AC.
All configuration — WiFi, MQTT, NTP, topics and behavior parameters — is managed from a web page embedded in the device itself. No configuration files to edit manually, no reflashing required to change parameters.
On first boot, or when the device cannot connect to any known WiFi network, the ESP8266 automatically enters captive portal mode.
It generates an open WiFi network called MITSUBISHI-AC-CONFIG and redirects any HTTP request to a configuration page where the SSID, password, and device hostname are entered.
If it fails to connect to the configured network within 20 seconds, it reopens the portal.
If the portal remains inactive for 5 minutes, the ESP reboots and retries the connection — useful when the device is configured first and the router second, as the ESP will keep retrying until it finds the new network. All MQTT configuration and timer profiles are preserved intact throughout this process.
To force the captive portal manually — for example to switch networks — press the FLASH button on the NodeMCU during boot, which clears the saved WiFi credentials.
Diagram 3: Captive portal WiFi flow
Firmware updates are performed without a cable or physical access to the device. From the main panel, OTA mode is triggered, rebooting the ESP into a minimal state — WiFi only, no CN105 or MQTT — to maximise available memory during the upload. Once in that mode, the web interface allows selecting the compiled .bin file and uploading it directly from the browser.
If the update does not fit in the sketch's free space — visible on the metrics page — the process is cancelled before anything is overwritten. If the device becomes unresponsive during a failed update, a power cycle clears the OTA flag from RTC memory and the ESP boots normally with the previous firmware intact.
Diagram 4: OTA mode flow
The system has been running since it was built — about two months — without any notable issues. The only reboots have been those needed during development and firmware updates. The longest uptime recorded to date is 20 days, as I am still applying improvements to the project. Free heap is stable at around 22KB and fragmentation below 3%. On an ESP8266 with 80KB of total RAM and all the functionality being asked of it, these numbers are the result of very deliberate design decisions, not luck.
The total hardware cost is around €10–15 as a rough guide, though it can be less if parts are reused from electronic scrap left over from other projects. The trickiest part to get right is the CN105 connector — not because it is hard to find, but because it does not appear to be fully standard and there are many similar-looking connectors, not always with detailed specifications.
For anyone with a Mitsubishi unit who has no interest in setting up a full home automation platform, this is a reasonable middle ground between the original wall remote and a home automation system. No cloud subscription, no proprietary adapter, no dependency on Mitsubishi's servers.
The project is in a very advanced state but the source code is not available at this time. I want to ensure long-term stability and polish a few details before making that decision. Depending on the feedback received and time available, I will consider releasing it in the future.