Jacksilky
Jacksilky

Reputation: 1

Code works locally but not on AWS lambda

the following lamdba code works perfectly fine when testing locally using Alex-app-server but when published and tested on AWS Lambda, it gets within the else statement and prints the console.log('OUT PUBLISH') But it doesn't publish the 'lambda/channelnumber' nor does it send the correct response back to me or print 'IN PUBLISH'

Any ideas why its just completing the bottom half of the else statement and not touching the publish function?

Code Snippet where I believe the problem lies

function (request, response) {
    var channelNumber = request.slot('CHANNELNUMBER');

    if (_.isEmpty(channelNumber)) {
        var prompt = 'I didn\'t hear a channel code. Tell me a channel code.';
        response.say(prompt).shouldEndSession(true);
        return true;
    } else {

        //Doesn't publish any of this?????
        thingShadows.publish('lambda/channelNumber', channelNumber, function () {
            var prompt1 = 'Okay.';
            response.say(prompt1).shouldEndSession(true);
            console.log('in publish');
        });

     ////But prints this??
        console.log('out publish');
        return true;

    }
}

Full Code

'use strict';
module.change_code = 1;
var Alexa = require('alexa-app');
var skill = new Alexa.app('smartmote');
var awsIot = require('aws-iot-device-sdk');
var deviceName = "tv";
var _ = require('lodash');
var path = require('path');

var host = "XXXXXXXXXXXXXXXXXXXX.iot.us-east-1.amazonaws.com";

//App id is the skill being used.
var app_id = "amzn1.ask.skill.YYYYYYYYYYYYYYYYYYYYY";

var thingShadows = awsIot.thingShadow({

    keyPath: path.join(__dirname, '/Raspi.private.key'),
    certPath: path.join(__dirname, '/Raspi.cert.pem'),
    caPath: path.join(__dirname, '/root-CA.crt'),
    clientId: deviceName,
    region: "us-east-1",
});

var reprompt = 'I didn\'t hear a channel, tell me a channel number or name to change to that channel';

skill.launch(function (request, response) {
    var prompt = 'To change channel, tell me a channel number.';
    response.say(prompt).reprompt(reprompt).shouldEndSession(true);
});

skill.intent('ChannelNumberIntent', {
        'slots': {
            'CHANNELNUMBER': 'CHANNELID'
        },
        'utterances': ['{|Change|put} {|the|on} {|channel} {|to} {-|CHANNELNUMBER}']
    },
    function (request, response) {
        var channelNumber = request.slot('CHANNELNUMBER');

        if (_.isEmpty(channelNumber)) {
            var prompt = 'I didn\'t hear a channel code. Tell me a channel code.';
            response.say(prompt).shouldEndSession(true);
            return true;
        } else {

            thingShadows.publish('lambda/channelNumber', channelNumber, function () {
                console.log('in pub');
                var prompt1 = 'Okay.';
                response.say(prompt1).shouldEndSession(true);
                callback();
            });

            console.log('out pub');
            return true;

        }    
    }
);

module.exports = skill;

Upvotes: 0

Views: 2373

Answers (1)

duncanhall
duncanhall

Reputation: 11431

This is most likely because of the asynchronous nature of your code.

You haven't told us what thingShadows.publish() does, but it appears to take a callback function as its second argument. Presumably this function will be called when publish() has finished doing whatever it does.

When running locally I would imagine that the output you see is (in this order):

out publish
in publish

Notice that out publish gets called before in publish. This is because the publish method is asynchronous, so execution will continue as soon as it is called. In your case, you are calling return immediately after calling publish, which probably means your lambda job is ending before it has a chance to log in publish.

You haven't provided enough information about the rest of your lambda code/setup to provide a full answer, but you need to make sure that you are waiting for your publish method to have finished before continuing. One way to achieve this is to use the callback object that is passed to your lambda handler:

exports.myHandler = function(event, context, callback) {

  // Other code

  thingShadows.publish('lambda/channelNumber', channelNumber, function () {
    var prompt1 = 'Okay.';
    response.say(prompt1).shouldEndSession(true);
    console.log('in publish');

    // When the publish method is complete, we can call `callback`
    // to tell lambda we are done
    callback();
  });  
}

Upvotes: 3

Related Questions