Amazon Echo Dotがやっと家に来ました。
- 出版社/メーカー: Amazon
- 発売日: 2017/11/15
- メディア: エレクトロニクス
- この商品を含むブログ (2件) を見る
Amazon Echoに今NHKで放送している番組を教えてもらう
作り方
下記のページの「スキル開発を始める」をクリックし、Amazonのアカウント情報を入力して開発を始めます。
developer.amazon.com
Alexa Skill Kitの「始める」をクリック。
「新しいスキルを開発」をクリック。
「カスタム対話モデル」を選択し、言語・スキル名・呼び出し名などを入力していき、画面下部の「次へ」をクリックします。
そうするとこの画面になります。
ここで前回の記事でも行ったように、IntentやSlots(前回の記事で言うEntities)の登録を行っていきます。 Intentとは要するに「こういう文がきたらこういう機能を呼び出すよ」という文例の定義で、Slotsは「文中にこういう単語が入りうるよ」という単語集の定義です。詳しくは公式のドキュメント
developer.amazon.com
や解説記事
dev.classmethod.jp
などをご参照ください。
ただ、実はこの画面からは簡易的な定義しかできません。ちょっと複雑な定義、例えば同じ単語に2つ以上呼び名がある場合などのSlotsの定義はここからはできないので、画面の「スキルビルダーを起動する」からスキルビルダーを起動します。
そうするとこんな画面が出てきます。ここでCode Editorを選択し
以下のコードを入力。「Apply Changes」、「Save Model」、「Build Model」とクリックしていきます。
{ "languageModel": { "types": [ { "name": "LIST_OF_STATIONS", "values": [ { "id": "sougou", "name": { "value": "NHK総合テレビ", "synonyms": [ "総合テレビ", "NHK", "総合", "nhk 総合テレビ", "nhk" ] } }, { "id": "etv", "name": { "value": "NHK教育テレビ", "synonyms": [ "教育テレビ", "教育", "nhk 教育テレビ" ] } }, { "id": "bs1", "name": { "value": "NHKBS1", "synonyms": [ "BS1", "nhkbs1" ] } }, { "id": "bspremium", "name": { "value": "NHKBSプレミアム", "synonyms": [ "BSプレミアム", "nhk bsプレミアム", "bsプレミアム" ] } } ] } ], "intents": [ { "name": "AMAZON.CancelIntent", "samples": [] }, { "name": "AMAZON.HelpIntent", "samples": [] }, { "name": "AMAZON.StopIntent", "samples": [] }, { "name": "GetTVProgram", "samples": [ "{Station} で放送している番組を教えて", "{Station}" ], "slots": [ { "name": "Station", "type": "LIST_OF_STATIONS" } ] } ], "invocationName": "ほたるの番組表" } }
それぞれの定義の意味、特にidやsynonymsについては、下記のドキュメントを見てください。
developer.amazon.com
次に、画面の「Configuration」をクリックします。するとこんな画面が出てきます。
前回の記事ではFirebaseを用いてバックグラウンドの処理を実装したわけですが、今回はAmazonのサービスなのでAWS Lambdaを用います。
というわけでAWSのコンソールに入り、Lambdaを選択。
「新しい関数を作成」を選択。
「設計図」を選択し、下の検索欄に「Alexa」と入力するとAlexaのテンプレートが出てくるので、「alexa-skills-kit-color-expert」を選択し、「設定」をクリックします。
すると以下のような画面が出てくるので、名前を入力し、ロール(アプリが他のAWSのリソースにアクセスする権限をまとめたもの)としてテンプレートから新しいロールを作成、ページ下部にある「関数を作成」をクリックします。
そうすると以下のような画面が出てきます。
コード編集欄でコードを編集していきます。今回のアプリではテンプレートをもとに以下のようなコードにしました。
'use strict'; const http = require('http'); const AREA = '';//取得したい番組表の地域ID const API_KEY = '';//ここにNHK番組表のAPI_KEYを入れておきます。 /** * This sample demonstrates a simple skill built with the Amazon Alexa Skills Kit. * The Intent Schema, Custom Slots, and Sample Utterances for this skill, as well as * testing instructions are located at http://amzn.to/1LzFrj6 * * For additional samples, visit the Alexa Skills Kit Getting Started guide at * http://amzn.to/1LGWsLG */ // --------------- Helpers that build all of the responses ----------------------- function buildSpeechletResponse(title, output, repromptText, shouldEndSession) { return { outputSpeech: { type: 'PlainText', text: output, }, card: { type: 'Simple', title: title, content: output, }, reprompt: { outputSpeech: { type: 'PlainText', text: repromptText, }, }, shouldEndSession, }; } function buildResponse(sessionAttributes, speechletResponse) { return { version: '1.0', sessionAttributes, response: speechletResponse, }; } // --------------- Functions that control the skill's behavior ----------------------- function getWelcomeResponse(callback) { // If we wanted to initialize the session to have some attributes we could add those here. const sessionAttributes = {}; const cardTitle = 'こんにちわ'; const speechOutput = 'こんにちわ、ほたるの番組表です。 ' + 'いま放送している番組を知りたい、テレビ局を教えて。'; // If the user either does not reply to the welcome message or says something that is not // understood, they will be prompted again with this text. const repromptText = 'いま放送している番組を知りたい、テレビ局を教えて。'; const shouldEndSession = false; callback(sessionAttributes, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession)); } function handleSessionEndRequest(callback) { const cardTitle = 'Session Ended'; const speechOutput = 'さようなら。'; // Setting this to true ends the session and exits the skill. const shouldEndSession = true; callback({}, buildSpeechletResponse(cardTitle, speechOutput, null, shouldEndSession)); } /** * Sets the color in the session and prepares the speech to reply to the user. */ function getTVProgram(intent, callback) { const cardTitle = "いま放送している番組"; const stationNameSlot = intent.slots.Station; let repromptText = ''; let sessionAttributes = {}; let shouldEndSession = true; let speechOutput = ''; const tvStation = { "sougou": "g1", "etv": "e1", "bs1": "s1", "bspremium": "s3" }; console.log("called Station Name"); console.log(stationNameSlot.value); let tvStationId = undefined; let tvStationName = undefined; if(stationNameSlot.resolutions && stationNameSlot.resolutions.resolutionsPerAuthority[0].values && tvStation[stationNameSlot.resolutions.resolutionsPerAuthority[0].values[0].value.id] ){ tvStationId = tvStation[stationNameSlot.resolutions.resolutionsPerAuthority[0].values[0].value.id]; tvStationName = stationNameSlot.resolutions.resolutionsPerAuthority[0].values[0].value.name; } if (tvStationId) { shouldEndSession = true; //オプションを定義 var url = 'http://api.nhk.or.jp/v2/pg/now/' + AREA + '/' + tvStationId + '.json?key=' + API_KEY; http.get(url, function(res) { var body = ''; res.setEncoding('utf8'); res.on('data', function(chunk) { body += chunk; }); res.on('end', function() { var ret = JSON.parse(body); speechOutput = `いま ${tvStationName} で放送している番組は` + ret.nowonair_list[tvStationId].present.title + 'です'; // Send simple response to user\ repromptText = speechOutput; callback(sessionAttributes, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession)); }); }).on('error', function(e) { console.log(e.message); }); } else { shouldEndSession = false; speechOutput = "すみません、よくわかりません。"; repromptText = "すみません、よくわかりません。"; callback(sessionAttributes, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession)); } } // --------------- Events ----------------------- /** * Called when the user launches the skill without specifying what they want. */ function onLaunch(launchRequest, callback) { console.log(`onLaunch requestId=${launchRequest.requestId}`); // Dispatch to your skill's launch. getWelcomeResponse(callback); } /** * Called when the user specifies an intent for this skill. */ function onIntent(intentRequest,callback) { console.log(`onIntent requestId=${intentRequest.requestId}`); const intent = intentRequest.intent; const intentName = intentRequest.intent.name; // Dispatch to your skill's intent handlers if (intentName === 'GetTVProgram') { getTVProgram(intent, callback); } else if (intentName === 'AMAZON.HelpIntent') { getWelcomeResponse(callback); } else if (intentName === 'AMAZON.StopIntent' || intentName === 'AMAZON.CancelIntent') { handleSessionEndRequest(callback); } else { throw new Error('Invalid intent'); } } // --------------- Main handler ----------------------- // Route the incoming request based on type (LaunchRequest, IntentRequest, // etc.) The JSON body of the request is provided in the event parameter. exports.handler = (event, context, callback) => { try { if (event.request.type === 'LaunchRequest') { onLaunch(event.request, (sessionAttributes, speechletResponse) => { callback(null, buildResponse(sessionAttributes, speechletResponse)); }); } else if (event.request.type === 'IntentRequest') { onIntent(event.request, (sessionAttributes, speechletResponse) => { callback(null, buildResponse(sessionAttributes, speechletResponse)); }); } else if (event.request.type === 'SessionEndedRequest') { callback(); } } catch (err) { callback(err); } };
コードを入力後、関数を保存、ARNをコピーし、Configurationの画面に戻り入力、「次へ」を入力すると、自身のAmazon Echoでアプリを動かすことが可能になります。
感想
スマートスピーカーのアプリの作り方は、Google AssistantもAmazon Alexaも似たようなものみたいですね。