Alexa技能学习:TypeError:无法读取未定义的属性“值”

时间:2018-11-21 18:14:09

标签: node.js aws-lambda alexa alexa-skills-kit

当我尝试测试我的基本技能时(我正在尝试学习如何创建它们),我总是遇到错误。 这是日志中的错误:

  

2018-11-21T16:10:55.759Z 06a36441-eda8-11e8-a421-f996bf66c592   意外的异常'TypeError:无法读取的属性'值'   未定义”:

     

TypeError:无法读取以下位置未定义的属性“值”   Object.getSuggestion(/var/task/index.js:31:54)在emitNone   (events.js:86:13)在AlexaRequestEmitter.emit(events.js:185:7)在   AlexaRequestEmitter.EmitEvent   (/var/task/node_modules/alexa-sdk/lib/alexa.js:216:10)在   AlexaRequestEmitter.ValidateRequest   (/var/task/node_modules/alexa-sdk/lib/alexa.js:181:23)在   AlexaRequestEmitter.HandleLambdaEvent   (/var/task/node_modules/alexa-sdk/lib/alexa.js:126:25)在   AlexaRequestEmitter.value   (/var/task/node_modules/alexa-sdk/lib/alexa.js:100:31)

     

在exports.handler(/var/task/index.js:52:9)

我该如何解决?

这是我的代码:

var Alexa = require('alexa-sdk');


const APP_ID = 'amzn1.ask.skill.ab07421a-0a92-4c2b-b3bd-998e14286xxx';


const skillData = [
    {
        city: "Austin",
        suggestion: "Austin has some of the most outstanding people."
    },
    {
        city: "San Antonio",
        suggestion: "San Antonio has some of the most outstanding people."    
    },
    {
        city: "Dallas",
        suggestion: "The Dallas metroplex is one of the hottest places."
    }
];


var number = 0;
while(number<3){
var handlers = {
  'LaunchRequest': function () {


      this.emit(':ask', 'Tell me the name of the major city you are closest to'
   },
  'Unhandled': function () {
      this.emit(':ask', 'Try saying a city name like Austin, San Antonio, or Dallas'); 
  },
  'getSuggestion': function() {
      var city = this.event.request.intent.slots.City.value;


      this.emit(':ask', getSuggestion(skillData,'city', city.toUpperCase()).suggestion + '. Give me another city and I\'ll hook you up with the best peeps.');
  },
  'AMAZON.HelpIntent': function () {
      this.emit(':ask', "What can I help you with?", "How can I help?");
  },
  'AMAZON.CancelIntent': function () {
      this.emit(':tell', "Okay!");
  },
  'AMAZON.StopIntent': function () {
      this.emit(':tell', "Goodbye!");
  },
};
number = number+1;
}


exports.handler = function(event, context, callback){
  var alexa = Alexa.handler(event, context);
  alexa.appId = APP_ID;
  alexa.registerHandlers(handlers);
  alexa.execute();
};


function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {
    if (arr[i][propName] == cityName) {
      return arr[i];
    }
  }
}

更新

我进行了以下建议的一些更改,但是,在初始响应后仍然出现错误。

  

“ errorMessage”:“无法读取未定义的属性'city'”

请查看我的新代码,并帮助我解决这个问题:

var Alexa = require('alexa-sdk');

const APP_ID = 'amzn1.ask.skill.ab07421a-0a92-4c2b-b3bd-998e14286xxx';

const skillData = [
    {
        city: 'Austin',
        suggestion: "Austin is blahblahblahblahlshflashdfasldfha blah."
    },
    {
        city: 'San Antonio',
        suggestion: "San Antonio has blahblahblahblahlshflashdfasldfha blah."    
    },
    {
        city: 'Dallas',
        suggestion: "The Dallas metroplex is one of the hottest blahblahblahbla blahblahblahblahblahblah."
    }
];

var number = 0;
while(number<3){
var handlers = {
  'LaunchRequest': function () {
      this.emit(':ask', 'Tell me the name of the major city you are closest to!', 'Which major city are you closest to?');
   },
  'Unhandled': function () {
      this.emit(':ask', "Try saying a city name like Austin, San Antonio, or Dallas"); 
  },
  'getSuggestion': function() {
      var city = this.event.request.intent.slots.city.value;

      this.emit(':ask', getSuggestion(skillData,'city', city.toUpperCase()).suggestion + '. Give me another city and I\'ll hook you up with the best peeps.');
  },
  'AMAZON.HelpIntent': function () {
      this.emit(':ask', "What can I help you with?", "How can I help?");
  },
  'AMAZON.CancelIntent': function () {
      this.emit(':tell', "Okay!");
  },
  'AMAZON.StopIntent': function () {
      this.emit(':tell', "Goodbye!");
  },
};

number = number+1;
}
exports.handler = function(event, context, callback){
  var alexa = Alexa.handler(event, context);
  alexa.appId = APP_ID;
  alexa.registerHandlers(handlers);
  alexa.execute();
};

function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {

    var prop = arr[i][propName];
    prop = prop.toUpperCase();

    if (prop == cityName) {
      return arr[i];
    }
  }
}

更新#2

在尝试了很多不同的事情之后,我有了在巴尔·辛普森的帮助下奔跑的技能!

但是,当用户说出城市名称时,该技能仍然会出错。我的交互模型中肯定有一个错误,如下所示:

   {
        "interactionModel": {
            "languageModel": {
                "invocationName": "city picker",
                "intents": [
                    {
                        "name": "AMAZON.FallbackIntent",
                        "samples": []
                    },
                    {
                        "name": "AMAZON.CancelIntent",
                        "samples": []
                    },
                    {
                        "name": "AMAZON.HelpIntent",
                        "samples": []
                    },
                    {
                        "name": "AMAZON.StopIntent",
                        "samples": [
                            "stop"
                        ]
                    },
                    {
                        "name": "AMAZON.NavigateHomeIntent",
                        "samples": []
                    },
                    {
                        "name": "getSuggestion",
                        "slots": [],
                        "samples": [
                            "san antonio",
                            "dallas",
                            "austin"
                        ]
                    }
                ],
                "types": []
            }
        }
    }

靠近!

作为最后的努力:

这是我位于Lambda的index.js。有人介意看这个吗?

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "LaunchRequest";
  },
  handle(handlerInput) {

    console.log("LaunchRequestHandler");
    let speechText = 'Lets get you into your new home. Tell me the name of the major city you are closest to!';
    let prompt = 'Which major city are you closest to?';

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(prompt)
      .getResponse();
  }
};

const GetSuggestionIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "getSuggestion"
    );
  },
  handle(handlerInput) {
    let intent = handlerInput.requestEnvelope.request.intent;
    let city = intent.slot.city.value;

    let suggestion = getSuggestion(skillData,'city', city.toUpperCase()).suggestion;

    return handlerInput.responseBuilder
      .speak(suggestion)
      .reprompt('prompt')
      .getResponse();
  }
};

const HelpIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "AMAZON.HelpIntent"
    );
  },
  handle(handlerInput) {
    const speechText = "Try saying a city name like Austin, San Antonio, or Dallas";
    const promptText = "How can I help?";

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(promptText)
      // .withSimpleCard("City Details", speechText)
      .getResponse();
  }
};

const CancelAndStopIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      (handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.CancelIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.StopIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.PauseIntent")
    );
  },
  handle(handlerInput) {

    const speechText = `Seeya later!`;

    return (
      handlerInput.responseBuilder
        .speak(speechText)
        .withShouldEndSession(true)
        .getResponse()
    );
  }
};

const SessionEndedRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
  },
  handle(handlerInput) {
    console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);

    return handlerInput.responseBuilder.getResponse();
  },
};

const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
    console.log(`Error handled: ${error.message}`);

    return handlerInput.responseBuilder
      .speak('Sorry, I can\'t understand the command. Try saying a city name like Austin, San Antonio, or Dallas')
      .reprompt('Try saying a city name like Austin, San Antonio, or Dallas')
      .getResponse();
  },
};

const SystemExceptionHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type ===
      "System.ExceptionEncountered"
    );
  },
  handle(handlerInput) {
    console.log(
      `System exception encountered: ${
      handlerInput.requestEnvelope.request.reason
      }`
    );
  }
};

const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = skillBuilder
  .addRequestHandlers(
    LaunchRequestHandler,
    GetSuggestionIntentHandler,
    CancelAndStopIntentHandler,
    HelpIntentHandler,
    SystemExceptionHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();
  
function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {

    var prop = arr[i][propName];
    prop = prop.toUpperCase();

    if (prop == cityName) {
      return arr[i];
    }
  }
}

这是我在开发人员门户网站上的交互模型:

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "city picker",
            "intents": [
                {
                    "name": "AMAZON.FallbackIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": [
                        "stop"
                    ]
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "getSuggestion",
                    "slots": [
                        {
                            "name": "city",
                            "type": "CITY_NAMES"
                        }
                    ],
                    "samples": [
                        "{city}"
                    ]
                }
            ],
            "types": [
                {
                    "name": "CITY_NAMES",
                    "values": [
                        {
                            "name": {
                                "value": "dallas"
                            }
                        },
                        {
                            "name": {
                                "value": "san antonio"
                            }
                        },
                        {
                            "name": {
                                "value": "austin"
                            }
                        }
                    ]
                }
            ]
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好。 alexa-sdk已弃用link。要获取新的SDK,请执行此操作。

1-在Lambda中创建一个新函数。

2-选择AWS无服务器应用程序存储库。 alexa-skills-kit-nodejs-factskill

3-选择alexa-skills-kit-nodejs-factskill。

4-单击部署。部署后,单击功能,您应该会看到刚创建的新功能,其名称类似于aws-serverless-repository-alexaskillskitnodejsfact-NR8HPILH8WNI。 enter image description here

5-删除代码,并以此替换代码。 enter image description here

const Alexa = require('ask-sdk');    
const skillData = [
            {
                city: 'Austin',
                suggestion: "Austin is blahblahblahblahlshflashdfasldfha blah."
            },
            {
                city: 'San Antonio',
                suggestion: "San Antonio has blahblahblahblahlshflashdfasldfha blah."    
            },
            {
                city: 'Dallas',
                suggestion: "The Dallas metroplex is one of the hottest blahblahblahbla blahblahblahblahblahblah."
            }
        ];

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "LaunchRequest";
  },
  handle(handlerInput) {

    console.log("LaunchRequestHandler");
    let speechText = 'Tell me the name of the major city you are closest to!';
    let prompt = 'Which major city are you closest to?';

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(prompt)
      .getResponse();
  }
};

const GetSuggestionIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "getSuggestion"
    );
  },
  handle(handlerInput) {
    let intent = handlerInput.requestEnvelope.request.intent;
    let city = intent.slots.city.value;

    let suggestion = getSuggestion(skillData,'city', city.toUpperCase()).suggestion;

    return handlerInput.responseBuilder
      .speak(suggestion)
      .reprompt('prompt')
      .getResponse();
  }
};

const HelpIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "AMAZON.HelpIntent"
    );
  },
  handle(handlerInput) {
    const speechText = "Try saying a city name like Austin, San Antonio, or Dallas";
    const promptText = "How can I help?";

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(promptText)
      // .withSimpleCard("City Details", speechText)
      .getResponse();
  }
};

const CancelAndStopIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      (handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.CancelIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.StopIntent" ||
        handlerInput.requestEnvelope.request.intent.name ===
        "AMAZON.PauseIntent")
    );
  },
  handle(handlerInput) {

    const speechText = `Goodbye`;

    return (
      handlerInput.responseBuilder
        .speak(speechText)
        .withShouldEndSession(true)
        .getResponse()
    );
  }
};

const SessionEndedRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
  },
  handle(handlerInput) {
    console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);

    return handlerInput.responseBuilder.getResponse();
  },
};

const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
    console.log(`Error handled: ${error.message}`);

    return handlerInput.responseBuilder
      .speak('Sorry, I can\'t understand the command. Try saying a city name like Austin, San Antonio, or Dallas')
      .reprompt('Try saying a city name like Austin, San Antonio, or Dallas')
      .getResponse();
  },
};

const SystemExceptionHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type ===
      "System.ExceptionEncountered"
    );
  },
  handle(handlerInput) {
    console.log(
      `System exception encountered: ${
      handlerInput.requestEnvelope.request.reason
      }`
    );
  }
};

const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = skillBuilder
  .addRequestHandlers(
    LaunchRequestHandler,
    GetSuggestionIntentHandler,
    CancelAndStopIntentHandler,
    HelpIntentHandler,
    SystemExceptionHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();

function getSuggestion(arr, propName, cityName) {
  for (var i=0; i < arr.length; i++) {

    var prop = arr[i][propName];
    prop = prop.toUpperCase();

    if (prop == cityName) {
      return arr[i];
    }
  }
}

6-转到developer.amazon.com,并将Alexa Skill端点更改为新的Lambda ARN。 enter image description here

添加广告位类型:

enter image description here

在这样的示例短语中指定广告位:

enter image description here

将广告位名称更改为城市:

enter image description here

因此,它不是MusicStation,而是城市。确保已在广告位值中输入了以下三个值:

将您的自定义广告位值添加到CITY_NAMES: Add slot values

如果您做对了,那么您的交互模型应该是这样的:

                "name": "getSuggestion",
                "slots": [
                    {
                        "name": "city",
                        "type": "CITY_NAMES"
                    }
                ],
                "samples": [
                    "city name is {city}",
                    "{city}"
                ]

测试Lambda代码

在下拉菜单中,选择“配置测试事件”。 enter image description here

从开发人员测试门户使用JSON创建新的测试事件,该事件应如下所示。

{
"version": "1.0",
"session": {
    "new": true,
    "sessionId": "amzn1.echo-api.session.XXXXXX",
    "application": {
        "applicationId": "amzn1.ask.skill.XXXXXX"
    },
    "user": {
        "userId": "amzn1.ask.account.XXXXXX"
    }
},
"context": {
    "AudioPlayer": {
        "playerActivity": "IDLE"
    },
    "System": {
        "application": {
            "applicationId": "amzn1.ask.skill.XXXXXX"
        },
        "user": {
            "userId": "amzn1.ask.account.XXXXXX"
        },
        "device": {
            "deviceId": "amzn1.ask.device.XXXXXX",
            "supportedInterfaces": {
                "AudioPlayer": {}
            }
        },
        "apiEndpoint": "https://api.eu.amazonalexa.com",
        "apiAccessToken": "ACCESS_TOKEN"
    },
},
"request": {
    "type": "IntentRequest",
    "requestId": "amzn1.echo-api.request.XXXX",
    "timestamp": "2018-12-03T20:28:29Z",
    "locale": "en-IN",
    "intent": {
        "name": "PlayRadioIntent",
        "confirmationStatus": "NONE",
        "slots": {
            "musicStation": {
                "name": "musicStation",
                "value": "classic rock",
                "resolutions": {
                    "resolutionsPerAuthority": [
                        {
                            "authority": "amzn1.er-authority.XXXX.RadioStations",
                            "status": {
                                "code": "ER_SUCCESS_MATCH"
                            },
                            "values": [
                                {
                                    "value": {
                                        "name": "Classic Rock",
                                        "id": "b8a5bd97a8a02691f9f81dcfb12184dd"
                                    }
                                }
                            ]
                        }
                    ]
                },
                "confirmationStatus": "NONE",
                "source": "USER"
            }
        }
    }
}

点击测试按钮

检查日志

测试结果看起来像这样吗?要查看日志,请单击logs。可能还有其他错误详细信息。

enter image description here