ESPHome component to send and receive HDMI-CEC messages.

Overview

HDMI-CEC ESPHome Component

An ESPHome component that supports receiving and transmitting HDMI-CEC messages to connected HDMI devices. The ultimate goal of this project is to eventually be merged into the core ESPHome project once it's up to quality. It's currently out for review as esphome/esphome#3017 (see also: esphome/esphome-docs#1789).

The core CEC driver is forked from s-moch/CEC.

My use case: I already have an IR blaster built with ESPHome, but my new TCL TV has a Bluetooth remote. I want to control my older sound gear (connected over optical) with the TV remote but this TV only supports controlling sound gear via HDMI (typically for HDMI-ARC devices). This component allows me to intercept HDMI-CEC volume commands and transmit the IR codes to control the soundbar. It also allows my Apple TV to control the soundbar (so I can control volume from the Remote app on my phone 📱 ). Theoretically it should allow you to make any older non-HDMI equipment work seamlessly with newer gear. You can also do things like monitor which source is selected, which HDMI devices are powered on, etc.

Drop me a line on Twitter or the ESPHome Discord if you end up trying it and/or have ideas for cool use cases!

Electronics

Since HDMI-CEC is a 3.3V protocol, no external components are needed. A HDMI breakout connector might be handy though. Just connect:

  • GPIO of your choice to HDMI pin 13 (the examples use GPIO4)
  • GND from the ESP board to HDMI pin 17 (DDC/CEC Ground)
  • 5V from the ESP board to HDMI pin 18 (typtically how the HDMI device knows something is connected)

Usage

For now on the ESP8266, until the HDMI driver is rewritten to fully use interrupts, it's a good idea to bump the CPU speed to 160MHz:

esphome:
  ...
  platformio_options:
    board_build.f_cpu: 160000000L

Add this repo to your external components

external_components:
  - source: github://johnboiles/esphome-hdmi-cec

Configure your hdmi_cec component. The on_message triggers will only fire if any specified source, destination, opcode, and data match. Something like this (the below is abbreviated -- see full example here).

hdmi_cec:
  # The initial logical address -- corresponds to device type. This may be
  # reassigned if there are other devices of the same type on the CEC bus.
  address: 0x05 # Audio system
  # Promiscuous mode can be enabled to allow receiving messages not intended for us
  promiscuous_mode: false
  # Typically the physical address is discovered based on the point-to-point
  # topology of the HDMI connections using the DDC line. We don't have access
  # to that so we just hardcode a physical address.
  physical_address: 0x4000
  pin: 4 # GPIO4
  on_message:
    - opcode: 0xC3 # Request ARC start
      then:
        - hdmi_cec.send: # Report ARC started
            destination: 0x0
            data: [ 0xC1 ]
    - opcode: 0x71 # Give audio status
      source: 0x0 # From the TV
      then:
        - hdmi_cec.send:
            destination: 0x0
            data: [ 0x7A, 0x7F ]
    - opcode: 0x46 # Give OSD name
      then:
        - hdmi_cec.send:
            destination: 0x0
            data: [0x47, 0x65, 0x73, 0x70, 0x68, 0x6F, 0x6D, 0x65]
    - data: [0x44, 0x41] # User control pressed: volume up
      then:
        - logger.log: "Volume up"

You can use the hmdi_cec.send action from anywhere you can use actions.

button:
  - platform: template
    name: TV Turn On
    on_press:
      - hdmi_cec.send:
          source: 0x05 # Optional since we'll default to `hdmi_cec.address`
          destination: 0x0
          data: [ 0x04 ]

Notes

  • The timing for receiving and parsing CEC messages depends on the timing with which loop is called and thus this is sensitive to other things the microcontroller are doing that may delay the loop method getting called. I've implemented pin change interrupts which makes receive more reliable but more work needs to be done to make this entirely interrupt driven. The ESP32 will probably work better as-is, though I haven't tried it yet.

TODO

  • Adapt or rewrite the CEC driver to be fully interrupt-driven.
  • Add GitHub action to test the build
  • Write tests?
  • Fritzing (or similar) connection diagram

See Also

You might also like...
EspHoMaTriX - A simple DIY status display with an 8x32 RGB LED panel implemented with esphome.io

EspHoMaTriX (ehmtx) A simple DIY status display with an 8x32 RGB LED panel implemented with esphome.io Introduction There are some status displays out

Allows for multiple SwitchBot buttons and curtains to be controlled via MQTT sent to ESP32. ESP32 will send BLE commands to switchbots and return MQTT responses to the broker. Also supports Meter/Temp Sensor

SwitchBot-MQTT-BLE-ESP32 Switchbot local control using ESP32. no switchbot hub used/required. works with any smarthub that supports MQTT https://githu

First-up chord-send and tap-and-hold chord repeat extensions to QMK.

Quantum Mechanical Keyboard Firmware This is a keyboard firmware based on the tmk_keyboard firmware with some useful features for Atmel AVR and ARM co

ROS1 and ROS2 messages for event based image sensors

ROS package with array messages for event based cameras This package has definitions for messages created by event based sensors. The events are kept

GPS parser which read raw GPS messages, selects only the valid ones and sends them to CAN bus

EagleTRT GPS System for Fenice GPS parser which read raw GPS messages, selects only the valid ones and sends them to CAN bus Compiling GPS Logger gps_

An embedded CAN bus sniffer which is able to monitor any of the vehicle internal CAN bus and perform some action by triggering new CAN messages.
An embedded CAN bus sniffer which is able to monitor any of the vehicle internal CAN bus and perform some action by triggering new CAN messages.

An embedded CAN bus sniffer which is able to monitor any of the vehicle internal CAN bus and perform some action by triggering new CAN messages. In this way certain vehicle functionality can be triggered by responding to custom steering wheel button events, or use the vehicle virtual cockpit to display OBD-PIDs values instead of relying on an external display to present new information to the user

BokutachiHook - Hook for Lunatic Rave 2 to parse score data and send it to an HTTP server, made specifically for Bokutachi IR.

BokutachiHook Hook for Lunatic Rave 2 to parse score data and send it to an HTTP server, made specifically for Bokutachi IR (https://bokutachi.xyz). T

CredBandit - Proof of concept Beacon Object File (BOF) that uses static x64 syscalls to perform a complete in memory dump of a process and send that back through your already existing Beacon communication channel

CredBandit CredBandit is a proof of concept Beacon Object File (BOF) that uses static x64 syscalls to perform a complete in memory dump of a process a

Off The Grid (OTG) Messenger is an easy way for people to communicate through text messages when in remote areas.
Off The Grid (OTG) Messenger is an easy way for people to communicate through text messages when in remote areas.

Off The Grid (OTG) Messenger is an easy way for people to communicate through text messages when in remote areas. With a theoretical transmission range of 10 miles (16kms), OTG messenger can be used by groups of people to stay connected when they are in areas not serviced by mobile connectivity.

Comments
  • OSD Name characters

    OSD Name characters

    Congratulations, nice project. Please share with us how to encode any string in OSD name

        - opcode: 0x46 # Give OSD name
          then:
            - hdmi_cec.send:
                destination: 0x0
                data: [0x47, 0x65, 0x73, 0x70, 0x68, 0x6F, 0x6D, 0x65] # esphome <- change this to anything
    
    opened by nagyrobi 1
  • Samsung UE50AU7102 (2021)

    Samsung UE50AU7102 (2021)

    Congrats for this project.

    With the Samsung model above it looks like it doesn't connect automatically the ARC device. I need to issue the commands manually. Made a button with all commands from your on_message section and if I trigger them manually, it will connect.

    - platform: template
      name: Connect speakers to TV
      on_press:
        - hdmi_cec.send:
            destination: 0x0
            data: [ 0xC1 ]
        - hdmi_cec.send:
            destination: 0xF
            data: [ 0x72, 0x01 ]
        - hdmi_cec.send:
            destination: 0x0
            data: [ 0x7A, 0x7F ]
        - hdmi_cec.send:
            destination: 0x0
            data: [ 0x7A, 0x7F ]
        - hdmi_cec.send:
            destination: 0x0
            data: [ 0x7E, 0x01 ]
        - hdmi_cec.send:
            destination: 0x0
            data: [0x47, 0x65, 0x73, 0x70, 0x68, 0x6F, 0x6D, 0x65] # esphome
        - hdmi_cec.send:
            destination: 0x0
            data: [0x87, 0x00, 0x13, 0x37]
    

    After I turn off and back on the TV again, connection is lost with ARC device and volume commands don't come through anymore. Since I have to connect the ESP to the USB port of the TV, which is powered down when the TV is off, they boot up together. I tried to add these commands to on_boot section of esphome with some delay but that's very unstable. Looks like it connects, but looses connection again. After I press the button, it stays connected.

    Also, I don't see the OSD name being set by the command.

    opened by nagyrobi 1
Owner
John Boiles
Building new things. Previously MyMaskMovement, Twitter/Periscope, Peer, Penny, Yelp, UT Austin
John Boiles
ESPHome Wordclock - based on esphome

ha-wordclock-esphome General This project is just for documentation purposes and our attempt (together with a friend) to build an Wordclock, which is

null 13 Dec 26, 2022
Simple ESPHome Wiegand custom component

esphome-wiegand Simple ESPHome Wiegand custom component Based on this code: https://github.com/Luisiado/wiegand_esphome_module To use: Drop wiegand_de

Av 24 Dec 26, 2022
Custom ESPHome Component for generic Sit-Stand-Desks

ESPHomeGenericSitStandDesk I have one of those generic relatively cheap Sit Stand Desks. In an effort to monitor my desk usage I developed this overki

Till 18 Dec 27, 2022
Send messages to a LED Matrix display through Telegram. Inspired by a tweet from Smarter Every Day

Send messages to a LED Matrix display through Telegram. Inspired by a tweet from Smarter Every Day

Brian Lough 23 Oct 8, 2022
gr-nrf24-sniffer is a tool to receive and decode wireless traffic from nRF24L01(+) modules

gr-nrf24-sniffer What is this? gr-nrf24-sniffer is a tool to receive and decode wireless traffic from nRF24L01(+) modules (or older nRF24xxx) using GN

null 5 Jul 18, 2022
ESPHome integration for the Xiaomi Mijia Bedside Lamp v2.

esphome-xiaomi_bslamp2 Warning: this code is still under development This code might not yet be production-ready. At this point, it is declared beta-q

Maurice Makaay 136 Dec 27, 2022
SmartShunt ve.direct to ESPHOME node

VictronSmartShunt-ESPHOME SmartShunt ve.direct to ESPHOME node A configured uart component is required. Example: victron: uart_id: the_uart sensor:

null 33 Dec 11, 2022
A collection of my ESPHome components.

ESPHome components A collection of my ESPHome components. To use this repository you should confugure it inside your yaml-configuration: external_comp

null 89 Jan 4, 2023
ESPHome BLE Keyboard

ESPHome BLE Keyboard The firmware implements the ability to connect your esp32 device as a BLE keyboard and send keystrokes via Home Assistant Table o

Dmitry Mamontov 33 Dec 29, 2022
Projects related to sync'ing esphome devices with other protocols: DDP, E131, etc...

esphome sync This project is due to a desire to leverage WLED's new virtual strip (via DDP) feature or software like xLights or LEDFx to controls ESP

tony 12 Dec 24, 2022