/
VoxaDocumentationRelease212RainAgencySep032018 VoxaDocumentationRelease212RainAgencySep032018

VoxaDocumentationRelease212RainAgencySep032018 - PDF document

willow
willow . @willow
Follow
344 views
Uploaded On 2021-08-23

VoxaDocumentationRelease212RainAgencySep032018 - PPT Presentation

Contents1Summary12WhyVoxavsotherframeworks33Features54Installation75InitialCon2guration96Respondingtoalexaevents117Usingthedevelopmentserver138Respondingtoanintentevent159ProjectSamples1791StarterKit1 ID: 869688

alexaevent 149 skill voxa 149 alexaevent voxa skill reply voxadocumentation release2 x0028fe00 150 callback atlast index json return model

Share:

Link:

Embed:

Download Presentation from below link

Download Pdf The PPT/PDF document "VoxaDocumentationRelease212RainAgencySep..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

1 VoxaDocumentationRelease2.1.2RainAgencyS
VoxaDocumentationRelease2.1.2RainAgencySep03,2018 Contents: 1Summary12WhyVoxavsotherframeworks33Features54Installation75InitialConguration96Respondingtoalexaevents117Usingthedevelopmentserver138Respondingtoanintentevent159ProjectSamples179.1StarterKit................................................179.2MyFirstPodcast.............................................179.3AccountLinking.............................................1710Links1910.1VoxaDocumentation!..........................................1910.2NewAlexadeveloper...........................................2110.3VoxaarchitecturepatternMVC.....................................2210.4Models..................................................2210.5ViewsandVariables...........................................2310.6Controllers................................................2510.7Transition.................................................2610.8ThealexaEventObje

2 ct......................................
ct........................................2710.9ThereplyObject............................................2710.10Voxa...................................................2810.11RequestFlow...............................................3410.12I18N...................................................3510.13Plugins..................................................3710.14Debugging................................................4010.15StarterKit................................................4010.16MyFirstPodcast.............................................42 i 10.17AccountLinking.............................................46 ii CHAPTER1 Summary Voxaisaframeworkthatprovidesawaytoorganizeaconversationalexperienceintoastatemachine.Eventhemostcomplexvoiceuserinterface(VUI)canberepresentedthroughthestatemachineanditprovidestheexibilityneededtobothberigidwhenneededinspecicstatesandexibletojumparoundstateswhenn

3 eeded. 1 VoxaDocumentation,Release2.1.2
eeded. 1 VoxaDocumentation,Release2.1.2 2Chapter1.Summary CHAPTER2 WhyVoxavsotherframeworks VoxaprovidesamorerobustframeworkforbuildingAlexaskills.Itprovidesadesignpatternthatwasn'tfoundinotherframeworks.CriticaltoVoxawasprovidingapluggableinterfaceandsupportingallofthelatestASKfeatures. 3 VoxaDocumentation,Release2.1.2 4Chapter2.WhyVoxavsotherframeworks CHAPTER3 Features •MVCPattern•StateorIntenthandling(StateMachine)•EasyintegrationwithseveralAnalyticsproviders•Easytomodifyresponsele(theview)•CompatibilitywithallSSMLfeatures•Workswithcompanionappcards•Supportsi18nintheresponses•Cleancodestructurewithaunittestingframework•Easyerrorhandling•Accountlinkingsupport•SeveralPlugins 5 VoxaDocumentation,Release2.1.2 6Chapter3.Features CHAPTER4 Installation Voxaisdistributedvianpm $npminstallvoxa--save 7 VoxaDocumentation,Release2.1.2 8Chapter4.Installation C

4 HAPTER5 InitialConguration Instantia
HAPTER5 InitialConguration InstantiatingaStateMachineSkillrequiresacongurationspecifyingyourViewsandVariables. usestrict;constVoxa=require(voxa);constviews=require(./views):constvariables=require(./variables);constskill=newVoxa({variables,views}); 9 VoxaDocumentation,Release2.1.2 10Chapter5.InitialConguration CHAPTER6 Respondingtoalexaevents Onceyouhaveyourskillconguredrespondingtoeventsisassimpleascallingtheskill.lambdamethod constskill=require(./MainStateMachine);exports.handler=skill.lambda(); 11 VoxaDocumentation,Release2.1.2 12Chapter6.Respondingtoalexaevents CHAPTER7 Usingthedevelopmentserver Theframeworkprovidesasimplebuiltinserverthat'sconguredtoserveallPOSTrequeststoyourskill,thisworksgreatwhendeveloping,speciallywhenpairedwithngrok //thiswillstartanhttpserverlisteningonport3000skill.startServer(3000); 13 VoxaDocumentation,Release2

5 .1.2 14Chapter7.Usingthedevelopmentserve
.1.2 14Chapter7.Usingthedevelopmentserver CHAPTER8 Respondingtoanintentevent skill.onIntent(HelpIntent,(alexaEvent)�={return{reply:HelpIntent.HelpAboutSkill};});skill.onIntent(ExitIntent,(alexaEvent)�={return{reply:ExitIntent.Farewell};}); 15 VoxaDocumentation,Release2.1.2 16Chapter8.Respondingtoanintentevent CHAPTER9 ProjectSamples Tohelpyougetstartedthestatemachinehasanumberofexampleprojectsyoucanuse.9.1StarterKitThisisthesimplestproject,itdenesthedefaultdirectorystructurewerecommendusingwithvoxaprojectsandhasanexampleserverless.ymllethatcanbeusedtodeployyourskilltoalambdafunction.9.2MyFirstPodcastInthisexampleyouwillseehowtoimplementapodcastskillbyhavingalistofaudiosinale(podcast.js)withtitlesandurls.ItimplementsallaudiointentsallowedbytheaudiobackgroundfeatureandhandlesalltheplaybackrequestsdispatchedbyAlexaonceanaudiohasstarted,sto

6 pped,failed,nishedornearlytonish
pped,failed,nishedornearlytonish.Keepinmindtheaudiosmustbehostedinasecureserver.9.3AccountLinkingAmorecomplexprojectthatshowshowtoworkwithaccountlinkingandmakeresponsesusingthemodelstate.Itusesserverlesstodeployyouraccountlinkingserverandskilltolambda,createadynamodbtabletostoreyouraccountlinkingandcreateans3buckettostoreyourstaticassets.ItalsohasagulptasktouploadyourassetstoS3 17 VoxaDocumentation,Release2.1.2 18Chapter9.ProjectSamples CHAPTER10 Links •search10.1VoxaDocumentation!10.1.1SummaryVoxaisanAlexaskillframeworkthatprovidesawaytoorganizeaskillintoastatemachine.Eventhemostcomplexvoiceuserinterface(VUI)canberepresentedthroughthestatemachineanditprovidestheexibilityneededtobothberigidwhenneededinspecicstatesandexibletojumparoundwhenallowingthatalsomakessense.10.1.2WhyVoxavsotherframeworksVoxaprovidesamorerobustframeworkforbuildingAlexaskills.Itprovidesadesignpatternthatwasn'tfou

7 ndinotherframeworks.CriticaltoVoxawaspro
ndinotherframeworks.CriticaltoVoxawasprovidingapluggableinterfaceandsupportingallofthelatestASKfeatures.10.1.3Features•MVCPattern•StateorIntenthandling(StateMachine)•EasyintegrationwithseveralAnalyticsproviders•Easytomodifyresponsele(theview)•CompatibilitywithallSSMLfeatures•CompatiblewithAudiodirectives•Workswithcompanionappcards•Supportsi18nintheresponses 19 VoxaDocumentation,Release2.1.2 •Cleancodestructurewithaunittestingframework•Easyerrorhandling•Accountlinkingsupport•PersistentsessionsupportusingDynamoDB•SeveralPlugins10.1.4InstallationVoxaisdistributedvianpm $npminstallvoxa--save 10.1.5InitialCongurationInstantiatingaStateMachineSkillrequiresacongurationspecifyingyourViewsandVariables. usestrict;constVoxa=require(voxa);constviews=require(./views):constvariables=require(./variables);cons

8 tskill=newVoxa({variables,views}); 10.1.
tskill=newVoxa({variables,views}); 10.1.6RespondingtoalexaeventsOnceyouhaveyourskillconguredrespondingtoeventsisassimpleascallingtheskill.lambdamethod constskill=require(./MainStateMachine);exports.handler=skill.lambda(); 10.1.7UsingthedevelopmentserverTheframeworkprovidesasimplebuiltinserverthat'sconguredtoserveallPOSTrequeststoyourskill,thisworksgreatwhendeveloping,speciallywhenpairedwithngrok //thiswillstartanhttpserverlisteningonport3000skill.startServer(3000); 10.1.8Respondingtoanintentevent skill.onIntent(HelpIntent,(alexaEvent)�={return{reply:HelpIntent.HelpAboutSkill};});skill.onIntent(ExitIntent,(alexaEvent)�={return{reply:ExitIntent.Farewell};}); 20Chapter10.Links VoxaDocumentation,Release2.1.2 10.2NewAlexadeveloperIftheskillsdevelopmentforalexaisanewthingforyou,wehavesomesuggestiontogetyoudeepintothisworld.10.2.1Getting

9 StartedwiththeAlexaSkillsAlexaprovidesas
StartedwiththeAlexaSkillsAlexaprovidesasetofbuilt-incapabilities,referredtoasskills.Forexample,Alexa'sabilitiesincludeplayingmusicfrommultipleproviders,answeringquestions,providingweatherforecasts,andqueryingWikipedia.TheAlexaSkillsKitletsyouteachAlexanewskills.CustomerscanaccessthesenewabilitiesbyaskingAlexaquestionsormakingrequests.Youcanbuildskillsthatprovideuserswithmanydifferenttypesofabilities.Forexample,askillmightdoanyoneofthefollowing:•Lookupanswerstospecicquestions(“Alexa,asktidepoolerforthehightidetodayinSeattle.”)•Challengetheuserwithpuzzlesorgames(“Alexa,playJeopardy.”)•Controllightsandotherdevicesinthehome(“Alexa,turnonthelivingroomlights.”)•Provideaudioortextcontentforacustomer'sashbrieng(“Alexa,givememyashbrieng”)Youcanseethedifferenttypesofskillsheretogotmoredeepreference.HowusersinteractwithAlexa?WithInteractionM

10 odel.EndusersinteractwithallofAlexa'sabi
odel.EndusersinteractwithallofAlexa'sabilitiesinthesameway–bywakingthedevicewiththewakeword(orabuttonforadevicesuchastheAmazonTap)andaskingaquestionormakingarequest.Forexample,usersinteractwiththebuilt-inWeatherservicelikethis:User:Alexa,what'stheweather?Alexa:RightnowinSeattle,therearecloudyskies...InthecontextofAlexa,aninteractionmodelissomewhatanalogoustoagraphicaluserinterfaceinatraditionalapp.Insteadofclickingbuttonsandselectingoptionsfromdialogboxes,usersmaketheirrequestsandrespondtoquestionsbyvoice.Hereyoucanseehowtheinteractionmodelworks10.2.2AmazonDeveloperServiceAccountAmazonWebServicesprovidesasuiteofsolutionsthatenabledevelopersandtheirorganizationstoleverageAma-zon.com'srobusttechnologyinfrastructureandcontentviasimpleAPIcalls.TherstthingyouneedtodoiscreateyourownAmazonDeveloperAccount.10.2.3RegisteringanAlexaskillRegisteringanewskillorabilityontheAmazonDeveloperPortalcreatesacongura

11 tioncontainingtheinformationthattheAlexa
tioncontainingtheinformationthattheAlexaserviceneedstodothefollowing:•RouterequeststotheAWSLambdafunctionorwebservicethatimplementstheskill,orfordevelopmentpurposeyoucanrunitlocallyusingngrok.•DisplayinformationabouttheskillintheAmazonAlexaApp.Theappshowsallpublishedskills,aswellasallofyourownskillscurrentlyunderdevelopment. 10.2.NewAlexadeveloper21 VoxaDocumentation,Release2.1.2 YoumustregisteraskillbeforeyoucantestitwiththeServiceSimulatorinthedeveloperportaloranAlexa-enableddevice.FollowtheseinstructionstoregisterandmanagingyourAlexaskill.10.3VoxaarchitecturepatternMVC 10.4ModelsModelsarethedatastructurethatholdsthecurrentstateofyourapplication,theframeworkdoesn'tmakemanyassumptionsonitandonlyrequireshaveafromEventmethodthatshouldinitializeitbasedonthealexaEventsessionattributesandaserializemethodthatshouldreturnJSON.stringifyablestructuretothenstoreinthesessionattributes usestrict;cons

12 t_=require(lodash);classModel{
t_=require(lodash);classModel{constructor(data){_.assign(this,data);}staticfromEvent(alexaEvent){ (continuesonnextpage) 22Chapter10.Links VoxaDocumentation,Release2.1.2 (continuedfrompreviouspage) returnnewthis(alexaEvent.session.attributes.modelData);}serialize(){returnthis;}}module.exports=Model; 10.5ViewsandVariables10.5.1ViewsViewsaretheVoxawayofhandlingrepliestotheuser,they'retemplatesofresponsesusingasimplejavascriptDSL.Theycancontainssmlandincludecards.Thereare5responsesinthefollowingsnippet:LaunchIntent.OpenResponse,ExitIntent.Farewell,HelpIntent.HelpAboutSkill,Count.SayandCount.TellAlso,there'saspecialtypeofviewwhichcancontainarraysofoptions,whenVoxandsoneofthoseliketheLaunchIntent.OpenResponseitwillselectarandomsampleanduseitastheresponse. constviews={LaunchIntent:{OpenResponse:{tell:[Hello! rea;&#xk-60;�time="3s"/Good{time}.Isthereanythingicandotohelp ,!youtoday?

13 1;,Hithere! rea;&#xk-60;ʏ
1;,Hithere! rea;&#xk-60;�time="3s"/Good{time}.Howmayibeofservice?,Good{time},Welcome!.Howcanihelpyou?,]},},ExitIntent:{Farewell:{tell:Ok.Formoreinfovisit{site}site.},},HelpIntent:{HelpAboutSkill:{tell:Formorehelpvisitexampledotcomcard:{type:Standard,text:Helpisavailableatishttp://example.com,},},},Count:{Say:{say:{count}},Tell:{tell:{count}},},}; Theycomein3forms:say,askandtell. 10.5.ViewsandVariables23 VoxaDocumentation,Release2.1.2 tellTellviewssendaresponsetoalexaandclosethesessioninmediately.They'reusedwhentheskillisdoneinteractingwiththeuser.TheExitIntent.Farewellisanexampleofthis.askAskviewsareusedtoprompttheuserforinformation,theysendaresponsetoalexabutkeepthesessionopensotheusercanrespond.TheLaunchIntent.OpenResponseisanaskview.sayWhilethetellandaskviewtypesareanexactrepresentationofthebasealexaprogrammingmod

14 el,thesayviewsaredifferent.They'reanabst
el,thesayviewsaredifferent.They'reanabstractioncreatedbyvoxatomakeitsimplertocomposeyourresponsesovermanystatetransitions.Theydon'tsendarespondtoalexabutinsteadmakeastatetransitioninternallyandcontinueexecutingyourskillcodeuntilthere'satelloraskresponse.10.5.2DirectivesNowyoucanincludedirectivesinyourviewsle.Hintdirectivecanbeeasilyspecifywithasimpleobjectcontainingahintkey. constviews={LaunchIntent:{OpenResponse:{tell:[Hello! rea;&#xk-60;�time="3s"/Good{time}.Isthereanythingicandotohelp ,!youtoday?,Hithere! rea;&#xk-60;�time="3s"/Good{time}.Howmayibeofservice?,Good{time},Welcome!.Howcanihelpyou?,],directives:[{hint:hint,},{type:Display.RenderTemplate,template:{type:"BodyTemplate1",textContent:{primaryText:{text:"Seemyfavoritecar",type:"PlainText"},secondaryText:{text:"Custom-painted",type:"PlainText"},tertiaryText:{text:"Byme!"

15 ,type:"PlainText"}}, (continuesonnextpag
,type:"PlainText"}}, (continuesonnextpage) 24Chapter10.Links VoxaDocumentation,Release2.1.2 (continuedfrompreviouspage) backButton:"VISIBLE"}}],},}; 10.5.3VariablesVariablesaretherenderingenginewayofaddinglogicintoyourviews.They'redessignedtobeverysimplesincemostofyourlogicshouldbeinyourmodelorcontrollers.Avariablesignatureis:variable(model,alexaEvent)Arguments•model–Theinstanceofyourmodelforthecurrentalexaevent.•AlexaEvent–Thecurrentalexaevent.ReturnsThevaluetoberenderedorapromiseresolvingtoavaluetoberenderedintheview. constvariables={site:functionsite(model){returnPromise.resolve(example.com);},count:functioncount(model){returnmodel.count;},locale:functionlocale(model,alexaEvent){returnalexaEvent.locale;}}; 10.6ControllersControllersinyourapplicationcontrolthelogicofyourskill,theyrespondtoalexaalexaEvents,externalresources,manipulatetheinputandgiveproperresponsesusingyourModel,

16 ViewsandVariables.Statescomeinoneoftwowa
ViewsandVariables.Statescomeinoneoftwoways,theycanbeanobjectofmappingsfromintentnametostate. skill.onState(entry,{LaunchIntent:launch,AMAZON.HelpIntent:help,}); OrtheycanbeafunctionthatgetsaalexaEventobject. skill.onState(launch,(alexaEvent)�={return{reply:LaunchIntent.OpenResponse,to:die};}); 10.6.Controllers25 VoxaDocumentation,Release2.1.2 Yourstateshouldrespondwithatransition.Thetransitionisaplainobjectthatcantakedirectives,toandreplykeys.10.6.1TheentrycontrollerTheentrycontrollerisspecialinthatit'sthedefaultstatetogotoatthebeginningofyoursessionandifyourstatereturnsnoresponse.Forexampleinthenextsnippedthere'sawaitingstatethatexpectsanAMAZON.NextIntentoranAMAZON.PreviousIntent,inthecasetheuserssayssomethingunexpectedlikeanAMAZON.HelpIntentthestatereturnsundened,theStateMachineframeworkhandlesthissituationsbyredirectingtot

17 heentrystate skill.onState(waiting&
heentrystate skill.onState(waiting,(alexaEvent)�={if(alexaEvent.intent.name===AMAZON.NextIntent){alexaEvent.model.index+=1;return{reply:Ingredients.Describe,to:waiting}}elseif(alexaEvent.intent.name===AMAZON.PreviousIntent){alexaEvent.model.index-=1;return{reply:Ingredients.Describe,to:waiting}}}); 10.6.2TheonIntenthelperForthesimplepatternofhavingacontrollerrespondtoanspecicintenttheframeworkprovidestheonIntenthelper skill.onIntent(LaunchIntent,(alexaEvent)�={return{reply:LaunchIntent.OpenResponse,to:die};}); IfyoureceiveaDisplay.ElementSelectedtyperequest,youcouldusethesameapproachforintentsandstate.VoxareceivesthistypeofrequestandturnsitintoDisplayElementSelectedIntent skill.onIntent(DisplayElementSelected,(alexaEvent)�={return{reply:DisplayElementSelected.

18 OpenResponse,to:die};});
OpenResponse,to:die};}); Underthehoodthiscreatesanewkeyintheentrycontrollerandanewstate10.7TransitionAtransitionistheresultofcontrollerexecution,it'sasimpleobjectwithkeysthatcontroltheowofexecutioninyourskill.10.7.1toThetokeyshouldbethenameofastateinyourstatemachine,whenpresentitindicatestotheframeworkthatitshouldmovetoanewstate.Ifabsentit'sassumedthattheframeworkshouldmovetothediestate. return{to:stateName}; 26Chapter10.Links VoxaDocumentation,Release2.1.2 10.7.2directivesDirectivesareusedpasseddirectlytothealexaresponse,theformatisdescribedinthealexadocumentation return{directives:[{type:AudioPlayer.Play,playBehavior:REPLACE_ALL,audioItem:{stream:{token:lesson.id,url:lesson.Url,offsetInMilliseconds:0,}}}],}; 10.7.3replyThereplykeycantake2forms,asimplestringpointingtooneofyourviewsoraReplyobject. return{reply:LaunchIntent.OpenResponse};constreply=new

19 Reply(alexaEvent,{tell:Hithere!
Reply(alexaEvent,{tell:Hithere!});return{reply}; 10.8ThealexaEventObjectclassAlexaEvent(event,lambdaContext)ThealexaEventobjectcontainsalltheinformationfromtheAlexaevent,it'sanobjectkeptfortheentirelifecycleofthestatemachinetransitionsandassuchisaperfectplaceformiddlewaretoputinformationthatshouldbeavailableoneveryrequest.AlexaEvent.AlexaEvent.modelThedefaultmiddlewareinstantiatesaModelandmakesitavailablethroughalexaEvent.modelAlexaEvent.AlexaEvent.intent.paramsThealexaEventobjectmakesintent.slotsavailablethroughintent.paramsafteraplyingasim-pletransformationso{slots:[{name:Dish,value:FriedChicken}]}becomes{Dish:FriedChicken}AlexaEvent.AlexaEvent.userAconveniencegettertoobtaintheuserfromsesssion.userorcontext.System.userAlexaEvent.AlexaEvent.tokenAconveniencegettertoobtainthetokenfromrequest.token.ThistokenisspeciedinDisplay.ElementSelectedrequest.10.9ThereplyObject

20 classReply(alexaEvent[,message])Thereply
classReply(alexaEvent[,message])ThereplyobjectisusedbytheframeworktorenderAlexaresponses,ittakesallofyourstatements, 10.8.ThealexaEventObject27 VoxaDocumentation,Release2.1.2 cardsanddirectivesandgeneratesaproperjsonresponseforAlexaArguments•alexaEvent(AlexaEvent)–•message–AmessageobjectReply.Reply.append(message)AddsstatementstotheReplyArguments•message–Anobjectwithkeysask,tell,say,reprompt,card,ordirectiveskeys.OranotherreplyobjectReturnstheReplyobjectReply.Reply.toJSON()ReturnsAnobjectwiththeproperformattosendbacktoAlexa,withstatementswrappedinSSMLtags,cards,repromptsanddirectivesReply.Reply.fulfillIntent(canFulll)Arguments•canFulfill–Astringwithpossiblevalues:YES|NO|MAYBEtofulllrequestReply.Reply.fulfillSlot(slotName,canUnderstand,canFulll)Arguments•slotName–Astringwiththeslottofulll•canUnderstand–Astringwithpossiblevalues:YES|NO|

21 MAYBEthatindicatesslotunderstanding•
MAYBEthatindicatesslotunderstanding•canFulfill–Astringwithpossiblevalues:YES|NOthatindicatesslotfulllment10.10VoxaclassVoxa(cong)Arguments•config–Congurationforyourskill,itshouldincludeViewsandVariablesandoptionallyamodelandalistofappIds.IfappIdsispresentthentheframeworkwillcheckeveryalexaeventandenforcetheapplicationidtomatchoneofthespeciedapplicationids. constskill=newVoxa({Model,variables,views,appIds}); Voxa.lambda()ReturnsAlambdahandlerthatwillcallyourskill.executemethod exports.handler=skill.lambda(); Voxa.execute(event)ThemainentrypointfortheSkillexecutionArguments 28Chapter10.Links VoxaDocumentation,Release2.1.2 •event–Theeventsentbyalexa.•context–ThecontextofthelambdafunctionReturnsPromiseAresponseresolvingtoajavascriptobjecttobesentasaresulttoAlexa. skill.execute(event,context).then(result�=callback(null,result)).catch(callback); Vox

22 a.onState(stateName,handler)Mapsahandler
a.onState(stateName,handler)MapsahandlertoastateArguments•stateName(string)–Thenameofthestate•handler(function/object)–ThecontrollertohandlethestateReturnsAnobjectorapromisethatresolvestoanobjectthatspeciesatransitiontoanotherstateand/oraviewtorender skill.onState(entry,{LaunchIntent:launch,AMAZON.HelpIntent:help,});skill.onState(launch,(alexaEvent)�={return{reply:LaunchIntent.OpenResponse,to:die};}); Voxa.onIntent(intentName,handler)AshortcutfordeniningstatecontrollersthatmapdirectlytoanintentArguments•intentName(string)–Thenameoftheintent•handler(function/object)–ThecontrollertohandlethestateReturnsAnobjectorapromisethatresolvestoanobjectthatspeciesatransitiontoanotherstateand/oraviewtorender skill.onIntent(HelpIntent,(alexaEvent)�={return{reply:HelpI

23 ntent.HelpAboutSkill};}); Voxa.onIn
ntent.HelpAboutSkill};}); Voxa.onIntentRequest(callback[,atLast])ThisisexecutedforallIntentRequestevents,defaultbehavioristoexecutetheStateMachinemachinery,yougenerallydon'tneedtooverridethis.Arguments•callback(function)–•last(bool)–ReturnsPromiseVoxa.onLaunchRequest(callback[,atLast])AddsacallbacktobeexecutedwhenprocessingaLaunchRequest,thedefaultbehavioristofakethealexaeventasanIntentRequestwithaLaunchIntentandjustdefertotheonIntentRequesthandlers.Yougenerallydon'tneedtooverridethis. 10.10.Voxa29 VoxaDocumentation,Release2.1.2 Voxa.onBeforeStateChanged(callback[,atLast])Thisisexecutedbeforeenteringeverystate,itcanbeusedtotrackstatechangesormakechangestothealexaeventobjectVoxa.onBeforeReplySent(callback[,atLast])Addsacallbacktobeexecutedjustbeforesendingthereply,internallythisisusedtoaddtheserializedmodelandnextstatetothesession.Itcanbeusedtoalterthereply,orforexampletotrackthena

24 lresponsesenttoauserinanalytics. skill.o
lresponsesenttoauserinanalytics. skill.onBeforeReplySent((alexaEvent,reply)�={constrendered=reply.toJSON();analytics.track(alexaEvent,rendered)}); Voxa.onAfterStateChanged(callback[,atLast])Addscallbackstobeexecutedontheresultofastatetransition,thisarecalledaftereverytransitionandinternallyit'susedtorenderthetransitionreplyusingtheviewsandvariablesThecallbacksgetalexaEvent,replyandtransitionparams,itshouldreturnthetransitionobject skill.onAfterStateChanged((alexaEvent,reply,transition)�={if(transition.reply===LaunchIntent.PlayTodayLesson){transition.reply=_.sample([LaunchIntent.PlayTodayLesson1,LaunchIntent.,!PlayTodayLesson2]);}returntransition;}); Voxa.onUnhandledState(callback[,atLast])Addsacallbacktobeexecutedwhenastatetransitionfailstogeneratearesult,thisusuallyhappenswhenredirectingtoamissingstateoranentrycallforanonconguredintent,thehandlersgetaal

25 exaeventparameterandshouldreturnatransit
exaeventparameterandshouldreturnatransitionthesameasastatecontrollerwould.Voxa.onSessionStarted(callback[,atLast])AddsacallbacktotheonSessinStartedevent,thisexecutesforalleventswherealexaEvent.session.new===trueThiscanbeusefultotrackanalytics skill.onSessionStarted((alexaEvent,reply)�={analytics.trackSessionStarted(alexaEvent);}); Voxa.onRequestStarted(callback[,atLast])Addsacallbacktobeexecutedwheneverthere'saLaunchRequest,IntentRequestoraSessionEndedRequest,thiscanbeusedtoinitializeyouranalyticsorgetyouraccountlinkinguserdata.Internallyit'susedtoinitializethemodelbasedontheeventsession skill.onRequestStarted((alexaEvent,reply)�={alexaEvent.model=this.config.Model.fromEvent(alexaEvent);}); Voxa.onSessionEnded(callback[,atLast])AddsacallbacktotheonSessionEndedevent,thisiscalledforeverySessionEndedRequestorwhentheskillreturnsatransitiontoastatewhereisTerminal===true,normallythisisatransit

26 iontothediestate.Youwouldnormallyusethis
iontothediestate.Youwouldnormallyusethistotrackanalytics 30Chapter10.Links VoxaDocumentation,Release2.1.2 Voxa.onSystem.ExceptionEncountered(callback[,atLast])ThishandlesSystem.ExceptionEncounteredeventthataresenttoyourskillwhenaresponsetoanAudioPlayereventcausesanerror returnPromise.reduce(errorHandlers,(result,errorHandler)�={if(result){returnresult;}returnPromise.resolve(errorHandler(alexaEvent,error));},null); 10.10.1ErrorhandlersYoucanregistermanyerrorhandlerstobeusedforthedifferentkindoferrorstheapplicationcouldgenerate.Theyallfollowthesamelogicwhereifthersterrortypeisnothandledthenthedefaultistobedeferredtothemoregeneralerrorhandlerthatultimatelyjustreturnsadefaulterrorreply.They'reexecutedsequentiallyandwillstopwhenthersthandlerreturnsareply.Voxa.onStateMachineError(callback[,atLast])ThishandlerwillcatchallerrorsgeneratedwhentryingtomaketransitionsinthestateMachine,thiscouldincludee

27 rrorsinthestatemachinecontrollers,,theha
rrorsinthestatemachinecontrollers,,thehandlersget(alexaEvent,reply,error)param-eters skill.onStateMachineError((alexaEvent,reply,error)�={//itgetsthecurrentreply,whichcouldbeincompleteduetoanerror.returnnewReply(alexaEvent,{tell:Anerrorinthecontrollerscode}).toJSON();}); Voxa.onError(callback[,atLast])Thisisthemoregeneralhandlerandwillcatchallunhandlederrorsintheframework,itgets(alexaEvent,error)parametersasarguments skill.onError((alexaEvent,error)�={returnnewReply(alexaEvent,{tell:Anunrecoverableerroroccurred.}).toJSON();}); 10.10.2PlaybackControllerhandlersHandleeventsfromtheAudioPlayerinterfaceaudioPlayerCallback(alexaEvent,reply)AllaudioplayermiddlewarecallbacksgetaalexaeventandareplyobjectArguments•alexaEvent(AlexaEvent)–ThealexaeventsentbyAlexa•reply(object)–AreplytobesentasaresponseReturnsobjectwriteYouralexaeventhandlershouldreturnanapprop

28 riateresponseaccordingtotheeventtype,thi
riateresponseaccordingtotheeventtype,thisgenerallymeansappendingtothereplyobjectInthefollowingexamplethealexaeventhandlerreturnsaREPLACE_ENQUEUEDdirectivetoaPlaybackNearlyFinished()event. 10.10.Voxa31 VoxaDocumentation,Release2.1.2 skill[onAudioPlayer.PlaybackNearlyFinished]((alexaEvent,reply)�={constdirectives={type:AudioPlayer.Play,playBehavior:REPLACE_ENQUEUED,token:"",url:https://www.dl-sounds.com/wp-content/uploads/edd/2016/09/Classical-Bed3-,!preview.mp3,offsetInMilliseconds:0,};returnreply.append({directives});}); Voxa.onAudioPlayer.PlaybackStarted(callback[,atLast])Voxa.onAudioPlayer.PlaybackFinished(callback[,atLast])Voxa.onAudioPlayer.PlaybackStopped(callback[,atLast])Voxa.onAudioPlayer.PlaybackFailed(callback[,atLast])Voxa.onAudioPlayer.PlaybackNearlyFinished(callback[,atLast])Voxa.onPlaybackController.NextCommandIssued(callback[,atLast])Voxa.onPla

29 ybackController.PauseCommandIssued(callb
ybackController.PauseCommandIssued(callback[,atLast])Voxa.onPlaybackController.PlayCommandIssued(callback[,atLast])Voxa.onPlaybackController.PreviousCommandIssued(callback[,atLast])10.10.3AlexaSkillEventhandlersHandlerequestfortheAlexaSkillEventsalexaSkillEventCallback(alexaEvent)AllthealexaskilleventcallbacksgetaalexaeventandareplyobjectArguments•alexaEvent(AlexaEvent)–ThealexaeventsentbyAlexa•reply(object)–AreplytobesentastheresponseReturnsobjectreplyAlexaonlyneedsanacknowledgementthatyoureceivedandprocessedtheeventsoitdoesn'tneedtoresendtheevent.JustreturningthereplyobjectisenoughThisisanexampleonhowyourskillcanprocessaSkillEnabled()event. skill[onAlexaSkillEvent.SkillEnabled]((alexaEvent,reply)�={constuserId=alexaEvent.user.userId;console.log(skillwasenabledforuser:${userId});returnreply;}); Voxa.onAlexaSkillEvent.SkillAccountLinked(callback[,atLast])Voxa

30 .onAlexaSkillEvent.SkillEnabled(callback
.onAlexaSkillEvent.SkillEnabled(callback[,atLast])Voxa.onAlexaSkillEvent.SkillDisabled(callback[,atLast])Voxa.onAlexaSkillEvent.SkillPermissionAccepted(callback[,atLast]) 32Chapter10.Links VoxaDocumentation,Release2.1.2 Voxa.onAlexaSkillEvent.SkillPermissionChanged(callback[,atLast])10.10.4AlexaListEventhandlersHandlerequestfortheAlexaListEventsalexaListEventCallback(alexaEvent)AllthealexalisteventcallbacksgetaalexaeventandareplyobjectArguments•alexaEvent(AlexaEvent)–ThealexaeventsentbyAlexa•reply(object)–AreplytobesentastheresponseReturnsobjectreplyAlexaonlyneedsanacknowledgementthatyoureceivedandprocessedtheeventsoitdoesn'tneedtoresendtheevent.JustreturningthereplyobjectisenoughThisisanexampleonhowyourskillcanprocessaItemsCreated()event. skill[onAlexaHouseholdListEvent.ItemsCreated]((alexaEvent,reply)�={constlistId=alexaEvent.request.body.listId;constuserId=alexaEven

31 t.user.userId;console.log(Itemscrea
t.user.userId;console.log(Itemscreatedforlist:${listId}foruser${userId});returnreply;}); Voxa.onAlexaHouseholdListEvent.ItemsCreated(callback[,atLast])Voxa.onAlexaHouseholdListEvent.ItemsUpdated(callback[,atLast])Voxa.onAlexaHouseholdListEvent.ItemsDeleted(callback[,atLast]) 10.10.Voxa33 VoxaDocumentation,Release2.1.2 10.11RequestFlow 34Chapter10.Links VoxaDocumentation,Release2.1.2 10.12I18NInternationalizationsupportisdoneusingthei18nextlibrary,thesametheAmazonAlexaNodeSDKuses.10.12.1ConguringtheskillforI18NTouseityouneedtocongureyourskilltousetheI18NRendererclassinsteadofthedefaultrendererclass. constVoxa=require(voxa);constskill=newVoxa({Model,variables,views,RenderClass:Voxa.I18NRenderer}); TheframeworktakescareofselectingthecorrectlocaleoneveryalexaeventbylookingatthealexaEvent.request.localeproperty.10.12.2ChangesinyourviewsTheotherchangeyouwillneedistodeneyourviewsusing

32 thei18nexttranslateformat: usestric
thei18nexttranslateformat: usestrict;constviews=(functionviews(){return{en-us:{translation:{LaunchIntent:{OpenResponse:{tell:Hello!Good{time}},},Question:{Ask:{ask:Whattimeisit?},},ExitIntent:{Farewell:{tell:Ok.Formoreinfovisit{site}site.},},Number:{One:{tell:{numberOne}},},Say:{Say:{say:say},},Random:{tell:[Random1,Random2,Random3]},},},de-de:{translation:{LaunchIntent:{OpenResponse:{tell:Hallo!guten{time}},},Question:{Ask:{ask:wiespätistes?},},ExitIntent:{Farewell:{tell:OkfürweitereInfosbesuchen{site}Website},},Number:{ (continuesonnextpage) 10.12.I18N35 VoxaDocumentation,Release2.1.2 (continuedfrompreviouspage) One:{tell:{numberOne}},},Say:{Say:{say:sagen},},Random:{tell:[zufällig1,zufällig2,zufällig3]},},},};}());

33 module.exports=views; 10.12.3VariablesVa
module.exports=views; 10.12.3VariablesVariablesshouldworkmostlythesameaswiththeDefaultRenderer,withtheexceptionthatvariableswillnowgetalocalekey usestrict;/***Variablesfortests**Copyright(c)2016RainAgency.*LicensedundertheMITlicense.*/constPromise=require(bluebird);constvariables={exitDirectiveMessage:functionexitDirectiveMessage(){return({text:Thanksforplaying!,type:PlainText,});},exitCard:functionexitCard(){return{type:Standard,title:title,text:text,image:{smallImageUrl:smallImage.jpg,largeImageUrl:largeImage.jpg,},};},exitArray:functionexitArray(){return[{a:1},{b:2},{c:3}];},time:functiontime(){consttoday=newDate();constcurHr=today.getHours();if(curHr12){ (continuesonnextpage) 36Chapter10.Links VoxaDocumentation,Release2.1.2 (continuedfrompreviouspage) returnPromise.resolve(Morning);}if(curHr18){returnPromis

34 e.resolve(Afternoon);}returnPr
e.resolve(Afternoon);}returnPromise.resolve(Evening);},site:functionsite(){returnPromise.resolve(example.com);},count:functioncount(model){returnmodel.count;},numberOne:functionnumberOne(model,request){if(request.request.locale===en-us){returnone;}elseif(request.request.locale===de-de){returnein;}return1;},};module.exports=variables; 10.13PluginsPluginsallowyoutomodifyhowtheStateMachineSkillhandlesanalexaevent.Whenapluginisregistereditwillusethedifferenthooksinyourskilltoaddfunctionality.Ifyouhaveseveralskillswithsimilarbehaviorthenyouransweristocreateaplugin.10.13.1UsingapluginAfterinstantiatingaStateMachineSkillyoucanregisterpluginsonit.BuiltinpluginscanbeaccessedthroughVoxa.plugins usestrict;constVoxa=require(voxa);constModel=require(./model);constviews=require(./views):constvariables=require(

35 ./variables);constskill=newVoxa({Mo
./variables);constskill=newVoxa({Model,variables,views});Voxa.plugins.replaceIntent(skill); 10.13.Plugins37 VoxaDocumentation,Release2.1.2 10.13.2StateFlowpluginStoresthestatetransitionsforeveryalexaeventinanarray.stateFlow(skill)StateFlowattachescallbackstoonRequestStarted(),onBeforeStateChanged()andonBeforeReplySent()totrackstatetransitionsinaalexaEvent.flowarrayArguments•skill(Voxa)–TheskillobjectUsage constalexa=require(alexa-statemachine);alexa.plugins.stateFlow.register(skill)skill.onBeforeReplySent((alexaEvent)�={console.log(alexaEvent.flow.join(�));//entry�firstState�secondState�die}); 10.13.3ReplaceIntentpluginItallowsyoutorenameanintentnamebasedonaregularexpression.Bydefaultitwillmatch/(.*)OnlyIntent$/andreplaceitwith$1Intent.replaceIntent(skill[,cong])ReplaceIntentpluginusesonIntentRequest()tomodifytheinco

36 mingrequestintentnameArguments•skil
mingrequestintentnameArguments•skill(Voxa)–ThestateMachineSkill•config–Anobjectwiththeregextolookforandthereplacevalue.Usage constskill=newVoxa({Model,variables,views});Voxa.plugins.replaceIntent(skill,{regex:/(.*)OnlyIntent$/,replace:$1Intent});Voxa.plugins.replaceIntent(skill,{regex:/^VeryLong(.*)/,replace:Long$1}); WhyOnlyIntents?Agoodpracticeistoisolateanutteranceintoanotherintentifitcontainsasingleslot.BycreatingtheOnlyIntent,Alexawillprioritizethisintentiftheusersaysonlyavaluefromthatslot.Let'sexplainwiththefollowingscenario.Youneedtheusertoprovideazipcode.YouwouldhaveanintentcalledZipCodeIntent.Butyoustillhavetomanageiftheuseronlysaysazipcodewithoutanyotherwords.Sothat'swhenwecreateanOnlyIntent.Let'scallitZipCodeOnlyIntent.Ourutterancelewillbelikethis: 38Chapter10.Links VoxaDocumentation,Release2.1.2 ZipCodeIntenthereismy{ZipCodeSlot}ZipCodeIntentmyzipis{ZipC

37 odeSlot}...ZipCodeOnlyIntent{ZipCodeSlot
odeSlot}...ZipCodeOnlyIntent{ZipCodeSlot} Butnowwehavetwostateswhicharebasicallythesame.ReplaceIntentpluginwillrenameallincomingrequestsintentsfromZipCodeOnlyIntenttoZipCodeIntent.10.13.4CloudWatchpluginItlogsaCloudWatchmetricwhentheskillcatchesanerrororsuccessexecution.Paramscloudwatch(skill,cloudwatch[,eventMetric])CloudWatchpluginusesVoxa.onError(),Voxa.onStateMachineError()andVoxa.onBeforeReplySent()tologmetricsArguments•skill(Voxa)–ThestateMachineSkill•cloudwatch–AnewAWS.CloudWatchobject.•putMetricDataParams–ParamsforputMetricDataUsage constAWS=require(aws-sdk);constskill=newVoxa({Model,variables,views});constcloudWatch=newAWS.CloudWatch({});consteventMetric={MetricName:CaughtError,//NameofyourmetricNamespace:SkillName//Nameofyourskill};Voxa.plugins.cloudwatch(skill,cloudWatch,eventMetric); 10.13.5AutoloadpluginItacceptsanadaptertoautoloadinfoin

38 tothemodelobjectcomingineveryalexareques
tothemodelobjectcomingineveryalexarequest.ParamsautoLoad(skill[,cong])Autoloadpluginusesskill.onSessionStartedtoloaddatathersttimetheuseropensaskillArguments•skill(Voxa)–ThestateMachineSkill. 10.13.Plugins39 VoxaDocumentation,Release2.1.2 •config–AnobjectwithanadapterkeywithagetPromisemethodinwhichyoucanhandleyourdatabaseaccesstofetchinformationfromanyresource.Usage constskill=newVoxa({Model,variables,views});Voxa.plugins.autoLoad(skill,{adapter}); 10.14DebuggingVoxausesthedebugmoduleinternallytologanumberofdifferentinternalevents,ifyouwanthavealookatthoseeventsyouhavetodeclarethefollowingenvironmentvariableDEBUG=voxaThisisanexampleofthelogoutput voxaReceivednewevent:{"version":"1.0","session":{"new":true,"sessionId":,!"SessionId.09162f2a-cf8f-414f-92e6-1e3616ecaa05","application":{"applicationId":,!"amzn1.ask.skill.1fe77997-14db-409b-926c-0d8c161e5376"},"attributes":{},"user":{,!"

39 userId":"amzn1.ask.account.","accessToke
userId":"amzn1.ask.account.","accessToken":""}},"request":{"type":"LaunchRequest",,!"requestId":"EdwRequestId.0f7b488d-c198-4374-9fb5-6c2034a5c883","timestamp":"2017-,!01-25T23:01:15Z","locale":"en-US"}}+0msvoxaInitializedmodellike{}+8msvoxaStartingthestatemachinefromentrystate+2svoxaRunningsimpleTransitionforentry+1msvoxaRunningonAfterStateChangeCallbacks+0msvoxaentrytransitionresultedin{"to":"launch"}+0msvoxaRunninglaunchenterfunction+1msvoxaRunningonAfterStateChangeCallbacks+0msvoxalaunchtransitionresultedin{"reply":"Intent.Launch","to":"entry","message":{,!"tell":"Welcomemail@example.com!"},"session":{"data":{},"reply":null}}+7ms 10.15StarterKitThisprojectisdesignedtobeasimpletemplateforyournewskills.Withsomewellthoughtdefaultsthathaveprovenusefulwhendevelopingreallifeskills.10.15.1DirectoryStructureIthasthefollowingdirectorystructure . README.md config env.js index.js local.json.example production.json (

40 continuesonnextpage) 40Chapter10.Links V
continuesonnextpage) 40Chapter10.Links VoxaDocumentation,Release2.1.2 (continuedfrompreviouspage) staging.json gulpfile.js package.json serverless.yml services skill MainStateMachine.js index.js variables.js views.js speechAssets IntentSchema.json SampleUtterances.txt customSlotTypes test server.js congBydefaultyourskillwillhavethefollowingenvironments:•local•staging•productionWhatenvironmentyou'reisdeterminedintheconfig/env.jsmoduleusingthefollowingcode:skillThisiswhereyourcodetohandlealexaeventsgoes,youwillusuallyhaveaStateMachinedenition,thiswillincludestates,middlewareandaModel,ViewsandVariablesspeechAssetsThisshouldbeaversioncontrolledcopyofyourintentschema,sampleutterrancesandcustomslots.server.jsAnhttpserverforyourskillconguredtolistenonport3000,thisshouldbeusedfordevelopmentonly.servicesJustacommonplacetoputmodelsandlibrariestestYouwritetestsright? 10.15.StarterKit41 VoxaDoc

41 umentation,Release2.1.2 gulpleAgulpr
umentation,Release2.1.2 gulpleAgulprunnerconguredwithawatchtaskthatstartsyourexpressserverandlistensforchangestoreloadyourapplication.serverless.ymlTheserverlessframeworkisatoolthathelpsyoumanageyourlambdaapplications,assumingyouhaveyourAWScredentialssetupproperlythisstarterkitdenestheveryminimumneededsoyoucandeployyourskilltolambdawiththefollowingcommand: $slsdeploy 10.15.2Dependencies(installtheserst)1.Ifyouareusingnode.jsforthersttime,installnode:•Installnvm,curl-o-https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh|bash,•Installnode6.10,nvminstall6.102.Installgulpglobally,npminstall-ggulp3.Installngrok,andaddittoyourlocalbin10.15.3Runningtheproject1.ClonetheStarterKitrepository2.Makesureyou'rerunningnode6.10,thisiseasiestwithnvm3.Inyourskilldirectory,installnodedependenciesusingnpminstall4.Createaconfig/local.jsonleusingconfig/local.json.exampleasanexample

42 5.Runtheprojectwithgulpwatch6.Atthispoin
5.Runtheprojectwithgulpwatch6.Atthispointyoushouldstartngrokhttp3000andcongureyourskillintheAmazonDeveloperpaneltousethengrokhttpsendpoint.10.16MyFirstPodcastThisprojectwillhelpyoubuildapodcastskillusingtheAudiodirectivestemplate.Youwillbeabletomanageloop,shuferequestsaswellasoffertheuserthepossibilitytostartanaudioover,pause,stopitorplaythenextorpreviousaudiofromapodcastlist.10.16.1DirectoryStructureIthasthefollowingdirectorystructure 42Chapter10.Links VoxaDocumentation,Release2.1.2 . README.md config env.js index.js local.json.example production.json staging.json gulpfile.js package.json serverless.yml services skill data podcast.js MainStateMachine.js index.js states.js variables.js views.js speechAssets IntentSchema.json SampleUtterances.txt customSlotTypes test server.js congBydefaultyourskillwillhavethefollowingenvironments:•local•staging•productionWhatenvironmentyou'reisdeter

43 minedintheconfig/env.jsmoduleusingthefol
minedintheconfig/env.jsmoduleusingthefollowingcode:skill10.16.2index.jsFirstleinvokedbythelambdafunction,itinitializesthestatemachine.Youdon'tneedtomodifythisle.10.16.3MainStateMachine.jsStatemachineisinitializedwithyourmodel,viewsandvariables.Theclassstates.jswillbeinchargetohandleallintentsandeventscomingfromAlexa.Youdon'tneedtomodifythisle.10.16.4states.jsAlleventsandintentsdispatchedbytheAlexaVoiceServicetoyourskillarehandledhere.YoucanintegrateanyothermoduleorAPIcallstothirdpartyservices,calldatabaseresourcesorjustsimplyreplyaHelloorGoodbye 10.16.MyFirstPodcast43 VoxaDocumentation,Release2.1.2 responsetotheuser.Theaudiointentshandledinthisexampleare:•AMAZON.CancelIntent•AMAZON.LoopOffIntent•AMAZON.LoopOnIntent•AMAZON.NextIntent•AMAZON.PauseIntent•AMAZON.PreviousIntent•AMAZON.RepeatIntent•AMAZON.ResumeIntent•AMAZON.ShufeOffIntent•AMAZON.Shu

44 feOnIntent•AMAZON.StartOverInte
feOnIntent•AMAZON.StartOverIntentYoucantrackthevaluesforloop,shufeandcurrentURLplayinginthetokenpropertyoftheAlexaeventinthepathalexaEvent.context.AudioPlayer.token: skill.onState(loopOff,(alexaEvent)�={if(alexaEvent.context){consttoken=JSON.parse(alexaEvent.context.AudioPlayer.token);constshuffle=token.shuffle;constloop=0;constoffsetInMilliseconds=alexaEvent.context.AudioPlayer.,!offsetInMilliseconds;letindex=token.index;if(index===podcast.length){index=0;}constdirectives=buildPlayDirective(podcast[index].url,index,shuffle, ,!loop,offsetInMilliseconds);return{reply:Intent.LoopDeactivated,to:die,directives};}return{reply:Intent.Exit,to:die};}); ForanyoftheseeventsyoucanmakeAlexatospeakafteruser'sactionwithareplyobject,optionallyyoucandenethediestateandpassthroughthedirectivesobjectwitheitheraAudioPlayer.PlayorAudioPlayer.Stopdirecti

45 vetype.Youcanalsohandledthefollowingplay
vetype.Youcanalsohandledthefollowingplaybackrequestevents:•AudioPlayer.PlaybackStarted•AudioPlayer.PlaybackFinished•AudioPlayer.PlaybackStopped•AudioPlayer.PlaybackNearlyFinished•AudioPlayer.PlaybackFailed 44Chapter10.Links VoxaDocumentation,Release2.1.2 You'renotallowedtorespondwithareplyobjectsinceit'sjustaneventmostfortrackignpurposes,soit'soptionaltoimplementandyoucandothefollowingsyntax: skill[onAudioPlayer.PlaybackStarted]((alexaEvent)�={console.log(onAudioPlayer.PlaybackStarted,JSON.stringify(alexaEvent,null, ,!2));}); IncasetheuserhasactivatedtheloopmodebydispatchingtheAMAZON.LoopOnIntentintent,youcanimplementaqueuelistintheAudioPlayer.PlaybackNearlyFinishedthisway: skill[onAudioPlayer.PlaybackNearlyFinished]((alexaEvent,reply)�={consttoken=JSON.parse(alexaEvent.context.AudioPlayer.token);if(token.loop===0){returnreply;}const

46 shuffle=token.shuffle;constloop=token.lo
shuffle=token.shuffle;constloop=token.loop;letindex=token.index+1;if(shuffle===1){index=randomIntInc(0,podcast.length-1);}elseif(index===podcast.length){index=0;}constdirectives=buildEnqueueDirective(podcast[index].url,index,shuffle, ,!loop);returnreply.append({directives});});functionbuildEnqueueDirective(url,index,shuffle,loop){constdirectives={};directives.type=AudioPlayer.Play;directives.playBehavior=REPLACE_ENQUEUED;directives.token=createToken(index,shuffle,loop);directives.url=podcast[index].url;directives.offsetInMilliseconds=0;returndirectives;} ThebuildEnqueueDirectivefunctionisinchargetobuildadirectiveobjectwithaqueuebehavior,whichwillallowtheskilltoplaythenextaudioassoonasthecurrentoneisnished.Thisiswhereyourcodetohandlealexaeventsgoes,youwillusuallyhaveaStateMachinedenition,thiswillincludestates,middlewareandaModel,ViewsandVariables.10.16.5data/podcast.jsAJSONvariablew

47 ithtitlesandurlsfor5audioexampleshostedi
ithtitlesandurlsfor5audioexampleshostedinasecureserver,allalongplayapodcastwhichtheusercanshufeorloop.Youcanmodifythislewithwhateverotheraudiotoaddtoyourplaylist.Keepinmindthattheymustbehostedinasecureserver.ThesupportedformatsfortheaudioleincludeAAC/MP4,MP3,HLS,PLSandM3U.Bitrates:16kbpsto384kbps. 10.16.MyFirstPodcast45 VoxaDocumentation,Release2.1.2 speechAssetsThisshouldbeaversioncontrolledcopyofyourintentschema,sampleutterrancesandcustomslots.server.jsAnhttpserverforyourskillconguredtolistenonport3000,thisshouldbeusedfordevelopmentonly.servicesJustacommonplacetoputmodelsandlibrariestestYouwritetestsright?gulpleAgulprunnerconguredwithawatchtaskthatstartsyourexpressserverandlistensforchangestoreloadyourapplication.serverless.ymlTheserverlessframeworkisatoolthathelpsyoumanageyourlambdaapplications,assumingyouhaveyourAWScredentialssetupproperlythisstarterkitdenestheveryminimumneeded

48 soyoucandeployyourskilltolambdawiththefo
soyoucandeployyourskilltolambdawiththefollowingcommand: $slsdeploy 10.16.6Runningtheproject1.ClonetheAudioPodcastSamplerepository2.Makesureyou'rerunningnode6.10,thisiseasiestwithnvm3.Createaconfig/local.jsonleusingconfig/local.json.exampleasanexample4.Runtheprojectwithgulpwatch5.CreateaskillinyourAmazonDeveloperPortalaccountundertheALEXAmenu.6.GototheinteractionmodeltabandcopytheintentschemaandutterancesfromthethespeechAssetsfolder.7.Atthispointyoushouldstartngrokhttp3000andcongureyourskillintheAmazonDeveloperpaneltousethengrokhttpsendpoint.10.17AccountLinkingThisprojectisdesignedtobeasimpletemplateforyournewskillswithaccountlinking.User'sinformationisstoredinaDynamoDBtablesoyoucanfetchitfromtheskillonceusersareauthenticated. 46Chapter10.Links VoxaDocumentation,Release2.1.2 10.17.1DirectoryStructureIthasthefollowingdirectorystructure . README.md config env.js index.js local.json.example production.jso

49 n staging.json gulpfile.js package.json
n staging.json gulpfile.js package.json serverless.yml services model.js userStorage.js skill MainStateMachine.js index.js states.js variables.js views.js speechAssets IntentSchema.json SampleUtterances.txt customSlotTypes test www infrastructure mount.js routes index.js skill.js server.js congBydefaultyourskillwillhavethefollowingenvironments:•local•staging•productionWhatenvironmentyou'reisdeterminedintheconfig/env.jsmoduleusingthefollowingcode:skill10.17.2index.jsFirstleinvokedbythelambdafunction,itinitializesthestatemachine.Youdon'tneedtomodifythisle. 10.17.AccountLinking47 VoxaDocumentation,Release2.1.2 10.17.3MainStateMachine.jsStatemachineisinitializedwithyourmodel,viewsandvariables.Theclassstates.jswillbeinchargetohandleallintentsandeventscomingfromAlexa.Youdon'tneedtomodifythisle.10.17.4states.jsAlleventsandintentsdispatchedbytheAlexaVoiceServicetoyourskillarehandledhere

50 .YoucanintegrateanyothermoduleorAPIcalls
.YoucanintegrateanyothermoduleorAPIcallstothirdpartyservices,calldatabaseresourcesorjustsimplyreplyaHelloorGoodbyeresponsetotheuser.Beforetheverybeginningofthelesson,youcanimplementthemethodonRequestStartedtofetchuser'sdatafromDynamoDBbasedontheaccessTokencomingfromAlexa skill.onRequestStarted((alexaEvent)�={if(!alexaEvent.session.user.accessToken){returnalexaEvent;}conststorage=newUserStorage();returnstorage.get(alexaEvent.session.user.accessToken).then((user)�={alexaEvent.model.user=user;returnalexaEvent;});}); IftheuserisnotauthenticatedyoucanalsosendaLinkingAccountcardtotheAlexaappsousersknowthatbeforeusingyourskill,theymustgetauthenticated.speechAssetsThisshouldbeaversioncontrolledcopyofyourintentschema,sampleutterrancesandcustomslots.wwwAstandardexpressprojectconguredtoserveyourskillinthe/skillroute.Combinedwithngrokthisisagreattoolwhendevelopingordebugging.10.17.5routes/index.

51 jsYoucanhandleallGETandPOSTrequestsforyo
jsYoucanhandleallGETandPOSTrequestsforyouraccountlinkingprojectshere.ThemostcommononewillbethePOSTcalloftheformafterusershitthesubmitbutton.Inthisexample,wegatheruser'sinformationandcreatearowinDynamoDBfortheirinformation.ForexampleyoucangenerateanUUIDtoidentifytheusersastheprimarykeyandsenditbacktoAlexaastheaccessTokensoyoucaneasilyfetchuser'sinformationlateron. router.post(/,(req,res,next)�={constmd=newMobileDetect(req.headers[user-agent]);constdb=newStorage();constemail=req.body.email;constcode=uuidV4().replace(/-/g,);constparams={id:code, (continuesonnextpage) 48Chapter10.Links VoxaDocumentation,Release2.1.2 (continuedfrompreviouspage) email,};returndb.put(params).then(()�={constredirect=${req.query.redirect_uri}#state=${req.query.state}&access_,!token=${code}&token_type=Bearer;if(md.is(AndroidOS)){console.log(redirectingandroidt

52 o:${redirect});res.redirect(redirec
o:${redirect});res.redirect(redirect);}else{console.log(redirectingwebto:${redirect});res.render(auth/success,{page:success,title:Success,redirectUrl:redirect,});}}).catch(next);}); Tonishtheauthenticationprocessyouhavetomakearedirectiontotheredirect_uriAmazonsendstoourservice.Sincetherecouldbe2originstoredirectto,wecreatethisURLdynamically;theseendpointscouldlooklikethis:•https://pitangui.amazon.com/spa/skill/account-linking-status.html?vendorId=xxx�-ForUnitedStatesstore•https://layla.amazon.com/spa/skill/account-linking-status.html?vendorId=xxxxxx�-ForUKandGermanystoreTheotherparameterstosendare:•access_token=YOUR-TOKEN•token_type=BearerservicesJustacommonplacetoputmodelsandlibraries10.17.6userStorage.jsUsethisleasanexampletohandledatabaselogic.SinceweuseDynamoDBforthisexample,weincluded2methods,aputandaget,souser

53 'sinformationgetstoredfromtheaccountlink
'sinformationgetstoredfromtheaccountlinkingprojectandgetfetchedfromthealexaskillside.ForreachingoutDynamoDByouneedsomepermissionsforyourlambdafunction.MakesuretograntyourlambdafunctionwitharolewithDynamoDBaccess.testYouwritetestsright? 10.17.AccountLinking49 VoxaDocumentation,Release2.1.2 gulpleAgulprunnerconguredwithawatchtaskthatstartsyourexpressserverandlistensforchangestoreloadyourapplication.serverless.ymlTheserverlessframeworkisatoolthathelpsyoumanageyourlambdaapplications,assumingyouhaveyourAWScredentialssetupproperlythisstarterkitdenestheveryminimumneededsoyoucandeployyourskilltolambdawiththefollowingcommand: $slsdeploy 10.17.7Runningtheproject1.ClonetheAccountLinkingSamplerepository2.Makesureyou'rerunningnode6.10,thisiseasiestwithnvm3.Createaconfig/local.jsonleusingconfig/local.json.exampleasanexample4.Runtheprojectwithgulpwatch5.Atthispointyoushouldstartngrokhttp3000andcongureyou

54 rskillintheAmazonDeveloperpaneltousethen
rskillintheAmazonDeveloperpaneltousethengrokhttpsendpoint. 50Chapter10.Links Index AAlexaEvent()(class),27AlexaEvent.AlexaEvent.intent.params(Alex-aEvent.AlexaEvent.intentattribute),27AlexaEvent.AlexaEvent.model(AlexaEvent.AlexaEventattribute),27AlexaEvent.AlexaEvent.token(AlexaEvent.AlexaEventattribute),27AlexaEvent.AlexaEvent.user(AlexaEvent.AlexaEventat-tribute),27alexaListEventCallback()(built-infunction),33alexaSkillEventCallback()(built-infunction),32audioPlayerCallback()(built-infunction),31autoLoad()(built-infunction),39Ccloudwatch()(built-infunction),39RreplaceIntent()(built-infunction),38Reply()(class),27Reply.Reply.append()(Reply.Replymethod),28Reply.Reply.fulllIntent()(Reply.Replymethod),28Reply.Reply.fulllSlot()(Reply.Replymethod),28Reply.Reply.toJSON()(Reply.Replymethod),28SstateFlow()(built-infunction),38Vvariable()(built-infunction),25Voxa()(class),28Voxa.execute()(Voxamethod),28Voxa.l

55 ambda()(Voxamethod),28Voxa.onAfterStateC
ambda()(Voxamethod),28Voxa.onAfterStateChanged()(Voxamethod),30Voxa.onAlexaHouseholdListEvent.ItemsCreated()(Voxa.onAlexaHouseholdListEventmethod),33Voxa.onAlexaHouseholdListEvent.ItemsDeleted()(Voxa.onAlexaHouseholdListEventmethod),33Voxa.onAlexaHouseholdListEvent.ItemsUpdated()(Voxa.onAlexaHouseholdListEventmethod),33Voxa.onAlexaSkillEvent.SkillAccountLinked()(Voxa.onAlexaSkillEventmethod),32Voxa.onAlexaSkillEvent.SkillDisabled()(Voxa.onAlexaSkillEventmethod),32Voxa.onAlexaSkillEvent.SkillEnabled()(Voxa.onAlexaSkillEventmethod),32Voxa.onAlexaSkillEvent.SkillPermissionAccepted()(Voxa.onAlexaSkillEventmethod),32Voxa.onAlexaSkillEvent.SkillPermissionChanged()(Voxa.onAlexaSkillEventmethod),32Voxa.onAudioPlayer.PlaybackFailed()(Voxa.onAudioPlayermethod),32Voxa.onAudioPlayer.PlaybackFinished()(Voxa.onAudioPlayermethod),32Voxa.onAudioPlayer.PlaybackNearlyFinished()(Voxa.onAudioPlayermethod),32Voxa.onAudioPlayer.Pl

56 aybackStarted()(Voxa.onAudioPlayermethod
aybackStarted()(Voxa.onAudioPlayermethod),32Voxa.onAudioPlayer.PlaybackStopped()(Voxa.onAudioPlayermethod),32Voxa.onBeforeReplySent()(Voxamethod),30Voxa.onBeforeStateChanged()(Voxamethod),29Voxa.onError()(Voxamethod),31Voxa.onIntent()(Voxamethod),29Voxa.onIntentRequest()(Voxamethod),29Voxa.onLaunchRequest()(Voxamethod),29Voxa.onPlaybackController.NextCommandIssued()(Voxa.onPlaybackControllermethod),32Voxa.onPlaybackController.PauseCommandIssued()(Voxa.onPlaybackControllermethod),32Voxa.onPlaybackController.PlayCommandIssued()(Voxa.onPlaybackControllermethod),32Voxa.onPlaybackController.PreviousCommandIssued()(Voxa.onPlaybackControllermethod),32 51 VoxaDocumentation,Release2.1.2 Voxa.onRequestStarted()(Voxamethod),30Voxa.onSessionEnded()(Voxamethod),30Voxa.onSessionStarted()(Voxamethod),30Voxa.onState()(Voxamethod),29Voxa.onStateMachineError()(Voxamethod),31Voxa.onSystem.ExceptionEncountered()(Voxa.onSystemmet

Related Contents


Next Show more