question

InnovationLab avatar image
InnovationLab asked ·

[SmartHomeSkill] "Sample Switch isn't responding..."

Hello,

I am new to creating a Smart Home Skill so I followed a Amazon sample for creating a Smart Home Skill, "skill-sample-nodejs-smarthome-switch", https://github.com/alexa/skill-sample-nodejs-smarthome-switch. The code I used is from the sample on GitHub.

I followed the steps successfully, but after running 'Discover devices', I can see the 'Sample Switch' in the list of devices but below the 'Sample Endpoint Description' it says "Failed to retrieve state". The code looks like it supports the status of the state.

If I test the skill via the Developer console, "Alexa turn on Sample Switch", it responds with "Sample Switch isn't responding. Please check its network connection and power supply. "


I would appreciate advice on how to resolve both issues. Below is my code.


'use strict';

let AWS = require('aws-sdk');
AWS.config.update({region:'us-east-1'});

let AlexaResponse = require("./alexa/skills/smarthome/AlexaResponse");


exports.handler = async function (event, context) {

    // Dump the request for logging - check the CloudWatch logs
    console.log("index.handler request  -----");
    console.log(JSON.stringify(event));

    if (context !== undefined) {
        console.log("index.handler context  -----");
        console.log(JSON.stringify(context));
    }

    // Validate we have an Alexa directive
    if (!('directive' in event)) {
        let aer = new AlexaResponse(
            {
                "name": "ErrorResponse",
                "payload": {
                    "type": "INVALID_DIRECTIVE",
                    "message": "Missing key: directive, Is request a valid Alexa directive?"
                }
            });
        return sendResponse(aer.get());
    }

    // Check the payload version
    if (event.directive.header.payloadVersion !== "3") {
        let aer = new AlexaResponse(
            {
                "name": "ErrorResponse",
                "payload": {
                    "type": "INTERNAL_ERROR",
                    "message": "This skill only supports Smart Home API version 3"
                }
            });
        return sendResponse(aer.get())
    }

    let namespace = ((event.directive || {}).header || {}).namespace;

    if (namespace.toLowerCase() === 'alexa.authorization') {
        let aar = new AlexaResponse({"namespace": "Alexa.Authorization", "name": "AcceptGrant.Response",});
        let granteeToken = event.directive.payload.grantee.token;
        let grantAuthCode = event.directive.payload.grant.code;
        return sendResponse(aar.get());
    }

    if (namespace.toLowerCase() === 'alexa.discovery') {
        let adr = new AlexaResponse({"namespace": "Alexa.Discovery", "name": "Discover.Response"});
        let capability_alexa = adr.createPayloadEndpointCapability();
        let capability_alexa_endpointhealth = adr.createPayloadEndpointCapability({"interface": "Alexa.EndpointHealth", "supported": [{"name": "connectivity"}],"proactivelyReported": true, "retrievable": true});
        let capability_alexa_powercontroller = adr.createPayloadEndpointCapability({"interface": "Alexa.PowerController", "supported": [{"name": "powerState"}]});
        let capability_alexa_contactsensor = adr.createPayloadEndpointCapability({"interface": "Alexa.ContactSensor", "supported": [{"name": "detectionState"}],"proactivelyReported": true, "retrievable": true});
        adr.addPayloadEndpoint({"friendlyName": "Sample Switch", "endpointId": "sample-switch-01", "capabilities": [capability_alexa_powercontroller]});
        adr.addPayloadEndpoint({"friendlyName": "Sample Sensor", "endpointId": "sample-sensor-01", "displayCategories": ["CONTACT_SENSOR"], "capabilities": [capability_alexa, capability_alexa_contactsensor, capability_alexa_endpointhealth]});
        return sendResponse(adr.get());
    }

    if (namespace.toLowerCase() === 'alexa.powercontroller') {
        console.log("DEBUG:", "TurnOn or TurnOff Request", JSON.stringify(event));

        let power_state_value = "OFF";

        if (event.directive.header.name === "TurnOn")
            power_state_value = "ON";

        let endpoint_id = event.directive.endpoint.endpointId;
        let token = event.directive.endpoint.scope.token;
        let correlationToken = event.directive.header.correlationToken;

        let ar = new AlexaResponse(
            {
                "correlationToken": correlationToken,
                "token": token,
                "endpointId": endpoint_id
            }
        );
        ar.addContextProperty({"namespace":"Alexa.PowerController", "name": "powerState", "value": power_state_value});

        // Check for an error when setting the state
        let state_set = sendDeviceState(endpoint_id, "powerState", power_state_value);
        if (!state_set) {
            return new AlexaResponse(
                {
                    "name": "ErrorResponse",
                    "payload": {
                        "type": "ENDPOINT_UNREACHABLE",
                        "message": "Unable to reach endpoint database."
                    }
                }).get();
        }

        return sendResponse(ar.get());
    }

};

function sendResponse(response)
{
    // TODO Validate the response
    console.log("index.handler response -----");
    console.log(JSON.stringify(response));
    return response
}

function sendDeviceState(endpoint_id, state, value) {
    let dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

    let key = state + "Value";
    let attribute_obj = {};
    attribute_obj[key] = {"Action": "PUT", "Value": {"S": value}};

    let request = dynamodb.updateItem(
        {
            TableName: "SampleSmartHome",
            Key: {"ItemId": {"S": endpoint_id}},
            AttributeUpdates: attribute_obj,
            ReturnValues: "UPDATED_NEW"
        });

    console.log("index.sendDeviceState request -----");
    console.log(request);

    let response = request.send();

    console.log("index.sendDeviceState response -----");
    console.log(response);
    return true;
}

alexa skills kitalexa smart homelambdasmart home
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

apeksha avatar image
apeksha answered ·

Hello there,

1. Is device is online and working without Alexa integration?If yes, Could you please provide us the skill Id of the skill.

2. "Failed to retrieve state" comes when the report state is not implemented.

Please check out the link for more information: https://developer.amazon.com/docs/smarthome/state-reporting-for-a-smart-home-skill.html

10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

InnovationLab avatar image
InnovationLab answered ·

Thanks for your reply. My skill Id, amzn1.ask.skill.8baace14-80fc-4c43-bb12-aa21ccbea27b.

Thank you for telling me about the Report State. The code doesn't implement that and the instructions shows nothing wrong after discovery.


Why do you think I can't turn it on?


10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

InnovationLab avatar image
InnovationLab answered ·

I re-did the sample and was able to turn on / turn off the sample switch. Not sure what the original problem was. I will add code to implement Report State.

10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.