Google HomeとRaspberryPiで最安で家電を制御するシステムを作ってみた。

AIスピーカー

先日、秋葉原にと冬コミ(一日目のみ)に行く旅行に行ってきました。
秋葉原のじゃんぱらでGoogle Home Mini未開封が4,980円だったので、思わず買ってしまいました。


3,000円の時に買っとけばよかったなぁっと思いながら、駅の広告にGoogleHomeが必ずあったりして、「通常6,000円だったら中古屋で買うか..」っとなり衝動買いしちゃいました。

単体でも十分楽しめるのですが、「やっぱり家電の制御に憧れる…でも色々買うのは高い…」
ってなったので、家にあったラズパイ2Bと、愉快仲間たち(1,000円以下の部品)で実現してみました。

スポンサーリンク

Google HomeとRaspberryPiで最安で家電を制御するシステムを作ってみた

参考サイト

赤外線発射装置等は↓を参考にしました
最近lircのコマンドが新しくなって、色々変わっているので気をつけてください。

どういうシステムにしたいのか

ハードは何にするのか

前置きが長くなりましたが、Google Homeで家電制御する方法は沢山あります。
Nature Remoを買ったり、Broadlink RM mini3をgeekbuyingGearBestなどの海外通販サイトで買ったり(amazonで買うと高すぎです)、irMagicianとラズパイで制御したり….などなど。

今回はそんな中でも最も安く実現できる(と思う)、LEDとGPIOでやる方法でやってみることにしました。
※基盤の作り方等は他のサイト様で紹介されていますので、省略します。
(要望があれば、やり方を別記事にて紹介します。)

今回はLircのirsend SEND_ONCE [デバイス] [on/off]で、家電が制御できる前提で書いていますのでご注意ください。

Google Homeからの制御はどうするか

ググってみると、IFTTTで発言内容からコマンド送信ってとこまでは、同じですが、
分岐点として、ラズパイのポートを開いてラズパイ自身をサーバー化したり、
MQTTブローカから、制御コマンドをもらってオンオフ制御するなど、ここでも色々あるようです。

自分は、前者はセキュリティー的にあまりよろしくないと考えたので、後者のMQTTブローカから制御コマンドをもらって制御するという方法をとることにしました。
(まあ、どちらにしろ100%安全なんてないんですけどね)

この記事ではMQTTブローカにBeebotteを使っています。

早速作っていきましょう!

まずは、コマンドの確認

まずは、普通にRaspberryPiのターミナルで送信するコマンドを確認しましょう。

自分はlightdがデバイス名、all_onがアクションで設定しています。
これで自分は部屋のシーリングライト(全灯)がつきます。

$ irsend SEND_ONCE lightd all_on

オフは

$ irsend SEND_ONCE lightd off

コマンドの設定は人それぞれ違うと思うので、適当に書き換えてください。(^^)

確認できたら、Beebotteのアカウントを作りましょう。

Beebotteの設定

Beebotteのサイトにアクセスします。アカウントを作ります。

次にCreate Newからチャンネル、リソースを作ります。
今回は

Channel: remote
Resource: irSignal

動作確認

 

↑のところにあるSecret Keyを、ConsoleメニューのSecret Keyの場所に入力し、SubscribeのChannelとResourceに、上で登録した"remote"と"irSignal"を入力し、Subscribeボタンを押下すると、画面右上部のMessagesに青い文字が表示されます。

その状態のまま、下記のcurlコマンドをラズパイのコンソールや、macのターミナルで実行すると、Messagesエリアにcurlで指定したものが表示されると思います。

curl -i -H "Content-Type: application/json" \ -X POST -d '{ "data": [{"commandType":"shell","group": "lightd","action":"all_on"}]}' \ http://api.beebotte.com/v1/data/publish/remote/irSignal?token=<チャンネルトークン>

チャンネルトークンは↓から

 

こんな感じで、メッセージが受け取れれば成功です。

 

IFTTTの設定

予め、Google Homeで使っているGoogleアカウントをIFTTTで連携しておいてください。

アプレットを作成(反応するコマンド作成)

ここのサイトから、アプレットを作ります。

「this」を選択。

Google Assistantを選択。

 

Say a simple phraseを選択。

 

画像の感じで行いたいことを書きます。
実行するためのコマンドは3つ書けます。

 

ポイント

《2018/11/23追記》ショートカットがルーティンに変わりました。

「電気をつけて」は公式コマンドに予約されているので、そのままだと使用できないようです。対策方法はとして
GoogleHome→IFTTT→HomeAssistantで部屋の電気を付けてみる - Qiita
を参考にしてみてください。
「自分の部屋の電気をつけて」の「を」をしっかり発音していても、聞き取れないことが多いので
「自分の部屋の電気つけて」とした方が良さそうです。

Google Homeが返す言葉も決めておきましょう。

続いて、Beebotteとやりとりできるようにします。

アプレットを作成(Webhooksの設定)

Webhooksを選択。

フォームが出るので埋めていきます。

項目内容
URLhttp://api.beebotte.com/v1/data/publish/remote/irSignal/?token=<チャンネルトークン>
Body { "data": [{"commandType":"shell","group": "lightd","action":"all_on"}]}
Content TypeApplication/json
MethodPOST

こんな感じです。

後はFinishでIFTTTでやることは終わりです。

RaspberryPi側での設定

PythonでRaspberry PiからBeebotteのから受信する。

MQTTライブラリインストール

BeeBotteを監視するためのライブラリをインストール

$ sudo pip3 install paho-mqtt

MQTTクライアントを作る

以下のコードは、Google Home + 赤外線コントローラ + Raspberry piで非IoTデバイスを操作の殆ど丸パクリです。

変えた所はシェルで

irsend SEND_ONCE デバイス(lightdなど) アクション(all_onなど)

と、した所くらいです。

本当は一からPythonを書くのが良いのですが、技術がないです。すいません。

$ nano mqtt_subscriber.py

 

#!/usr/bin/python
# -*- coding: utf-8 -*-

import paho.mqtt.client as mqtt
import json
import commands

host = 'mqtt.beebotte.com'
port = 1883
username = '<Secret Key>'

topic = 'remote/irSignal'

def on_connect(client, userdata, flags, respons_code):
print('status {0}'.format(respons_code))
client.subscribe(topic, 1)

def on_message(client, userdata, msg):
print(msg.topic + ' ' + str(msg.payload))
json_dict = json.loads(str(msg.payload))
group = json_dict['data'][0]['group']
action = json_dict['data'][0]['action']
commandType = json_dict['data'][0]['commandType']
print('debug:' + 'commandType is ' + commandType + ' / ' + 'group is ' + group + ' / ' + 'action is ' + action)

if commandType == 'shell':
commands.getoutput("irsend SEND_ONCE " + group + " " + action)
else:
print('エラー')

if __name__ == '__main__':
client = mqtt.Client(protocol=mqtt.MQTTv311)

client.username_pw_set(username)
client.username_pw_set(username)

### callback function
client.on_connect = on_connect
client.on_message = on_message

client.connect(host, port=port, keepalive=60)
client.loop_forever()

MQTTクライアントの実行

コードを保存したら、

$ python mqtt_subscriber.py


で実行する。
コンソール上に「status 0」が表示されれば大丈夫なようです。
0以外のステータスが表示されている場合、設定に不備がある可能性があります。
こちらを参考にしながら解決してください。

MQTTクライアントのテスト実行

先程と同じくテストコマンドを実行します。

curl -i -H "Content-Type: application/json" \ -X POST -d '{ "data": [{"commandType":"shell","group": "lightd","action":"all_on"}]}' \ http://api.beebotte.com/v1/data/publish/remote/irSignal?token=<チャンネルトークン>

実行する際は、mqtt_subscriber.pyが動いてる状態で行ってください。

これで電気がつけば成功です。

ついでにGoogle Homeでも「自分の部屋の電気つけて」と言って電気がつくか試しましょう。

Google Homeが聞き取ったログはマイ アクティビティ-Google アシスタントで確認できます。

成功したら次は常駐させるためにサービス化します。

(うまくいかなかった)MQTTクライアントのサービス化

〈追記〉サービス化で行けると思ってたのですが、自動起動でエラーを吐くので、ro.localのでやることにします。このサービス化の方法は一応メモ程度に残しておきます。

ro.localでのやり方は下の方で紹介しています。

権限を与える

まずは権限を与えます。

$ sudo chmod 755 mqtt_subscriber.py

ユニット定義ファイルを作る

$ sudo nano /usr/lib/systemd/system/mqtt_subscriber.service
[Unit]
Description=mqtt_subscriber

[Service]
ExecStart=/home/pi/mqtt_subscriber.py
Restart=always
Type=simple
PIDFile=/var/run/mqtt_subscriber.pid

[Install]
WantedBy=multi-user.target

ExecStartはmqtt_subscriber.pyの場所を指定してください。

デーモンを起動する

$ sudo systemctl daemon-reload
$ sudo systemctl start mqtt_subscriber.service

デーモンをリロードしたら、新しく作ったmqtt_subscriber.serviceが認識されます。
そしてstartで起動させます。

成功したら

$ sudo systemctl enable mqtt_subscriber.service

で、起動時に起動できるようにしましょう。

これで、きちんと起動できれば完成です。お疲れ様でした。

/etc/rc.localに自動起動できるよう記述する。

記述内容

$ sudo nano /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
sleep 20
sudo mount -a

# mqtt_subscriberを自動起動する。
cd /home/pi
nohup ./mqtt_subscriber.py &

exit 0

/etc/ro.localの有効化

http://peacejet.hatenablog.com/entry/2017/07/08/000907

を参考にしてください。

再起動してちゃんと実行されれば成功です。お疲れ様でした。

スポンサーリンク

総括的な何か

思いの外流行っているAIスピーカー。
購入前は、おもちゃ程度にしか思ってなかったのですが、家電制御(リモコン)、アラーム(時計)、音楽を鳴らす(スピーカー&音楽プレイヤー)などと色んなものが一つになった感じです。(う~ん語彙力。。。)

ラズパイも活用できたりして思いの外、役立っています。

2018年1月1日に投稿しようと思っていたのですが色々あって1/2になちゃいましたー。

本年も、Till0196並びに「Till0196のぼーびろく」をよろしくお願いします。

コメント