0
votes

I'm developing an Alexa Skill which can return the amount of calories for a requested food item for a University project, to do this I've been making use of the Nutritionix api which can return the amount of calories of different food types based on a search term. In my code I am searching for the term the user has requested via the API, and returning the amount of calories of the 1st item in the array of food items returned. However, when I test the function in test part of the Amazon Developer console I receive a response of "The response is invalid". There are no errors being logged in CloudWatch, and i've actually used console.log to make sure the speech output is being correctly created in my code (which it is, I can see this in CloudWatch).

The only messages that appear in Cloudwatch are "Warning: Application ID is not set", which shouldn't be an issue, and "American Colossal has 540 calories." which relates to the request pictured below.

Get Response is invalid issue as you can see

This is my code, I've removed my app-id and app-key below for security purposes but both are correct as the https request is running correctly, if anyone can see what is causing the issue I'd appreciate it. As far as I can tell the issue must be occuring during "this.emit(":tell",speechOutput);" but I'm not sure why. Thanks.

"use strict";

//Variables
var Alexa = require("alexa-sdk");
var SKILL_NAME = "Nutrition Info";
var APP_ID = "";
var https = require("https");

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

var handlers = {
    'LaunchRequest': function(){
        this.emit(":ask", 'Welcome to the Nutrition Information app, you can ask me how many calories are in a large variety of different foods', 'Ask me how many calories there are in different food stuffs');
    },
    'GetCaloriesIntent': function() {
        this.emit('GetCalories');
    },
    'GetCalories' : function() {
        var foodString = this.event.request.intent.slots.FoodStuff.value;
        var speechOutput = '';
        var options = {
          host: 'trackapi.nutritionix.com',
          port: 443,
          path: '/v2/search/instant?query=' + foodString,
          method: 'GET',
          headers: {
              "x-app-id": [REMOVED THIS FOR SECURITY PURPOSES],
              "x-app-key": [REMOVED THIS FOR SECURITY PURPOSES]
              }
        };


        var req = https.request(options, function(res) {

          var data = ""
          res.setEncoding('UTF-8');
          res.on('data', function (chunk) { data += chunk })
          res.on('end', function() {
            var result = JSON.parse(data);
            var speechOutput = result.branded[0].food_name + " has " + result.branded[0].nf_calories + " calories.";
            console.log(speechOutput);
            this.emit(":tell",speechOutput);
          })
        });

        req.on("error",function(err) {this.emit(":tell","Sorry, there was an issue processing your request.")});

        req.end();

    },
    'AMAZON.HelpIntent' : function() {
        var speechOutput = "You can get nutrition information by asking how many calories there are in a food stuff";
        var reprompt = "What can I help you with?";
        this.emit(":ask", speechOutput, reprompt);
    },
    'AMAZON.StopIntent' : function() {
        this.emit(":tell","Goodbye!");
    },
    'AMAZON.CancelIntent' : function() {
        this.emit(":tell","Goodbye!");
    }
}
1

1 Answers

0
votes

Typical, I've found the resolution almost immediately after posting this! For anyone who's having a similar issue. It is because the "this" being referred to within the API call is not the correct one, this is how I resolved it.

var foodString = this.event.request.intent.slots.FoodStuff.value;
        var speechOutput = '';
        const self = this;
        var options = {
          host: 'trackapi.nutritionix.com',
          port: 443,
          path: '/v2/search/instant?query=' + foodString,
          method: 'GET',
          headers: {
              "x-app-id": [Removed for security purposes],
              "x-app-key": [Removed for security purposes]
              }
        };


        var req = https.request(options, function(res) {

          var data = ""
          res.setEncoding('UTF-8');
          res.on('data', function (chunk) { data += chunk })
          res.on('end', function() {
            var result = JSON.parse(data);
            var speechOutput = result.branded[0].food_name + " has " + result.branded[0].nf_calories + " calories.";
            console.log(speechOutput);
            self.emit(":tell",speechOutput);
          })
        });

        req.on("error",function(err) {self.emit(":tell","Sorry, there was an issue processing your request")});

        req.end();

Having a const that stays as "this" at the beginning of the function prevents the issue from happening.