はじめに
RaspberryPi3を使ってIR信号(赤外線信号)を送信して家電を制御するためにしたことをメモ。
本当はIRKitがあれば簡単にできる(記事)。しかし現在買現在買うことができず、後継機はあるようだがすぐには手に入れることができなさそうなので、、ラズパイのGPIOからIR送信する。(こっちは低コストですから (´;ω;`)ブワッ
やりたいことはスマホやPCからラズパイにIR送信のリクエストを送り、GPIOからIR送信することで家電を制御できるようにする。
必要なもの
最低限必要なものは、ラズパイ・赤外線受信モジュール・赤外線LED。
一応、赤外線送信を強くするためトランジスタを使った回路にしているが、受光器に直接向けるのならば問題ないと思う。ただ、エアコンや照明のような少し距離があるものだと、シンプルな回路だと光量が弱く届かないかもしれないので注意が必要。
構成とリクエストについて
リクエストは、iOS/Androidとプラットフォームを選ばず操作したいのでREST Apiでできるようにする。
また、iOS限定だが、せっかくiOS10がリリースされ、公式にhomeアプリがプリインストールされたのでhomebridgeも導入してラズパイをhomekit製品としてiPhoneから操作できるようにもする。
ものすごく大まかな構成
実践
IR解析してIR送信する
LIRCを使ってリモコンキーの解析、送信をする。
LIRCはリモコンキーのデコードや送信をコンフィグやコマンドラインなどを行うことができるLinuxのパッケージ。
LIRCのinstallとsetup
install
パッケージからインストール
$ sudo apt-get install -y lirc
ハードウェア設定
/etc/lirc/hardware.conf
にデーモン起動時の引数・デバイス・モジュールを指定する。
詳しくは公式のoption項目を参照してください。
※ sudo
コマンドで編集します
LIRCD_ARGS="--uinput"
DRIVER="default"
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
カーネルモジュール・GPIOを設定
ラズパイのブートコンフィグ(/boot/config.txt
)にモジュールと使用するGPIOを追記する。
dtoverlay
を使ってデバイスツリーにモジュール(lirc-rpi
)を追加、そしてGPIOの設定。
ここではIR送信をGOIO17、受信をGPIO18としている。
※ sudo
コマンドで編集
# Uncomment this to enable the lirc-rpi module
dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=18,gpio_in_pull=up
確認する
再起動して正常にドライバが起動しているか確認する。
lirc_rpi
はラズパイのデバイスドライバで、ソースをから、 lirc_rpi
は lirc_dev
をロードして使っている。
# 再起動
$ sudo reboot
:
# 起動できているかdmesgで確認する
$ dmesg | grep lirc
[ 4.077720] lirc_dev: IR Remote Control driver registered, major 245
[ 4.117482] lirc_rpi: module is from the staging directory, the quality is unknown, you have been warned.
[ 5.070398] lirc_rpi: auto-detected active low receiver on GPIO pin 18
[ 5.070709] lirc_rpi lirc_rpi: lirc_dev: driver lirc_rpi registered at minor = 0
[ 5.070719] lirc_rpi: driver registered!
[ 8.883938] input: lircd as /devices/virtual/input/input0
# ドライバの確認
$ lsmod | grep lirc
lirc_rpi 6478 0
lirc_dev 8310 1 lirc_rpi
rc_core 16468 1 lirc_dev
IRコマンドを解析してconfigを作成する
送信したいリモコンコードを解析してconfファイルを作成する。
IR受信用の回路を組む
入力ピンとして設定した GOIO18
にIRレシーバーを接続。IR受信モジュールの正面左から5V・GRD・GPIO18。
IR受信が有効化どうか確認する
mode2
コマンドを使って待受状態にする。テレビのリモコンなどをレシーバーに向けて送信してみて数字の羅列が流れればOK。
# lircデーモンを停止
$ sudo /etc/init.d/lircd stop
# IR受信信号を表示
$ mode2 -d /dev/lirc0
# 何かリモコンコードを送信してみて以下のような出力がでれば受信できています
# (待機時は何も出力されない)
pulse 573
space 1639
:
configファイルを作成
リモコン操作したい機器のコンフィグファイルを作成する。
コンフィグファイルの作成作業は、リモコンごとに行う。
例えば、エアコン・テレビ・コンポ、と3つのリモコンのコンフィグを作りたいならば3回行う。そして3つのコンフィグファイルを一つのコンフィグファイルにまとめる。このまとめたファイルが最終的なコンフィグファイルとなる。
リモコンのconfigファイル作成
irrecord
コマンドを実行してコメントに従ってconfigファイルを作成する。
$ irrecord -n -d /dev/lirc0 ./tv.conf
# Enter二回押して登録開始
Press RETURN now to start recording.
# ボタンを押し続けたりする
Please enter the name for the next button (press <ENTER> to finish recording)
# ここで登録するコマンド名を入力
# そしてリモコンで登録したいコマンドを押して受信させる
:
# 繰り返す
Please enter the name for the next button (press <ENTER> to finish recording)
# 終わりはそのままEnter
configファイルの編集
読み込みでエラーになるようなので、name
を空白なしの文字列に変更する。
$ vim ./tv.conf
# コメントは消してもいいと思う
begin remote
name tv # ここの名前を空白なしの文字列に変更する
:
end remote
configファイルをコピーする
作成したconfigファイルを /etc/lirc/lircd.conf
にマージ。もし他のリモコンを作りたい場合は irrecord
コマンドからの作業を繰り返す。
$ sudo su
# テレビのリモコンをマージ
% cat ./tv.conf >> /etc/lirc/lircd.conf
# 照明のリモコンをマージ
% cat ./room_right.conf >> /etc/lirc/lircd.conf
:
% exit
# 再読込
$ sudo /etc/init.d/lirc restart
登録したリモコンコードを確認してみる
irw
を実行して、登録したリモコンをレシーバに向かって送信してみる。
正常に登録されている場合は登録した内容が出力される。もしうまく行かなければ、 lirc
のりスタートなどしてみてください。
$ irw
# 登録したリモコンをレシーバに向かって送信する
0000000000000xxx 00 power tv
IR送信してみる
送信は irsend
コマンド。
送信用の回路を組む
送信する赤外線LEDを強化するためにトランジスタで増幅した回路で、少しは強化されているはず。。
もしトランジスタなどない場合はGPIOとGRDにつなげるだけか、拡散キャップつけるでもいいと思う。
登録してあるリモコンコードを表示
まずは、先程作成したコンフィグファイルから、登録できているか確認してみる。
# 登録してあるリスト表示 1
$ irsend list "" ""
irsend: tv
irsend: room_light
# 登録してあるリスト表示 2 (更に詳細)
$ irsend list tv ""
irsend: 00000000000048b7 power
irsend: 00000000000058a7 vol-up
:
送信する
コマンドを実行でIRコードが送信される。 しっかりと送れていれば電源やチャンネルなど変えることができるはず。復数連続で送らなければ操作できないデバイスもあるので、その場合は for
分など使って繰り返し送信する必要があるかも。
# 一回送信
$ irsend send_once tv power
# 複数回送信してみる
$ for i in {0..5}; do irsend send_once tv vol-up; echo $i; done;
WebIOPiを使いWeb経由でIR送信できるようにする
Web経由でのスクリプト操作をするために、REST APiやHTTPサーバを簡単に構築できるWebIOPiを導入する。
WebIOPiの構築
Python3必須。それとRasoberryPi2,3の場合、パッチを当てる。(ボードの種類が変わり、GPIOの配置など異なるため)
python3 install
python3をインストール済みの場合はスキップしてください。
- install
$ sudo apt-get install python3-dev python3-pip
- python link
$ which python
/usr/bin/python
$ cd /usr/bin/
$ sudo unlink python
$ sudo ln -s python3.4 python
# check
$ python -V
Python 3.4.2
WebIOPi install
ここからWebIOPiのインストール作業。
本体のdownload
$ mkdir ~/webIOPi
$ wget http://sourceforge.net/projects/webiopi/files/WebIOPi-0.7.1.tar.gz
$ tar -zxvf WebIOPi-0.7.1.tar.gz
パッチをあてる
オリジナルのWebIOPiは初代ラズパイ用なのでボード型番、GPIO配列が異なるので、そのままだと動作しない。そこでRaspberryPi2,3用に修正パッチをあてる必要がある。(https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98981)
# patchをclone
$ cd ~
$ git clone https://github.com/acrobotic/Ai_Demos_RPi
# patchをあてる
$ cd ./WebIOPi-0.7.1
$ patch -p0 -i ../Ai_Demos_RPi/demos/gpio/webiopi_raspberry_pi_2_cpu_support.patch
$ patch -p0 -i ../Ai_Demos_RPi/demos/gpio/webiopi_raspberry_pi_2_gpio_40_pin.patch
$ patch -p0 -i ../Ai_Demos_RPi/demos/gpio/webiopi_raspberry_pi_2_gpio_mapping.patch
install
パッチをあてた後に、setup.sh
でインストール。
$ sudo ./setup.sh
Do you want to access WebIOPi over Internet? [y/n] n # for Waves : 特に今は必要ない
# Raspberry-pi 再起動
自動起動設定
自動起動するため、SystemServiceに登録する。
# 登録
sudo systemctl enable webiopi.service
# start / stop
sudo systemctl start webiopi.service
sudo systemctl stop webiopi.service
起動と停止、再起動は他のサービスと同じ。
$ sudo service webiopi start # 起動
$ sudo service webiopi stop # 停止
$ sudo service webiopi restart # 再起動
debug modeで動作したい場合は -d
で直接起動するとログなどがコンソールに出力される。
$ sudo webiopi -c /etc/webiopi/config -d
HTTPサーバにアクセスする
http://<raspberry pi3 address>:8000
でアクセスでる。ログインのユーザとパスワードは webiopi
/ raspberry
。
リスト一番上の GPIO Header
にアクセスして、LEDなどを繋いでGPIOを操作することができるか確認してみる。
Password認証を無効にしたい場合は /etc/webiopi/config
を以下のように編集することで可能。
$ sudo vim /etc/webiopi/config
passwd-file = /etc/webiopi/passwd
↓ # コメントアウトする
#passwd-file = /etc/webiopi/passwd
REST Apiを使ってみる
色々とあるが、基本的なON/OFFを試してみる。(LEDなどをつなげて確認してみるとわかりやすい)
# on
curl -X POST <raspberry pi address>:8000/GPIO/27/value/1
# off
curl -X POST <raspberry pi address>:8000/GPIO/27/value/0
WebIOpi スクリプト
IR送信するPythonスクリプトを作成して、REST Api経由で実行できるようにする。
scriptファイルの作成
適当な場所にスクリプトファイルを作成。種類・コマンド・送信回数を引数として、先程設定した irsend
コマンドを実行しするだけのシンプルなスクリプト。IR送信は基本的にレスポンスはない投げっぱなしなので、戻り値は何でもよくて、ここでは OK
としている。
公式のサンプル参考にしているが、GPIO操作を直接しないので setup()
や loop()
は書いてない。
import webiopi
import os
@webiopi.macro
def sendIr(kind, command, count="1"):
for _ in range(int(count)):
os.system("irsend send_once " + kind + " " + command)
return "OK"
scriptファイルの設定
/etc/webiopi/config
に先ほど作成したスクリプトファイルを指定する。
[SCRIPTS]
# Load custom scripts syntax :
# name = sourcefile
# each sourcefile may have setup, loop and destroy functions and macros
myscript = <your project dir>/webIOPi/project/script.py
REST Apiからscriptを実行してみる
curl
コマンドで確認。scriptはPOSTリクエスト。 (http://webiopi.trouch.com/RESTAPI.html#call-a-macro-on-the-server)
$ curl -X POST <raspberry pi address>:8000/macros/sendIr/tv,power,1
OK
Webページからもスクリプト実行できるようにする
先ほど作成したスクリプトをWebページからも実行してみる。
htmlファイルの作成
ここも公式のサンプルを参考にしている。
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="/webiopi.js"></script>
<script>
webiopi().ready(function(){
// webiopiとjqueryの読み込みをする
$("send_ir").click(function(){
// callback object
var callback = function(macro, args, response) {
// do nothing
}
// 引数は配列。これはサンプルのためハードコード。
var args = ["kenwood", "power", "3"];
// method name, args, callback
// - callbackが必要ないならnullでも良い
webiopi().callMacro("sendIr", args, callbcak);
});
});
</script>
<title>sendir</title>
</head>
<body>
<p id="send_ir">send ir test</p>
</body>
</html>
htmlファイルの設定
スクリプトファイル同様、htmlファイルがあるディレクトリを指定する。
[HTTP]
:
doc-root = <your project dir>/webIOPi/project
アクセスしてスクリプトを実行してみる
http://<raspberry pi address>:8000
にアクセスすると先ほど作成した index.html
が表示されるはず。さらに send ir test
をクリックするとIR送信スクリプトが実行される。ログなどを仕込みながら確認してみてください。
ここまでくれば、リモコンコード送信するボタンを追加していけばブラウザから家電を操作することができる。
iOSホームアプリから制御する
homebridgeを使ってラズパイをHomeKit製品としてiOS製品に認識させ、ホームアプリ(iOS10から追加されたアップルの公式アプリ)に登録してIR送信リクエストを行えるようにする。
homebridgeの構築
homebridgeの構築には、local dnsの avahi
、 nodejs
が必要。
avahi install
avahiはローカルでホスト名のアクセスを可能とさせるDNSのようなもで、AppleのBonjour同様、導入するとローカルネットワーク内でホスト名でアクセスすることができる。
$ sudo apt-get install libavahi-compat-libdnssd-dev
nodejs install
すでに導入している場合はスキップしてください。ここでは v6.6.0
をインストールする。
- install
$ sudo apt-get install -y nodejs npm
- インストールされた場所にパスが通るように修正
$ sudo npm cache clean
# n はバージョン管理ツール
$ sudo npm install n -g
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
n@2.1.4 /usr/local/lib/node_modules/n
$ sudo n stable
install : node-v6.6.0
mkdir : /usr/local/n/versions/node/6.6.0
fetch : https://nodejs.org/dist/v6.6.0/node-v6.6.0-linux-armv7l.tar.gz
######################################################################## 100.0%
installed : v6.6.0
#version確認
$ node -v
v6.6.0
homebridge install
homebridge本体と、HTTPリクエストさせるプラグインをインストールする。多くのプラグインがあるので、npnjsで探して試すのも面白いかも。
$ sudo npm install -g homebridge
$ sudo npm install -g homebridge-http # https://github.com/rudders/homebridge-http
configファイルの作成
コンフィグにあるリストがホームアプリが認識する操作リスト(アクセサリ)となる。json形式で、デフォルトはホームディレクトリ直下の ~/.homebridge/config.json
となっている。
このファイルに先程構築したREST Apiをコマンドごとに追加していく。以下コンフィグファイルの説明。
-
username
はラズパイのMACアドレスなのでifconfig
などで調べて追加する。 - 追加したいコマンドを
accessories
の配列に追加する。 -
service
はソースからSwitch
かLight
のようだが、それで挙動が変わる感じはなかったのでどちらでもいいと思う。 -
status_url
ホームアプリ起動時や、送信後などにステータス取得するためのURL。IR送信は投げっぱなしで、ステータスなど無いのがほとんどなので、常にOFFでもいいと思う。ここでは一応GPIOの値を取るようにしている。 -
on_url
/off_url
はどちらも同じで、IR送信のREST Apiを自身のWebIOPiのアドレス (http://localhost:8000
)にリクエスト指定する。
{
"bridge":
{
"name": "Homebridge",
"username": "B8:27:XX:XX:XX:XX",
"port": 51826,
"pin": "031-45-154"
},
"accessories": [
{ "accessory" : "Http", "http_method": "POST",
"searvice":"Switch",
"status_url": "http://localhost:8000/GPIO/17/value", "switchHandling": "yes",
"name" : "コンポ電源",
"on_url" : "http://localhost:8000/macros/sendIr/kenwood,power",
"off_url" : "http://localhost:8000/macros/sendIr/kenwood,power"
},
:
:
]
}
自動起動設定する
方法はいくつもあるようだが、init.d
に起動スクリプトを追加することにする。
起動スクリプトの作成
templateからスクリプトを作成して、serviceとして登録する。
# templateをダウンロード
$ sudo curl https://raw.githubusercontent.com/fhd/init-script-template/master/template /etc/init.d/homebridge
# 編集
$ sudo vim /etc/init.d/homebridge
:
dir=<your home directry>
cmd="DEBUG=* /usr/local/bin/homebridge"
user=<your name>
:
権限設定して登録
$ sudo chmod 755 /etc/init.d/homebridge
$ sudo update-rc.d homebridge defaults
# 再起動
$ sudo reboot
起動できているか確認
ログを確認してみる。起動が成功すると最後にPINコードが表示される。これはホームアプリ登録時に必要となる。(~/.homebridge/config.json
に記載されている)
$ cat /var/log/homebridge.log
:
[10/26/2016, 11:52:01 PM] [TV-up] Initializing Http accessory...
[10/26/2016, 11:52:01 PM] [TV-down] Initializing Http accessory...
[10/26/2016, 11:52:01 PM] [TV-mute] Initializing Http accessory...
Scan this code with your HomeKit App on your iOS device to pair with Homebridge:
┌────────────┐
│ 031-45-154 │
└────────────┘
[10/26/2016, 11:52:01 PM] Homebridge is running on port 51826.
ホームアプリに登録して操作してみる
同一ネットワークで起動できているなら Homebridge
が出現するはずなのでタップ。 このまま追加
でコード入力へ。。 (ターミナルの画面だと正常にスキャンできないので コードを手動で入力
をタップして直接入力がおすすめ)
認識するためにコードを入力する
config.json
のアクセサリが追加される。 アクセサリの よく使う項目に含める
を有効にするとコントロールセンターからアクセスできる。
これでiPhoneにHomeKit製品として認識させることができた。ただし、試したところ認識できるのは一台のみで、他のiPhoneで認識することはできず、1対1のようだ。
おしまい
今は赤外線LEDをスターウォーズのBB-2に仕込んでテレビの操作ができるようにしています。iPhoneはHomeKit経由で、AndroidはWebブラウザ経由でテレビやコンポを操作しています。WebはBootstrapなどで簡単にレスポンシブデザインなページができるのでセンスがなくても何とかなりました。
自分でがっつりコードを書かなくても様々なライブラリの組み合わせで実用性のあるものを作れるのは楽しいですね。最近はESP8266にハマりだしたので、それらを使った複数部屋へのリモコンネットワーク構築を考えています。