Fork of dslatford/electriq_ac with sleep mode and Smart Cool (reported as the "Auto" climate mode) added.
This external component for ESPhome replaces the Tuya firmware within the ESP8266 wifi module found inside Electriq branded air conditioning units for integration into Home Assistant. Developed on the 12000 Smart model, others may also be supported.
This is a fork of dslatford/electriq_ac. The original already supports the cool, dry, fan-only and heat modes, custom fan speeds, vertical swing, target temperature, room-temperature readout and the heat-mode fan overrun automation. This fork adds the two operating features the original left unimplemented:
- Sleep mode — exposed in Home Assistant as the Sleep preset. Sleep is a flag in protocol byte 4 (
b[2], bit0x40), sent alongside the swing bits and read back from the MCU so the preset always reflects the unit's actual state. - Smart Cool — exposed as the Auto climate mode. (ESPHome's climate modes are a fixed enum and can't be renamed, so the unit's "Smart Cool" maps to
AUTOand appears as "Auto" in Home Assistant.) The MCU reports this mode as nibble0x00(b[1] = 0x90); selecting Auto sends the same.
Two smaller improvements come along with it: the mode decoder now logs an explicit warning for any unrecognised mode nibble instead of silently falling back to Cool — which is how Smart Cool's 0x00 value was identified from the device logs — and the example overrun automation is corrected to use this component's custom fan modes ("Max"/"Low") instead of the standard HIGH/LOW that no longer exist here.
The Electriq 12000 BTU WiFi Smart AC with Heat Pump is a portable AC unit sold by (and a brand name of?) https://www.appliancesdirect.co.uk
It includes a Tuya-manufactured ESP8266-based WiFi module that communicates via a serial protocol with unit's MCU. 'Smart' control is via the Tuya Smart app, via a Chinese companies cloud infrastructure. No thank-you!
While Tuya have a well-documented protocol for incorporating their technology into third party products, supported by ESPhome and Tasmota (Tuya MCU), this AC unit doesn't utilise that protocol. While there are similarities, this protocol uses fixed-length messages without variable data fields, and a single byte header. Only the baud rate and checksum byte, and concept of heartbeat messages match the published protocol. Fortunately, this protocol was simple to reverse engineer.
Perhaps this is an older firmware, or a proprietary / lightweight protocol running alongside the documented one? I have two units both purchased during 2021. For the curious, the firmware's boot messages include the output:
[N]user_main.c:313 SDK version:2.1.1(317e50f)
[N]user_main.c:317 fireware info name:esp_gushang_aircon version:1.0.7
[N]user_main.c:319 tuya sdk compiled at May 20 2020 14:40:05
The protocol was examined using Sigrok/Pulseview and a cheap logic analyser.
9600 baud 8/N/1 5v UART. Logic level shifter employed on Tuya module. Be careful if experimenting with other modules not 5v tolerant.
Each byte position has a fixed purpose (unlike the published Tuya MCU protocol with varying data lengths).
ESP > MCU heartbeat / command message
12 byte word
Two message types are sent. A heartbeat message is issued approx every 2 seconds (1800ms). Only the header, version and checksum bytes are non-zero. This prompts the MCU to return its status.
The other message type commands the MCU into changing its operating mode, fan speed, set temperature, swing, Celsius or Fahrenheit display and sleep mode.
Byte 1 = Header, fixed 0xAA in both directions
Byte 2 = Version(?) 0x02 for heartbeat, or 0x03 for command messages
Byte 3 = Fan speed and mode. MSB represents fan speed and LSB the mode. Fan speed of 0x1n represents standby (off)
Byte 4 = Swing, Celsius or Fahrenheit and Sleep mode
Byte 5 = Target temperature
Byte 6-8 = Unknown, 0x00
Byte 9 = Unknown, 0x0B
Byte 11 = Unknown, 0x00
Byte 12 = Checksum (reminder of sum of all bytes / 256)
MCU > ESP status report
17 byte word
As above, with these differences:
Byte 2 = Version(?) 0x00
Byte 9 = Temperature probe 1 (used as room temperature)
Byte 10 = Temperature probe 2 (unused in Tuya app)
Byte 11-12 = Unknown, 0x00
Byte 13 = Action (Idle or active)
Byte 14-16 = Unknown, 0x00
Byte 17 = Checksum (reminder of sum of all bytes / 256)
With ESPHome installed, create a new device of type ESP8266. Add the following to your device YAML configuration:
external_components:
- source: github://VideoScape/electriq_ac
components: [ electriq_ac ]
uart:
tx_pin: GPIO15
rx_pin: GPIO13
baud_rate: 9600
climate:
- platform: electriq_ac
name: "Electriq AC"See example.yaml for a complete configuration example, using secrets and substitutions (my preference).
ESPHome will automatically download and compile the component from this repository. The first installation must be done via serial as below, but subsequent updates can be done OTA.
This is where you need to break out the soldering iron :)
Initial flashing is done with the module OUT of and DISCONNECTED FROM the air conditioning unit.
Installed in my units are Tuya wifi modules model TYJW2S-5V-BL. Tuya has good documentation on these. The programming pins are down the side, mine were unpopulated so I soldered a strip of pin headers for dupont cables. Connect TX, RX, GND 3.3v to a USB>TTL Serial converter (I use a cheap FTDI clone), ensuring it's set to 3.3v! While the MCU communications are 5v logic levels, applying 5v directly to the ESP chip will probably destroy it. Before plugging in the USB thus powering on the module, keep the reset button pressed. Plug in and release the button to put the ESP chip into bootloader mode.
Here is where you will want to learn from my mistake and BACK UP YOUR ORIGINAL FIRMWARE! I didn't, then I discovered this doesn't talk the published Tuya protocol, and that's pretty much why I now have two AC units... ;)
You can backup the firmware using esptool.py Ensure you download the version there, and don't rely on a version supplied by Ubuntu etc. I found that was lacking the 'stub' code required to read the flash memory. The command I used to backup the original flash is:
esptool.py -b 9600 read_flash 0 0x200000 tuya2M.bin
For some reason (probably that clone FTDI) I had to use 9600 baud else I got errors, but somehow writing at 115200 is just fine.
You may now flash the downloaded ESPhome firmware with your ESP tool-of-choice (mine is Tasmotizer). Reinstall the module.
Should you wish to restore the original Tuya firmware, you can, using:
esptool.py write_flash 0 tuya2M.bin
You can use the verify_flash option to ensure its correctly written back. However note that there's a unique ID embedded in this flash image. If you flash back to second device and pair that up, it will replace any existing pairing you had using the same flash image. Also be aware that flash image will contain your wifi password in clear text, if you had already paired it up.
Once powered up, the device should register on your network and appear online within ESPhome's dashboard. You should be prompted to create a new device in home assistant, and create a default lovelace card. From here everything should work as you might expect. You can control the operating mode, fan speed, set temperature and swing mode from Home Assistant. Sleep mode is exposed as a preset, and Smart Cool as an operating mode (it appears as "Auto" in Home Assistant, since ESPHome's climate modes are a fixed enum and can't be renamed). C/F switching is still unimplemented. You should see the temperature readout (in Celsius), and the UI will report when the unit is 'off' vs when it is 'idle'. That is, turned on in heating or cooling modes but fan off (idle) while at set temperature.
These AC units have, in my opinion, a design flaw in that when reaching set point in heating mode, both compressor and fan shut down together. The latent heat in the evaporator has nowhere to go, so the measured temperature (which we assume to mean room temperature!) rises many degrees. This has the negative effect of preventing further heating for an excessive period, without turning the set point right up. The MCU should overrun the fan after turning off the compressor to remove this latent heat.
Fortunately that now happens! I've implemented this in a standard ESPhome automation, configured in the example YAML file. It's optional, and you may omit this by simply not using the configuration below the overrun comment.
Figuring out this logic revealed the MCU can't be trusted to report what you expect when you would expect it (leading to race conditions and faulty logic, for example the MCU might report state HEATING for a few moments when it's already IDLE). Ultimately this lead to improvements within the main code to detect mode and current state (idle/heating etc) among other tweaks.
For external component compatibility, this repository is structured as follows:
electriq_ac/
├── README.md
├── components/
│ └── electriq_ac/
│ ├── __init__.py # Component registration
│ ├── climate.py # Climate platform configuration
│ ├── electriq_ac.h # Component header
│ └── electriq_ac.cpp # Component implementation
└── example.yaml # Example configuration
This is 2026, and I have very limited coding abilities (I wrote all this code originally, but have no idea how, a rare manic creative phase?) so Claude was used to assist converting this from an original "custom component" for which support was dropped by ESPHome, into a modern "external component". I wouldn't have managed this myself.
Bugs will exist. There's the possibility that due to who-knows-what, a command from Home Assistant might not make it to the module. I'm unsure why this (only very rarely) happens (and might even be fixed!), but rather than checking for individual mode / fan / swing / temperature changes, perhaps the code could poll Home Assistant for all the states, and apply them where the expected state differs from the states reported by the MCU? Probably more work for Claude.