Google Homeからサーバーにアクセスして結果を喋らせる

#やりたいこと
Google Homeに特定のワードで話しかけると、自分で用意しておいたサーバーにリクエストを送り、そのレスポンスを喋らせる。そのための最小限のステップ。


#今回つくった最終的な会話
「お疲れ様です。」
と言うと、
音声では「どうもどうも！」
文字では「平素より大変お世話になっております。」
と返してくれる。

この"どうもどうも！"と"平素より大変お世話になっております。"は、サーバーからJSONで取得した文字列。

#手順
（2018年2月時点版）

##概要
Google Home （中身はGoogleアシスタント） と、自分独自の会話をしたいときには、「[Actions on Google](https://developers.google.com/actions/extending-the-assistant)」というプラットフォーム上で「Googleアシスタントのアプリ」という形で開発する。

このときに、「あー言えば、こう言う」という具体的な内容は「[Dialogflow](https://dialogflow.com/)」という言語解析エンジンを使って設定していく。設定はブラウザから簡単にできるようになっているが、固有名詞が多くて最初とっつきにくい。慣れれば簡単ぽい。

自分で用意したサーバーからデータを取得したい場合は、このDialogflow内の「Webhook」という機能を使う。Dialogflowからは、アクセスしたいURLと同時に投げたいパラメータなどを設定するだけ。次に、アクセスされたサーバーからDialogflowにどう値を渡すかというと、決まった形式のJSONを返すだけでよし。

また、ここで作るのは、あくまでGoogleアシスタントのアプリなので、Google Home本体を持っていなくても、スマホのGoogleアシスタントでも同時に使えるようになる。

##下準備：サーバーを用意する

Google Home（正確には後述するDialogflowのWebhook）からアクセスしたいサーバーを用意しておく。

最低限、以下ふたつを記述したJSONを返すのであればなんでもよい様子。
※ 今回は、V1 APIを使用。

```
{
    “speech”: “喋らせたい文章”,
    “displayText”: “画面上で表示させたい文章”
}
```
displayTextは、Googleアシスタントなどで表示される文章。

他にもDialogflow上で処理するデータなども色々盛り込めるみたい。
詳しくは、[Webhook requirements](https://dialogflow.com/docs/fulfillment)を参考。

以下、上記JSONを返すPHPのサンプル。

```
<?php
$arr = array(
	'speech' => "どうもどうも！", 
	'displayText' => "平素より大変お世話になっております。"
);
header("Content-Type: application/json; charset=utf-8");
echo json_encode($arr);

```

サーバー上でこのJSONの文字列を作る処理次第で、色んな応用が効く。

これをGAEや適当なサーバーにアップして、ウェブからアクセスできるようにしておく。

---

##Actions on Googleの操作

https://console.actions.google.com/ にアクセス

① 「Add/import project」から、
プロジェクトの名前をつけて、リージョンを選び「Create Project」。

![スクリーンショット-2018-02-24-19.00.29.png](https://qiita-image-store.s3.amazonaws.com/0/64523/e52d61b8-9fa6-6292-85e0-93251fc83e3a.png)

② プロジェクトのページができたら、
「Overview」の「１Add actions to your app」から「ADD ACTIONS」。

![スクリーンショット 2018-02-25 1.59.21.png](https://qiita-image-store.s3.amazonaws.com/0/64523/ba71029e-a983-92f5-4ca5-77c0c0d5dc26.png)

③ 「Dialogflow」を「BUILD」。
<img width="1181" alt="スクリーンショット 2018-02-24 19.05.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/64523/0a13b60f-a1f3-8d60-6f70-68447c978d26.png">

---

##Dialogflowの操作
ここから先は、[Dialogflow](https://console.dialogflow.com/
)上の作業になる。
Dialogflowでつくる「Agent」を、Actions on Googleの「プロジェクト」内で「Action」として使用する仕組み。

###「Agent」の新規作成
「DEFAULT LANGUAGE」は日本語で喋らすなら、「Japanese-ja」を選択しとく。
「GOOGLE PROJECT」には、すでにさっきActions on Googleで作成したプロジェクトが紐付けられているはず。
このまま「CREATE」ボタンを押すとAgentを作成できる。
![スクリーンショット 2018-02-25 2.13.13.png](https://qiita-image-store.s3.amazonaws.com/0/64523/abff424e-cf29-8dc8-087d-85b25f90dc88.png)

そのまま「Intents」新規作成画面になるので、「CREATE INTENT」。
![スクリーンショット 2018-02-25 2.21.49.png](https://qiita-image-store.s3.amazonaws.com/0/64523/59c0ddd7-6c13-0526-9d54-61802c4700b3.png)


###Intentsを編集
この「Intents」で、「こう言われたら、こうする」を設定していく。

まずは、内容に応じて適当に名前をつける（ここでは、"あいさつ"）。

そして、今回は特定のフレーズ（”お疲れさまです”）に反応して、サーバーにリクエスト送りたいので以下ふたつを設定。

1. 「Training phrases」セクション ＞ 「ADD TRAINING PHRASES」
反応させたいフレーズ（”お疲れ様です”）を追加。

1. 「Fulfillment」セクション ＞ 「ENABLE FULFILLMENT」
「Enable webhook call for this intent」をオンにする。

設定したら、画面上部の「SAVE」。

![スクリーンショット 2018-02-25 3.13.31.png](https://qiita-image-store.s3.amazonaws.com/0/64523/9d6db01f-767e-3f96-5745-ab9a7c5167bd.png)


###Fulfillmentを編集
画面左のメニューより、「Fulfillment」を選択。

「Webhook」を「ENABLED」にして、最初に下準備しておいたサーバーのURLを設定する。
必要に応じて、その他のパラメータ入力。

入力したら、画面一番下の「SAVE」を忘れずに。
![スクリーンショット 2018-02-25 2.35.37.png](https://qiita-image-store.s3.amazonaws.com/0/64523/6d209ad1-6dc7-3cd3-4bb4-7bc6d6ddc38a.png)


###Dialogflowで一旦テスト
Fulfullmentの設定までしたら、Dialogflow画面右で試してみる。
設定したレスポンスが返ってきたら成功。
※ここでは、マイク入力でも、タイプ入力しても、同じく”speech”で設定したテキストが返ってくる模様。
![スクリーンショット 2018-02-25 2.55.21.png](https://qiita-image-store.s3.amazonaws.com/0/64523/32df7e5c-a982-de79-98ce-bbf72b97330e.png)

---

##Actions on Googleの操作２

###Simulatorでテスト
Actions on Googleに戻り、メニューから「Simulator」を選択。
「テスト用アプリにつないで」
と音声入力かタイプ入力すると、Dialogflowで作った会話をはじめることができる。
（Googleアカウントがリンクされていれば、この時点ですでにGoogle Home実機に話しかけても動作するはず）
![スクリーンショット 2018-02-25 3.55.33.png](https://qiita-image-store.s3.amazonaws.com/0/64523/5e3658a5-ef40-79b0-e2f5-4b5bcfa3e35b.png)


「お疲れ様です」と言うと、音声では「どうもどうも」と言ってきて、文字では「平素より大変お世話になっております」と挨拶してきたら成功。

---

#もうちょっとカスタムしてみる

###テスト用アプリに繋いだあとの「こんにちは！」の部分を変更したい

このままだと挨拶終わっちゃってるし。
Dialogflowのメニューの「Intents」から、「Default Welcome Intent」を編集する。
![スクリーンショット 2018-02-25 3.50.23.png](https://qiita-image-store.s3.amazonaws.com/0/64523/2848f9ba-e83c-b945-b54e-34c6495a91fc.png)

「Responses」セクションの「Text response」の部分を変更してSAVE。
![スクリーンショット 2018-02-25 3.51.25.png](https://qiita-image-store.s3.amazonaws.com/0/64523/04b4aa43-8c35-5418-1685-2edbada7bdea.png)

![スクリーンショット 2018-02-25 3.53.27.png](https://qiita-image-store.s3.amazonaws.com/0/64523/29f3bbe3-58d6-91d0-80d6-57b86b526b0c.png)


###一度挨拶したらもう会話を終わらせたい
一度お互い挨拶済んでからも、Google Homeがずっと待機状態（音声待ちの状態）でいる。
何も言ってないのに「すみません、よく聞き取れませんでした。」などと言ってくる。
そんなときは、DialogflowのIntentの設定で、「Reponses」セクション ＞ 「ADD RESPONSE」 ＞ 「Set this intent as end of conversation」をオンにすると、お互い挨拶した時点で会話を終了できる。


![スクリーンショット 2018-02-25 4.00.39.png](https://qiita-image-store.s3.amazonaws.com/0/64523/e3b7694a-6682-1a9f-fece-53512c2043cd.png)


###「テスト用アプリ」という名前を変更したい
「ねえグーグル、◯◯◯につないで」
「はい。 ◯◯◯のテストバージョンです。」
の、◯◯◯の部分を変更したい。

Actions on Googleの「Overview」 ＞ 「App information」の項目を埋めていく。
![スクリーンショット 2018-02-25 4.48.29.png](https://qiita-image-store.s3.amazonaws.com/0/64523/724f183e-0323-8527-f52b-3a9ebf101047.png)
![スクリーンショット 2018-02-25 4.48.48.png](https://qiita-image-store.s3.amazonaws.com/0/64523/8de076da-95d4-d1b2-d920-a7b06da23850.png)

全項目埋めないとSAVEできない様なので、（公開をしない限り）ダミーでもいいので全部うめる。
（「Assistant app name」 が日本語で入力できるときと英数字しか受け付けないときがある？）

無事、SAVEできたら、再び「Overview」画面にいき、一番下の「TEST DRAFT」すると反映される。
![スクリーンショット 2018-02-25 4.51.54.png](https://qiita-image-store.s3.amazonaws.com/0/64523/f6e74c00-5059-d0d8-b51f-fa34fd791095.png)


今回の最終形
![スクリーンショット 2018-02-25 4.53.58.png](https://qiita-image-store.s3.amazonaws.com/0/64523/0920007e-b06a-8d48-689a-b32e127be05b.png)

設定項目を見る限り、「につないで」の部分もカスタムできるっぽいが、少なくてもテストバージョンでは反映されない。公開バージョンは未確認。


---

#参考にした記事
https://qiita.com/miso_develop/items/28cbfcdfb61d455ce346
https://qiita.com/kotatu_km/items/c06f45c6692dceb9258d