2018年3月17日土曜日

Google Homeに話しかけて、家のRaspberry Piで処理する

Google Homeを購入したのですが、Google Homeにはホームネットワークにコマンドを送信したりする機能がありません。ここは残念なところで、 Apple の HomeKit の様にもっと「Home」を全面に出した機能が欲しいものです。
そこで、今回は Google Home に話しかけたコマンドを家の Raspberry Pi で処理するための手順をまとめます。

Google Homeの購入

Google Home Mini をビックカメラのキャンペーン中に半額で購入しました。


今回の流れ


  1. Google Home Mini の設定
  2. Google の Firebase で Database を作成
  3. Raspberry Pi で Node.js のプログラムを作成
  4. IFTTT で Google Home Mini と Node.js の連携を設定

Google Home Mini の設定

iPhone 7 の Google Home アプリを使って設定しましたが、特に詰まるところはなく、スムーズに終えられます。

Google の Firebase で Database を作成

新規プロジェクトを追加

Firebase のコンソールで新規プロジェクトを追加します。





「プロジェクトを作成」ボタンを押してから、しばらく待つと新規プロジェクトが作成されます。

Database を作成

今回は、PlayStation4 を操作するので、以下の様にデータを定義してみました。




Database のルールを設定

今回作成した「playstation」のデータには、認証無しでアクセスさせるように設定します。



ここについては、そのうち権限設定を良い感じに設定出来るようにしたいです。
Firebase ドキュメント - データベース ルールを使ってみる


Firebase の設定を取得

「Project Overview」を押してプロジェクトトップに戻り、「ウェブアプリに Firebase を追加」からプロジェクトの設定をコピーします。






Raspberry Pi で Node.js のプログラムを作成

作成したアプリケーションは GitHub の GoogleHome リポジトリで公開しています。

PlayStation4 を操作するために ps4-waker を使います。

ps4-waker のインストール


$ cd /path/to/project
$ npm install ps4-waker --save

PlayStation4 を操作するためにクレデンシャル情報の取得

以下の手順でご自身の PlayStation4 を操作するためのクレデンシャル情報を取得出来ます。
  1. ps4-waker の起動
  2. スマートフォンで「PS4 Second Screen」アプリの起動
  3. PlayStation4 で PINコードを確認し、 ps4-waker に入力する
    • 「設定」→「モバイルアプリ接続設定」→「機器を登録する」を選択し、PINを表示

初回のみ、クレデンシャルが無いので /home/pi/.ps4-wake.credentials.json を作ります。作成時のみroot権限を求められます。

$ sudo ./node_modules/.bin/ps4-waker -c ~/.ps4-wake.credentials.json
No credentials; Use the PS4 Second Screen App and try to connect to PS4-Waker
Got credentials!  { 'client-type': 'i',
'auth-type': 'C',
'user-credential': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' }
Go to 'Settings -> PlayStation(R) App Connection Settings -> Add Device' on your PS4 to obtain the PIN code.
Pin code> XXXXXXXX
Logged into device! Future uses should succeed

正常に取得できていれば、 PlayStation4 の状態が確認できます。
$ ./node_modules/.bin/ps4-waker search
{
  "type": "device",
  "statusLine": "200 Ok",
  "statusCode": "200",
  "status": "Ok",
  "host-id": "XXXXXXXXXXXX",
  "host-type": "PS4",
  "host-name": "PS4-123",
  "host-request-port": "997",
  "device-discovery-protocol-version": "00020020",
  "system-version": "05508011",
  "running-app-name": "torne™ PlayStation®4",
  "running-app-titleid": "CUSA00442",
  "address": "XXX.XXX.XXX.XXX"
}

Scripting API の利用

ps4-waker はコマンドだけではなく、スクリプトからも実行することができます。
const {Device} = require('ps4-waker');

var ps4 = new Device();
ps4.turnOn().then(() => ps4.close());  // 起動
ps4.turnOff().then(() => ps4.close());  // スタンバイ(電源のオフではないです)
ps4.startTitle('CUSA00442').then(() => ps4.close());  // トルネの起動

titleId は PlayStation Store の URL から取得することができます。
トルネの場合は、「https://store.playstation.com/ja-jp/product/JA0003-CUSA00442_00-TORNEPS400000000」なので「CUSA00442」となります。


自動起動するようにサービス化

自動起動のために、サービス化しました。こちらの設定については GitHub の RaspberryPi リポジトリで公開しています。

ユーザの追加
$ sudo useradd --system googlehome
$ sudo su googlehome -s /bin/sh

サービスの設定ファイル作成
$ vi /etc/default/google-home
# Defaults / Configuration options for google-home

# If you uncomment the following line, google-home will log more
# You can display this via systemd's journalctl: journalctl -f -u google-home
# DEBUG=*
NODE_PATH=/home/pi/Projects/GoogleHome/lib
$ sudo chmod 755 /etc/default/google-home
$ vi /etc/systemd/system/google-home.service
[Unit]
Description=Node.js GoogleHome Server
After=syslog.target network-online.target

[Service]
Type=simple
User=googlehome
EnvironmentFile=/etc/default/google-home
ExecStart=/usr/bin/node /home/pi/Projects/GoogleHome/app/index.js
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target
$ sudo chmod 644 /etc/systemd/system/google-home.service

サービス開始
$ sudo systemctl daemon-reload
$ sudo systemctl enable google-home
$ sudo systemctl start google-home
Created symlink from /etc/systemd/system/multi-user.target.wants/google-home.service to /etc/systemd/system/google-home.service.
$ sudo systemctl status google-home
$ sudo journalctl -f -u google-home
もし google-home.service ファイルを別なフォルダで管理して、 /etc/systemd/system にシンボリックリンクを貼った場合には以下のエラーで実行することができませんでした。

$ sudo systemctl enable google-home
Failed to execute operation: No such file or directory
そのため、自動起動設定を行ってからシンボリックリンクを作成しました。

IFTTT で Google Home Mini と Node.js の連携を設定

IFTTT の My Applets から「New Applet」を押して追加します。

  1. 「this」は「Google Assistant」を選択
    1. 「Say a phrase with a text ingredient」を選択
    2. 「What do you want to say?」と「What do you want the Assistant to say in response?」と「Language」を設定
  2. 「that」は「Webhooks」を選択
    1. 「Make a web request」を選択
    2. 「URL」には、 Firebase で作成したデータの URLをコピー
    3. 「Method」は PUT
    4. 「Content Type」は application/json
    5. 「Body」は "{{TextField}}"


確認

正しく設定できていれば、 Google Home に「プレステを起動」と話かけることでご自身の PlayStation4 が起動するはずです。