先日Google Nest miniをお迎えしたので、家のテレビを操作してみようと思ったところ、手元のテレビでは直接の操作に対応していませんでした。
Google Nest mini以外でもテレビを操作する方法がないかを調べたところ、HDMI CECを使えばいけそうでした。
- Consumer Electronics Control - Wikipedia
- CEC - Official Kodi Wiki
- 「HDMI CEC」――AV機器メーカーによる囲い込みポイント - ITmedia NEWS
- Raspberry PiでHDMIディスプレイを調査する[EDID/CEC] | 犬アイコンのみっきー
手元にある道具では、Raspberry PiとテレビをHDMIで接続し、libcec
と cec-client
を使えば良さそうでした。
Raspberry Pi のcec 制御とHDMIのオンオフ - それマグで!
せっかくなのでPythonでlibcecを直接扱う方法がないかを調べたところ python-cec
がありました。READMEには「libcec bindings for Python」と書かれていました。
trainman419/python-cec
最新リリースは 2018/11/9 でしたが、Github上では今年もcommitされていたため、試してみることにしました。
なお、久しぶりにRaspberry Piをさわるため、セットアップするところからメモに残します。
目次
環境
開発はWindows上で、実行はRaspberry Piで行います。
Raspberry Pi
- Raspberry Pi 2 model B
- Raspberry Pi OS (Raspbian) 10
- Python 3.7
- python-cec 0.2.7
- 固定IP化
- SSH可
Windows 10
- Windows10 1909
- PyCharm Professional 2020.3
- Windows上でPythonを書き、Raspberry Pi上で実行するため
- Raspberry Pi上でPythonを書くなら不要
- Windows Terminal
- Git bash
ssh-copy-id
コマンドで、公開鍵認証用のSSH鍵を転送するため- Raspberry Piログインをパスワード認証のままとするなら不要
テレビ
ネットワーク構成図
Windows10 - Raspberry Pi間は有線LAN、Raspberry Pi - テレビ間はHDMIとします。
----------------------------------------- Windows10 [IPアドレス:DHCP (192.168.0.xxx)] ----------------------------------------- | (LANケーブル) | ----------------------------------------- スイッチングハブ ----------------------------------------- | (LANケーブル) | ----------------------------------------- (`eth0` : オンボードLANアダプタ) Raspberry Pi 2 Model B [IPアドレス:固定 (192.168.0.50)] ----------------------------------------- | (HDMIケーブル) | ----------------------------------------- テレビ -----------------------------------------
事前準備
Windows Terminalの準備
以下を参考に、Windows TerminalをMicrosoft storeからインストールします。また、自分がPowerShellに慣れていないため、デフォルトで cmd.exe
が動くように切り替えます。
Windows Terminal Tips - Qiita
Raspberry Pi ImagerによるOS書き込み
最近は Raspberry Pi Imager
を使ってmicroSDにOSを書き込むようになっていました。
「圧倒的に速い」──ラズパイにOSをインストールする新ツール「Raspberry Pi Imager」 (1/2) - ITmedia NEWS
今回はCLIでしかラズパイを使いませんが、ひとまず Raspbian
を選んで書き込んでおきます。
Raspberry PiにてSSHを許可
以下を参考に、WindowsにOSの入ったmicroSDを接続し、Windows Terminalを使ってmicroSD上に ssh
ファイルを置いておきます。
- SSH (Secure Shell) - Raspberry Pi Documentation
- How to create an empty file at the command line in Windows? - Stack Overflow
# microSDへ移動 >cd /d E:\ # 空のsshファイルを作成 E:\>cd . > ssh # 確認 E:\>dir ドライブ E のボリューム ラベルは boot です ... 2020/12/31 09:08 0 ssh
ちなみに、macの場合は以下のコマンドでsshファイルを作成します。
% touch /Volumes/boot/ssh
Raspberry Piの起動と接続確認
OSの入ったmicroSDをRaspberry Piに接続し、電源を入れます。
その後、Windows TerminalからSSHで接続確認をします。
# パスワード認証によるSSH接続 >ssh pi@raspberrypi.local pi@raspberrypi.local's password: <raspberry> # Raspberry Piのバージョン確認 $ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 10 (buster) Release: 10 Codename: buster
Raspberry Piのログインを公開鍵認証に切り替え
パスワード認証から公開鍵認証に切り替えます。
Windows TerminalでSSH鍵の生成
# ssh-kegenで生成し、ログインユーザの .ssh フォルダにSSH鍵 pi_rsa を入れる >ssh-keygen -t rsa -b 4096 -f %USERPROFILE%/.ssh/pi_rsa # パスフレーズなし Enter passphrase (empty for no passphrase):
SSH用公開鍵をRaspberry Piに登録
Raspberry Piに公開鍵でSSHするために、Windowsで作成した公開鍵を登録します。
しかし、Windowsには ssh-copy-id
コマンドがありません。
代替案はいくつかあるようです。
Is there an equivalent to ssh-copy-id for Windows? - Server Fault
上記方法でも良いのですが、手元に何かないかなと思ったところ、Git bashがインストールされていることを思い出しました。
Git bashには ssh-copy-id
コマンドがあったため、使ってみます。
$ ssh-copy-id -i ~/.ssh/pi_rsa.pub pi@raspberrypi.local /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys pi@raspberrypi.local's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'pi@raspberrypi.local'" and check to make sure that only the key(s) you wanted were added.
登録できたようなので、Windows Terminalから公開鍵方式でログインしてみます。
# 公開鍵認証によるSSH >ssh -i %USERPROFILE%/.ssh/pi_rsa pi@raspberrypi.local # Raspberry Piのバージョン確認 $ lsb_release -a No LSB modules are available. ...
Raspberry Piにvimを入れる
デフォルトでは vim-tiny
なので、 vim
に差し替えます。
RaspberryPi3のセットアップ続き〜VimやNFS設定 - Qiita
# アンインストール $ sudo apt-get --purge remove vim-common vim-tiny # vimをインストール $ sudo apt-get install vim
Raspberry Piを固定IP化
以前行ったとおり、 /etc/dhcpcd.conf
を修正し、固定IP化します。
Python2 + Scapyで、Raspberry Pi 2 Model B をブリッジにできるか試してみた #router_jisaku - メモ的な思考的な
# /etc/dhcpcd.conf を開く $ vi /etc/dhcpcd.conf # 末尾に追加 interface eth0 static ip_address=192.168.0.50/24 static routers=192.168.0.1 static domain_name_servers=192.168.0.1
追加した内容で有効化します。
$ sudo service dhcpcd reload
IPアドレスが変更となるので、Windows TerminalのSSH接続が切れます。そのため、再接続します。
> ssh -i %USERPROFILE%/.ssh/pi_rsa pi@raspberrypi.local
/boot/config.txtの編集
デフォルトでは、Raspberry PiをHDMI接続したときにCEC信号が送られてしまうため、それを無効化しておきます。
$ vi /boot/config.txt # 以下を追加 hdmi_ignore_cec_init=1
Raspberry PiのデフォルトのPythonをPython3にする
Raspberry PiのデフォルトのPythonのバージョンを見たところ、Python2系でした。
そのため、デフォルトをPython3系へと切り替えます。インストール済はPython3.7でしたが、今回扱う範囲では問題なかったので、Python3系の最新にはしません。
RaspberryPiでPythonのデフォルトをPython2.7からPython3に変更する | そう備忘録
# シンボリックリンクの確認 $ ls -l /usr/bin | grep python ... lrwxrwxrwx 1 root root 7 Mar 4 2019 python -> python2 ... lrwxrwxrwx 1 root root 9 Mar 26 2019 python3 -> python3.7 ... # 変更 $ cd /usr/bin pi@raspberrypi:/usr/bin $ sudo unlink python pi@raspberrypi:/usr/bin $ sudo ln -s python3 python # バージョン確認 $ python --version Python 3.7.3
cec-clientのインストールと動作確認
まずは、Raspberry PiからHDMI CECを使った操作ができるかを確認します。
cec-clientは cec-utils
に含まれるため、インストールします。
$ sudo apt-get update $ sudo apt-get upgrade -y $ sudo apt-get install cec-utils -y
cec-clientの動作確認をします。
$ sudo cec-client -l libCEC version: 4.0.4, compiled on Linux-4.15.0-48-generic ... , features: P8_USB, DRM, P8_detect, randr, RPi, Exynos, AOCEC Found devices: 1 device: 1 com port: RPI vendor id: 2708 product id: 1001 firmware version: 1 type: Raspberry Pi
cec-clientを使った操作ですが、Raspberry Piの tvservice
をoffにしておかないと動作しません。
$ echo "scan" | cec-client -d 1 -s # エラーが出て動かない log level set to 1 opening a connection to the CEC adapter... ERROR: [ 421] RegisterLogicalAddress - CEC is being used by another application. Run "tvservice --off" and try again. ERROR: [ 421] Open - vc_cec could not be initialised ERROR: [ 421] could not open a connection (try 1)
そこで、 tvserviceをoffにします。
Raspberry Pi Documentation
$ tvservice -o Powering off HDMI
再度実行すると、scanや電源ON/OFFができました。
# Scan $ echo "scan" | cec-client -d 1 -s log level set to 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: Unknown osd string: TV CEC version: 1.4 power status: standby language: ??? 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 currently active source: unknown (-1) # 電源ON $ echo 'on 0' | cec-client -s ... DEBUG: [ 1814] >> TV (0) -> Recorder 1 (1): report power status (90) DEBUG: [ 1814] expected response received (90: report power status) DEBUG: [ 1814] << requesting vendor ID of 'TV' (0) DEBUG: [ 1814] 'give device vendor id' is marked as unsupported feature for device 'TV' NOTICE: [ 1814] << powering on 'TV' (0) TRAFFIC: [ 1815] << 10:04 DEBUG: [ 1906] TV (0): power status changed from 'standby' to 'in transition from standby to on' # 電源OFF (スタンバイ) $ echo 'standby 0' | cec-client -s ... TRAFFIC: [ 2590] >> 01:9f DEBUG: [ 2591] >> TV (0) -> Recorder 1 (1): get cec version (9F) TRAFFIC: [ 3351] >> 0f:36 DEBUG: [ 3351] TV (0): power status changed from 'on' to 'standby' DEBUG: [ 3351] >> TV (0) -> Broadcast (F): standby (36)
python-cecを使った操作
ここからが本題です。
今回はpython-cecを使い、Raspberry Piからテレビを操作します。
trainman419/python-cec
Windows上のPyCharmのPythonインタプリタをRaspberry PiのPythonにする
Raspberry Pi上で実装しても良いですが、せっかくので、ローカルのWindows上で実装したものをRaspberry Pi上で実行することにします。
なお、この方法はPyCharm Professionalが必要です。
Raspberry Pi上でvenv上にpython-cecを入れる
# ディレクトリを作り移動 pi@raspberrypi:~ $ mkdir projects pi@raspberrypi:~ $ cd projects/ pi@raspberrypi:~/projects $ mkdir python_cec_sample pi@raspberrypi:~/projects $ cd python_cec_sample # venv環境を作る $ python -m venv env $ source env/bin/activate # python-cecを入れる $ pip install cec --no-cache-dir Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple Collecting cec Downloading https://www.piwheels.org/simple/cec/cec-0.2.7-cp37-cp37m-linux_armv7l.whl (146kB) 100% |████████████████████████████████| 153kB 268kB/s Installing collected packages: cec Successfully installed cec-0.2.7
Windows上でPyCharmからプロジェクトを作成する
File > New Project...
から新しいPythonプロジェクトを作成します。
設定は以下のようにします。
- 左ペインで
Pure Python
を選択 - 右側の
Location
に、ローカルに保存する場所(例:D:\projects\python_cec_sample) を指定 - Python Interpreter欄にある、
Previously configured Interperter
の右ボタンより、Add Python Interpreter
へ遷移 SSH Interpreter
を選択- Existing server configuration の右ボタンより
SSH configurations
へ遷移 +
を押して追加- 設定内容
- Host: 上記で設定したRaspberry Piの固定IP (
192.168.0.50
) - Port:
22
- Username:
pi
- Authentication type:
Key pair
- private key file: 上記で作ったprivateキー pi_rsa の場所
- Passphrase: 空欄
- Host: 上記で設定したRaspberry Piの固定IP (
- Test connectionをクリック、接続できればOKとする
- Connected to pi@192.168.0.50:22 のInterpriter指定は、Raspberry Piのvenv環境のPythonを指定 (
/home/pi/projects/python_cec_sample/env/bin/python
) Execute code using this interpreter with root privileges via sudo
にチェックを入れる- Remote project locationには、
/home/pi/projects/python_cec_sample
を指定
上記により、PyCharm上で import ce
と入力したときの補完が効くようになります。
もし補完が効かない場合は、以下を参考にリモートの再読み込みを行います。
【PyCharm】リモートインタプリタでライブラリ追加した際に正しく認識させる方法 | ゆとって生きたい。
- Project Interpreterの歯車マークで
Show All...
を選択 - ツリーマーク (Show paths for the selected interpreter) をクリック
- リフレッシュマーク (Reload List of Paths) をクリック
Pythonスクリプトの作成
python-cecのREADMEを読むと、できることが一通り書かれています。
このPythonスクリプトを実行すると、テレビの電源ON/OFFや音量調整ができたり、情報を出力できました。
import cec def main(): cec.init() tv = cec.Device(cec.CECDEVICE_TV) # 電源が入っているか print(tv.is_on()) # => True / False # if tv.is_on(): # # 電源がONの場合、次はスタンバイにする # tv.standby() # else: # # 電源が入っていない場合、電源を入れる # tv.power_on() # ベンダ print(tv.vendor) # => 000000 # 言語 print(tv.language) # => ??? (電源ONの場合は、jpn) print(tv.osd_string) # => TV print(tv.cec_version) # => 1.4 # 音量周りは、一度にどちらかだけ # 音量を一段階上げる # cec.volume_up() # 音量を一段階下げる cec.volume_down() if __name__ == '__main__': main()
ソースコード
Githubに上げました。
https://github.com/thinkAmi-sandbox/python_cec-sample