Reputation: 1436
I am trying to build a skill that calls a REST API to get data. I am using the HelloWorld sample and modifying it to fit my need. I am using the Request node (node.js) to issue the request.
However, for the hell of me I can't get it to work. I see in the log that the function is called and the correct result is coming back, yet the response sent to Alexa is empty!! Any idea what I am missing?
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
console.log("HelloWorldIntentHandler 1: ");
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
handle(handlerInput) {
console.log("HelloWorldIntentHandler 2");
var speechText = 'Hello World';
Request.get(url, function(error, response, body) {
console.log("I'm here")
var data = JSON.parse(body)
var result = data.records.totalNum
if (result > 0) {
speechText = "There are " + result + " matches";
} else {
speechText = "ERROR";
}
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
});
},
};
The error in the log is
Error handled: speechOutput.trim is not a function
Upvotes: 3
Views: 1538
Reputation: 91
For what it is worth, I ran into the same issue and found out (the hard way) that the response I was returning from my api call contained text that was not properly formatted for SSML ( String returned contained an '&' in my case ).
So I found this lib that seems to not only help, but generally be a good idea to use if you can't be 100% sure of your result.
See: https://www.npmjs.com/package/ssml-builder
Hope this helps someone.
~Rob
I guess I better add a code example too. This is not tested, but is what your code might look like using the lib I mentioned there ^^^.
const Speech = require( 'ssml-builder' );
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
console.log("HelloWorldIntentHandler 1: ");
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
handle(handlerInput) {
console.log("HelloWorldIntentHandler 2");
let speechText = 'Hello World';
Request.get(url, function(error, response, body) {
console.log("I'm here");
let data = JSON.parse(body);
let result = data.records.totalNum;
if (result > 0) {
let speech = new Speech();
speech.say(`There are ${result} matches`);
speechText = speech.ssml(true);
} else {
speechText = "ERROR";
}
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
});
},
};
Upvotes: 1
Reputation: 1436
I was able to get this to work using Axios instead of Request.
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
console.log("HelloWorldIntentHandler 1: ");
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
async handle(handlerInput) {
console.log("HelloWorldIntentHandler 2");
var speechText = 'default';
try {
const response = await Axios.get(url);
var result = response.data.totalRecs;
if (result > 0) {
speechText = "There are " + result + " matches";
} else {
speechText = "ERROR";
}
console.log("text=" + speechText);
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
} catch (error) {
console.log(error);
}
},
};
Upvotes: 2
Reputation: 692
Put your return
inside the if else statement.
Request.get(url, function(error, response, body) {
console.log("I'm here")
var data = JSON.parse(body)
var result = data.records.totalNum
if (result > 0) {
speechText = "There are " + result + " matches";
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
});
} else {
speechText = "ERROR";
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
});
}
}
This will force your handler to return the result in your if else statement.
Upvotes: -1