Actions On Googleなんちゃって中級編

Google Home便利ですよね。
突然半額になったときは泣きましたけど。負けずとGoogle Home miniを2台買って計4台です。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">我こそは全部屋にGoogle Home設置するマンなり。<br>(計4つ)<br>お店でシール配ってた。 <a href="https://t.co/hPccYdsfjf">pic.twitter.com/hPccYdsfjf</a></p>&mdash; ode (@odetarou) <a href="https://twitter.com/odetarou/status/937258989150015489?ref_src=twsrc%5Etfw">2017年12月3日</a></blockquote>

そんなこんなで使いこなすためにActions On Googleについてあまり書かれていない調査してわかったことのメモになります。

# Actions On GoogleのほうがIFTTTより早い
(2017/12/09時点において)
大体2秒以上は早いです。
発話してから、jsが実行されるまでの時間をストップウォッチでアナログ計測しました(ずれはありますが参考までに)
実際に試すと感じますがこの2秒の差は大きいと思います。IFTTT本当遅い。。
なので私はActions On Googleを使っています。
IFTTTのほうがシンプルなので早くなってくれれば良いんですけど。

### Actions On Google (5回計測)
1.8秒
1.99秒
1.34秒
1.54秒
1.86秒

### IFTTT (5回計測)
3.91秒
3.77秒
4.10秒
3.77秒
4.65秒


# Actions On GoogleのDraftアプリは1週間すぎると無効になる問題
**追記 : 2018/04/04にHPを確認したところ30daysとなっていたので、大体1ヶ月に伸びたようです。**

どうも8日経つと無効になるようです。

10月末ぐらいからActions On Googleにて個人用のアプリをいくつか作って家の照明をつけたり、[GoogleHome自身で音楽を流したり](https://qiita.com/odetarou/items/0e134ff845826d16170c) していたんですが
たまに呼びかけても「すみません、よくわかりません」となってアプリが認識しない状況になりました。
最初は原因がわからず何かソースいじったかなとjsと格闘していたんですが、とりあえずアプリをドラフト申請しなおしたら直ったのですが、
2回めも起きたのでいろいろ調べたところ、公式英語ドキュメントにドラフト申請だと1週間すぎると無効になるという記載を発見。

https://developers.google.com/actions/tools/simulator

>Your app is testable for up to 7 days. After 7 days, you have to reupload the action package for testing using the gactions tool or the Dialogflow Actions on Google integrations screen.

自動翻訳にて

>あなたのアプリは最大7日間テスト可能です。7日後、gactionsツールを使用してテストするためにアクションパッケージを再アップロードするか、Googleインテグレーション画面のDialogflow Actions画面を再アップロードする必要があります。

まじですか、、
シミュレータだけでなく、実機上でもこれにヒットすると思われたので検証してみました。

2017/11/29 02:15 認識しなくなるのを確認
2017/11/29 02:18 test draft申請
2017/12/06 02:51 この時点では動作するのを確認
2017/12/06 11:53 この時点では動作するのを確認
2017/12/07 10:20 動作しないのを確認（再現しちゃったよ。。）

11月は30日までなので
29,30,1,2,3,4,5,6日は稼働していて8日間は大丈夫という結果になりました。
ドキュメントの7日間というのは実質7日23:59:59なのかも？

## 回避策
test draft申請をしなおせば期間がのびます。

どうも最近はシミュレータ画面を見た際にも伸びるように思えます。上部にある日付が更新されるのでこれが指標に思えます。
<img width="602" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/132679/80384e60-f64e-2675-fb76-c0c5b6d0e2e9.png">

とはいえ、こんな作業毎週するのも現実的ではないので
思いつく手としてはドキュメントに記載のとおりgactionsツールを使いアップするのをcronに登録するなどでしょうか。
このgactionsツールはDialogFlowで作った際には使えないためActions SDKを利用した場合のみ使えるようです。
特にDIalogFlowを使わないでも照明を消すや単純なコマンドであればActions SDKのほうが最初からjsで書けてシンプルではあるので問題はなさそうです。今後はActions SDKのほうが流行るかも？

Actions SDKの使い方は下記がわかりやすかったです。
https://qiita.com/flum1025/items/7cfe6a1e59627debe8f7
https://github.com/actions-on-google/actionssdk-say-number-nodejs

もしDialogFlowをどうしても使いたい場合はスクレイピングしてシミュレータ画面を見るぐらいしか思いつきません(やりたくない。。）

**追記 : 2019/01/26**
Actions SDKの場合は
https://developers.google.com/actions/tools/gactions-cli
を見ると
gactions test --project プロジェクト名 --action_package パッケージ名.json を使えばずっと運用できそうです。
認識しなくなったプロジェクトのにこちらのコマンドを実行したら再び認識するのを確認しました。
gactions updateの実行のみでは認識しませんでした。
updateがアプリの更新で、testがシミュレーターの起動と思われます。
>By default, you can test indefinitely

なので無期限？確認中。
とりあえずcronで1日1回動かせば問題ないかと思われます。


# Actions On Google たまに起動が遅い問題(CloudFunctionコールドスタート)
たまに発話してから起動するまでに時間がかかる場合がありました。8秒や10秒かかるときもあります。
なぜかなーと思って推測したところ恐らくCloudFunctionが寝てしまって起きるのに時間がかかっていると思います。
cronにて定期的にcurlでCloudFunctionのurlを1分おきに叩くようにしたところ、改善しました。
もしくはCloudFunctionを使わないで別途APIを立てるでも改善すると思います。

下記がCloudFunctionのログですが、朝起きたばっかや、しばらく時間が経った際に1000ms以上になります(実際は1秒どころでなく、8秒ぐらいかかるという)
![Inkedcloud function log_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/132679/342d4560-0b27-aa9b-d5a4-cb5a88338ef1.jpeg)

下記curlで叩く際のurlサンプルです。idなどは伏せているので適当にセットしてください。CloudFunctionのログからコピーするのがよいです。不要なパラメータが多そうですが面倒なのでそのまま貼り付けて使ってます。

```bash
curl 'https://us-central1-プロジェクトid.cloudfunctions.net/dialogflowFirebaseFulfillment' -H 'Content-Type: application/json;charset=UTF-8' -X POST -d '{"originalRequest":{"source":"google","version":"2","data":{"isInSandbox":true,"surface":{"capabilities":[{"name":"actions.capability.AUDIO_OUTPUT"},{"name":"actions.capability.MEDIA_RESPONSE_AUDIO"}]},"inputs":[{"rawInputs":[{"query":"test","inputType":"VOICE"}],"arguments":[{"rawText":"test","textValue":"test","name":"trigger_query"}],"intent":"actions.intent.MAIN"}],"user":{"lastSeen":"2017-11-27T17:03:06Z","locale":"ja-JP","userId":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},"conversation":{"conversationId":"111111111111","type":"NEW"},"availableSurfaces":[{"capabilities":[{"name":"actions.capability.AUDIO_OUTPUT"},{"name":"actions.capability.SCREEN_OUTPUT"}]}]}},"id":"xxxxxxxxxxxxxxxxxxxxx","timestamp":"2017-11-27T17:26:40.742Z","lang":"ja","result":{"source":"agent","resolvedQuery":"test","speech":"","action":"action.hoge","actionIncomplete":false,"parameters":{"light":"off"},"contexts":[{"name":"google_assistant_welcome","parameters":{"light":"off","light.original":"test"},"lifespan":0},{"name":"actions_capability_audio_output","parameters":{"light":"off","light.original":"test"},"lifespan":0},{"name":"google_assistant_input_type_voice","parameters":{"light":"off","light.original":"test"},"lifespan":0},{"name":"actions_capability_media_response_audio","parameters":{"light":"off","light.original":"test"},"lifespan":0}],"metadata":{"matchedParameters":[{"dataType":"@light","name":"light","value":"$light","isList":false}],"intentName":"test","intentId":"xxxxxxxxxxxxxxxxxxxxxxxx","webhookUsed":"true","webhookForSlotFillingUsed":"false","nluResponseTime":231},"fulfillment":{"speech":"test","messages":[{"type":0,"speech":"test"}]},"score":0.75},"status":{"code":200,"errorType":"success","webhookTimedOut":false},"sessionId":"1111111111"}'
```


aws lambdaも同様の問題あり。
https://qiita.com/keita-nishimoto/items/d1c524a97dc844cb02cc
５分間隔で定期リクエストするのが回避策とのこと。

開発環境でcloud functions(firebase)の動作が遅い理由
https://qiita.com/Masaaki/items/54cf16c6c55cdae91b82

Firebase cloud functions is very slow
https://stackoverflow.com/questions/42726870/firebase-cloud-functions-is-very-slow

GAEのスピンアップ遅い問題も有名だったけど、似てそう。
http://www.bunkei-programmer.net/entry/2016/06/05/130329

# トリガーフレーズが面倒問題

Google on Actionのトリガーフレーズの規約は下記参照
https://developers.google.com/actions/localization/languages-locales#japanese
"$nameにつないで"
"$nameと話す"
"$nameにつなぐ"
"$nameと会話"
"$nameに ... 頼む"
"$nameに ... 言う"

例えばアプリ名が「セバスチャン」に対して「電気を付けて」という場合は

パターン１：
自分: ねぇグーグル セバスチャンにつないで
Google: わかりました。テストバージョンのセバスチャンです。はい。
自分: 電気を付けて
Google: 電気を付けました。

やりとりが長い。。複雑なやりとりでもないので、これならIFTTTを使ったほうがいいですね。

パターン２：
自分: ねぇグーグル セバスチャンに電気付けてと言う
Google: わかりました。テストバージョンのセバスチャンです。電気を付けました。

これなら短いのですが言い回しがわかりづらいです。。
なので下記のようにHomeアプリのショートカットを使うことでわかりやすく回避できます。
![Screenshot_20171209-235210.png](https://qiita-image-store.s3.amazonaws.com/0/132679/a4b8f8e4-7225-bfd3-d609-f88fd0298296.png)

# GoogleCastをActions On Googleから直接使えるか？
使えなそうです。
Play Musicやラジコでは音声のストリーミングができていますが特別モードっぽい？
Cast開始時の「ディロン?」みたいな音もでていないしCastではなさそう。
[google-home-notifier](https://github.com/noelportugal/google-home-notifier) でCastする方法がありますが、これは制御アプリがLAN内に必要なのと、
複数台Google Homeがあった場合にどちらのデバイスから発話されたか認識できない問題があり、Cast先のデバイスが固定になってしまいます。
Actions On Google側でデバイス名が取得できればよいのですが無さそうでした。

stackoverflowでもCastはできないよとの回答されていました。
https://stackoverflow.com/questions/47319136/can-i-use-google-home-to-automatically-chromecast-my-own-content

# 住所や名前などの個人情報を取得
デバイス名が取得できない代わりにデバイスの住所を取得する方法があったので利用してみました。
試した結果としては、毎回ユーザーの許諾を取る必要がありデバイス判定に使うには厳しかったです。
ショッピングアプリなどで発送先の連絡に使う目的のAPIなんでしょうね。

参考情報(英語)
https://developers.google.com/actions/assistant/helpers#user_information
https://medium.com/google-developer-experts/handling-permissions-with-dialogflow-and-actions-on-google-b08c8f228c00

# SmartHome Apps(ダイレクトアクション）
複数台のGoogle Homeを利用して照明などの家電を操作する場合の決定版です。Hueのように1階、2階の電気を同時にけしたり1階のみを消したりすることが可能になります。
仕組みとしてはHueのような家電メーカーが実装する仕様をオレオレで実装する形になります。

Direct Action(ダイレクトアクション)という直接実行できるモードになります。
通常のActions On Googleでの会話型で実行するものはConversation Actionという言います。

**追記 : 2020/12/21**
ダイレクトアクションを利用するにはHome Assistantを使うのがおすすめです。下記記事参照。
Google HomeでIFTTT(有料化)の代わりにHome Assistantが便利だったので画像多めで導入解説
https://qiita.com/odetarou/items/4407d06d030c83180364

より細かい制御をしたくプログラムに自信のあるかたはGoogle提供のnodejsでのサンプル実装があるためそれをカスタマイズなども（大変そうですが）
https://github.com/actions-on-google/smart-home-nodejs

※下記の2アプリは更新停止しているためHome AssistantかNode.jsで独自実装がおすすめです。
**追記終わり**

実装したアプリを探したところ２つありました、どちらも日本の方でREADMEもわかりやすいです。

**Beatrice**
http://www.misuzilla.org/Blog/2017/11/09/Beatrice
https://github.com/mayuki/Beatrice
.Net Core C#実装
10月ごろには開発されていて安定しているように見えます。
iosのHomebridgeを意識しててアーキテクチャはよさそう。

**ha-aog-firestore**
https://github.com/yasu-hide/ha-aog-firestore
nodejs実装
12月にリリースされて開発真っ只なので現時点(2017/12/10)では実用にはまだ厳しそうにみえましたが期待です。
firebaseのCloudFunctionとfirestore、実行結果先にはrealtimedbを利用しているため既にrealtimedbのデータを利用して家電を制御している方には馴染みやすいかと思います。

仕組みが複雑なので難易度はちと高いです。頑張りましょう。

公式ドキュメント(英語)
https://developers.google.com/assistant/smarthome/overview

# その他 (Actions On GoogleではなくGoogle Homeのですがついでに紹介)
## Google Home隠しAPI
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Google Homeに隠しAPIあったんだ<br>http://ローカルIP:8008/setup/eureka_info<br>でstatus取得。ノイズレベルとかも認識してるっぽい<br><br>他にも夜間モード設定、アラーム取得&amp;削除、OSSライセンスなど。地味なのばっかですが。<br><br>英語記事<a href="https://t.co/9o90mJJhOu">https://t.co/9o90mJJhOu</a><br><br>API一覧まとめ<a href="https://t.co/Jai0EC58rV">https://t.co/Jai0EC58rV</a></p>&mdash; ode (@odetarou) <a href="https://twitter.com/odetarou/status/1183247249637134338?ref_src=twsrc%5Etfw">October 13, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## ブロードキャストをWebAPIで実行できるソフト(日本語NG)
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Google HomeへのブロードキャストをWebAPIで実行できるソフト見つけたけど実装が興味深い(日本語はNG)<br>オレオレAssitantデバイスをソフト的にNodeで作って任意のテキストを実行する形(ここは日本語OK)<br>&quot;broadcast 英語メッセージ&quot;でブロードキャストが可能<br><br>Assistant Relay<a href="https://t.co/j5Oo6Aihzu">https://t.co/j5Oo6Aihzu</a></p>&mdash; ode (@odetarou) <a href="https://twitter.com/odetarou/status/1183397260584861697?ref_src=twsrc%5Etfw">October 13, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 最後に

「テストバージョン」と言われるのもつらいし、1週間問題もつらいので、グーグルさん個人用途の申請なしで使えるActions On Googleを開放してくだせー。

**追記 : 2020/12/21**
下記記事にテストバージョン言われない方法2020年に再調査しましたがまだのようです…
https://qiita.com/odetarou/items/4407d06d030c83180364#google-homegoogle-assistant%E3%81%A7%E3%81%AEapi%E9%80%A3%E6%90%BA%E6%A8%A1%E7%B4%A2