やりたいこと
Amazon Echoを使っていると、リングが黄色に光って「通知」が来ることがあります。この通知機能「Amazonで注文した商品の配送状態」や「JR東日本 列車運行情報案内」をお知らせしてくれる機能で非常に便利です。
今回は、Alexaに「通知」を送ることをやってみたいと思います。ちなみに、この通知を送る機能は「プロアクティブイベントAPI」という物を利用しますが、少々実装が面倒なのが難点です。
全体の流れ
プロアクティブイベントAPI利用の、全体の流れは以下の通りです。
1.Alexaスキルの作成
2.スキルマニュフェストの追加
3.通知の許可
4.アクセストークンの取得
5.プロアクティブイベントAPIの呼び出し
Alexaスキルの作成
まずは、通知を送るのに必要なAlexaスキルを作成します。ただ、スキルの作成といっても、中身は無い空のスキルを作るだけで十分です。
①Alexa Skills Kit開発者コンソールにアクセス
PCのブラウザで「Alexa Skills Kit開発者コンソール」にアクセスし、Amazon Echoに紐づいているAmazonアカウントでログインします。
②スキルの作成
画面右側の「スキルの作成」ボタンをクリックして、新しいスキルを作成します。
③スキルの設定
スキルの作成画面では、以下を設定し、右上の「スキルを作成」ボタンをクリックします。
・スキル名:適当にスキル名をつけます
・スキルに追加するモデル:カスタム
・スキルのバックエンドリソース:Alexa-hostd(Node.js)
なお、スキル名は、通知を送った時に「[スキル名]から◯件の通知があります・・・・」というように、Alexaが発音するので、それを意識してつけると良いと思います。
④エンドポイントメニューの表示
スキル作成の画面が開いたら「ビルドタブ」の左側のメニューの「エンドポイント」を選択します。
⑤スキルIDのメモ
あとで必要になるので、エンドポイントの画面に表示されている「スキルID」をテキストエディタにメモしておきます。
⑥アクセス権限の設定
次に、左側メニューの一番下にある「アクセス権限」のメニューを選択します。
⑦スキルメッセージング情報の取得
アクセス権限の画面で「リマインダー」のスイッチをONにして有効化し、画面一番下に表示される「AlexaクライアントID」と「Alexaクライアントシークレット」をテキストエディタなどにメモします。
※私はここで1日ハマりました。「リマインダー」などを有効化しないとAlexaスキルメッセージングが表示されないのが分からず「Alexaスキルメッセージング」の表示がない!ない!?ってなってました。
Alexa Skills Kit開発者コンソールでの作業はここまでです。
スキルマニュフェストの追加
ここからは、作成したスキルてプロアクティブイベント機能を利用可能にするために、スキルマニュフェストを追加していきます。本当は、Alexa Skills Kit開発者コンソールで設定できると簡単なのですが、2019年10月現在はできないようなので、Alexa Skills Kitコマンドラインインターフェースを使って、コマンドラインから操作します。
Alexa Skills Kitコマンドラインインターフェースがインストールされていない方は「遂にでた! Alexa Skill Kit のCLIでデプロイまでやってみた」などを参考にインストールしてください。
①スキル情報の取得
まずは、以下のコマンドを実行して、上で作成したスキルのスキルマニュフェストを取得します。
※xxxxxxxxxxの部分は上でメモした「スキルID」に変更してください。
$ask api get-skill -s amzn1.ask.skill.xxxxxxxxxxx >testSkill.json
②スキルマニュフェストの追加
スキルがプロアクティブイベント機能を利用できるように、取得したスキルマニュフェストに「events」と「permissions」を追加します。当然ながら、コメントは削除してくださいね。
「events」の中で指定している「メッセージアラートスキーマ(AMAZON.MessageAlert.Activated)」は、「◯◯から、◯◯からのメッセージが◯件あります。」というような形式で、通知を送るものです。この他にもいろいな形式が用意されていますが、詳細はプロアクティブイベントのスキーマを参照ください。ただ、逆に言うと、スキーマに定義された形式以外の通知はできないのが現状なので、少々自由度が低いという感触です。
{
"manifest": {
"apis": {
"custom": {
"endpoint": {
"uri": "arn:aws:lambda:us-east-1:000000000000:function:bfc1ffac-0000-0000-0000-000000000000:Release_0"
}
}
},
↓↓↓↓↓↓↓ここから追加↓↓↓↓↓↓↓↓↓↓
"events": {
"publications": [
{
↓↓↓メッセージアラートスキーマ機能を利用する
"eventName": "AMAZON.MessageAlert.Activated"
}
],
"subscriptions": [
{
"eventName": "SKILL_PROACTIVE_SUBSCRIPTION_CHANGED"
}
],
"endpoint": {
↓↓↓有効なものならなんでOKなので、上のendpointをコピーして記載する
"uri": "arn:aws:lambda:us-east-1:000000000000:function:bfc1ffac-0000-0000-0000-000000000000:Release_0"
}
↑↑↑↑↑↑↑↑ここまで追加↑↑↑↑↑↑↑↑↑
},
"permissions": [
{
"name": "alexa::alerts:reminders:skill:readwrite"
}, ←カンマも忘れずに追加
↓↓↓↓↓↓↓ここから追加↓↓↓↓↓↓↓↓↓↓
{
"name": "alexa::devices:all:notifications:write"
}
↑↑↑↑↑↑↑↑ここまで追加↑↑↑↑↑↑↑↑↑
],
"publishingInformation": {
"locales": {
"ja-JP": {
"name": "通知テスト"
}
}
}
}
}
③スキル情報の更新
次に、以下のコマンドを実行して、変更したスキルマニュフェストでスキルを更新します。
※xxxxxxxxxxの部分は上でメモした「スキルID」に変更してください。
$ask api update-skill -s amzn1.ask.skill.xxxxxxxxxxx -f testSkill.json
Update skill request submitted.
Please use the following command to track the skill status:
ask api get-skill-status -s amzn1.ask.skill.xxxxxxxxxxx
④スキル情報の更新確認
スキルマニュフェストが正しく更新されているか確認するために、以下のコマンドを実行します。応答で帰ってきた文の中の「manifest」の部分のstatusが「SUCCEEDED」になっていることを確認します。
$ask api get-skill-status -s amzn1.ask.skill.xxxxxxxxxxx
{
"interactionModel": {
"ja-JP": {
"eTag": "xxxxxxxxxxxxxxxxxxxx",
"lastUpdateRequest": {
"buildDetails": {
"steps": [
{
"name": "LANGUAGE_MODEL_QUICK_BUILD",
"status": "SUCCEEDED"
},
{
"name": "LANGUAGE_MODEL_FULL_BUILD",
"status": "SUCCEEDED"
}
]
},
"status": "SUCCEEDED"
},
"version": "2"
}
},
"manifest": {
"eTag": "xxxxxxxxxxxxxxxxxxxx",
"lastUpdateRequest": {
"status": "SUCCEEDED" ←ここが「SUCCEEDED」になっているか確認
}
}
}
通知の許可
スキルマニュフェストの変更で、新しく作成したスキルで「通知」が利用可能になりました。ただし「通知」は、スキルを利用するユーザの許可がなければ送れないので、スマホのAlexaアプリから通知の許可を行います。
①スキル画面を開く
スマホのAlexaアプリを開き、メニュー「スキル・ゲーム」→「有効なスキル」→「開発」と進み、上で作成したスキルを選択して、スキルの画面を表示させます。
②スキルの有効化
「有効にして使用する」のボタンをクリックします。
③スキルの設定
スキルの画面に戻ったら、今度は「設定」ボタンをクリックします。
④通知の有効化
「リマインダー」と「Alexaの通知」のチェックを入れ「アクセス権を保存」ボタンをクリックします。※リマインダーはチェックしなくても良いと思いますが、念のため。
これで、Alexaスキル側の設定は完了です。
アクセストークンの取得
次に、通知を送る側の設定を行います。まずは、通知を送るために必要なアクセストークンを取得します。
①アクセストークンの取得
curlコマンドを使って、以下ようにWebAPIアクセスするとアクセストークンが取得できます。
なお、xxxxの部分には上でメモした「AlexaクライアントID」、yyyyの部分には上でメモした「Alexaクライアントシークレット」に変更してください。
$curl -i -X POST \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id=amzn1.application-oa2-client.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&client_secret=yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy&scope=alexa::proactive_events' \
https://api.amazon.com/auth/o2/token
うまくWebAPIにアクセスできると、以下のような応答が返ってきて、「access_token」の部分が今後必要になるアクセストークンになります。
HTTP/1.1 200 OK
Server: Server
Date: Fri, 18 Oct 2019 07:00:38 GMT
Content-Type: application/json;charset=UTF-8
Content-Length: 403
Connection: keep-alive
x-amzn-RequestId: 8410f500-6ffa-4051-b742-68e501d9637b
X-Amz-Date: Fri, 18 Oct 2019 07:00:38 GMT
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding,X-Amzn-CDN-Cache,X-Amzn-AX-Treatment,User-Agent
x-amz-rid: P2AE7SB1JW1G71QRM63K
{"access_token":"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz","expires_in":3600,"scope":"alexa::proactive_events","token_type":"bearer"}
プロアクティブイベントAPIの呼び出し
ここまで来たらもう一息です。通知を送る側のアプリを作成します。
①通知アプリの作成
AlexaのプロアクティブイベントAPIを呼び出すアプリケーション「sendEvent.js」を以下のように作成します。
なお、tokenのzzzzzの部分は、上で取得したアクセストークンに置き換えてください。
const rp = require('request-promise');
const token = 'zzzzzzzzzzzz';
sendEvent();
async function sendEvent() {
const body = JSON.stringify(makeBody());
const url = 'https://api.fe.amazonalexa.com/v1/proactiveEvents/stages/development'
const options = {
method: 'POST',
uri: url,
timeout: 10000,
body: body,
headers: {
'Content-Type': 'application/json',
'Content-Length': body.length,
'Authorization' : 'Bearer ' + token
}
};
await rp(options);
}
function makeBody() {
let now = new Date();
let delTime = new Date();
delTime.setMinutes(now.getMinutes() + 60*8);
return {
'timestamp': now.toISOString(),
'referenceId': 'id',
'expiryTime': delTime.toISOString(),
'event': {
'name': 'AMAZON.MessageAlert.Activated',
'payload': {
'state': {
'status': 'UNREAD',
'freshness': 'NEW'
},
'messageGroup': {
'creator': {
'name': 'tesuto tsuuchi...'
},
'count': 1,
'urgency': 'URGENT'
}
}
},
'localizedAttributes': [
{
'locale': 'ja-JP',
}
],
'relevantAudience': {
'type': 'Multicast',
'payload': {}
}
}
}
プログラム内の「makeBody」内で、通知する内容を指定しています。ポイントだけ書くと、expiryTimeは通知を消すまでの時間、freshnessは新規通知が既存の通知かの指定、nameは通知の作成者(日本語だとうまくいかないのでローマ字で)です。
②テスト
それでは、以下のようにして作成したプログラムを実行してみましょう!!!!
$node sendEvent.js
どうですか?Alexaが「ピローロン」と言って、リングが黄色く光りましたか?黄色く光ったら「アレクサ、通知ある?」と話しかけましょう。すると、アレクサが通知を読み上げてくれると思います。
おわりに
今回はAlexaに通知を送ることをやってみました。スマートホームなど、ちょっとしたことをAlexaが通知でおしえてくれたら良いなーと思うことが多いので、この機能を今後使っていこうと思います。
コメント