5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Raspberry Pi 3 + LIRC + Pythonでテレビのon/off

Last updated at Posted at 2019-02-07

背景

Raspberry PiからテレビのOn/Offを赤外線で制御するにはLIRCというライブラリが便利そうだということがわかりました。

しかし、LIRC向けのPythonライブラリで信号を出せるものがどうにも見つかりません(検索上位に出るpython-lircは受信=学習側のようです)。そこで念のためにLIRCのコードを見てみると、0.10.1 からPythonライブラリが同梱されていることに気づきました。

そこでこの記事ではLIRCに同梱されたPythonライブラリを使ってテレビをOn/Offするサンプルを作成します。

環境

  • Raspberry Pi Model B V1.2
  • 2018-11-13-raspbian-stretch-lite
  • 赤外線LED OSI5FU5111C-40
  • 200ohm 抵抗

LIRCのインストール

以下のコマンドでLIRCはインストールされますが、デフォルト環境では0.9.4c-9がインストールされてしまうため、Pythonのライブラリが入りません。

pi@raspberrypi:~$ sudo apt-get install lirc

そこで /etc/apt/sources.listを以下のように変更し、testingリポジトリを参照できるようにします。


deb http://raspbian.raspberrypi.org/raspbian/ stretch main contrib non-free rpi
deb http://raspbian.raspberrypi.org/raspbian/ testing main contrib non-free rpi #追加
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
# deb-src http://raspbian.raspberrypi.org/raspbian/ stretch main contrib non-free rpi                                                                                 

そしてお約束のアップデートをかけます。

pi@raspberrypi:~$ sudo apt-get update

インストール。0.10.1-5がインストールされます。

pi@raspberrypi:~$ sudo apt-get install lirc

念のためにPythonライブラリが入っていることも確認しましょう。

pi@raspberrypi:~$ tree /usr/lib/arm-linux-gnueabihf/python3.7/site-packages/lirc
/usr/lib/arm-linux-gnueabihf/python3.7/site-packages/lirc
├── async_client.py
├── client.py
├── _client.so
├── config.py
├── database.py
├── __init__.py
└── paths.py

Python3.7のインストール

インストールされたライブラリがPython3.7用となっているのでPython3.7をインストールします。

sudo apt-get install python3.7

LIRCの設定

こちらのサイトを参考に設定を行います。感謝。

/boot/config.txt
# Uncomment this to enable the lirc-rpi module
dtoverlay=lirc-rpi
dtparam=gpio_out_pin=25
dtparam=gpio_in_pin=24
/etc/lirc/lirc_options.conf
[lircd]
nodaemon        = False
# driver          = devinput
driver          = default
# device          = auto
device          = /dev/lirc0

再起動しておきましょう。以下のドライバがロードされていればOKなようです。

pi@raspberrypi:~$ lsmod | grep lirc
lirc_rpi               16384  2
lirc_dev               16384  1 lirc_rpi

また、制御したい機器に合わせて/etc/lirc/lircd.conf.dに設定ファイルを置きます。ここに大量の設定ファイルがあるので、該当するものがあればそのまま使えると思います。

私の場合はSONYのRM-JD030というリモコンですが、なかったのでSONYのテレビ一般用っぽいファイルをコピーし、以下のような設定にしました。

/etc/lirc/lircd.conf.d/sony.tv.conf
begin remote

  name  SONY-TV
  bits            7
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       2574   444
  one          1246   557
  zero          625   557
  ptrail        580
  post_data_bits  4
  post_data      0x8
  gap          45239
  toggle_bit      0
  min_repeat      2


      begin codes
          POWER                    0x54
      end codes

end remote

設定ファイルを配置したらデーモンを再起動します。

pi@raspberrypi:~$ sudo /etc/init.d/lircd  restart

設定が反映されていることを確認します。

pi@raspberrypi:~$ irsend LIST "" ""

SONY-TV
devinput-32
devinput-64

以下のコマンドで試し打ちします。

pi@raspberrypi:~$ irsend SEND_ONCE SONY-TV POWER

Pythonからの制御

同梱のテストが参考になります。公式サイトのbrowse the repositoryはリンクが切れているようなので、手元にクローンして確認します。

pi@raspberrypi:~$ git clone git://git.code.sf.net/p/lirc/git lirc
pi@raspberrypi:~$ cd lirc
pi@raspberrypi:~$ vi python-pkg/tests/test_client.py
python-pkg/tests/test_client.py
137     def testRemotesCommmand(self):
138         ''' Do LIST without arguments . '''
139
140         if os.path.exists(_SOCKET):
141             os.unlink(_SOCKET)
142         cmd = [_SOCAT, 'UNIX-LISTEN:' + _SOCKET,
143                'EXEC:"%s ./dummy-server 100"' % _EXPECT]
144         with subprocess.Popen(cmd,
145                               stdout = subprocess.PIPE,
146                               stderr = subprocess.STDOUT) as child:
147             _wait_for_socket()
148             with CommandConnection(socket_path=_SOCKET) as conn:
149                 reply = lirc.ListRemotesCommand(conn).run()
150             self.assertEqual(len(reply.data), 2)
151             self.assertEqual(reply.success, True)
152             self.assertEqual(reply.data[0], 'mceusb1')
153             self.assertEqual(reply.data[1], 'mceusb2')
154             self.assertEqual(reply.sighup, False)

どうやらCommandConnectionクラスにsocket_pathを設定してインスタンスを作成。さらに、Commandクラスの各種サブクラスのインスタンスを作成してrun()を呼べばよさそうです。

また、socket_pathは以下の設定ファイルに記述されています。

/etc/lirc/lirc_options.conf
[lircd]
# 中略
output          = /var/run/lirc/lircd

テストではListRemotesCommandクラス使用していますが(irsend LIST "" ""と同様の挙動)、コマンドの送信にはSendCommandクラスが使えそうです。

ちなみに、実装は以下の個所となります。

python-pkg/lirc/client.py
598 class SendCommand(Command):
599     ''' Send given key, see SEND_ONCE in lircd(8) manpage. '''
600
601     def __init__(self, connection: AbstractConnection,
602                  remote: str, keys: str):
603         if not len(keys):
604             raise ValueError('No keys to send given')
605         cmd = 'SEND_ONCE %s %s\n' % (remote, ' '.join(keys))
606         Command.__init__(self, cmd, connection)

以上より、このようなサンプルとなりました。

sample.py
import lirc

conn = lirc.CommandConnection(socket_path='/var/run/lirc/lircd')
lirc.SendCommand(conn, remote='SONY-TV', keys=['POWER']).run()

irsend SEND_ONCE SONY-TV POWERと一致した呼び出しで分かりやすいですね。

5
7
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
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?