Amazon Alexa
1. first test
The skill is created with Custom and Alexa-Hosted options. the other way could be with an aws account on AWS console. using lambdas.Testing
2. Second test Collect slots turn-by-turn
Code on
The sample on documents say
const speakOutput = `Thanks, I'll remember that you were born ${month} ${day} ${year}.`;
but don't work that way, after debuging find that it has to be changed by:
const CaptureBirthdayIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'CaptureBirthdayIntent';
},
handle(handlerInput) {
const year = handlerInput.requestEnvelope.request.intent.slots.year.value;
const month = handlerInput.requestEnvelope.request.intent.slots.month.value;
const day = handlerInput.requestEnvelope.request.intent.slots.day.value;
const speakOutput = `Thanks, I'll remember that you were born .`;
return handlerInput.responseBuilder
.speak(speakOutput.concat(`${month} ${day} ${year}`))
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
note: it seem that it is not totaly necesary, after other testing rounds, the intent has to been called a second time to respond like it suppouse to be.
Testing
3. Persisting data on S3
change the code of the intent cake walk like this as the documentation say
// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
// session persistence, api calls, and more.
const Alexa = require('ask-sdk-core');
const persistenceAdapter = require('ask-sdk-s3-persistence-adapter');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {
const speakOutput = 'Hello! I am Cakewalk. What is your birthday?';
const repromptText = 'I was born Nov. 6th, 2014. When were you born?';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(repromptText)
.getResponse();
}
};
const HasBirthdayLaunchRequestHandler = {
canHandle(handlerInput) {
const attributesManager = handlerInput.attributesManager;
const sessionAttributes = attributesManager.getSessionAttributes() || {};
const year = sessionAttributes.hasOwnProperty('year') ? sessionAttributes.year : 0;
const month = sessionAttributes.hasOwnProperty('month') ? sessionAttributes.month : 0;
const day = sessionAttributes.hasOwnProperty('day') ? sessionAttributes.day : 0;
return handlerInput.requestEnvelope.request.type === 'LaunchRequest' && year && month && day;
},
handle(handlerInput) {
const attributesManager = handlerInput.attributesManager;
const sessionAttributes = attributesManager.getSessionAttributes() || {};
const year = sessionAttributes.hasOwnProperty('year') ? sessionAttributes.year : 0;
const month = sessionAttributes.hasOwnProperty('month') ? sessionAttributes.month : 0;
const day = sessionAttributes.hasOwnProperty('day') ? sessionAttributes.day : 0;
// TODO:: Use the settings API to get current date and then compute how many days until user's birthday
// TODO:: Say Happy birthday on the user's birthday
const speakOutput = `Welcome back. It looks like there are X more days until your y-th birthday.`;
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const CaptureBirthdayIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'CaptureBirthdayIntent';
},
async handle(handlerInput) {
const year = handlerInput.requestEnvelope.request.intent.slots.year.value;
const month = handlerInput.requestEnvelope.request.intent.slots.month.value;
const day = handlerInput.requestEnvelope.request.intent.slots.day.value;
const attributesManager = handlerInput.attributesManager;
const birthdayAttributes = {
"year" : year,
"month" : month,
"day" : day
};
attributesManager.setPersistentAttributes(birthdayAttributes);
await attributesManager.savePersistentAttributes();
const speakOutput = `Thanks, I'll remember that you were born .${month} ${day} ${year}`;
return handlerInput.responseBuilder
//.speak(speakOutput.concat(`${month} ${day} ${year}`))
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speakOutput = 'You can say hello to me! How can I help?';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
|| Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speakOutput = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};
// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
},
handle(handlerInput) {
const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
const speakOutput = `You just triggered ${intentName}`;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.stack}`);
const speakOutput = `Sorry, I had trouble doing what you asked. Please try again.`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
const LoadBirthdayInterceptor = {
async process(handlerInput) {
const attributesManager = handlerInput.attributesManager;
const sessionAttributes = await attributesManager.getPersistentAttributes() || {};
const year = sessionAttributes.hasOwnProperty('year') ? sessionAttributes.year : 0;
const month = sessionAttributes.hasOwnProperty('month') ? sessionAttributes.month : 0;
const day = sessionAttributes.hasOwnProperty('day') ? sessionAttributes.day : 0;
if (year && month && day) {
attributesManager.setSessionAttributes(sessionAttributes);
}
}
};
// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
HasBirthdayLaunchRequestHandler,
LaunchRequestHandler,
CaptureBirthdayIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
)
.withPersistenceAdapter(
new persistenceAdapter.S3PersistenceAdapter({bucketName:process.env.S3_PERSISTENCE_BUCKET})
)
.addRequestInterceptors(
LoadBirthdayInterceptor
)
.addErrorHandlers(
ErrorHandler,
)
.lambda();
Testing
3.1 Deleteing Persisted data.
Correction: has been capture the day as "two" when it has to be "second" , that why on year appears like 21970. correcting and seen the data in S3, we have:
Notes:
https://github.com/alexa/skill-sample-nodejs-first-skill
Crear un layer en AWS console o alternativamente usar Alexa pero no contara con todas las posibilidades que se dan en AWS console
En AWS console add trigger Alexa Skills Kit. se habilita y se a add. ya tendriamos el skill y el trigger con el evento.
ARN amazon resourse name
al crear el skill teemos la opcion de Custom -> Provision your own (para AWS console) o Alexa hosted node.js
en module-1 copiar el json y index a donde depositemos el repo cloud en alexa
D:\temp\alexasdk>npm i --save ask-sdk
npm WARN saveError ENOENT: no such file or directory, open 'D:\temp\alexasdk\package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open 'D:\temp\alexasdk\package.json'
npm WARN alexasdk No description
npm WARN alexasdk No repository field.
npm WARN alexasdk No README data
npm WARN alexasdk No license field.
+ ask-sdk@2.7.0
added 35 packages from 80 contributors and audited 52 packages in 13.635s
found 0 vulnerabilities
D:\temp\alexasdk>ls
"ls" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.
D:\temp\alexasdk>dir
El volumen de la unidad D no tiene etiqueta.
El número de serie del volumen es: 10FB-BD7D
Directorio de D:\temp\alexasdk
08/11/2019 10:05 a. m. <DIR> .
08/11/2019 10:05 a. m. <DIR> ..
08/11/2019 10:05 a. m. <DIR> node_modules
08/11/2019 10:05 a. m. 10,482 package-lock.json
1 archivos 10,482 bytes
3 dirs 317,245,050,880 bytes libres
D:\temp\alexasdk>mkdir nodejs
Instalar adaptador de pesisntencia
npm i --save ask-sdk-s3-persistence
D:\temp\alexasdk>npm i --save ask-sdk-s3-persistence-adapter
npm WARN saveError ENOENT: no such file or directory, open 'D:\temp\alexasdk\package.json'
npm WARN enoent ENOENT: no such file or directory, open 'D:\temp\alexasdk\package.json'
npm WARN alexasdk No description
npm WARN alexasdk No repository field.
npm WARN alexasdk No README data
npm WARN alexasdk No license field.
+ ask-sdk-s3-persistence-adapter@2.7.0
added 1 package from 2 contributors and audited 358 packages in 0.998s
found 0 vulnerabilities
No hay comentarios:
Publicar un comentario