スマートスピーカー最近ますます流行ってきていますね。私もスマートスピーカーアプリ開発に挑戦している最中です。そこで、私がスマートスピーカーアプリ開発で知り得た知識や作成の流れを共有していきたいと思います。
前回からの続きになっていますので、もしよろしければ前回の記事も参照ください。前回はDialogFlowのinline Editorで簡単なプログラミングをしてみる流れについて説明しました。
それでは、inlineエディターの代わりにAzure Functionsで作ったAPIを呼んでいきたいと思います。
Azure Functionで、天気情報が取得可能なWebAPIから天気情報を取得し、その結果をDialogFlowに返すという動きを実装してみます。
今回も作ったアプリはシミュレーターを用いて検証しますので、PCさえあればGoogle HomeやAndroidスマホをお持ちでない場合でも作って検証することができます。
・DialogFlowのWebhookの使い方が分かるようになる
必要なもの
・パソコン
・ブラウザ(Google Chrome推奨)
シミュレーターを使うので、スマートスピーカー(Google Home)は無くても問題ありません。
それでは進めていきましょう。
目次
Azure FunctionsでWebhook用のAPIを作成
Dialogflowのプロジェクトは前回の「Hello World」プロジェクトをそのまま流用します。
まずはAzureからポータルにログインします。アカウントが無い方は作成してからログインしてください。
ポータルにログインしたら、左ペインの「リソースの作成」でWebAPIを作成していきます。今回は、作成するWebAPIにはサーバレスのAzure Functionsを使用します。
アプリ名とかは任意の名前で結構です。今回は「weather-get」という名前を付けました。また、他の項目はサーバーの場所を日本に、プログラミング言語をnode.jsにしています。
デプロイが終わりましたら早速プロジェクトに移動しましょう。
「新しい関数」を選択してWebAPIを新規に作成します。
今回はお試しなので、「ポータル内」でプログラミングしていきます。
Dialogflowから呼び出すので、「webhook + API」を選択して、「作成」しましょう。
サンプルコードが記載されたプロジェクトが表示されますので、まずは「実行」して動かしてみましょう。出力に”Hello Azure”と出るはずです。
ではこのコードを改造して、天気を応答するようにしていきましょう。
まずは、天気を取得するためにフリーで使用可能なWebAPI「Weather Hacks」を使っていきます。
お天気Webサービス仕様 – Weather Hacks – livedoor 天気情報
このWebAPIの使い方は非常に簡単で、以下のURLに場所のIDをくっつけるだけでその場所の天気情報が取得できます。
“http://weather.livedoor.com/forecast/webservice/json/v1″ + ”city=ID情報”
天気情報はJSON形式で返答され、JSONの仕様はトップページに書かれている通りです。
リクエストパラメータ
JSONデータをリクエストする際のベースとなるURLは以下になります。
http://weather.livedoor.com/forecast/webservice/json/v1
このURLに下の表のパラメータを加え、実際にリクエストします。
パラメータ名 説明 city 地域別に定義されたID番号を表します。
リクエストする地域とidの対応は 全国の地点定義表(RSS) 内の
「1次細分区(cityタグ)」のidをご参照下さい。(例・佐賀県 伊万里=410020)
(例)「福岡県・久留米の天気」を取得する場合 下記URLにアクセスしてJSONデータを取得します。
基本URL + 久留米のID(400040)引用元:Weather Hacks
今回は「大阪」「京都」「東京」「愛知」「北海道」の5都道府県の天気が知りたいので、全国の地点定義表(RSS)から5地点のIDを調べます。
ここのIDは市町村単位のものがあるので、一番大きそうな市町村のIDを採用することにします。
- 大阪:id=”270000“
- 京都:id=”260010“
- 東京:id=”130010“
- 愛知:id=”230010“
- 北海道:id=”016010“
としました。
さて、Azureに戻ってこのWebAPIを呼び出してみます。
なお、node.jsではhttpリクエストにはrequestモジュールを使用したほうが簡単ですので、”request”が使えるようにrequestモジュールをコンソールからインストールしましょう。
Function Appの「weather-get」→「プラットフォーム機能」→「高度なツール(Kudu)」の順に選択してKuduを起動します。
Kuduの「Denug console」から「PowerShell」を選択します。
「site」→「wwwroot」の順にクリックし、ルート階層まで移動します。
ここでnpm installを実行してrequestモジュールをインストールしていきます。
まずはお決まりの”npm init”を実行して、あとはEnterキー連打で良いです。
“npm install request”でrequestモジュールをインストールします。赤字で何か出ていますがrequestモジュール自体はインストールされていますのでいったん無視して構いません。
これでrequestモジュールのインストールが完了しましたのでプロジェクトに戻ります。
ひとまず大阪だけの天気を取得するため、下の図のようなソースコードに書き換えました。(クリックで拡大します)
doRequest()にWebAPIのURLを渡し、requestでGETメソッドを実行してるだけの単純なソースです。
これを実行してみましょう。
うーん。。。レスポンスをログっているのですが、何かおかしいですね。日本語が入っているのが期待値なのですが、ユニコードエスケープ(uxxxx形式)で返ってきています。
1行追加して、evalで変換してみると、日本語になりましたね。取得成功です!
では返ってきたJSONデータから天気情報を抜き出してみましょう。天気情報はJSONの”forecasts”の”telop”にあるようですので、そこを見てみます。
ログってみると、取れましたね!「雨時々曇」です。
ではこのAzureで作ったWebAPIを呼び出した際に、呼び出し元に大阪の天気を返すテキストを設定して、実際にDialogflowから呼び出してみます。
まずは呼び出し元に大阪の天気を返すテキストを設定します。
DialogflowでWebAPIを呼び出すよう設定する
DialogflowからAzureで作成したWebAPIを呼び出すには、そのWebAPIのURLが必要ですので、Azure上から取得(URLをコピー)しましょう。
「関数URLの取得」をクリックし、表示されたURL右側の「コピー」をクリックすればクリップボードにこのWebAPIのURLがコピーされます。
ではDialogflow側を設定していきましょう。
Webhookをenableに変更し、URL欄に先ほどコピーしたURLを貼り付けてSAVEします。
加えて、インテントの「Enable webhook call for slot filling」も有効にしておきます。
さぁ準備は整いました。右上のシミュレーターから「今日の大阪の天気は」と入力してみましょう。「今日の大阪の天気は雨時々曇です」と応答されることが期待値です。
あれ?応答結果は「雨です」になっていますね。正しく結果が通知されていないようです。
下の「DIAGNOSTIC INFO」を見てみると、
文字列としてはDialogflowに返ってきています。
なぜこの通り喋らないのか?と調べたところ、私が仕様を理解していなかっただけでした。
Google Assistantに応答してほしいメッセージを喋らせる場合は”fulfillmentText”で指定しないといけないのでした。(何でもいいと思ってました。壮絶な勘違いです。)
というわけで、Azureのソースコードを修正します。
bodyの”取得成功”を”fulfillmentText”に変更しました。
結果は以下の通り、期待通り応答が返るようになりました!成功です!
Actions on Googleのシミュレーターでも確認してみましょう。
上手くいってますね。大丈夫そうです。
以上がDialogFlowのWebhookでAzureを指定し呼び出す流れです。
条件分岐してみる
大阪だけだったので、他の5都市も応答できるようAzureのソースコードを条件分岐してみます。
こんな感じですね。
if文の条件式になっているreqはこの関数の入力引数なんですが、その中の”body.queryResult.parameters.Location”に、地名の情報が入っています。今回だと「今日の東京の天気は」だと、「東京」が”req.body.queryResult.parameters.Location”に入っていますので、これで地名による条件分岐が可能です。
あとはその地名によってリクエストするWebAPIのIDをその地名の物に変えるだけですね。
- 大阪:id=”270000“
- 京都:id=”260010“
- 東京:id=”130010“
- 愛知:id=”230010“
- 北海道:id=”016010“
これをDialogflowから実行してみましょう。
北海道の場合、東京の場合もうまく応答できていますね。成功です。
まとめ
今回は、inlineエディターの代わりにAzure Functionsで作ったAPIを呼んで応答する簡単なプログラムを作成してみました。
ここまでの流れが分かれば、様々なアプリを開発できるのではないでしょうか。