Drive an Airton air-conditioner (most likely a TCL clone) from MQTT / Home Assistant, using an ESP32 running Tasmota wired to the A/C unit's internal serial bus, plus these Berry scripts.
The ESP talks the unit's serial protocol directly (no IR), exposes the A/C to Home Assistant over MQTT, and can either let the A/C regulate on its own sensor or run its own hysteresis thermostat on an external room-temperature source — independently per heating and cooling mode.
Original discussion: arendst/Tasmota#17328 (protocol work with pingus / pingus.org).
First published project — the code is pragmatic rather than elegant, but it has been running daily for a long time. Comments and contributions welcome.
- Mode (auto / cool / dry / fan_only / heat / off), fan speed, louvre swing, temperature setpoint.
- Per-mode regulation (heat and cool configured independently): let the A/C regulate on its own sensor (with an offset), or have the ESP regulate with a hysteresis thermostat on a room temperature read from MQTT or polled over HTTP.
- Home Assistant MQTT auto-discovery — the climate entity appears by itself, no YAML to write.
- Clean HA feedback: HA always sees the user's setpoint (never the internal offset, never the 17/31 °C hysteresis extremes); the current temperature reported to HA is selectable.
- IR-remote / external-change sync: when someone uses the IR remote, the ESP reconciles its state from the A/C feedback frames instead of overwriting the change.
- A periodic Wi-Fi heartbeat keeps the Wi-Fi icon lit on the unit's display.
- A built-in web config page and a live control panel on the Tasmota main page.
- An ESP32 (developed on an M5Stack Atom) wired to the A/C unit's serial bus.
- Serial pins (configurable in
Berryton.be): RX = GPIO32, TX = GPIO26, 9600 8N1. - The unit drives the line at 5 V → a bidirectional level shifter is recommended. (It has also run for over a year directly without one — at your own risk; opinions differ on ESP32 5 V tolerance.)
- Flash Tasmota (ESP32 build) on the ESP.
- Upload the
.befiles to the Tasmota filesystem (UFS) and anautoexec.bethat loads them, e.g.:load("Berryton.be") # core (required) load("berryton_config.be") # web config page (optional) load("berryton_panel.be") # main-page control panel (optional) load("berryton_emul.be") # bench emulator, no real A/C (optional)
- Restart the device (a full
Restart, not justBrRestart) so Berry recompiles with a clean heap — the core file is large and a fragmented-heap reload can run out of memory. - On first boot, wait ~1-2 minutes for the script to recover the A/C state before the MQTT feedback is correct.
Keep each
.befile comfortably under ~30 KB — the on-device Berry compiler is memory-bound. Design notes live inNOTES.mdand the observed serial frame layout inFRAMES.md.
All settings live in a single BerrytonConfig object, persisted to flash and editable from the Berryton AC
page in the Tasmota Configuration menu (provided by berryton_config.be).
For each mode (heat_* / cool_*) you choose a source of regulation:
| Source | Who regulates | Uses |
|---|---|---|
ac |
the A/C on its own sensor | *_offset (°C added in heat / subtracted in cool, to compensate the unit's high, enclosed sensor) |
mqtt |
the ESP (hysteresis) on a room temp from MQTT | *_temp_topic, *_hyst |
http |
the ESP (hysteresis) on a room temp polled over HTTP | *_http_url, *_http_interval, *_hyst |
In hysteresis (mqtt/http) mode the ESP forces the unit to 17 °C or 31 °C to run flat-out or coast. The
offset and the 17/31 values never leak to Home Assistant — HA always receives the user's real setpoint.
Other settings: a single AC MQTT name (cmnd/<name>/… + tele/<name>/… are derived from it), beep, HA device name & unique id, HA discovery on/off, full
vs simplified command set, the temperature reported to HA (A/C sensor vs regulation source), debug logging,
and a bench serial_emulation toggle. Saving applies immediately — no Berry restart needed. The day-to-day
ionizer / sleep / eco / display flags are toggled from the main-page control panel, not here.
A live control panel is added to the Tasmota main page (berryton_panel.be), and a per-mode
Berryton AC settings page to the Configuration menu (berryton_config.be):
| Control panel (main page) | Config page |
|---|---|
![]() |
![]() |
Everything on the web UI is also exposed to Home Assistant via MQTT auto-discovery (ha_discovery_enabled = 1,
nothing to add to configuration.yaml): the climate entity, a switch per config-word flag
(ionizer / sleep / eco / display / beep), a binary_sensor for the IR-remote Wi-Fi link, and a number for
the timer (shows the remaining time, settable in minutes) — so anything you can toggle or see on the panel is
also visible/controllable from HA and MQTT.
With the default prefixes cmnd/Newclim/ and tele/Newclim/:
| Direction | Topic | Payload |
|---|---|---|
| command | cmnd/Newclim/mode/set · fan/set · swing/set · temperature/set |
the value |
| command | cmnd/Newclim/ionizer/set · sleep/set · eco/set · display/set · beep/set |
1 / 0 |
| command | cmnd/Newclim/timer/set |
timer in minutes (0 = cancel) |
| feedback | tele/Newclim/mode/get · fan/get · swing/get |
current value |
| feedback | tele/Newclim/ionizer/get · sleep/get · eco/get · display/get · beep/get |
1 / 0 |
| feedback | tele/Newclim/timer/get |
remaining timer (minutes) |
| feedback | tele/Newclim/Actualtemp/get |
current temperature shown to HA |
| feedback | tele/Newclim/Actualsetpoint/get |
the user setpoint |
| feedback | tele/Newclim/remote/get |
IR-remote Wi-Fi state (on/off) |
| File | Role |
|---|---|
Berryton.be |
core: serial protocol, regulation, MQTT, HA discovery, frame buffering |
berryton_config.be |
web config page (sections + radios) |
berryton_panel.be |
live control panel on the Tasmota main page |
berryton_emul.be |
bench emulator (fake A/C feedback frames, no real unit) |
tools/bcheck.sh |
compile-check .be files off-device (builds the standalone Berry interpreter) |
tools/tb.sh |
drive a test ESP32 over HTTP (eval, console, UFS upload) |
NOTES.md |
design notes & regulation glossary |
FRAMES.md |
observed Airton serial frame layout |
Protocol work with pingus (pingus.org). Modbus CRC snippet from https://github.com/peepshow-21/ns-flash/blob/master/berry/nxpanel.be.

