Using HDMI-CEC on a Raspberry Pi

In this tutorial, we will be showing you how you can control a TV by using HDMI-CEC and a Raspberry Pi.

Raspberry Pi HDMI-CEC

HDMI-CEC is a special protocol designed for TVs to communicate with another device over an HDMI cable. This protocol allows the TV to control another device while also allowing that device to control the TV.

Most modern TVs have implemented support for this protocol, but it often has to be enabled within the TV’s settings. Searching for the model of your TV should help you find what this setting is called.

Using the HDMI-CEC protocol, you can use your Raspberry Pi to control a TV in a variety of different ways, such as turning it off and on or changing the volume.

Equipment List

Below is the equipment that you will likely need to complete this tutorial on using HDMI-CEC from your Raspberry Pi.

Recommended

Optional

For this tutorial on using HDMI-CEC, we were running the latest available version of Raspbian Buster running on a Raspberry Pi 4.

This tutorial should function with older Raspberry Pi’s and older versions of the Raspbian operating system.

Installing cec-client to Your Raspberry Pi

In this section, we will be showing you the simple steps to installing the cec-client software on your Raspberry Pi.

cec-client is the software package that we will be utilizing on the Raspberry Pi to control a device over the HDMI-CEC protocol.

1. Our first task is to update the package list on our Raspberry Pi as well as upgrade the currently installed packages.

We can achieve this task by running the following two commands.

sudo apt update
sudo apt upgrade

The first command will update the package list. The second command will upgrade the installed packages.

2. Our next step is to install the cec-utils package. This package contains the cec-client software that we will be utilizing later in this tutorial.

We can install this package to our Raspberry Pi by running the following command.

sudo apt install cec-utils

Using the tools provided by this package, we will be able to send commands using CEC over the HDMI cable that’s connected to our Raspberry Pi.

Interacting with a TV over HDMI-CEC Using the Raspberry Pi

In this section, we will be showing you the various ways of using the cec-client software to interact with other devices.

Throughout this section, you will notice there is a couple of things we will be doing for each step.

The first is using echo and the pipe (|). We are using these two things to pass the command directly through to the cec-client software without having to launch it.

Additionally, we are using both the -s and -d options with the cec-client software.

The -s option tells the software that we are going to be  issuing a single command. The software will start up, issue the command then immediately exit.

The -d 1 option sets the debug level for the software. By setting it to 1, the cec-client software will only display errors.

This setting significantly reduces the amount of text that will flood the console.

Scanning for HDMI-CEC Devices from your Raspberry Pi

1. The first thing you will need to do is scan for available devices that are advertising that they have CEC capability.

Scan for HDMI-CEC capable devices by running the following command on your Raspberry Pi.

echo 'scan' | cec-client -s -d 1

2. From this command, you should see a list of devices that your Raspberry Pi now has access to.

You need to identify the device that you want to interact with. Typically the “os string:” and” vendor:” fields will help you identify the device you want to interact with.

Once you have identified the correct device, make a note of the “address:” or the device number.

opening a connection to the CEC adapter...
requesting CEC bus information ...
CEC bus information
===================
device #0: TV
address:       0.0.0.0
active source: no
vendor:        Sony
osd string:    TV
CEC version:   1.4
power status:  standby
language:      eng


device #1: Recorder 1
address:       1.0.0.0
active source: no
vendor:        Pulse Eight
osd string:    CECTester
CEC version:   1.4
power status:  on
language:      eng


device #4: Playback 1
address:       3.0.0.0
active source: no
vendor:        Sony
osd string:    PlayStation 4
CEC version:   1.3a
power status:  standby
language:      ???

Please note that “device #1: Recorder 1” in this example is the Raspberry Pi’s own CEC connection so we can safely ignore it.

3. For example, if we wanted to control our “Sony TV“, we can see that the device number would be “0“, and the address for the device would be “0.0.0.0“.

Once you have either the device number or device address, you can begin to send commands to it.

Sending the “on” Command over HDMI-CEC

Using the cec-client to turn on your device is a relatively easy process.

echo 'on <DEVICEADDRESS>' | cec-client -s -d 1

As you can see from above, all we need to do is send the command on followed by the device address or device number.

Example of Turning a Device ON Over HDMI-CEC

For example, if we wanted to turn on our Sony TV that has the address of “0.0.0.0“, we would make use of the command like below.

echo 'on 0.0.0.0' | cec-client -s -d 1

Sending the “standby” Command over HDMI-CEC

If you would like to turn your TV off (Put it into standby) using your Raspberry Pi, you can also do this easily using HDMI-CEC.

echo 'standby <DEVICEADDRESS>' | cec-client -s -d 1

To put the TV into standby, all you need to do is send the “standby” command, followed by the device’s address or number.

Example of Turning a Device OFF Over HDMI-CEC

Using this command is relatively straightforward.

To put our Sony TV into standby, all we need to do is send “standby” followed by our devices address of  “0.0.0.0“.

echo 'standby 0.0.0.0 | cec-client -s -d 1

Getting the Power Status over HDMI-CEC

You can even make use of HDMI-CEC on your Raspberry Pi to retrieve the power status of the device.

echo 'pow <DEVICEADDRESS>' | cec-client -s -d 1

Using the pow command, you can find out whether the device you are connecting to is currently powered on or is in standby mode.

This command can be helpful for deciding whether you need to power the TV on or off, especially if managing a device remotely.

Example of Getting the Power Status over HDMI-CEC

Like most HDMI-CEC commands, it is relatively easy to make use of this. All you need to do is reference pow followed by the device address.

echo 'pow 0.0.0.0' | cec-client -s -d 1

If your device is in standby you will see something like what we have below appear in your terminal.

opening a connection to the CEC adapter...
power status: standby

Retrieving Additional CEC-Client Commands

If you would like to check what other commands you can issue to your TV from your Raspberry Pi using HDMI-CEC, you can use the following command.

echo 'h' | cec-client -s -d 1

What this command does is retrieve the available commands that the cec-client software knows how to handle.

From this command, you should get a list of commands, as we have below.

================================================================================
Available commands:

[tx] {bytes}              transfer bytes over the CEC line.
[txn] {bytes}             transfer bytes but don't wait for transmission ACK.
[on] {address}            power on the device with the given logical address.
[standby] {address}       put the device with the given address in standby mode.
[la] {logical address}    change the logical address of the CEC adapter.
[p] {device} {port}       change the HDMI port number of the CEC adapter.
[pa] {physical address}   change the physical address of the CEC adapter.
[as]                      make the CEC adapter the active source.
[is]                      mark the CEC adapter as inactive source.
[osd] {addr} {string}     set OSD message on the specified device.
[ver] {addr}              get the CEC version of the specified device.
[ven] {addr}              get the vendor ID of the specified device.
[lang] {addr}             get the menu language of the specified device.
[pow] {addr}              get the power status of the specified device.
[name] {addr}             get the OSD name of the specified device.
[poll] {addr}             poll the specified device.
[lad]                     lists active devices on the bus
[ad] {addr}               checks whether the specified device is active.
[at] {type}               checks whether the specified device type is active.
[sp] {addr}               makes the specified physical address active.
[spl] {addr}              makes the specified logical address active.
[volup]                   send a volume up command to the amp if present
[voldown]                 send a volume down command to the amp if present
[mute]                    send a mute/unmute command to the amp if present
[self]                    show the list of addresses controlled by libCEC
[scan]                    scan the CEC bus and display device info
[mon] {1|0}               enable or disable CEC bus monitoring.
[log] {1 - 31}            change the log level. see cectypes.h for values.
[ping]                    send a ping command to the CEC adapter.
[bl]                      to let the adapter enter the bootloader, to upgrade
                          the flash rom.
[r]                       reconnect to the CEC adapter.
[h] or [help]             show this help.
[q] or [quit]             to quit the CEC test client and switch off all
                          connected CEC devices.
================================================================================

At this point, you should now have learned how to use cec-client on your Raspberry Pi to control devices that support the HDMI-CEC protocol.

If you have any issues with HDMI-CEC on your Raspberry Pi, feel free to drop a comment below.

Leave a Reply

Your email address will not be published. Required fields are marked *

5 Comments

  1. Avatar for berg
    berg on

    Really helpful! Thanks!

  2. Avatar for Jeff Sadowski
    Jeff Sadowski on

    I got around to trying this out last night. I can turn on and off the TV. I was not successful at turning on my receiver but I can see it in the device scan. I’m not able to change the volume maybe I need to set the active source to the Pulse Eight?

  3. Avatar for Aaron
    Aaron on

    This works with the raspberry pi zero w also.

  4. Avatar for OlderMan
    OlderMan on

    Be aware that on the Raspberry Pi 4 only the HDMI plug next to the USB-C will work with cec commands.

    1. Avatar for AnotherOldMan
      AnotherOldMan on

      I think both might work. The PI 4 has /dev/cec0 and /dev/cec1. By default cec-utils seem to use /dev/cec0. E.g.: echo ‘scan’ | cec-client -s -d 1 /dev/cec0 gives me lots of errors echo ‘scan’ | cec-client -s -d 1 /dev/cec1 works (on a PI 400 which is just a PI 4 in a nice case with keyboard and passive cooling).

      @author: Awesome post, helped a lot. However, now I still need to find out how to listen to and act upon commands from the TV remote :O