ESPHome now has a native hdmi_cec component. Pull request #9189 by Jos van Eijndhoven was merged into the development branch on 15 October 2026. That branch is already numbered 2026.11.0-dev, and the component is not in the 2026.10 betas, so 2026.11 is the first release that can include it. An ESPHome device wired to the CEC line of an HDMI port hears the messages a TV exchanges with the equipment attached to it, can run automations on them and can send its own: standby, power on, volume, input selection.
The code continues Palakis' external component esphome-native-hdmi-cec, which was itself based on earlier work by johnboiles.
Wiring and configuration
CEC is a single wire in every HDMI cable, pin 13 of the connector, shared by all devices on the link, including those behind an A/V receiver or an HDMI switch. The draft documentation (esphome.io pull request #7733, not merged yet) connects one GPIO to pin 13 and ground to pin 17. Feeding the board's 5 V to pin 18 is optional but recommended, because it tells the TV that something is connected. The pin runs as an open-drain output with a weak pull-up, so a first test needs no extra parts.
hdmi_cec:
id: cec
pin: GPIO9
address: 0x5
on_message:
- opcode: 0x8F # Give Device Power Status
then:
- hdmi_cec.send:
destination: !lambda return source;
data: [0x90, 0x00] # Report Power Status: on
address is the logical address the device answers to (0x5 is an audio system, 0x4 a playback device). on_message filters by source, destination, opcode or the first bytes of the payload. promiscuous_mode also passes on messages meant for other devices, and monitor_mode only listens, with no acknowledgements and no sending. The hdmi_cec.send action takes a destination (0xF for a broadcast) and up to 15 bytes, opcode first. Lambdas can call id(cec).send(...), and an API action lets Home Assistant send any message.
What is still missing
The merged code is part 1, the bus core: receiving in a GPIO interrupt, bit-banged sending with retries, and collision detection. The device does not answer the TV on its own. A TV asks a new device for its physical address, on-screen name, vendor ID and power status, and treats it as absent if nothing comes back, so you have to answer what your TV needs with on_message automations. Built-in replies, a UART transmit option and a message decoder were split into part 2 (#20797). ESPHome maintainer bdraco wrote that he does not intend to finish it and left the branch for someone else to pick up.
The documentation adds two practical notes. Sending happens bit by bit in the main loop, about 25 ms per byte, so the loop can stall for up to 400 ms per message, and a slow-operation warning in the log is expected. The CEC line also sits at 3.3 V whenever the TV is on, even if the ESPHome board has no power. For that case the docs recommend a small relay or an I²C level shifter such as the TXS0102 or TCA9517 to disconnect the GPIO.
The component was tested on the ESP32-S3, ESP32-C3 (Arduino and ESP-IDF) and ESP8266, and compiles for RP2040 and BK72xx. On the ESP8266 it uses hardware timer 1, which PWM and servo outputs use as well. Pull request #20794, merged the same day, makes ESPHome refuse a configuration in which two components claim that timer; registering hdmi_cec with the check is left to a follow-up.