0
0

Raspberry PiでHDMI-CECを出力し、テレビの操作を行う

Posted at

テレビに接続しているゲーム機には、本体を起動するとテレビも連動して起動させて、HDMIの入力も自動で切り替えてくれる機能を持っています。
我が家ではPCもテレビに接続しているのですが、PCからはそういったテレビ連動はできません。
そこを何とかできないか、ということで家に転がっていたRaspberry Piで何とかする、というのがこの記事の内容です。

外部機器がテレビを操作する「HDMI-CEC」について

Nintendo Switchのようなゲーム機はテレビとの電源連動機能を持っており、本体を起動すると「テレビの電源を入れて」「HDMIの入力切替を行って」自動的にゲーム画面がテレビに表示されます。
この機能は HDMI CEC(Consumer Electronics Control) という規格に基づく信号を送信することで実現しています。
で、ゲーム機がCECを送信出来るのならPCでもCECを送信できるだろうと思ったのですが、ハードウェアレベルで実装してないためできないらしいです。
そしてPCはCECの信号を送信できないのですが、実はRaspberry PiはCECの信号を出力することができます。

やりたいこと

テレビに接続したPCを起動したら

  • テレビをつける
  • PCを接続しているHDMI入力に切り替える

PCがシャットダウンしたら

  • テレビの電源を落とす

Raspberry Piの準備

OSはRaspbianを使用。
CECの使用するためにcec-utilsをインストールしてください。

apt update
apt install cec-utils

CECの使用方法

cec-utilsでCECフレームを送信する方法はいくつかあるのですが、ここではechoで必要なメッセージを出力して、single-commandモード(-s)で実行するcec-clientに渡す方法を使います。

サンプル:TVの電源を付けるコマンド
echo "tx 10:04" | cec-client -s

txを先頭に入力し、続けて引数としてCECフレームを入力します。
CECフレームの先頭2バイト部分10は、1バイト目が送信元論理アドレス、2バイト目が送信先論理アドレスとなります。
テレビの論理アドレスは0で固定、送信元となるRaspberry Piの論理アドレスはcec-client -lコマンドで出力されるdevice情報から確認できます。
この記事では、Raspberry Piの論理アドレスは1であるものとしてCECフレームを作成します。

# cec-client -l
libCEC version: 6.0.2, compiled on Linux-5.10.63-v8+ ... , features: P8_USB, DRM, P8_detect, randr, RPi, Exynos, Linux, AOCEC
Found devices: 1

device:              1
com port:            RPI
vendor id:           2708
product id:          1001
firmware version:    1
type:                Raspberry Pi

HDMIの入力切替を行う際には、「物理アドレス」も指定しなくてはいけません。
調査方法は割愛しますが、基本的に「HDMI 1:1.0.0.0」~「HDMI 4:4.0.0.0」というようなアドレッシングになっています。

この記事で使用するCECフレームの内容は以下の通り。

CECフレーム 機能 備考
10:04 テレビの電源をONにする echo "on 0"と同値
10:36 テレビの電源をOFFにする echo "standby 0"と同値
1f:82:20:00 いわゆる"HDMI 2"をアクティブにする 宛先論理アドレスはTVの0ではなく、ブロードキャストのfを指定する必要がある
3-4バイト目はアクティブソースを指定する宣言
5-8バイト目は対象となるHDMI入力の物理アドレスを指定する

PC(Windows)との連動

本当はWindowsのタスクスケジューラーを使い、起動時/終了時にRaspberry PiにHTTPアクセスをしてCECの操作をしたかったのですが、どうしてもタスクスケジューラーが機能してくれませんでした。
(たぶん私の知識不足)
そのため、「Raspberry PiからPCに定期的にpingを打ち、その結果でCECの操作を行う」という方法としました。

具体的に、以下のようなシェルをRaspberry Pi上に配置し、systemdにてサービス化させました。

  1. 1秒周期でWindowsPCにpingを打つ
  2. ping応答があればカウント変数をデクリメント。ただしカウント変数がすでに"0"なら何もしない
  3. デクリメントした結果が"0"になった場合、TVの電源をON+"HDMI 2"をアクティブにする
  4. ping応答がなければカウント変数をインクリメント。ただしカウント変数がすでに"3"なら何もしない
  5. インクリメントした結果が"3"になった場合、TVの電源をOFFにする
#!/bin/bash

CNT=0

while true
do
  ping -c 1 -w 1 <WindowsPCのIPアドレス> > /dev/null
  BUF=$?
  if [ $BUF -eq 0 ]; then
    if [ $CNT -gt 0 ]; then
      CNT=`echo $(($CNT-1))`
      if [ $CNT -eq 0 ]; then
        echo "tx 10:04"|/usr/bin/cec-client -s -d 1 > /dev/null
        echo "tx 1f:82:20:00"|/usr/bin/cec-client -s -d 1 > /dev/null
      fi
    else
      CNT=0
    fi
  else
    if [ $CNT -lt 3 ]; then
      CNT=`echo $(($CNT+1))`
      if [ $CNT -eq 3 ]; then
        echo "tx 10:36"|/usr/bin/cec-client -s -d 1 > /dev/null
      fi
    else
      CNT=3
    fi
  fi
  sleep 1
done
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0