调用getThingShadow似乎没有在lambda函数中执行

时间:2018-01-14 22:59:59

标签: lambda aws-lambda alexa-skills-kit aws-iot

我正在研究一个lambda alexa技能处理程序,它与aws IoT中的一个事物阴影集成在一起。我的问题是下面对iotData.getThingShadow的调用似乎没有执行。在回调函数中没有生成任何控制台消息,并且没有填充对象objState。这是代码片段。

   // get the shadow for the home-garage-door
    console.log('Getting thing shadow');

    iotData.getThingShadow(params, function(err, data) {
        console.log('Inside of getThingShadow callback');
        if (err){
            //Handle the error here
            console.log('Problem getting the thing shadow');
            console.log(err, err.stack);
            responseString = "I had trouble contacting the garage door, sorry";
        }
        else {
            console.log("Data back from shadow", JSON.stringify(data));
            payload = data.payload;
            objState = JSON.parse(payload);
        }
    });

    console.log('After getting the Shadow'); 

以下是我测试时生成的日志条目。有没有人有任何想法我可能有什么不对?

2018-01-14T22:55:15.564Z    fbdde171-f97d-11e7-bc0b-116e508011bd    Getting thing shadow
2018-01-14T22:55:16.127Z    fbdde171-f97d-11e7-bc0b-116e508011bd    After getting the Shadow
2018-01-14T22:55:16.165Z    fbdde171-f97d-11e7-bc0b-116e508011bd    objState: undefined

这是完整的代码。

/**
    Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.

    Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at

        http://aws.amazon.com/apache2.0/

    or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

/**
 *
 */

/**
 * App ID for the skill
 */
 var APP_ID = 'amzn1.ask.skill.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'; 


/**
 * The AlexaSkill prototype and helper functions
 */
var AlexaSkill = require('./AlexaSkill');
var AWS = require('aws-sdk');

/**
 * GarageDoorIntentHandler is a child of AlexaSkill.
 * To read more about inheritance in JavaScript, see the link below.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
 */
var GarageDoorIntentHandler = function () {
    AlexaSkill.call(this, APP_ID);
};

// Extend AlexaSkill
GarageDoorIntentHandler.prototype = Object.create(AlexaSkill.prototype);
GarageDoorIntentHandler.prototype.constructor = GarageDoorIntentHandler;

GarageDoorIntentHandler.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    console.log("GarageDoorIntentHandler onSessionStarted requestId: " + sessionStartedRequest.requestId
        + ", sessionId: " + session.sessionId);
    // any initialization logic goes here
};

GarageDoorIntentHandler.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    console.log("GarageDoorIntentHandler onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    var speechOutput = "Welcome to the Automated Garage door for Alexa, you can say open the garage door or close the garage door";
    var repromptText = "You can say open or close the garage door";
    response.ask(speechOutput, repromptText);
};

GarageDoorIntentHandler.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    console.log("GarageDoorIntentHandler onSessionEnded requestId: " + sessionEndedRequest.requestId
        + ", sessionId: " + session.sessionId);
    // any cleanup logic goes here
};

GarageDoorIntentHandler.prototype.intentHandlers = {

    // register custom intent handlers
    "moveDoorIntent": function (intent, session, response) {

        var responseString = ''; 
        var payload = {};
        var objState;

        var desiredDoorState = intent.slots.direction.value;

        var iotData = new AWS.IotData({endpoint: "XXXXXXXXXXXXXX.iot.us-east-1.amazonaws.com"});

        console.log('iotData: ' + JSON.stringify(iotData));

        var params = { "thingName" : "<My Thing Name Was Removed for Posting>" };


        console.log('Intent: ' + JSON.stringify(intent));

        // get the shadow for the home-garage-door
        console.log('Getting thing shadow');

        iotData.getThingShadow(params, function(err, data) {
            console.log('Inside of getThingShadow callback');
            if (err){
                //Handle the error here
                console.log('Problem getting the thing shadow');
                console.log(err, err.stack);
                responseString = "I had trouble contacting the garage door, sorry";
            }
            else {
                console.log("Data back from shadow", JSON.stringify(data));
                payload = data.payload;
                objState = JSON.parse(payload);
            }
        });

        console.log('After getting the Shadow');

        switch(desiredDoorState.toUpperCase()) {
            case 'OPEN':
                console.log('objState: ' + JSON.stringify(objState));
                switch (objState.state.reported.status.toUpperCase()) {
                    case 'OPEN': 
                        responseString = "I checked and the door is already open"; 
                        break;
                    case 'CLOSED':
                        responseString = "Ok, I am closing the garage door"; 
                        params.payload = buildObjectState('desired', 'doorActivated', true, 'string');
                        iotData.updateThingShadow(params, function(err, data) {
                            if (err){
                                //Handle the error here
                                console.log(err, err.stack);
                                responseString = "I had trouble doing that, sorry";
                            }
                            else {
                                responseString = "Ok, I opened the garage door";
                                console.log("Data back from shadow", data);
                            }
                        });
                }
                break;
            case 'CLOSE':
                break;
            default: 

        } // switch

        response.tellWithCard(responseString, "Open or Close the Garage Door", responseString);
    },

    "getDoorStateIntent": function (intent, session, response) {
        response.tellWithCard("You can say hello to me!", "You can say hello to me!");
    }
};


/**
*   Helper function to build the state object for the shadow document
**/

function buildObjectState (section, key, value, format) {

    var objState =  {state: {}};

    objState.state[section] = {};
    objState.state[section][key] = value;


    if (format === 'object') {
        return objState;
    } else if (format === 'string') {
        return JSON.stringify(objState);
    } else return; 

}

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {

    console.log('received an event'); 
    // Create an instance of the garageDoorIntentHandler.
    var garageDoorIntentHandler = new GarageDoorIntentHandler();
    garageDoorIntentHandler.execute(event, context);
};

2 个答案:

答案 0 :(得分:2)

在Javascript中,代码执行继续到下一行,而不等待异步函数调用完成。您的代码中的错误是因为您在没有值时访问了objState

请参阅下面的评论,以便更好地了解它。

// This is called BEFORE iotData.getThingShadow()
console.log('Getting thing shadow');

iotData.getThingShadow(params, function(err, data) {
    console.log('Inside of getThingShadow callback');
    if (err) {
        //Handle the error here
        console.log('Problem getting the thing shadow');
        console.log(err, err.stack);
        responseString = "I had trouble contacting the garage door, sorry";
    } else {
        console.log("Data back from shadow", JSON.stringify(data));
        payload = data.payload;
        // This is populated AFTER iotData.getThingShadow() finishes
        objState = JSON.parse(payload);
        // This is where you put the code that you want to happen AFTER 
        // iotData.getThingShadow() finishes.
        console.log(objState)
    }
});

// This will execute without waiting for iotData.getThingShadow() to finish
console.log('After getting the Shadow');

// This will be undefined since iotData.getThingShadow() did NOT return 
// yet and objState has NOT been populated
console.log(objState)

因此,要修复它,请在回调函数内部移动您想要发生的代码iotData.getThingShadow()FINISHES。

答案 1 :(得分:2)

看起来你的IOT对象嵌套在Intent中。

我会移动您的IoT阴影并初始化为他们自己的

/Initialize Up Top of Script
AWS.config.region = process.env.IOT_REGION;
var IOT_Data = new AWS.IotData({endpoint: process.env.IOT_ENDPOINT});
var IOT_Thing = process.env.IOT_THING_NAME;

然后我使用辅助函数:

function getShadow(dataObj){
    IOT_Data.getThingShadow(dataObj, function (err, data) {
      if (err) console.log(err, err.stack); // an error occurred
      else     console.log(data);           // successful response
    })
}

您的物联网对象现在可以随时随地使用。我已经将这种设置用于多种技能而没有问题。