RailsでAPI作ってGoogle Home Miniに喋らせてみた

会社で技術発表の順番が回ってきた・・・
正直技術関係は苦手ｗ

でもやるからには面白いことをやりたい！
ってことで、最近ちょっと気になっていたスマートスピーカー開発をしてみることにした

と雑談はこの程度で

## 今回使った最低限のもの
・PC（自分はmac）
・Ruby on Rails（gem grape）
・Googleアカウント
・Actions on Google
・Dialogflow(V2)
・Google Home Mini
・スマホ
・ネット環境

## 準備
・スマホのGoogleホームアプリからGoogle Home Miniをデバイス登録（これでアカウントが同期される）
・[dialogflow](https://dialogflow.com/)に登録

## イメージ
![dialogflow_add.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/f62ed90c-ee67-0c35-d79a-5e4e13b8e151.png)
何か間違ってるかもだけどたぶんこんな感じｗ
（Actions on Googleは後から気づいたので後付け・・・）

## 簡単手順（詳しく知りたい人は他のサイトを参考にしてください）
1. [Actions on Google](https://console.actions.google.com/u/0/)でプロジェクト作成
![Actions on Google.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/02e391b0-d57b-c133-42a6-bf0b66e0303f.png)
2. 右下にあるconversationalを選択
![ca277d790b0c6d90011dbc77a1077b9d.dat  PNG Image  1792 × 1139 pixels    Scaled  81  .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/02a147a6-2bc2-b6b9-ba02-8b744770d55f.png)
3. 呼ぶ名前を決める
![Actions on Google(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/c52c913b-2102-1d79-9950-449bda83b0f3.png)
![Actions on Google(2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/d8176c16-8a2b-b607-a3da-8ceb1e508dfd.png)
4. Actionの作成
![Actions on Google(3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/b9502cc6-b035-3f42-00f4-cbc8ed14bbea.png)
![Actions on Google(4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/3cfcedfa-6104-aa13-3489-f5bc6d1c7844.png)
5. 自動でDialogflowが立ち上がるので、Agent（プロジェクトみたいなもの？）を作成する
![Dialogflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/f0b86a20-8a68-15aa-ba54-fdd5aff142f4.png)
6. Intents（実際処理するところ）の作成を行う
![Dialogflow(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/d906ade1-fb02-6725-6e51-17e5a26f030a.png)
7. しゃべる内容（フレーズ）を設定する（複数設定可能）
![Dialogflow(3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/8f9619c7-40f1-1348-b7b7-543b2daa521f.png)
8. パラメーターの設定
![Dialogflow(4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/7d84f410-9e7e-95fc-7fe6-c1820fe68c44.png)
フレーズの中で変数のように扱いたいものをなぞるとパラメーターが設定可能
![Dialogflow(5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/4caa66d8-9ee8-5904-9aaf-0383172c496e.png)
必須にしたいならチェックを入れる
![Dialogflow(6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/bada2a89-78f3-cfcd-20a2-e6a8a4f33fb6.png)
（一応もう一つのフレーズのパラメーターもなぞっておいた）
![Dialogflow(7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/645968e6-e86e-49c2-e53a-6d6303b7b02f.png)
9. レスポンスの設定
![Dialogflow(8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/31bc1d89-8b8c-585d-6f7c-bf0263089e1a.png)
パラメーターを利用していろんなパターンを返せる（返される会話はランダム）
![Dialogflow(9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/133e41e4-3e83-36c7-497c-ee79e7a73bbe.png)
10. 試してみる

名前を設定してSAVE
![Dialogflow(10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/68f63727-8699-cc1d-5dfc-cb34bf4d84b0.png)
右上でしゃべってみる
![Dialogflow(19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/477f8ca7-dd81-ff62-a4f6-e0e4fd0f845a.png)
結果が返ってくることを確認
![Dialogflow(11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/3dcf5a17-6d93-04c7-61c3-f6793660b39f.png)

## APIと連動

### APIの用意

ざっくり書くとこんな感じ

```
  desc 'POST /api/qiita_sample/test'
  params do
  end
  post '/test' do
    # UTF-8を指定しないと文字化けで返って読み上げてくれない
    content_type 'application/json; charset=UTF-8;'

    ret = %w(サンプル テスト 本気 本物)
    prms = JSON.parse(request.body.read, symbolize_names: true)[:queryResult][:parameters]
    present fulfillmentText: "これが#{ prms[:any] }？これは#{ ret[Random.new.rand(0..3)] }です"
  end
```

重要なのはPOSTで作成して、

```
{ fulfillmentText: 'hoge' }
```

の形式で返すこと（Dialogflowのversionで変わるので注意。これはV2）

### Dialogflowに戻る

1. Fulfillmentを設定
![Dialogflow(12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/ad147be1-0da4-3021-8b69-3eb9271c4c09.png)
Enabledにして、APIのURL（適当なやつだとダメみたい）を入力して右下のSAVE
2. 先ほど作ったIntentsを選択
![Dialogflow(14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/41d1bc65-d3ac-4e06-9639-7ffec4b1fe87.png)
3. 一番下にあるFulfillmentを有効にする（レスポンスは無視されるようになる）
![Dialogflow(16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/db3cc299-5ffe-ace2-5786-75b70cea58f2.png)
SAVEを忘れずに
4. IntegrationsからSimulatorを起動
![Dialogflow(17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/e8bed9e1-3186-b246-6c8f-dde846ceff0d.png)
スイッチONしてTEST起動
![Dialogflow(18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/05bf7955-a0a3-732e-60d4-85dd1a0a988b.png)
5. 自動でSimulatorが立ち上がるのでテスト
![Actions on Google(5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/663d758c-0b32-7ff5-9f56-514eb5fb7892.png)

## 終わり

これだけで自分のGoogle Home Miniに話しかけると、Simulatorと同じように動かすことが可能！
設定したパラメーターをうまく処理してくれなかったりするので、本来はEntitiesなどを利用したほうがいいと思う

Dialogflowのバージョンが変わったばかりなのかネットにあまり情報がなくてすごい苦労しました。。。
V1が結構わかりづらいように感じたけど、V2はだいぶシンプルなので、今後バージョンがあがってもそれほど変更はないとは思うけど、動かなかった場合にはバージョンを注意するといいと思う