Alexa Home Skill では Payload Version v3 を利用する


Alexa Home Skill を使ってみようとした時に詰まったのでメモ.

Payload Version v2 のサイトは古い

いくつか説明サイトがあるがレスポンスの
Payload Versionv2にしているものは古いので公式説明ページを参照することをおすすめします.

現在(2018/01/12)は,Lambdaに用意されているalexa-smart-home-skill-adapterテンプレートも古いままで,これをそのまま使うと versionがv2なので Alexa スキルのデフォルト設定の v3 にしているとデバイスを見つけてくれないので注意が必要.公式説明ページにLambdaの書き換えるコードも書いてあります.

追記(実際にアレクサでスキルを試す場合)

Alexa Skill を作ってみる分には公式説明ページで十分でしたが,実際にコードをアレクサで試す場合には公式ページではレスポンスをうまく返せていないのでAlexaは「○○は応答していません」とエラーを返します.そこでLambdaの関数を書き換えました.基本は公式ページのコードを引用しています.

index.js
exports.handler = function(request, context) {
    if (request.directive.header.namespace === 'Alexa.Discovery' && request.directive.header.name === 'Discover') {
        log("DEGUG:", "Discover request", JSON.stringify(request));
        handleDiscovery(request, context, "");
    }
    else if (request.directive.header.namespace === 'Alexa.PowerController') {
        if (request.directive.header.name === 'TurnOn' || request.directive.header.name === 'TurnOff') {
            log("DEBUG:", "TurnOn or TurnOff Request", JSON.stringify(request));
            handlePowerControl(request, context);
        }
    }

    function handleDiscovery(request, context) {
        var payload = {
            "endpoints": [{
                "endpointId": "demo_id",
                "manufacturerName": "Smart Device Company",
                "friendlyName": "電気",
                "description": "smart switch",
                "displayCategories": ["SWITCH"],
                "cookie": {
                    "key1": "arbitrary key/value pairs for skill to reference this endpoint.",
                    "key2": "There can be multiple entries",
                    "key3": "but they should only be used for reference purposes.",
                    "key4": "This is not a suitable place to maintain current endpoint state."
                },
                "capabilities": [{
                        "type": "AlexaInterface",
                        "interface": "Alexa",
                        "version": "3"
                    },
                    {
                        "interface": "Alexa.PowerController",
                        "version": "3",
                        "type": "AlexaInterface",
                        "properties": {
                            "supported": [{
                                "name": "powerState"
                            }],
                            "retrievable": true
                        }
                    }
                ]
            }]
        };
        var header = request.directive.header;
        header.name = "Discover.Response";
        log("DEBUG", "Discovery Response: ", JSON.stringify({ header: header, payload: payload }));
        context.succeed({ event: { header: header, payload: payload } });
    }

    function log(message, message1, message2) {
        console.log(message + message1 + message2);
    }

    function handlePowerControl(request, context) {
        // get device ID passed in during discovery
        var requestMethod = request.directive.header.name;
        // get user token pass in request
        var requestToken = request.directive.endpoint.scope.token;
        var powerResult;

        if (requestMethod === "TurnOn") {

            // Make the call to your device cloud for control 
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "ON";
        }
        else if (requestMethod === "TurnOff") {
            // Make the call to your device cloud for control and check for success 
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "OFF";
        }

        var response = {
            "context": {
                "properties": [{
                    "namespace": "Alexa.PowerController",
                    "name": "powerState",
                    "value": powerResult,
                    "timeOfSample": "2017-02-03T16:20:50.52Z",
                    "uncertaintyInMilliseconds": 500
                }]
            },
            "event": {
                "header": {
                    "namespace": "Alexa",
                    "name": "Response",
                    "payloadVersion": "3",
                    "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4",
                    "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg=="
                },
                "payload": {}
            }
        };


        log("DEBUG", "Alexa.PowerController ", JSON.stringify(response));
        context.succeed(response);
    }
};

これで「電気をつけて」とAlexaにお願いすると「はい」と返答してくれます.