简体   繁体   中英

Trouble with an undefined object in Alexa Skills Custom Intents

I am currently attempting to make an Alexa skill that will issue a "Find my iPhone" alert to my apple devices when I give alexa the correct prompts. I am quite new to developing for the alexa skill set and coding at that (especially in node.js). Here is my quote:

var phoneId = "I have my values here";
var ipadId = "I have my values here";
var macId = "I have my values here";
var deviceId = "";


var APP_ID = ''; //replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";

var AlexaSkill = require('./AlexaSkill');
var alexaResponse;

//Import Apple.js
var Apple = require('./Apple');
var apple = new Apple();

var alertSuccess = "Alert sent to Kenny's phone";
var alertFailed = "Alert couldn't be sent to Kenny's phone. Good luck finding it.";

var FindDevice = function () {
    AlexaSkill.call(this, APP_ID);
};

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

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

FindDevice.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    console.log("Quote onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    getWelcomeResponse(response);
};

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

FindDevice.prototype.intentHandlers = {
    // register custom intent handlers
    "FindDeviceIntent": function (intent, session, response) {
        determineDevice(intent, session, response);
    }
};

/**
 * Returns the welcome response for when a user invokes this skill.
 */
function getWelcomeResponse(response) {
    // If we wanted to initialize the session to have some attributes we could add those here.
    var speechText = "Welcome to the Lost Device. Which device shall I find?";
    var repromptText = "<speak>Please choose a category by saying, " +
        "iPhone <break time=\"0.2s\" /> " +
        "Mac <break time=\"0.2s\" /> " +
        "iPad <break time=\"0.2s\" /></speak>";

    var speechOutput = {
        speech: speechText,
        type: AlexaSkill.speechOutputType.PLAIN_TEXT
    };
    var repromptOutput = {
        speech: repromptText,
        type: AlexaSkill.speechOutputType.SSML
    };
    response.ask(speechOutput, repromptOutput);
}

  function determineDevice(intent, session, response) {
    var deviceSlot = intent.slots.Device;

    if (deviceSlot == "iPhone") {
      deviceId = phoneId;
      pingDevice(deviceId);
    } else if (deviceSlot == "iPad") {
      deviceId = ipadId;
      pingDevice(deviceId);
    } else if (deviceSlot == "Mac") {
      deviceId = macId;
      pingDevice(deviceId);
    } else {
      var speechText = "None of those are valid devices. Please try again.";
      speechOutput = {
          speech: speechText,
          type: AlexaSkill.speechOutputType.PLAIN_TEXT
        };
      response.tell(speechOutput);
    }
}

  function pingDevice(deviceId) {
    apple.sendAlert(deviceId, 'Glad you found your phone.', function(success, result){
        if(success){
            console.log("Alert Sent Successfully");
            var speechOutput = alertSuccess;
            response.tell(speechOutput);
        } else {
            console.log("Alert Unsuccessful");
            console.log(result);
            var speechOutput = alertFailed;
            response.tell(speechOutput);
        }
    });
  }

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
    // Create an instance of the FindDevice skill.
    var findDevice = new FindDevice();
    findDevice.execute(event, context);
};

Here is the error from lambda:

{
  "errorMessage": "Cannot read property 'PLAIN_TEXT' of undefined",
  "errorType": "TypeError",
  "stackTrace": [
    "getWelcomeResponse (/var/task/index.js:87:42)",
    "FindDevice.eventHandlers.onLaunch (/var/task/index.js:58:5)",
    "FindDevice.LaunchRequest (/var/task/AlexaSkill.js:10:37)",
    "FindDevice.AlexaSkill.execute (/var/task/AlexaSkill.js:91:24)",
    "exports.handler (/var/task/index.js:137:16)"
  ]
}

I understand that there is an undefined object here, but for the life of me I can't figure out where the code is going wrong. I am trying to take the Slot from my intent and then change the device to ping based on the slot word used. Also because I am so new to this a lot of the coding is just being done by patching things together. I did find that when I removed the .PLAIN_TEXT lines all together the code ran in lambda, but then broke in the alexa skills test area. I get the hunch I don't understand how the slots from intents are passed, but I am having trouble finding material I can understand on that matter. Any help would be fantastic!

Within the determineDevice function, you're accessing the "Device" slot object directly, rather than the actual value passed in, therefore it will never match your pre-defined set of device names.

A slot object has a name and a value - if you take a look at the Service Request JSON in the Service Simulator within the Developer Console when you're testing your Alexa skill, you'll see something like the following:

{
"session": {
    "sessionId": "SessionId.dd05eb31-ae83-4058-b6d5-df55fbe51040",
    "application": {
    "applicationId": "amzn1.ask.skill.61dc6132-1727-4e56-b194-5996b626cb5a"
    },
    "attributes": {
    },
    "user": {
    "userId": "amzn1.ask.account.XXXXXXXXXXXX"
    },
    "new": false
},
"request": {
    "type": "IntentRequest",
    "requestId": "EdwRequestId.6f083909-a831-495f-9b55-75be9f37a9d7",
    "locale": "en-GB",
    "timestamp": "2017-07-23T22:14:45Z",
    "intent": {
    "name": "AnswerIntent",
    "slots": {
        "person": {
        "name": "person",
        "value": "Fred"
        }
    }
    }
},
"version": "1.0"
}

Note I have a slot called "person" in this case, but to get the value in the slot, you need to access the "value" property. In your example, you would change the first line of the determineDevice function to:

var deviceSlot = intent.slots.Device.value;

As an aside, I've found the Alexa-cookbook Github repository an essential resource for learning how to work with the Alexa SDK, there are examples in there for most scenarios.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM