ifttt
ngrok
node-red
AmazonEcho
GoogleHome

素人でもスマートスピーカーから家電を操作できた

こと始め

  • Google HomeのCMみたいに声で照明をつけたい!
  • Amazon EchoとeRemote miniを買ったけど、コレジャナイ!
  • Raspberry Piというものがあれば、いい感じに自作できるらしい

やりたいこと

無題プレゼンテーション-2.png

素人具合

  • 一応IT業界
  • 普段はワードとパワポしか使わない非エンジニア
  • webは全然わからない
  • linux触ったことない
  • プログラミングできない
  • markdownわからない

使ったもの

ハードウェア

  • Google Home/Amazon Echo(どちらか)
  • eRemote mini(RM mini3)
  • Raspberry Pi Zero W

ソフトウェア・サービス

  • node-RED
  • python-broadlink
  • IFTTT
  • ngrok

工数

  • 1人日くらい

参考にした主な記事

この記事は「素人でも上の記事を見てできたよ!」というものなので、特に新規性はありません。ごめんなさい。

0.事前準備

情報収集

  • RM mini3を制御できるpythonライブラリ?があって、これを使えばいいらしい
  • APIはnode-REDというもので簡単に作れそう
  • AlexaやGoogle HomeからAPIを叩くには、IFTTTとwebhooksを使うといいらしい
  • ngrokで自宅のサーバをインターネットに公開できるらしい

ざっくり設計

無題プレゼンテーション-3.png

1.Raspberry Piのセットアップ

Raspberry Pi(以下Rpiと書きます)を買ってセットアップしました。わかりやすい参考情報はwebに沢山ありましたので、詳細は割愛します。

購入

スイッチサイエンスというサイトでRaspberry Pi zero Wのケース付きを注文。2日程度で届きました。MicroSDカードはAmazonでトランセンドの16GBを買いました。

セットアップ

Raspbian(OS)をセットアップします。以下のサイトを参考にLiteをインストールして、とりあえず家のMacからsshで接続できるようになりました。

参考1:Raspberry Piの無線LANをmicroSDで設定する
参考2:Raspberry Piの無線LANをmicroSDで簡単に設定するためのツールを作った

2.Python-broadlink

RpiにRM mini3を制御するためのpythonツールを導入して、簡単なテストをしました。
手順はほとんど以下の参考サイトと同じです。

Echosim.ioを使うと日本でもAlexaでSmart Homeを実現できるので、安価なBlack Beanで照明やエアコンを制御してみた

インストール

まずgitをインストールし、gitでpython-broadlinkをダウンロードします。
素人なので、gitが何かは特に気にしません。

実行したコマンド
sudo apt-get install git
git clone https://github.com/mjg59/python-broadlink.git

次にpipをインストールし、pipでbroadlinkというライブラリをインストールします。
素人なので、python-devとpipが何かはよくわかりませんが、とりあえずインストールしました(あとで調べました)。

実行したコマンド
sudo apt-get install python-dev
sudo apt-get install python-pip
sudo pip install broadlink

リモコンの学習

まずbroadlink_discoveryを実行して、同じネットワーク内のRM mini 3を探し、参考サイトのとおりに「ROOM.device」というファイルを作ります。
(ここで人生で初めてviというものを使ったのですが、たった1行のテキストファイルを作るのに30分くらいかかりました。。。)

実行したコマンド
./broadlink_discovery
vi ROOM.device

(このあとviで操作してテキストを編集する)

次にpython-broadlinkのcliコマンドを使って、照明のリモコンのON/OFFを学習させます。ここも参考サイトのとおりです。

実行したコマンド(とリモコンの操作)
./broadlink_cli --device @ROOM.device --learnfile LIGHT.on

(RM mini3に向けてリモコンのONボタンを押す)

./broadlink_cli --device @ROOM.device --learnfile LIGHT.off

(RM mini3に向けてリモコンのOFFボタンを押す)

動作テスト

以下のコマンドで、Rpiから照明のON/OFFができました。すごい!

実行したコマンド
./broadlink_cli --device @ROOM.device --send @LIGHT.on
./broadlink_cli --device @ROOM.device --send @LIGHT.off

3.node-RED

Rpiにnode-REDというツールを導入して、HTTPからpython-broadlinkを操作できるようにしました。

参考1:第三回 Raspberry Pi 3に最新のNode.jsをインストールする
参考2:Node-RED日本ユーザ会 - Running on Raspberry Pi

node.jsのインストール

node.jsというものが必要らしいので、これをRpiにインストールします。
例によって、npmが何かは気にしません。

実行したコード
sudo apt-get install nodejs npm

次にnという何かをインストールして、node.jsのLTS版をインストール(?)します。
この辺りは正直、一体自分が何をしてるのか全くわかりませんでした。
(一応、後で勉強しました。)

実行したコード
sudo npm cache clean
sudo npm install n -g
sudo n lts

node-REDのインストール

npmでnode-REDをインストールします。「--unsafe-perm」が何かはわかりません。

実行したコード
sudo npm install -g --unsafe-perm node-red

起動します。自動起動の設定については参考2に書いてありますので省略します。

実行したコード
node-red-pi --max-old-space-size=256

手元のPCのブラウザからRpiのIPアドレスの1880ポートにアクセスしてみて、node-REDの画面が表示されたら成功です。

node-REDのフロー作成

node-REDのGUIエディタで、python-broadlinkを実行するAPIを定義します。

手元のMacのSafariから以下のアドレスにアクセスして、http-in、http-response、execノードをつなげてフローを定義しました。

スクリーンショット 2017-12-17 22.47.16.png

RESTfulとかよくわからないので、http-inのURIは適当に決めました。

動作テスト

手元のMacのブラウザで、RpiのIP:1880/Lihgt/on/にアクセスすると、部屋の照明がつきました。すごい!

4.セキュリティ設定

node-REDを外部に公開するため、簡単なセキュリティ設定をしました。
ただ、設定内容にあまり自信がないのと、試行錯誤を記録しておらずコマンドを再現できなくなってしまったので、概要だけ書きます。

ファイアウォールの導入

無用なポートを公開してしまわないよう、Rpiにファイアウォールを導入します。特に理由はないのですが、iptablesではなくfirewalldを使いました。

後でわかったことなのですが、ngrokは特定のポートのみを指定して公開するため、ここの対策は実は不要だったかもしれません

node-REDのeditor認証設定

node-REDをwebサーバ代わりに公開するので、editorに他人がアクセスできないよう、settings.jsを編集してパスワード認証を設定しました

node-REDのHTTP-inノードの認証設定

他人に我が家の照明をON/OFFされないよう、node-REDのWeb API(HTTP-inノード)にもBASIC認証を設定します。
※BASIC認証で充分であるのかについては確証がありませんが、設定しないよりはマシだと思います。

node-RED実行ユーザの作成

node-REDのAPIから意図しない操作を実行された場合を想定して、実行専用のユーザを作成し、乗っ取られても大したことができないように権限設定しました。

5.ngrokでAPIを公開

ngrokで、Rpiのnode-REDのポートをインターネットに公開しました。

アカウント登録

ngrokのサイトから、アカウントを登録します。
https://ngrok.com

ngrokのインストール

Rpiにngrokをインストールします。

実行したコマンド
(コマンドのログがどっか行ってしまいました。。。後で書き足します。)

インストールしたngrokにauthを登録します。

実行したコマンド
(コマンドのログがどっか行ってしまいました。。。後で書き足します。)

ngrok 起動

いよいよngrokを起動して、node-REDで作ったAPIを公開します。

node-REDのポート設定を変えていなければ、以下のように1880ポートを指定してngrokを起動すると、公開が開始されます。

実行したコマンド
./ngrok http 1880

動作テスト

ngrokに表示されたURLに、BASIC認証と定義したAPIのURLを付け加えて、他のPCやスマホのブラウザからアクセスしてみます。

照明がついたらテスト成功です。

6.IFTTT設定

alexa又はGoogle Assistantと連携して、WebhooksでAPIを叩けるようにしました。

IFTTTサインイン

IFTTTのアカウントを持っていなければ、まずはサインインします。

Appletのトリガを設定

IFTTTでAppletを作成します。トリガ(this)にalexaかGoogle Assistantを設定し、トリガーとするフレーズを決めます。

私は当初はAmazon Echo(alexa)を使う予定でしたが、IFTTTを呼び出すのに「トリガー」と発声しなければならないのが嫌だったのと、Google Assistantは任意の返事を設定できる点が気に入り、Google Homeに切り替えました。

AppletのActionを設定

アクション(that)でwebhooksを選択し、ngrokで公開しているAPIのURLを設定します。このときBASIC認証の情報も忘れずに入れ込みます。

認証情報を平文で直接打ち込むというセキュリティ的に残念な実装ですが、悪用されても我が家の照明が操作されるだけなので諦めました。

完成

スマートスピーカーに「照明をつけて」と言うと、照明がつきます。

先人の知見と素晴らしいサービスを使って、素人でもスマートな暮らしを手に入れることができました。

レスポンスタイム

「照明をつけて」と言い終わってから、だいたい2秒でRM mini3 が動作します。
若干遅い気もしますが、Google Homeだと返事を設定できるので、「わかりました」→電気がつく、という感じでほとんどストレスはありません。

TVのチャンネルを変える、とかだとちょっと遅いかも。

おわりに

これまでlinuxやCLI、各種webサービスに触る機会がなかったので、いい勉強になりました。

またこの雑文を書くにあたってmarkdownも初めて使いましたが、とても気に入りました。

内容に関してはほぼ付け焼き刃の知識のみで書いていますので、誤りがあったらすみません。ご指摘いただけると幸いです。

今後の改善点

  • ngrokの起動のたびに変わってしまうURLをwebhooksに直打ちしてるブサイクな実装をどうにかしたい
  • セキュリティ的に不安な実装があまりに多いので、せめて不正検知の仕組みを入れたい
  • そもそも同じネットワークにいるGoogle homeとRM mini3がインターネット経由でしか連携できないのをどうにかしたい