初めに

この記事はスマートスピーカーアドベントカレンダー 2017の13日目の記事です。

遅くなってしまい大変申し訳ありません。
やりたいことが無事に動作したので、記事を公開します。
なお、私は電子工作は素人レベル、Webのセキュリティに関しても専門ではないので、間違っている点についてはぜひ指摘をお願いします。

やりたいこと

タイトルの通り、Google HomeからRaspberry Piを経由してリモコンのコントロールを行います。
既にFirebase等を使って実現されている方々もいる中恐縮ですが、ラズパイにサーバーを立ててWebhookから呼び出す単純な方式で作ります。
取り敢えずは自分が知っている知識の範囲で作成して見たかったので、次は是非Firebaseも試して見たいと思います。

作業の流れとしては以下の通りです。

  1. ラズパイにApache2+PHPをインストールする
  2. 無料のダイナミックDNSサービスに登録する
  3. Let's Encryptで証明書を発行し、https化する
  4. ラズパイに赤外線リモコン受光モジュールを接続してリモコンの赤外線を解析する
  5. ラズパイに赤外線LEDを接続してリモコンを操作する
  6. PHPでWebからリモコンを操作する
  7. IFTTTを使ってGoogle HomeからWebhookを呼び出し、リモコンの操作をする

作業手順

ラズパイにApache2+PHPをインストールする


OSはRaspbianを使用している前提です。
Raspbianはapt-get installが使えるので、以下のコマンドでApache2とPHPをインストール可能です。

sudo apt-get install apache2 php5

インストール完了後、Apache2でhttpsを使用できるようにSSLモジュールを有効化したいので、以下のコマンドを実行します。

// 必要なモジュールのシンボリックリンクを作成する
sudo ln -s /etc/apache2/mods-available/ssl* /etc/apache2/mods-enable/
sudo ln -s /etc/apache2/mods-available/socache_shmcb.load /etc/apache2/mods-enable/
// Apache2をリスタートする
sudo apachectl restart

エラーが発生しなければ完了です。

無料のダイナミックDNSサービスに登録する


マンションタイプの回線など、固定のグローバルIPが振られていない場合はダイナミックDNSに登録する必要があります。
以下の様な無料サービスがあるので、登録してダイナミックDNSにグローバルIPを登録して下さい。
私はieServer.netを使用しています。
※そもそもグローバルIPが振られず、ローカルIPが振られる場合はサーバーを立てることが出来ませんので注意して下さい。
ieServer.net
MyDNS.jp
NoIP
また、ルーターを使用している場合は設定を変更して、Port 80で来た通信をサーバーに転送するように設定して下さい。
設定したDNSにアクセスして、/var/www/html/index.htmlが表示されたらOKです。
ダイナミックDNSに最新のIPを定期的に更新する処理が必要なので、そちらも合わせて設定して下さい。

Let's Encryptで証明書を発行し、https化する


少しでもセキュリティを向上させたいので、Let's Encryptでhttps化します。
sshでLet's Encryptの証明書が導入可能な、certbotを導入します。
certbot
RaspbianはDebianベースなので、ApacheDebian (other)を選択し、手順に従ってSSL証明書を導入します。
登録するDNSが接続可能でないと登録できないので、注意して下さい。
ここでApache2のサイトの設定なども作ってくれます。

ラズパイに赤外線リモコン受光モジュールを接続してリモコンの赤外線を解析する


参考にさせて頂いたリンク
※リンク内のリンクも参考にさせて頂きました。
Slack経由で家の外からエアコンをon, offできる装置を、Raspberry Piで作ってみた。(しかも御坂美琴ちゃんが応答してくれる)
Raspberry pi 3 で部屋の赤外線受信できる機器をコントロール!

ラズパイの設定方法等は上記リンク内容と変わらないため、時間の都合で省略させて頂きます。

ここがハマリポイントでした…
最初に一つ赤外線リモコン受光モジュールを買ってきたのですが、リモコンの信号以外の信号を常に拾ってしまい全くリモコンの信号が拾えませんでした。
その後ネットで調べて、受光モジュールのデータシートの通りにパラコンデンサを組んでみましたが、それでも安定しませんでした。
なので再度パーツを買い足し、いくつか試したので結果を以下に記載します。
※以下の検証結果は全て間に何も挟まないで直接接続した結果です。

赤外線リモコン受信モジュールPL-IRM1261-C438
最初に買ったモジュールです。
1つめはノイズを拾ってしまい全く駄目でしたが、個体差かと思いもう一つ買ったところ、そちらは全く問題ありませんでした。

赤外線リモコン受信モジュール GP1UXC41QS
こちらは5個入りで250円でした。
試してみたところ5個中2個は定期的にノイズを拾っていました。

赤外線リモコン受信モジュールOSRB38C9AA
2個入りでしたが、2個とも問題なく使えました。

赤外線リモコン受信モジュール PL-IRM0101(38kHz)シールド付
1つしか買いませんでしたが、問題なく使えました。

赤外線リモコン受信モジュール SPS-448-1(38kHz)
1つ買いましたが、ノイズを拾って駄目でした。

個々のモジュールの性能差もあると思うのでなんとも言えない部分はありますが、結論としては念のために複数買った方が良いということが分かりました。

ラズパイに赤外線LEDを接続してリモコンを操作する


こちらも少しハマりました。
設定に関しては受光モジュールの参考リンクの通りなので、時間の都合もあり省略します。

赤外線LEDを使ってリモコンに信号を送るのですが思った通りに操作できず、光っているのか光っていないのかよく分かりません。
なので、以下の方法を使って調べます。

  1. 普通のLEDに差し替えてみる
  2. スマホのカメラを使って見てみる(機種によっては赤外線が見えないようなので注意)

2.の方法を使う場合、暗くしたほうが分かりやすいです。
ここでLEDは方向があり、線の長い方が+で短い方が-というのを思い出しました。
上記方法で光っているのは分かりましたが、いくら赤外線LEDを受光口に向けても全然操作が出来ずに困りました。
しかし、何故か赤外線LEDを上に向けて操作する機器から少し離したところ、無事に操作できるようになりました。

PHPでWebからリモコンを操作する


こちらは特に大きな問題なく出来ました。
以下の様なshellスクリプトを作成して、PHPから呼び出す様にしました。

irsend SEND_ONCE xxxx xxxx

作成したらsudo chmod +x scriptnameで実行権限を付ける必要があります。

PHP側はセキュリティを上げるためにトークンを付けることにしました。

<?php
  $token = "xxxxxxxxxxx"; //ランダムな長めの値
  if(isset($_GET['token']) && $_GET['token'] == $token){
    // shellスクリプトはWeb上からアクセス不可なディレクトリに配置する
    shell_exec('../script.sh');
  }

この状態でWeb上からトークンを付けてURLにアクセスして、リモコンの操作ができたら成功です。

IFTTTを使ってGoogle HomeからWebhookを呼び出し、リモコンの操作をする

IFTTTの設定もさほど難しくありません。
Appletを作成して、this側にGoogle Asistantを選択し、「テレビつけて」「テレビ消して」など、操作したい言葉に反応するように設定します。
そしてthat側にWebhookを指定し、動作確認したURLを設定するだけです。

作成した後にGoogle Homeに設定した言葉を話しかけて、期待通りに動作したら成功です。

感想

一旦やりきったので今回のところは満足です。
しかしながら受光モジュールの部分でつまずき、その後お店まで再度行ってパーツを買い足すなどの大きなロスが発生してしまいました。
今回の経験で電子工作の部品はそこまで高いものではないのであれば、念のために複数種類を数個買っておこうと思いました。
また、Firebaseなどを使って実現している方も多くいるので、そちらにも挑戦しようと思いました。
今回作ったものは赤外線LEDの設置位置がデリケート過ぎるので、キャップを買って改善するか試してみようと思います。

色々と省略してしまい申し訳ありませんが、気力が湧いたらまた記事を修正しようと思います。

今後もスマートスピーカーで便利なものを作りましたら記事にして投稿しようと思いますのでよろしくお願いします。