スキルからガジェットにカスタムディレクティブを送信する



スキルからガジェットにカスタムディレクティブを送信する

カスタムスキルからガジェットの動作をトリガーするには、スキル応答の一部として1つまたは複数のカスタムディレクティブを送信します。カスタムディレクティブを使用することで、スキルからガジェットだけが理解できる任意のペイロードを送信できます。

カスタムディレクティブをサポートするには、まずカスタムインターフェースを定義し、次にガジェットのファームウェアで、定義したカスタムディレクティブをデコードできるコードを追加します。次に、カスタムインターフェースコントローラーを使用して、スキルコードからカスタムディレクティブを送信します。このインターフェースは、Alexa Skills Kit開発者コンソールまたはAlexa Skills Kitコマンドラインインターフェース(ASK CLI)を使用してスキルをセットアップする際に、スキルに追加します。

このトピックでは、利用可能なガジェットをクエリする方法と、スキルから利用可能なガジェットにカスタムディレクティブを送信する方法について説明します。インターフェースを定義する方法や、そのインターフェースをサポートするためにガジェットで行うべき処理については、カスタムインターフェースの詳細を参照してください。また、ガジェットからスキルにカスタムイベントを送信することもできます。詳しくはガジェットからカスタムイベントを受信するを参照してください。

サンプルコードについては、GitHubのAlexa Gadgets Raspberry Piサンプルを参照してください。

概要

次の図と下の説明は、スキルとガジェットの間の対話の概要を示しています。

Alexa Gadgetにカスタムディレクティブを送信する

手順は以下のとおりです。詳細については、このページの後半で詳しく説明します。

  1. スキルを起動する – Alexaアプリでスキルを有効にした後、「アレクサ、[スキルの呼び出し名]を開いて」などのフレーズでスキルを起動します。これを受けて、Alexaはスキルにリクエストを送信します。通常、これは起動リクエストで行いますが、特定のインテントを使用してスキルを呼び出すこともできます。
  2. 利用可能なガジェットをクエリする – スキルの起動時、スキルコードでAlexaサービスエンドポイントをクエリして、スキルに対して利用可能なガジェットがあるかどうかを確認する必要があります(これついては、このトピックで後ほど詳しく説明します)。「利用可能」とは、ガジェットが現在ユーザーのEchoデバイスに接続されていて、さらにガジェットがスキルの作成に使用した開発者アカウントで開発者ポータルに登録されていることを意味します。ガジェットのクエリ手順は3段階に分かれます。
    1. Alexaのリクエストから情報を取得する – スキルは、Alexaのリクエストが含まれるコンテキストオブジェクトから情報を抽出します。
    2. Endpoint Enumeration APIを呼び出す – スキルは抽出された情報を使用して、エンドポイント列挙APIにHTTPS GETリクエストを送信します。Endpoint Enumeration APIは、すべての利用可能なガジェットのエンドポイントID(ガジェットID)、名前、機能を返します。
    3. エンドポイントIDを保存する – スキルは、返されたエンドポイントID(ある場合)をスキルのセッションアトリビュートに保存し、スキルセッション全体を通して利用可能なガジェットにディレクティブを送信できるようにします。このスキルセッション内で再度ガジェットのクエリをする必要はありません。
  3. スキルが応答する – スキルがAlexaに応答します。応答のコンテンツは、前のステップでスキルが利用可能なガジェットを見つけたかどうかに応じて異なります。
    • 利用可能なガジェットあり – ガジェットのクエリで1つ以上のガジェットが返された場合、スキルはスキルセッション全体を通して、利用可能なガジェットをターゲットとしたカスタムディレクティブを使用し、Alexaからのあらゆるリクエストに応答できます。その後、AlexaはEchoデバイスにディレクティブを送信します。
    • 利用可能なガジェットなし – ガジェットのクエリでガジェットが返されなかった場合、スキルコードはそのデザインに基づいて対応します。たとえば、ガジェットが必須ではない場合、スキルは動作を続行します。ガジェットが必須な場合は、スキルはガジェットが必要であることをユーザーに伝え、動作を終了します。
  4. ガジェットがディレクティブを受信する – クエリで取得されたエンドポイントIDをターゲットとしたカスタムディレクティブをスキルが送信すると、Echoデバイスはカスタムディレクティブをガジェットに渡します。このカスタムディレクティブは.protoファイルにバイナリー形式で記述され、Bluetooth経由で渡されます。ガジェットは、文字列でペイロードを抽出し、適宜対応します。

前提条件

カスタムディレクティブを送信するためのスキルコードをガジェットに追加する前に、以下を実行します。

  • Echoデバイスのソフトウェアバージョンが、開始する前にに記載されているバージョン以降であることを確認します。Echoデバイスのソフトウェアバージョンを確認するには、Alexaアプリで設定デバイスの設定>デバイス>その他デバイスのソフトウェアバージョンの順に移動します。Echoデバイスのソフトウェアバージョンを最新にするには、以下を実行します。
    • 画面の付いていないEchoデバイスの場合 – 「アレクサ、ソフトウェアをアップデートして」と呼びかけます。
    • 画面付きEchoデバイスの場合 – Echoデバイスで設定デバイスオプションソフトウェアアップデートの確認の順に選択します。
  • インターフェースが定義されており、ガジェットがそのインターフェースのサポートを宣言していることを確認します。これらの要素の詳細については、カスタムインターフェースの詳細を参照してください。
  • カスタムスキルを作成し、スキルのサポート対象インターフェースにカスタムインターフェースコントローラーのインターフェースを追加します。詳しくは、ガジェットにスキルを設定するを参照してください。

ステップ1: スキルを起動する

ユーザーがスキルを呼び出すとスキルセッションが開始されます。これにより、Alexaはスキルにリクエストを送信します。通常、これは起動リクエストで行いますが、特定のインテントを使用してスキルを呼び出すこともできます。リクエストにはコンテキストオブジェクトが含まれます。

ステップ2: 利用可能なガジェットをクエリする

このステップは3つの部分に分かれます。まず、スキルがAlexaのリクエストから情報を取得する必要があります。次にEndpoint Enumeration APIを呼び出します。その後、Endpoint Enumeration APIから返されたエンドポイントIDを保存します。

Alexaのリクエストから情報を取得する

Alexaのリクエストのコンテキストオブジェクトから、apiEndpointapiAccessTokenの2つのフィールドの値を取得する必要があります。

  • apiEndpointはAlexaエンドポイントのベースURLで、スキルの地理的な場所に応じて異なります。たとえば、米国のエンドポイントはhttps://api.amazonalexa.com/となります。
  • apiAccessTokenは、スキルに付与された権限をカプセル化しています。これはSystemオブジェクト内にあり、contextオブジェクトに入れ子にされています。

次の例は、LaunchRequestでのapiEndpointapiAccessTokenを示しています。

{
    "version": "1.0",
    "session": {
        "new": true,
        "sessionId": "amzn1.echo-api.session.1",
        "application": {
            "applicationId": "amzn1.ask.skill.1"
        },
        "user": {
            "userId": "amzn1.ask.account.1"
        },
        "attributes": {}
    },

    "context": {
        "AudioPlayer": {
            "playerActivity": "IDLE"
        },
        "System": {
            "application": {
                "applicationId": "amzn1.ask.skill.1"
            },
            "user": {
                "userId": "amzn1.ask.account.1"
            },
            "device": {
                "deviceId": "amzn1.ask.device.1",
                "supportedInterfaces": {
                    "AudioPlayer": {}
                }
            },
            "apiEndpoint": "https://api.amazonalexa.com",
            "apiAccessToken": "someToken"
        }
    },

    "request": {
        "type": "LaunchRequest",
        "requestId": "amzn1.echo-api.request.1",
        "timestamp": "2018-05-11T17:33:01Z",
        "locale": "ja-JP",
        "shouldLinkResultBeReturned": false
    }
}

Endpoint Enumeration APIを呼び出す

apiEndpointapiAccessTokenが取得できたので、次にスキルは利用可能なガジェットをクエリできます。スキルに対してガジェットを利用可能にするには、ガジェットが次の条件を満たしている必要があります。

  • ガジェットが現在ユーザーのEchoデバイスに接続されている。
  • ガジェットがスキルと同じ開発者アカウントで開発者ポータルに登録されている。

これらの条件を満たすすべてのガジェットのリストを取得するには、前のステップで取得したapiEndpointapiAccessTokenを使用してEndpoint Enumeration APIを呼び出します。エンドポイントIDはスキルセッションが終わるまで有効なので、Endpoint Enumeration APIの呼び出しはセッションあたり1回のみで構いません。通常、スキルセッションの間、特定のガジェットのエンドポイントIDは変わりませんが、状況によってはガジェットのエンドポイントIDが変化することがあります(スキルを無効にして再度有効にした場合など)。

Endpoint Enumeration APIを呼び出すには、Alexa Skills Kit SDKのEndpoint Enumeration Serviceクライアントを使用するか、<apiEndpoint>/v1/endpointsエンドポイントにHTTPS GETリクエストを送ります。この<apiEndpoint>には、Alexaのリクエストから取得したapiEndpointのアドレスが入ります。GETリクエストの形式は次のとおりです。

GET <apiEndpoint>/v1/endpoints HTTP/1.1 Authorization: Bearer <apiAccessToken>

たとえば、apiEndpointhttps://api.amazonalexa.com/で、apiAccessTokenabcde12345の場合、Endpoint Enumeration APIを呼び出すスキルのリクエストは次のようになります。

GET https://api.amazonalexa.com/v1/endpoints HTTP/1.1 Authorization: Bearer abcde12345

Alexaがリクエストを処理できる場合、Alexaは、スキルからのディレクティブの送信先として利用可能なエンドポイント(ガジェット)のリストを含むHTTP 200ステータスコードを含んだ応答を返します。各エンドポイントには、ガジェットがAlexa.Discovery.Discover.Responseイベントで定義したID、名前、機能のリストがあります。エンドポイントの形式は次のとおりです。

{
  "endpoints": [
    {
      "endpointId": "amzn1.ask.endpoint.ABC123",
      "friendlyName": "Gadget123",
      "capabilities": [
          {
              "type":"AlexaInterface",
              "interface":"Custom.CustomInterface1",
              "version":"1.0"
          }
       ]
    },
    {
      "endpointId": "amzn1.ask.endpoint.XYZ789",
      "friendlyName": "Gadget789",
      "capabilities": [
          {
              "type":"AlexaInterface",
              "interface":"Custom.CustomInterface1",
              "version":"1.0"
          }
       ]
    }
  ]
}

以下は、ガジェットの/v1/endpoints応答のフィールドについての説明です。

フィールド 説明
endpointId ガジェットの一意のIDです。 文字列
friendlyName ガジェットの名前です。この名前はユーザーまたはプラットフォームによって変更されることがあるため、Bluethoothのフレンドリー名とは異なる場合があります。 文字列
capabilities ガジェットがサポートする機能のリストです。 配列
capabilities.type 機能インターフェースのタイプです。これは通常、AlexaInterfaceです。 文字列
capabilities.interface 機能インターフェースの名前です。 文字列
capabilities.version ガジェットがサポートする機能インターフェースのバージョンです。 文字列

ユーザーのEchoデバイスが利用可能なガジェットに接続されていない場合、エンドポイントのリストは空になります。

エンドポイントIDを保存する

スキルのセッションアトリビュートにエンドポイントID(ガジェットID)を保存します。エンドポイントIDはスキルセッションが終わるまで有効なので、再度IDをクエリする必要はありません。

ステップ3: ガジェットをターゲットとしたディレクティブを使用してAlexaに応答する

ガジェットのリストが取得できたので、ガジェットにディレクティブを送信できます。そのためには、Alexaのリクエストへの応答にCustomInterfaceController.SendDirectiveディレクティブを含めます。次の点にご注意ください。

  • Endpoint Enumeration APIはガジェットがサポートするすべての機能を返しますが、スキルがガジェットに送信できるディレクティブは、カスタムインターフェースに属するもの(つまり、Custom.で始まるインターフェース)のみです。
  • 各ディレクティブは1つのガジェット(1つのエンドポイントID)をターゲットとしているため、複数のガジェットに同じディレクティブを送りたい場合、(同じ応答内の)各ガジェットに対して同じディレクティブを含めます。つまり、単独の応答に複数のディレクティブが含まれることになります。
  • スキルの応答の最大サイズは24KBです。この制限は、応答のすべてのディレクティブとスピーチを含めたものです。

以下は、2つのガジェットにCustom.Robot.Spinディレクティブを送る応答の例です。

{
  "version": "1.0",
  "sessionAttributes": {},
  "response": {
    "outputSpeech": {},
    "card": {},
    "reprompt": {},
    "shouldEndSession": true,
    "directives": [
      {
        "type": "CustomInterfaceController.SendDirective",
        "endpoint": {
          "endpointId": "amzn1.ask.endpoint.ABC123"
        },
        "header": {
          "namespace": "Custom.Robot",
          "name": "Spin"
        },
        "payload": { 
          "direction": "clockwise",
          "times": 5
        }
      },
      {
        "type": "CustomInterfaceController.SendDirective",
        "endpoint": {
          "endpointId": "amzn1.ask.endpoint.XYZ789"
        },
        "header": {
          "namespace": "Custom.Robot",
          "name": "Spin"
        },
        "payload": { 
          "color": "clockwise",
          "times": 5
        }
      }      
    ]
  }
}

完全な応答の形式については、カスタムスキルのJSONインターフェースのリファレンス応答の形式を参照してください。

以下は、CustomInterfaceController.SendDirectiveディレクティブのフィールドについての説明です。

フィールド 説明 必須
type CustomInterfaceController.SendDirectiveです。 文字列
endpoint ディレクティブの送信先であるガジェットです。各ディレクティブは、1つのガジェット(1つのエンドポイントID)のみをターゲットにできます。同じディレクティブを複数のガジェットに送信したい場合、応答の各ガジェットに1つずつディレクティブを含めます。 オブジェクト
endpoint.endpointId ディレクティブの送信先であるガジェットのIDです。 文字列
header ディレクティブのヘッダーを含むオブジェクトです。 オブジェクト
header.namespace 開発者が定義したインターフェースの名前です。 文字列
header.name 開発者が定義したディレクティブの名前です。 文字列
payload ガジェットに送信する自由形式JSONオブジェクトです。 オブジェクト

ステップ4: ガジェットでディレクティブをデコードする

スキルがAlexaへの応答にカスタムディレクティブを含めた後、ディレクティブはAlexaによってEchoデバイスに渡され、さらにBluetoothを経由してガジェットに渡されます。Alexa Gadgets Toolkitディレクティブと同様に、ガジェットは.protoファイルにバイナリー形式で記述されたディレクティブを受信します。その後、ガジェットはディレクティブをデコードして処理する必要があります。詳細については、ステップ3: ガジェットでディレクティブを処理するを参照してください。