Edited at

RaspberryPi3とhomekitとwebIOPiで家電操作する

More than 1 year has passed since last update.


はじめに

RaspberryPi3を使ってIR信号(赤外線信号)を送信して家電を制御するためにしたことをメモ。

本当はIRKitがあれば簡単にできる(記事)。しかし現在買現在買うことができず、後継機はあるようだがすぐには手に入れることができなさそうなので、、ラズパイのGPIOからIR送信する。(こっちは低コストですから (´;ω;`)ブワッ

やりたいことはスマホやPCからラズパイにIR送信のリクエストを送り、GPIOからIR送信することで家電を制御できるようにする。


必要なもの

最低限必要なものは、ラズパイ・赤外線受信モジュール赤外線LED

一応、赤外線送信を強くするためトランジスタを使った回路にしているが、受光器に直接向けるのならば問題ないと思う。ただ、エアコンや照明のような少し距離があるものだと、シンプルな回路だと光量が弱く届かないかもしれないので注意が必要。


構成とリクエストについて

リクエストは、iOS/Androidとプラットフォームを選ばず操作したいのでREST Apiでできるようにする。

また、iOS限定だが、せっかくiOS10がリリースされ、公式にhomeアプリがプリインストールされたのでhomebridgeも導入してラズパイをhomekit製品としてiPhoneから操作できるようにもする。

ものすごく大まかな構成

スクリーンショット 2016-11-03 22.54.45.png


実践


IR解析してIR送信する

LIRCを使ってリモコンキーの解析、送信をする。

LIRCはリモコンキーのデコードや送信をコンフィグやコマンドラインなどを行うことができるLinuxのパッケージ。


LIRCのinstallとsetup


install

パッケージからインストール

$ sudo apt-get install -y lirc


ハードウェア設定

/etc/lirc/hardware.conf にデーモン起動時の引数・デバイス・モジュールを指定する。

詳しくは公式のoption項目を参照してください。

sudo コマンドで編集します


/etc/lirc/hardware.conf

LIRCD_ARGS="--uinput"

DRIVER="default"
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"


カーネルモジュール・GPIOを設定

ラズパイのブートコンフィグ(/boot/config.txt)にモジュールと使用するGPIOを追記する。

dtoverlayを使ってデバイスツリーにモジュール(lirc-rpi)を追加、そしてGPIOの設定。

ここではIR送信をGOIO17、受信をGPIO18としている。

sudo コマンドで編集


/boot/config.txt

# 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_rpilirc_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_receive.png


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につなげるだけか、拡散キャップつけるでもいいと思う。

ir_send.png


登録してあるリモコンコードを表示

まずは、先程作成したコンフィグファイルから、登録できているか確認してみる。

# 登録してあるリスト表示 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を操作することができるか確認してみる。

スクリーンショット 2016-10-26 22.39.10.png

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() は書いてない。


script.py

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 に先ほど作成したスクリプトファイルを指定する。


/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ファイルの作成

ここも公式のサンプルを参考にしている。


index.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ファイルがあるディレクトリを指定する。


/etc/webiopi/config

[HTTP]

:
doc-root = <your project dir>/webIOPi/project


アクセスしてスクリプトを実行してみる

http://<raspberry pi address>:8000 にアクセスすると先ほど作成した index.html が表示されるはず。さらに send ir test をクリックするとIR送信スクリプトが実行される。ログなどを仕込みながら確認してみてください。

スクリーンショット 2016-10-26 22.37.37.png

ここまでくれば、リモコンコード送信するボタンを追加していけばブラウザから家電を操作することができる。


iOSホームアプリから制御する

homebridgeを使ってラズパイをHomeKit製品としてiOS製品に認識させ、ホームアプリ(iOS10から追加されたアップルの公式アプリ)に登録してIR送信リクエストを行えるようにする。


homebridgeの構築

homebridgeの構築には、local dnsの avahinodejs が必要。


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ソースから SwitchLight のようだが、それで挙動が変わる感じはなかったのでどちらでもいいと思う。


  • status_url ホームアプリ起動時や、送信後などにステータス取得するためのURL。IR送信は投げっぱなしで、ステータスなど無いのがほとんどなので、常にOFFでもいいと思う。ここでは一応GPIOの値を取るようにしている。


  • on_url / off_url はどちらも同じで、IR送信のREST Apiを自身のWebIOPiのアドレス (http://localhost:8000)にリクエスト指定する。


config.json

{

"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.


ホームアプリに登録して操作してみる

ホームアプリを起動して アクセサリを追加 をタップ

スクリーンショット 2016-11-03 21.00.47.pngスクリーンショット 2016-11-03 20.52.30.png

同一ネットワークで起動できているなら Homebridge が出現するはずなのでタップ。 このまま追加 でコード入力へ。。 (ターミナルの画面だと正常にスキャンできないので コードを手動で入力 をタップして直接入力がおすすめ)

スクリーンショット 2016-11-03 20.53.26.pngスクリーンショット 2016-11-03 20.54.03.png

認識するためにコードを入力する

スクリーンショット 2016-11-03 20.56.36.png

config.json のアクセサリが追加される。 アクセサリの よく使う項目に含める を有効にするとコントロールセンターからアクセスできる。

スクリーンショット 2016-11-03 20.57.22.pngスクリーンショット 2016-11-03 21.16.14.png

これでiPhoneにHomeKit製品として認識させることができた。ただし、試したところ認識できるのは一台のみで、他のiPhoneで認識することはできず、1対1のようだ。


おしまい

今は赤外線LEDをスターウォーズのBB-2に仕込んでテレビの操作ができるようにしています。iPhoneはHomeKit経由で、AndroidはWebブラウザ経由でテレビやコンポを操作しています。WebはBootstrapなどで簡単にレスポンシブデザインなページができるのでセンスがなくても何とかなりました。

自分でがっつりコードを書かなくても様々なライブラリの組み合わせで実用性のあるものを作れるのは楽しいですね。最近はESP8266にハマりだしたので、それらを使った複数部屋へのリモコンネットワーク構築を考えています。

スクリーンショット 2016-11-03 23.18.20.png