
スマートホームスキルの作り方をシリーズでお届けしたいと思います。
カスタムスキルの作り方については「Alexaスキル開発トレーニングシリーズ 第1回 初めてのスキル開発」を確認してください。
インターネットに接続された電球や、スマートロックなどのスマートホームデバイスを声でコントロールすることを可能にするスキルをスマートホームスキルと言います。専用のAPIがあり、これを使うことで、自然な発話でのスマートホームデバイスの操作を実現できます。例えば次のような感じです。
ユーザー:リビングの電気をつけて
Alexa:はい (リビングの電気がつく)
ユーザー:玄関の鍵をかけて
Alexa:玄関の鍵をロックしています
Alexa:玄関の鍵をロックしました(玄関の鍵がロックされる)
ここではこのスマートホームスキルAPI を使ったスマートホームスキルの作り方を説明します。
スマートホームスキルAPI の詳細については以下を確認してください。
ここで説明する内容を実際に行うには事前に以下を準備しておく必要があります。
|   TIPS *1 開発者ポータルのアカウントは amazon.co.jp のアカウントから作成することを推奨します。amazon.co.jp アカウントで作成された開発者ポータルアカウントで開発したスキルは、同じアカウントに紐づいた Alexa デバイスで直接テストをすることができます。amazon.co.jp のアカウントで開発者ポータルアカウントを作るには、あらかじめ amazon.co.jp アカウントを www.amazon.co.jp で作成、同じ ID、パスワードで developer.amazon.com にログインします。  |  
  
開発者ポータルにスマートホームスキルを新規に登録します。開発者ポータル(developer.amazon.com)にログインし、[新しいスキルを追加する] からスキルを追加します。
|   TIPS 開発者ポータルのログインIDは、Alexa に設定しているものと同じものを使うことを推奨します。同じ ID を使うと、作成したスキルを Alexa 端末ですぐに試すことができます。  |  
  
次の通り設定します。
以下は手順を進めたときのスクリーンショットです。



[保存] ボタンを押して設定を保存します。
ユーザーからの処理を行うバックエンドロジックは AWS Lambda 関数で受けとり、処理します。AWS Lambda 関数を作りましょう。
AWS (https://aws.amazon.com/ )にログインします。サービスから Lambda を開き、地域は日本の場合はオレゴン、米国向けの場合は米国東部(バージニア北部)を選択、[関数の作成] を押して Lambda の新規作成を開始します。

「関数の作成」では [一から作成] を選択し、それぞれ以下のように入力します。

右下の [関数の作成] ボタンを押し、設定を保存します。
次に、開発者ポータルに戻り、作成中のスキルのスキルIDを確認してください。スキルIDは amzn.ask.skill から始まる文字列です。これをクリップボードにコピーしておきます。

再び Lambda 関数の作成に戻ります。トリガーで「Alexa Smart Home」を選択、「トリガーの設定」で先ほどクリップボードにコピーしたスキルIDをペーストします。

右下の [追加] ボタンを押してトリガーの設定を保存します。次に右上の[保存]ボタンを押してこれまでの設定を保存します。
次に Lambda 関数を選択します。

「基本設定」の「タイムアウト」を確認してください。この値は 7 秒にすることを推奨します。Alexaがスキルからの応答を待つ最大時間が約7秒だからです。Lambdaからの応答は 7秒以内に行う必要があります。

設定を変更したら、[保存] を押して変更内容を保存しておきましょう。次に Lambda関数の中身を仕上げていきます。
作成した Lambda関数の処理を実装します。
スマートホームスキルのサンプルコードが https://github.com/alexa/alexa-smarthome にありますので、ダウンロードしてください。今回はこのサンプルコードを利用して Lambda関数を仕上げます。
今回作成した Lambda 関数のベースとなるコードはダウンロードしたコードの sample_lambda/python の配下にあります。
ここでは SAMPLE_APPLIANCES で連携デバイスを設定しています。friendlyName はデバイスを呼び出すときの呼び出し名で、Alexa アプリで表示されるそのデバイスの名前にもなります。日本語環境では任意の日本語に書き換えてください。
manufactureName と friendlyDescription は Alexaアプリで検出されたデバイスに対して表示される付加情報です。これらの情報によってユーザーは、そのデバイスはどのスキルが提供していて、何ができるかを知ることができます。これらも日本語に書き換えることができます。
    :           :
SAMPLE_APPLIANCES = [
    {
        "applianceId": "endpoint-001",
        "manufacturerName": "マイスマートホームサンプル",
        "modelName": "Smart Switch",
        "version": "1",
        "friendlyName": "スイッチ",
        "friendlyDescription": "マイスマートホームスイッチ オン・オフが可能",
        "isReachable": True,
        "actions": [
            "turnOn",
            "turnOff"
        ],
        "additionalApplianceDetails": {
            "detail1": "For simplicity, this is the only appliance",
            "detail2": "that has some values in the additionalApplianceDetails"
        }
    },
    {
        "applianceId": "endpoint-002",
        "manufacturerName": "マイスマートホームサンプル",
        "modelName": "Smart Light",
        "version": "1",
        "friendlyName": "ライト",
        "friendlyDescription": "マイスマートホームスイッチ オン・オフ、色、色温度、明るさの変更が可能",
        "isReachable": True,
        "actions": [
            "turnOn",
            "turnOff",
            "setPercentage",
            "incrementPercentage",
            "decrementPercentage",
            "setColor",
            "setColorTemperature",
            "incrementColorTemperature",
            "decrementColorTemperature"
        ],
        "additionalApplianceDetails": {}
    },
                       
    :           :
 
modelName には対象のデバイスがサポートしている機能をデバイスのタイプとして指定します。サンプルコードでは次の表にあるmodelNameが設定できるように作られていますが、いくつかはまだ日本語環境ではサポートされていません。日本語対応の欄を参考に、使える modelName を確認してください。
サンプルコード内 modelName の取れる値と日本語サポート状況(2018年2月22日現在)
| modelName | 日本語対応 | 
|---|---|
| Smart Switch | ◯ | 
| Smart Light | ◯ | 
| Smart White Light | ◯ | 
| Smart Thermostat | × | 
| Smart Lock | ◯ | 
| Smart Scene | ◯ | 
| Smart Activity | ◯ | 
| Smart Camera | × | 
|   NOTE サンプルプログラムでは、スマートホームスキルAPIの 旧バージョン (v2) と新バージョン (v3) の両方に対応できるような実装を行なっています。日本語環境に適用する場合は v2 の対応は不要です。このため、よりシンプルな実装にすることも可能です。  |  
  
次に validation_schemas の配下にある alexa_smart_home_message_schema.json を sample_lambda/python フォルダーにコピーします。これは Lambda 関数から Alexa への応答が正しい形式かどうかをチェックするスキーマファイルで、サンプルコードの中の validation.py が利用しています。

ここまでできたら、ファイルをダウンロードし、配下のファイルを一つの zip ファイルにまとめます。

AWS に戻ります。Lambda 関数に、作成した zip ファイルをアップロードします。
ハンドラは lambda.lambda_handler にします。全て設定したら右上の [保存] ボタンを押します。ファイルの読み込みが開始されます。

正しく取り込まれると、次のようになります。

  
作成した Lambda関数と開発者ポータルで設定しているスキルとを紐付け、スキルの設定を仕上げます。紐づけるために必要な情報は Lambda関数の ARN です。Lambda関数の ARN は Lambda 作成画面の右上で確認することができます。

作成した Lambda関数の ARN を開発者ポータル、スキルのエンドポイントに設定します。

アカウントリンクを設定します。アカウントリンクはスマートホームスキルでは必須です。
アカウントリンクによりあなたのクラウドシステムが管理する各ユーザーのデバイスと Alexaデバイスのユーザーとが紐づきます。
アカウントリンクでは OAuth2.0 サーバーの情報を設定する必要があります。アカウントの連携機能の実装を後回しにし、まずは決められたデバイスに対して操作を行いたい場合、「Login with Amazon(Amazon でログイン)」が使えます。 「Login with Amazon」はAmazon ID の基本情報に対するアクセスを OAuth 2.0 を通してスキルに提供します。ユーザーはスキルを有効にするときに、Amazon.co.jpで使っているメールアドレスとパスワードでログインすることになります。
「Login with Amazon」をスキルに設定する方法は次が参考になります。
「Alexa Account Linking: 5 Steps to Seamlessly Link Your Alexa Skill with Login with Amazon」
作成したスキルは、スキルを作成したアカウントと同じIDで設定されている Alexaデバイスではすでに使える状態になっており、有効化することでテストすることができます。別のアカウントに紐づいているデバイスでテストする場合は、ベータテスト機能を使います。
|   ベータテスト機能 開発中のスキルを公開前に複数のAlexaユーザーに試行してもらうための機能です。ベータテスト機能を使う手順は以下の通りです。 
  |  
  
設定が完了すると、該当スキルは「有効なスキル」の一つとしてAlexaアプリから確認できるようになります。スキルを有効にし、アカウントリンクを行います。

スキルが有効になるとスキルが管理するデバイスが検出できるようになります。Alexaデバイスに「アレクサ、デバイスを見つけて」と話しかけると検出できます。Alexaアプリの「端末の検出」から検出することもできます。

検出がうまくいくとfriendlyNameで定義したデバイスが一覧で表示されます。次のスクリーンショットは、スマートフォンの Alexaアプリでスマートホームタブに表示されているデバイスの一覧です。

デバイスが正しく検出されると、ユーザーは検出されたデバイス名で操作を行うことができます。以下に代表的な発話例を示します。
今回実装したサンプルコードはディレクティブに対して任意の返答を行うだけで、実際のデバイスとの連携、操作は行いません。サンプルコードの以下の部分がディレクティブを処理しています。ここにデバイス操作を行うための API 呼び出しを実装していけば実際のデバイス操作ができることになります。
         :             :
def handle_non_discovery_v3(request):
    request_namespace = request["directive"]["header"]["namespace"]
    request_name = request["directive"]["header"]["name"]
    if request_namespace == "Alexa.PowerController":
        if request_name == "TurnOn":
            value = "ON"
        else:
            value = "OFF"
        response = {
            "context": {
                "properties": [
                    {
                        "namespace": "Alexa.PowerController",
                        "name": "powerState",
                        "value": value,
                        "timeOfSample": get_utc_timestamp(),
                        "uncertaintyInMilliseconds": 500
                    }
                ]
            },
            "event": {
                "header": {
                    "namespace": "Alexa",
                    "name": "Response",
                    "payloadVersion": "3",
                    "messageId": get_uuid(),
                    "correlationToken": request["directive"]["header"]["correlationToken"]
                },
                "endpoint": {
                    "scope": {
                        "type": "BearerToken",
                        "token": "access-token-from-Amazon"
                    },
                    "endpointId": request["directive"]["endpoint"]["endpointId"]
                },
                "payload": {}
            }
        }
        return response
         :             :
 
最後に、繰り返しにはなりますが、このサンプルプログラムでは、スマートホームスキルAPIの 旧バージョン (v2) と新バージョン (v3) の両方に対応できるような実装を行っています。日本語環境に適用する場合は v2 の対応は不要ですので、よりシンプルな実装にすることも可能です。
このブログの続きは、こちらをご覧ください: スマートホームスキルを作る (2) 各ディレクテイブを処理する
編集注: コンソールのアップデートに伴い、一部内容を更新しました(2018/3/26)