Most modern HDMI connected devices support Consumer Electronics Control (CEC). It allows devices to send commands to each other, typically to get the TV to switch input and control volume. If you have ever turned on a Game Console and had your TV automatically change input to that device you have seen CEC in action. It is very convenient and useful, sort of a universal remote that works.
Every manufacturer seems to have it’s own branding of CEC (e.g. Samsung Anynet+, LG SimpLink, Sharp Aquos Link) but it may need to be enabled. Check your manual for details.
Using a Raspberry Pi connected to a TV that supports CEC, you can use the command line cec-client
application to control the inputs and the TV itself. These are notes on how to use cec-client
and understand the different options.
Hardware: Raspberry Pi 2 Model B
OS: OMSC November 2016 (2016.11-1)
NOTE: This will work with Raspbian as well, as OMSC (Open Source Media Center) just a repackaging of Raspbian.
This is specific to Samsung, but will be simlar on other TVs that support CEC.
Enable CEC in: System > General > Anynet+ (HDMI-CEC) (ensure that Auto Turn Off option is enabled).
sudo apt-get install cec-utils
The First step is to use the cec-client on the Raspberry Pi to scan the HDMI devices. This will include the TV, the Raspberry Pi and any other devices, typically listed as either Recorder #
or Playback #
.
echo "scan" | cec-client RPI -s -d 1
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: Samsung
osd string: TV
CEC version: 1.3a
power status: on
language: eng
device #1: Recorder 1
address: 1.0.0.0
active source: no
vendor: Unknown
osd string: CECTester
CEC version: 1.4
power status: standby
language: ???
device #2: Recorder 2
address: 2.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: ???
currently active source: unknown (-1)
As listed, the setup is:
Name | Address | Device |
---|---|---|
Samsung TV | 0.0.0.0 | TV |
Raspberry Pi | 1.0.0.0 | Recorder 1 |
Tivo with Pulse Eight USB-CEC adapter | 2.0.0.0 | Recorder 2 |
PlayStation 4 | 3.0.0.0 | Playback 1 |
NOTE: The Tivo is old enough not to support cec, so originally I bought the Pulse Eight USB-CEC adapter when I was only using the single command approach. With the ability to send a HDMI-cec frame I believe I can remove it from the setup, as I can address the device from the Raspberry Pi. But I am getting ahead of myself…
The following is the simplest way to call the cec-client, with no address specified. However, using this approach I was not able to send commands from one device to another devices.
In other words, from the Raspberry Pi I can only send commands to the Raspberry Pi (make active / inactive source) and not send from the Raspberry Pi commands to make the Tivo or PlayStation active.
It is possible to turn the TV on or off (standby) from the Raspberry Pi.
echo "standby 0" | cec-client RPI -s -d 1
echo "on 0" | cec-client RPI -s -d 1
echo "as" | cec-client RPI -s -d 1
echo "is" | cec-client RPI -s -d 1
Honestly it took me longer then it should have to understand how the HDMI-CEC frames worked. Partly it was confusion on my part about what the addresses of the devices were. Running the single commands above with debug on (-d 1) allowed me to see what address/source it was using for the Raspberry Pi, then the rest sort of fell into place.
Use echo "scan" | cec-client RPI -s -d 1
to determine the source address (2.0.0.0) and source (Recording2) of the Raspberry Pi. Next using http://www.cec-o-matic.com/ I was able to reproduce not only the single commands, but also target other devices from the Raspberry Pi.
Many thanks to http://www.cec-o-matic.com/, without which I don’t think I would have figured out the settings.
NOTE: Change the source to match your Raspberry Pi as reported by running echo "scan" | cec-client RPI -s -d 1
.
– Source: Recording2
– Destination: TV
– Message: Image View On
echo "tx 20:04" | cec-client RPI -s -d 4
– Source: Recording2
– Destination: TV
– Message: Standby
echo "tx 20:36" | cec-client RPI -s -d 4
– Source: Recording2
– Destination: Broadcast
– Message: Active Source, 1.0.0.0
echo "tx 2F:82:10:00" | cec-client RPI -s -d 4
– Source: Recording2
– Destination: Broadcast
– Message: Active Source, 2.0.0.0
echo "tx 2F:82:20:00" | cec-client RPI -s -d 4
– Source: Recording2
– Destination: Broadcast
– Message: Active Source, 3.0.0.0
echo "tx 2F:82:30:00" | cec-client RPI -s -d 4
Using HDMI-cec frames are much more powerful then sending simple commands, but initially more complicated. Hopefully these notes will help others get over the cec learning curve.
Source: https://blog.gordonturner.com/2016/12/14/using-cec-client-on-a-raspberry-pi/ (2019-05-13)
Hello rmtsrc, let me tell you that you did a pretty nice work here.
I spent a few weeks struggling to figure out how to use CEC to switch my active HDMI sources, and the answer was given to me through your work.
Given that, did you try any other commands to do other functionalities? I mean, I know that supposedly we can send notifications to the TV screen using CEC (specifically, using the command to send OSD messages). In this way, did you try to do any of this? Can you suggest to me how to do it (which command can do this)?
I've been struggling with it, and I greatly appreciate your help.
Best regards,
Gabriel Faria