![[日本語Alexa] プロアクティブイベントでごみ収集の通知を送ってみた](https://devio2023-media.developers.io/wp-content/uploads/2018/12/alexa-eyecatch.jpg)
[日本語Alexa] プロアクティブイベントでごみ収集の通知を送ってみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
AIソリューション部の平内(SIN)です。
Alexaの ProactiveEvents APIを使用して、ゴミ収集について通知してみました。
最初に、動作しているようすです。スキルの有効化と通知の許可を設定し、ローカルのJavaScriptから通知を送ってます。
作業した手順は、以下のとりです。
- スキルの作成 (特に何も実装していません)
- プロアクティブイベントの追加
- 通知の許可
- 通知の送信
2 スキルの作成
今回のスキルは、通知を受け取るためだけに使用するので、特に何も実装していません。 Lambdaの配置もお任せということで、「Alexaがホスト」を使用して作成しました。
SMAPIからスキルを指定するために必要なので、スキルIDをコピーしておきます。

続いて、アクセス権限を開いて、一番下に表示されているAlexaスキルメッセージングのクライアントIDとクライアントシークレットをコピーしておきます。

この2つは、通知を送信する時に必要になります。

3 プロアクティブイベントの追加
スキルのマニフェストにpermissionsと、eventsを追加する作業です。現在、この作業はコンソールから行うことができないため、SMAPIが必要です。
取得
$ ask api get-skill -s amzn1.ask.skill.xxxxx-xxxx-xxxx > skill.json
更新
$ ask api update-skill -s amzn1.ask.skill.xxxxx-xxxx-xxxx -f skill.json
マニフェストの文法などに誤りがあると、更新に失敗するので、update-skillがちゃんと書き換えに成功しているかどうか、念のため、get-skillで更新されたものを確認することをお勧めします。
更新前後のマニフェストは、以下のとおりです。permissions に alexa::devices:all:notifications:write を追加し、events に使用するイベントの種類を指定します。
endpointは、どこで使用されているのか、ちょっと分からないのですが、有効なLambdaのarnである必要があるようです。
更新前
{
  "manifest": {
    "apis": {
      "custom": {
        "endpoint": {
          "uri": "arn:aws:lambda:us-east-1:647216831504:function:de401ac6-7b67-4c36-963f-56dd13736589:Release_0"
        }
      }
    },
    "permissions": [],
    "publishingInformation": {
      "locales": {
        "ja-JP": {
          "name": "通知サンプル"
        }
      }
    }
  }
}
更新後
{
  "manifest": {
    "apis": {
      "custom": {
        "endpoint": {
          "uri": "arn:aws:lambda:us-east-1:647216831504:function:de401ac6-7b67-4c36-963f-56dd13736589:Release_0"
        },
        "interfaces": []
      }
    },
    "permissions": [
      {
        "name": "alexa::devices:all:notifications:write"
      }
    ],
    "events": {
      "publications": [
        {
          "eventName": "AMAZON.TrashCollectionAlert.Activated"
        }
      ],
      "endpoint": {
        "uri": "arn:aws:lambda:us-east-1:xxxxxxxxx:function:sample"
      },
      "subscriptions": [
        {
          "eventName": "SKILL_PROACTIVE_SUBSCRIPTION_CHANGED"
        }
      ]
    },
    "publishingInformation": {
      "locales": {
        "ja-JP": {
          "name": "通知サンプル"
        }
      }
    }
  }
}
今回、設定した、ごみ収集のリマインダー以外のイベントについては、以下をご参照下さい。
プロアクティブイベントAPI
4 通知の許可
マニフェストを更新すると、Alexaアプリでのスキルの表示が変わります。

「設定」からこれを許可することで、スキルは通知を受け取ることができるようになります。
 

5 通知の送信
通知を送るには、次の2つ作業が必要です。
- アクセストークン取得
- ProactiveEvents APIの呼び出し
(1) アクセストークン取得
開発者コンソールでコピーした、クライアントIDとクライアントシークレットを使用してOAuth2サーバからトークンを取得します。サンプルでは、getToken(clientId, clientSecret) で実装しました。
(2) ProactiveEvents APIの呼び出し
トークンを使用して、イベントに応じたJSONをproactiveEventsのエンドポイントに送信します。 サンプルでは、sendEvent(token)で実装しました。
イベントごとの送信するJSONは、以下をご参照下さい。
プロアクティブイベントのスキーマ
今回は、簡略化のためtrashCollectionAlertEvent()で決め打ちで実装しています。
(3) コード
実装したコードの全部です。
const rp = require('request-promise');
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
notify(); 
async function notify() {
    const token = await getToken(clientId, clientSecret);
    await sendEvent(token);
}
async function getToken(clientId, clientSecret) {
    const uri = 'https://api.amazon.com/auth/o2/token'
    let body = 'grant_type=client_credentials';
    body += '&client_id=' + clientId;
    body += '&client_secret=' + clientSecret;
    body += '&scope=alexa::proactive_events';
    const options = {
        method: 'POST',
        uri: uri,
        timeout: 30 * 1000,
        body: body,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    };
    const data = await rp(options);
    return JSON.parse(data).access_token;
}
async function sendEvent(token) {
    const body = JSON.stringify(trashCollectionAlertEvent());
    const uri = 'https://api.fe.amazonalexa.com/v1/proactiveEvents/stages/development'
    //const uri = 'https://api.fe.amazonalexa.com/v1/proactiveEvents/' // 公開スキルでは、こちら
    const options = {
        method: 'POST',
        uri: uri,
        timeout: 30 * 1000,
        body: body,
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': body.length,
            'Authorization' : 'Bearer ' + token
        }
    };
    await rp(options);
}
function trashCollectionAlertEvent() {
    let timestamp = new Date();
    let expiryTime = new Date();
    expiryTime.setMinutes(expiryTime.getMinutes() + 60);
    return {
        'timestamp': timestamp.toISOString(),
        'referenceId': 'id-'+ new Date().getTime(),
        'expiryTime': expiryTime.toISOString(),
        'event': {
            'name': 'AMAZON.TrashCollectionAlert.Activated',
            'payload': {
                'alert': {
                    'garbageTypes': [
                        'PET_BOTTLES',
                        'RECYCLABLE_PLASTICS',
                        'WASTE_PAPER',
                        'COMPOSTABLE',
                    ],
                    'collectionDayOfWeek': 'TUESDAY'
                }
            }
        },
        'localizedAttributes': [
            {
                'locale': 'ja-JP',
                'sellerName': 'TrashCollection'
            }
        ],
        'relevantAudience': {
            'type': 'Multicast',
            'payload': {}
        }
    }
}
6 最後に
今回は、Alexaのプロアクティブ・イベントでゴミ収集について通知してみました。 この仕様は、日本語で利用できるようになって、しばらく時間がたったと思うのですが、思ったより日本語での情報が公開されていない印象です。
イベントの種類によって、使い方が少し変わってきそうなので、もう少し、確認作業を進めたいと思っています。
7 参考リンク
通知の概要
プロアクティブイベントAPI
プロアクティブイベントのスキーマ
スキルマニフェストのスキーマ
スキルにイベントを追加する
Alexa Proactive Events API
弊社では、Amazon Connectに関するキャンペーンを行なっています。
【6/27(木)東京】「1時間でクラウド型コンタクトセンターを構築できるようになる!無料Amazon Connectハンズオンセミナー」を開催します
また、音声を中心とした各種ソリューションの開発支援を行なっております。








