iMON-MINI × UbuntuでLinux-PCを赤外線リモコンで操作

当社では、Linux(Ubuntu8.04)に音楽プレーヤーを入れてBGMを流すことがあるのですが、
電話があったときに止めたりするのに、PCから操作するのが面倒!
ということで、赤外線リモコンで制御できるようにしました。

「Linuxで赤外線リモコン」は検索するといろいろあるようで、
このサイトを参考にPC-OP-RS1を使ってみようかと思ったのですが、
送信機能はいらないのと、リモコンを別に用意しないといけない
(あるものが使えればOKですが、使えないかもしれない)ので、
もう少し調べてみました。


こちらのサイトで、受信だけであれば特別な工作はいらないような記述があったので、
とりあえずこのサイトに記載されているiMONの比較的安価なものを探し出して
動かしてみることにしました。

リモコン)
 iMON-MINI http://www.ask-corp.jp/products/RC029.html
 実売価格は4,000くらい。

PC)
 linux (Ubuntu8.04) kernel 2.6.24-19

やったこと)
 lircをインストールして、動かしてみようとしましたが、よくわからず断念。
 ただ、dmesgをみると、デバイスを接続したときにHIDとして認識されているようなので、
 lircはあきらめて、HIDとして取れるデータで何かできないか調べてみました。

 結論からいえば、/dev/usb/hiddev1とかを読むとリモコンのデータが取れました。
 iMONをPCのUSBポートにつないで、

    > sudo od -x /dev/usb/hiddev1

 とかやって、リモコンのボタンをポチポチしてみればわかります。
 ※hiddev1のところは環境によって異なります。

 これで取れることがわかったので、覚えたてのpythonで簡単なスクリプトをつくって、
 リモコンデータ保存、リモコン制御できるようにしてみました。
 ※今回はちゃんとpythonの教科書をみながら書いたので、少しはマシにかけました。

プログラム仕様)
 データ保存コマンドで、リモコンデータを取得し、そのデータに名前を付けます。
 リモコンデーモンコマンド(マシン起動中は動かしっぱなし)の設定ファイルに、その名前と
 実行するコマンドの対応を書きます。

ソース)
 各コマンドの使い方はusageにあります。

 リモコンデータ保存コマンド mkdata.py

#!/usr/bin/python

import sys

usage = '''
mkdata.py [--device=devicefile] [--length=length] conffile
  devicefile:
    hiddev file (default auto-set)
  length:
    ir-command length (default "128")
'''

vendor_id = 0x15c2
product_id = 0x0041
checkfile='/sys/class/usb/hiddev%d/device/modalias'
devbase='/dev/usb/hiddev%d'

for index in range(15):
  try:
    fd = file(checkfile % index,'r')
    line = fd.readline()
    if line.startswith('usb:v%04Xp%04X' % (vendor_id,product_id)):
      devfile = devbase % index
      break
    fd.close()
  except:
    pass

irlength = 128
conffile = 'data.conf'
for arg in sys.argv[1:]:
  if arg.find('--device=') != -1:
    devfile = arg.split('=')[1]
  elif arg.find('--length=') != -1:
    irlength = arg.split('=')[1]
  elif arg == '--help' or arg == '-h':
    print usage
    sys.exit()
  else:
    conffile = arg

writefd = file(conffile,'w')
while True:
  keyword = raw_input("Input Keyword (exit for 'q'): ")
  keyword = keyword.strip('n')
  if keyword == 'q':
    break
  print 'Please push your remote controller'
  fd = file(devfile,'rb')
  readbin = fd.read(irlength)
  fd.close()
  datastr = ""
  for readch in readbin:
    datastr += '%02x ' % ord(readch)
  # output
  writefd.write(keyword + ',' + datastr+'n')

writefd.close()

 リモコンデーモンコマンド hidird.py

#!/usr/bin/python

import sys
import os

usage = '''
hidird.py [--device=devicefile] [--dataconf=data_conffile] [--commandconf=command_conffile]
  devicefile:
    hidraw device file name (default auto-set)
  data_conffile:
    IR data information configuration file (default "data.conf")
  command_conffile:
    Definition of relation between IR-Data and Console-Command (default "ircmd.conf")
'''

vendor_id = 0x15c2
product_id = 0x0041
checkfile='/sys/class/usb/hiddev%d/device/modalias'
devbase='/dev/usb/hiddev%d'

for index in range(15):
  try:
    fd = file(checkfile % index,'r')
    line = fd.readline()
    if line.startswith('usb:v%04Xp%04X' % (vendor_id,product_id)):
      devfile = devbase % index
      print 'device file:'+devfile
      break
    fd.close()
  except:
    pass

ir_conffile = 'data.conf'
exec_conffile = 'ircmd.conf'

for arg in sys.argv[1:]:
  if arg.find('--device=') != -1:
    devfile = arg.split('=')[1]
  elif arg.find('--dataconf=') != -1:
    ir_conffile = arg.split('=')[1]
  elif arg.find('--commandconf=') != -1:
    exec_conffile = arg.split('=')[1]
  else:
    print usage
    sys.exit()

ir_datalength=16

# read IR map
try:
  fd = file(ir_conffile,'r')
except:
  print "Cannot find the file:"+ir_conffile
  sys.exit()

irmap = {}
for readline in fd:
  irpair = readline.split(',')
  irbin = []
  for value in irpair[1].split(' '):
    if value != '' and value != 'n':
      irbin.append(chr(int(value,16)))
  irmap[tuple(irbin)] = irpair[0]
  ir_datalength = len(irbin)
fd.close()

while True:
  try:
    fd = file(devfile,'rb')
    #readbin = fd.read(ir_datalength)
    readbin = tuple(fd.read(ir_datalength))
    fd.close()
    if irmap.has_key(readbin):
      print "Receive:"+irmap[readbin]
      try:
        fd = file(exec_conffile,'r')
        for line in fd:
          if line.startswith(irmap[readbin]+","):
            os.system(line.split(',')[1])
        fd.close()
      except:
        pass
    else:
      print "Receive:Unknown ir-data"
      sys.exit()
  except:
    break

設定ファイル)
 (参考)リモコンデーモンコマンド用設定ファイル ircmd.conf

power-on,echo power on
power-off,echo pushed poweroff
volume-up,mpc volume +3
volume-down,mpc volume -3
mute,mpc pause
play,mpc toggle

補足)
 リモコンデーモンコマンドですが、
 手でリモコンをさえぎったりした時に、変なデータがとれてUnknownになることがあるのですが、
 なぜか今の環境ではいったんUnknownになるとずーっとUnknownになる、という状態に陥りました。
 とりあえず、Unknownになったらプログラムを終了するようにして、デーモンコマンドをループする次のような
 シェルスクリプトを書いて対処しています。

 ループスクリプト irloop

#!/bin/sh

cd /home/xxx/irctrl

killall -9 hidird.py > /dev/null 2>&1
while true
do
  ./hidird.py
  sleep 1
done

参考サイト:

12/16注記:本記事記載のプログラムですが、いったん異常なデータを取得するとiMONを抜き差ししないと復活しない問題があります。ご要望(と私の余裕)があれば解析して対処します。(たぶんリセットするようなデータをiMONに送る必要があると思います。)
2010/2/13追記:
コメントいただきましたので、少し詳しく使い方を書きます。
☆ツールの使い方

・大まかな流れ
1. mkdata.pyで、リモコンのボタンを押した時に受信したデータにわかりやすい名前をつける。
2. 1でつけた名前を使って、ボタンが押されたときに実行させたいコマンドを設定ファイルに書く。
3. hidird.pyを起動し、実際にリモコンのボタンが押されたときに、コマンドを実行させる。

・詳しい説明
1. リモコンデータに名前をつける。

例えば、データが取れるデバイスのファイル名が、”/dev/usbmon4″の場合、

mkdata.py --device=/dev/usbmon4 data.conf

を実行してください。

なお、/dev/usbmon4から取得できるデータのサイズ(それぞれのリモコンデータを識別するのに必要なサイズ)が128バイトでなければ、mkdata.pyコマンドのパラメータに、–length=256 (256バイトの場合)のように追加してください。

mkdata.pyを起動すると、
Input Keyword (exit for ‘q’):
と表示されますので、たとえば再生ボタンを登録したいのであれば、
‘play’
のような文字列を入力してから、リモコンの再生ボタンを押して下さい。
そうすると、data.confに’play’というキーワードと再生ボタンを押した時に/dev/usbmon4に出力されるデータの対応が保存されます。

2. 設定ファイルを書く
先程、playというキーワードでデータをとったので例えば、
play,echo pushed play button
という内容で保存します。ファイル名はircmd.confとします。

3. hidird.pyの実行

hidird.py --device=/dev/usbmon4

を実行します。
すると、リモコンの再生ボタンをおすと、’pushed play button’という表示がコンソールに出てくると思います。

16 Comments

  1. ubuntu 9.10 + xbmc + ps3 BD リモコン でHDDレコーダーをつくりました。

    xbmc上では、BDリモコンは動作しておりますが、デスクトップでは動作しません。
    xbmcが安定していれば全く問題ないのですが、たまに落ちたりするので、その場合にキーボード・マウスをつないでいない環境ではどうしようもなく、またわざわざつなぐのも面倒なので、リモコンでなんとかならないかと検索しているところで、こちらへたどり着きました。

    私の環境では、
    sudo od -x /dev/usbmon4
    でコマンドが送信されていることを確認いたしました。

    非常に初心者の質問で申し訳ございませんが、このスクリプトはどのようにして使用するのですか?
    また、キーボードエミュレートは可能でしょうか?

    よろしくお願いいたします。

  2. うどん玉さん、コメントありがとうございます。
    なかなか面白そうなHackをされていますね。

    さて、ご質問の件ですが、使い方のご説明の前にまず、
    プロセスが落ちてお困りでしたら、プロセス監視ツールみたいなものを
    使ってみるのも一案かと思います。
    いまググってみたところ、
    http://ubulog.blogspot.com/2009/02/ubuntu.html
    というサイトに簡単なツールがありました。

    で、使い方の説明ですが、長くなったので、本文の方に追記しました。
    もしよろしければご覧ください。

    あと、キーボードエミュレートについてはちょっと私にはわかりませんが、
    本ツールの仕組みが、リモコンのボタンをなんらかのコマンドに対応付ける
    ものになりますので、その範囲内でお考えいただければよいかと思います。

  3. 早速のresありがとうございます。

    プロセス監視ツール。。いいですね。
    わざわざ調べていただきありがとうございます。

    さて、詳細な説明を加えていただきましたので、早速導入させていただきましたが、いきなりつまづいております。

    # sudo su –
    # python mkdata.py 窶電evice=/dev/input/event6 data.conf
    (前回は/dev/usbmon4でしたが、再度設定しなおすと上記でコマンドを確認できました。)
    とすると、説明どおりに
    Input Keyword (exit for ‘q’):
    と返ってきます。
    しかし、play と入力すると

    Please push your remote controller
    Traceback (most recent call last):
    File “mkdata.py”, line 49, in
    fd = file(devfile,’rb’)
    NameError: name ‘devfile’ is not defined

    となってしまいます。

    どうすればいいでしょうか?
    ubuntu 9.10 です。

    重ね重ねよろしくお願いいたします。

  4. うどん玉さん、すみません。
    mkdata.pyのオプション”device”ですが、’-‘(ハイフン)は2つ必要です。
    2つ書いたのですが、表示は1つになってしまっていましたね。
    (わかりやすいように本文の方をちょっと直しておきました。)
    お手数ですが、もう一度トライしてみていただけますでしょうか?

  5. Hello!

    I don’t speek english.
    This is google ㅡ.ㅡ+

    Can I get help?

    ubuntu version 9.10
    After connecting the remote control to be caught in hiddev1 was OK.
    . Py file, please let us know how to set up.

  6. Thank you for your comments.

    I don’t speek English too 😉

    The file .py need to have execute permission.
    After writing .py file by any editor, change permission of the file.
    $ chmod +x mkdata.py

    If .py file has execute permission, you can execute the file.
    For example,
    $ ./mkdata.py data.conf

    If you get any error messages, please tell me the messages.

    Thank you.

  7. Thank you for fast and friendly reply.

    . Py files are present on the desktop.
    Using gedit text editor. py file was created.

    This messages

    File “./mkdata.py”, line 3
    import sys
    ^

    Once again, thank you kindly reply.

    IndentationError : unexpected indent

  8. Thank you for every time.

    . py files to be processed after the job creation please outlined.
    After the last set is wrong, re-install Ubuntu has.

    I’m sorry,. py writing instruction, and then I will proceed to other matters such as care Uh, please outlined wondering?

    Thank you once again.

  9. The extension “.py” means that the file is Python script.
    Python is very popular programing language.
    On Ubuntu, Python is installed by default.

    On this article I wrote, all of the script is Python script.
    So you should understand Python at least on beginner level.

    If you cannot understand about Python at all now,
    I recommend you to receive the support about Python in your mother language.
    For example, search the keyword ‘Python’ by google.

    I hope you solve this problem.

    Thanks.

  10. Hi, I would like to thank sincerely each time
    First, thanks for the python has it own study
    Thank you sincerely.

    python mkdata.py –device=/dev/usbmon2 data.conf

    Then conducted by running the input keyword
    data.conf information stored in the remote control could be confirmed.

    However,
    Play, echo pushed play button
    in no listing of the contents.

    what should I do here?

  11. I do not ripple delete. I’m sorry.

    hidird.py run the file, but frankly,
    An error has been identified as follows.

    device file:/dev/usb/hiddev1
    Traceback (most recent call last):
    File “hidird.py”, line 61, in
    irbin.append(chr(int(value,16)))
    ValueError: invalid literal for int() with base 16: “n’up'”

    Obtain advice on this part

  12. Hello.

    We are almost there!
    Please do the following steps.

    Step1
    Connect iMON to your PC.

    Step2
    Enter this command.

    $ python mkdata.py data.conf

    Step3
    So you will get the message “Input Keyword (exit for ‘q’): “,
    Enter the keyword like ‘up’, ‘down’ or others.

    Step4
    And you will get the message “Please push your remote controller”.
    Push the button on your remote control.
    The button corresponds the keyword you enter.
    After pushing the button, please repeat Step3 for registing the other buttons.

    Step5
    Edit the file ‘ircmd.conf’ as following command.

    $ vi ircmd.conf

    Content of ‘ircmd.conf’ is like this.

    up,echo pushed up
    down,echo pushed down

    ‘up’ or ‘down’ is the keyword you regist at Step3 – Step4.
    ‘echo pushed up’ or ‘echo pushed down’ is the command which is executed at pushing the button on your remote control.

    Step6
    Enter this command.

    $ python hidird.py

    If you get the message ‘pushed up’ or ‘pushed down’ at pushing the button on your remote control,
    it is a success.

    Best of luck!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*