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

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

# Payload Version v2 のサイトは古い
いくつか説明サイトがあるがレスポンスの
`Payload Version`を`v2`にしているものは古いので[公式説明ページ](https://developer.amazon.com/ja/docs/smarthome/steps-to-build-a-smart-home-skill.html#register-as-an-amazon-developer-and-create-the-skill)を参照することをおすすめします．

現在(2018/01/12）は，Lambdaに用意されている`alexa-smart-home-skill-adapter`テンプレートも古いままで，これをそのまま使うと versionが`v2`なので Alexa スキルのデフォルト設定の `v3` にしているとデバイスを見つけてくれないので注意が必要．[公式説明ページ](https://developer.amazon.com/ja/docs/smarthome/steps-to-build-a-smart-home-skill.html#register-as-an-amazon-developer-and-create-the-skill)にLambdaの書き換えるコードも書いてあります．

# 追記（実際にアレクサでスキルを試す場合）
Alexa Skill を作ってみる分には[公式説明ページ](https://developer.amazon.com/ja/docs/smarthome/steps-to-build-a-smart-home-skill.html#register-as-an-amazon-developer-and-create-the-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にお願いすると「はい」と返答してくれます．