Alexa custom skill sending LaunchRequest not IntentRequest - alexa-skills-kit

I am new to Alexa development so excuse my ignorance. Essentially I am trying to build a basic custom skill such that when I say Alexa, kodi pause it sends PauseTV intent to Lambda and when I say Alexa, kodi play it sends PlayTV intent to Lambda.
At the moment my skill is only ever sending a LaunchRequest, I cannot get it to send the specific intent. Below is my skill JSON:
{
"interactionModel": {
"languageModel": {
"invocationName": "kodi",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "PauseTV",
"slots": [],
"samples": [
"pause"
]
},
{
"name": "PlayTV",
"slots": [],
"samples": [
"play"
]
}
],
"types": []
}
}
Any assistance will be appreciated!

Related

The language expression property '0' can't be evaluated, property name must be a string - ARM Template error while adding Key Vault access policy

I've been working on an issue and seem to be stuck, so asking on so in case anyone can help.
To describe the issue, I've got an existing Azure Key Vault setup, and wish to add a number of access policies to this resource group. It needs to be conditional as if the function name is "false" then that function should not be added to key vault access policy.
variable section:
"variables": {
"functionAccess": {
"value": [
{
"name": "[parameters('Function_1')]"
},
{
"name": "[parameters('Function_2')]"
},
{
"name": "[parameters('Function_3')]"
}
]
}
}
My Template :
{
"apiVersion": "2016-10-01",
"condition": "[not(equals(variables('functionAccess')[CopyIndex()].name, 'false'))]",
"copy": {
"batchSize": 1,
"count": "[length(variables('functionAccess'))]",
"mode": "Serial",
"name": "accessPolicies"
},
"name": "[concat(parameters('KeyVault_Name'), '/add')]",
"properties": {
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[if(not(equals(variables('functionAccess')[CopyIndex()].name, 'false')), reference(concat('Microsoft.Web/sites/', variables('functionAccess')[CopyIndex()].name), '2016-08-01', 'Full').identity.principalId, json('null'))]",
"permissions": {
"keys": [
"get",
"list"
],
"secrets": [
"get",
"list"
],
"certificates": [
"get",
"list"
]
}
}
]
},
"type": "Microsoft.KeyVault/vaults/accessPolicies"
}
When I deploy my ARM template for the azure key vault I got this error message:
The language expression property '0' can't be evaluated, property name must be a string.
also tried below, but same error:
{
"apiVersion": "2018-02-14",
"name": "[concat(parameters('KeyVault_Name'), '/add')]",
"properties": {
"copy": [
{
"batchSize": 1,
"count": "[length(variables('functionAccess'))]",
"mode": "serial",
"name": "accessPolicies",
"input": {
"condition": "[not(equals(variables('functionAccess')[copyIndex('accessPolicies')].name, 'false'))]",
"tenantId": "[subscription().tenantId]",
"objectId": "[if(not(equals(variables('functionAccess')[copyIndex('accessPolicies')].name, 'false')), reference(concat('Microsoft.Web/sites/', variables('functionAccess')[copyIndex('accessPolicies')].name), '2016-08-01', 'Full').identity.principalId, json('null'))]",
"permissions": {
"keys": [
"get",
"list"
],
"secrets": [
"get",
"list"
],
"certificates": [
"get",
"list"
]
}
}
}
]
},
"type": "Microsoft.KeyVault/vaults/accessPolicies"
}
There are a few options for dealing with filtering an array for copy operation. I deploy my ARM templates from PowerShell scripts and use PowerShell to setup parameter values. When I need special logic handle different inputs for different environments, I let PowerShell handle it.
If you must handle the filtering in ARM and you have the option to input a CSV list of functions, then perhaps the following will work. You can then use the functionAccessArray to iterate over in the copy operation.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
"functionAccessCsv": "Function-0,Function-1,false,Function-4,false,Function-6,Function-7",
"functionAccessFiltered": "[replace(replace(variables('functionAccessCsv'), 'false', ''), ',,', ',')]",
"functionAccessArray": "[split(variables('functionAccessFiltered'), ',')]"
},
"resources": [
],
"outputs": {
"functionAccessCsvFiltered": {
"type": "string",
"value": "[variables('functionAccessFiltered')]"
},
"functionAccessArray": {
"type": "array",
"value": "[variables('functionAccessArray')]"
}
}
}
The result:
I just had the same issue. By using an array parameter with a default value instead of a variable, I got it to work.
"parameters": {
"functionAccess": {
"type": "array",
"defaultValue": [
"value1",
"value2",
"value3"
]
}
}

Function MSDeploy and Event Grid Subscription Race Condition in ARM Template

I am deploying a function using MSDeploy extensions and then deploying event grid subscription with this function as endpoint. Event grid deployment fails with message -
"details": [
{
"code": "Endpoint validation",
"message": "The attempt to validate the provided azure endpoint resource:/subscriptions/XXXXX/resourceGroups/ResourceGroupName/providers/Microsoft.Web/sites/FunctionAppName/functions/EndpointName failed."
}
]
I believe this is because event grid subscription tried to get created before the function endpoint deployed with MSDeploy is up and running.
How can i avoid this race condition?
Note: Deploying the same template again creates the event grid fine.
Template being used-
//function app
{
"apiVersion": "2018-11-01",
"type": "Microsoft.Web/sites",
"name": "[parameters('functionAppName')]",
"location": "[resourceGroup().location]",
"kind": "functionapp",
"dependsOn": [
"[variables('azureFunction_serverFarmResourceId')]"
],
"properties": {
"serverFarmId": "[variables('azureFunction_serverFarmResourceId')]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),variables('storageAccountApiVersion')).keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),variables('storageAccountApiVersion')).keys[0].value)]"//"[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(parameters('functionAppName'))]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~3"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "~10"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('microsoft.insights/components/', parameters('functionApp_applicationInsightsName')), '2015-05-01').InstrumentationKey]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
}
]
}
},
"resources": [
{
"apiVersion": "2018-11-01",
"name": "MSDeploy",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]"
],
"properties": {
"packageUri": "[parameters('functionAppDeployPackageUri')]"
},
"type": "extensions"
}
]
},
//event grid
{
"type": "Microsoft.Storage/storageAccounts/providers/eventSubscriptions",
"name": "[concat(parameters('storageAccountName'), '/Microsoft.EventGrid/', parameters('blobcreate_eventsubscription_name'))]",
"apiVersion": "2020-04-01-preview",
"dependsOn": [
"[concat('Microsoft.Web/sites/', parameters('functionAppName'), '/extensions/MSDeploy')]",
"[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
],
"properties": {
"destination": {
"endpointType": "AzureFunction",
"properties": {
"resourceId": "[concat(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '/functions/', variables('egressDataProcessorFunctionName'))]"
}
},
"filter": {
"subjectBeginsWith": "[concat('/blobServices/default/containers/', parameters('storageAccounts_mainblob_name'))]",
"subjectEndsWith": ".xml",
"includedEventTypes": [
"Microsoft.Storage.BlobCreated"
],
"advancedFilters": []
},
"retryPolicy": {
"maxDeliveryAttempts": "[parameters('eventgrid_maxDeliveryAttemps')]",
"eventTimeToLiveInMinutes": "[parameters('eventgrid_eventTimeToLiveInMinutes')]"
},
"deadLetterDestination": {
"endpointType": "StorageBlob",
"properties": {
"resourceId": "[variables('storageAccountResourceId')]",
"blobContainerName": "[parameters('storageAccounts_deadletterblob_name')]"
}
}
}
}
One way is to deploy your function app as a linked template, and then have your root template:
Deploy the function app template with the function url as an output.
Deploy an Event Grid subscription that depends on the function app deployment and references its output.
Another possibility is to spit appsettings into a childresource, and have that depend on your MSDeploy resource, then the Event Grid depend on appsettings.

I am not seeing dialogState in Alexa's event in AWS lambda logs, for a multiturn dialog?

I created an intent with slots in Alexa. This triggers an AWS lambda written in Python. I am logging the 'event'. I expect event['request']['dialogState'] to be present but it is not. Am I missing something?
Event:
{u'session': {u'application': {u'applicationId': u'amzn1.ask.skill.b2a191bb-7ee2-4fa7-aa7b-456d4bd2ee35'}, u'sessionId': u'Sessi onId.afb747ea-01ae-4094-ba10-ac49405a99df', u'user': {u'userId': u'amzn1.ask.account.BFHTSNCIVD2HA563BEPLRW5TSCESQEZXCIULPPB2ULOZBIJRCPM 5Z5NWOWH3HWNOZRTY4WT3FZFVGWWPKRSKC4ZNDSB2EYB45TYQ3RNY67CZPGF4GBMV6CL57C5MJVPIQPH25DQWGXGALDBCBRHMG5IA3Y26UHI7MHPIV3665ZU5OESS3UBADD7MDYQ BWJZFB3XHJS6IM2Y5UTQ', u'accessToken': None}, u'new': False, u'attributes': {}}, u'request': {u'locale': u'en-US', u'type': u'IntentRequ est', u'intent': {u'slots': {u'ncpu': {u'name': u'ncpu'}, u'nmem': {u'name': u'nmem'}}, u'name': u'CreateVM'}, u'requestId': u'EdwReques tId.c9de162a-d606-43a1-9257-b7367c9da5de', u'timestamp': u'2017-10-24T09:43:17Z'}, u'version': u'1.0', u'context': {u'AudioPlayer': {u'p layerActivity': u'IDLE'}, u'System': {u'device': {u'supportedInterfaces': {}}, u'application': {u'applicationId': u'amzn1.ask.skill.b2a1 91bb-7ee2-4fa7-aa7b-456d4bd2ee35'}, u'user': {u'userId': u'amzn1.ask.account.BFHTSNCIVD2HA563BEPLRW5TSCESQEZXCIULPPB2ULOZBIJRCPM5Z5NWOWH 3HWNOZRTY4WT3FZFVGWWPKRSKC4ZNDSB2EYB45TYQ3RNY67CZPGF4GBMV6CL57C5MJVPIQPH25DQWGXGALDBCBRHMG5IA3Y26UHI7MHPIV3665ZU5OESS3UBADD7MDYQBWJZFB3X HJS6IM2Y5UTQ'}}}}
You can not test you skills inside of the Amazon developer portal because these will not return a Dialogstate for your dialog. If you want to test your skill i suggest you go to echosim.io or get an echo dot to experiment with.
If you don't want to test with echosim.io or a real echo device and you have your skill code inside of AWS Lambda you can always test your code there with the test command.
Example:
{
"session": {
"new": true,
"sessionId": "SessionId.******************0ed735901",
"application": {
"applicationId": "amzn1.ask.skill.e96d9***********3ee1b958e6ca"
},
"attributes": {},
"user": {
"userId": "amzn1.ask.account.AGMQGVEZFE355BBMXYBQGFN7TRN5E5CSGUU5Y3AUNEBT3DOZ7IOQ3K7G3RGIOI7BEJVLVR4CWSARSTMAF5RNA4QW************DURTSESLYMYDVIQLWA2LF6PHG3KB3UEOLZWYBBWLRKCFFMG7JFP7TNKCS2RQ4KOGPIMOT2PGQT3S2HAOBNJSAA
}
},
"request": {
"type": "IntentRequest",
"dialogState": "IN_PROGRESS",
"requestId": "EdwRequestId.5b2a45f7-e4bb-44cd-ba9f-1cfe138d577f",
"intent": {
"name": "SearchIntent",
"slots": {
"AnswerTime": {
"name": "AnswerTime",
"value": "Nope"
},
"FirstTime": {
"name": "FirstTime",
"value": "02:00"
},
"SecondTime": {
"name": "SecondTime"
},
"Date": {
"name": "Date",
"value": "2017-10-20"
},
"Name": {
"name": "Name",
"value": "Liam De Lee"
}
}
},
"locale": "en-US",
"timestamp": "2017-10-19T13:29:17Z"
},
"context": {
"AudioPlayer": {
"playerActivity": "IDLE"
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.e96d95e0-8cbd-41d2-a280-3ee1b958e6ca"
},
"user": {
"userId": "amzn1.ask.account.AGMQGVEZFE355BBMXYBQGFN7TRN5E5CSGUU5Y3AUNEBT3DOZ7IOQ3K7G3RGIOI7BEJVLVR4CWSARSTMAF5RNA4QW************DURTSESLYMYDVIQLWA2LF6PHG3KB3UEOLZWYBBWLRKCFFMG7JFP7TNKCS2RQ4KOGPIMOT2PGQT3S2HAOBNJSAA"
},
"device": {
"supportedInterfaces": {}
}
}
},
"version": "1.0"
}
Note: Service Simulator does not currently support testing audio
player directives, dialog model, customer permissions and customer
account linking.
Amazon developer portal.

Provide request header for Microsoft.Scheduler/jobCollections/jobs

I want to know how to provide from my Azure WebApp the user/password to provide header for my webjob
{
"name": "[concat('TraitementTableAzure-', parameters('HeliosEnvironnementName'), '-js')]",
"type": "jobs",
"apiVersion": "2016-03-01",
"location": "[resourceGroup().location]",
"properties": {
"action": {
"request": {
"method": "Post",
"uri": "[concat('https://', parameters('AzureWebAppWebJobs'), '.scm.azurewebsites.net/api/triggeredwebjobs/', parameters('HeliosEnvironnementName'), '_TraitementTableAzure/run')]",
"headers": {
"authorization": "[concat('Basic ', reference('???').???)]" }
},
"type": "Http",
"retryPolicy": {
"retryType": "Fixed"
}
},
"startTime": "[parameters('SchedulesStartTime').SchedulerTraitementTableAzureStartTime]",
"recurrence": {
"frequency": "Day",
"interval": 1
},
"state": "Enabled"
},
"dependsOn": [
"[resourceId('Microsoft.Scheduler/jobCollections', variables('AzureSchedulerName'))]"
],
"tags": {
"displayName": "Cedule_TraitementTableAzure"
}
},
I found information over Azure Portal but not in ARM Template under webjob Properties. How can reference information on the blue arrow over my ARM template ?
How can reference information on the blue arrow over my ARM template ?
If we want to get the publishingPassword, then we could use ListPublishingCredentials API in the ARM template via list function, list(concat('Microsoft.Web/sites/', parameters('websisteName') ,'/config/publishingcredentials'), '2016-08-01').properties.publishingPassword
According to your template, it seems the that you want to call WebJob REST API, If it is that case, the authorization header is base64(publishusername:publishpassword).
base64(concat(list(concat('Microsoft.Web/sites/', parameters('websisteName'),'/config/publishingcredentials'), '2016-08-01').properties.publishingUserName,':',list(concat('Microsoft.Web/sites/', parameters('websisteName') ,'/config/publishingcredentials'), '2016-08-01').properties.publishingPassword))
I write a demo to test it on my side, it works correctly .
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"websisteName": {
"type": "string"
}
},
"resources": [],
"outputs": {
"base64Output": {
"type": "string",
"value": "[base64(concat(list(concat('Microsoft.Web/sites/', parameters('websisteName'),'/config/publishingcredentials'), '2016-08-01').properties.publishingUserName,':',list(concat('Microsoft.Web/sites/', parameters('websisteName') ,'/config/publishingcredentials'), '2016-08-01').properties.publishingPassword))]"
}
}
}

copyIndex() inside a listKeys()

We're trying to deploy an ARM template which deploys a Stream Analytics job with n Event Hubs outputs depending on an input parameter.
Right now we're having success with all but the listKeys() function inside the outputs property copy loop function which gets each Event Hub's primary keys:
"sharedAccessPolicyKey": "[listKeys(resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules', variables('clientEventHubNamespace'), parameters('clients')[copyIndex('outputs')].id, variables('clientEventHubClientSharedAccessName')), '2015-08-01').primaryKey]"
We get the error:
17:44:31 - Error: Code=InvalidTemplate; Message=Deployment template
validation failed: 'The template resource
'tailor-router-axgf7t3gtspue' at line '129' and column '10' is not
valid: The template function 'copyIndex' is not expected at this
location. The function can only be used in a resource with copy
specified. Please see https://aka.ms/arm-copy for usage details..
Please see https://aka.ms/arm-template-expressions for usage
details.'.
However, if we change this to be a specific index:
"sharedAccessPolicyKey": "[listKeys(resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules', variables('clientEventHubNamespace'), parameters('clients')[0].id, variables('clientEventHubClientSharedAccessName')), '2015-08-01').primaryKey]"
it works.
Is copyIndex('propertyName') inside a listKeys() a supported function?
If not, is there a workaround that would achieve the same effect?
Kind regards,
Nick
Stream Analytics job resource definition:
{
"apiVersion": "2016-03-01",
"type": "Microsoft.StreamAnalytics/StreamingJobs",
"name": "[variables('routerStreamAnalyticsName')]",
"location": "[variables('location')]",
"dependsOn": [ "clientsEventHubCopy" ],
"tags": {
"boundedContext": "[variables('boundedContextName')]"
},
"properties": {
"sku": {
"name": "[parameters('routerStreamAnalyticsSkuTier')]"
},
"outputErrorPolicy": "drop",
"eventsOutOfOrderPolicy": "adjust",
"eventsOutOfOrderMaxDelayInSeconds": 0,
"eventsLateArrivalMaxDelayInSeconds": 5,
"dataLocale": "en-US",
"compatibilityLevel": "1.0",
"inputs": [
{
"name": "input0",
"properties": {
"type": "stream",
"serialization": {
"type": "Avro"
},
"datasource": {
"type": "Microsoft.ServiceBus/EventHub",
"properties": {
"serviceBusNamespace": "[parameters('input0EventHubNamespace')]",
"sharedAccessPolicyName": "[parameters('input0EventHubSharedAccessPolicyName')]",
"sharedAccessPolicyKey": "[parameters('input0EventHubSharedAccessPolicyKey')]",
"eventHubName": "[parameters('input0EventHubName')]"
}
}
}
}
],
"transformation": {
"name": "routing",
"properties": {
"streamingUnits": "[parameters('routerStreamAnalyticsSkuTier')]",
"query": "omitted"
}
},
"copy": [
{
"name": "outputs",
"count": "[length(parameters('clients'))]",
"input": {
"name": "[parameters('clients')[copyIndex('outputs')].id]",
"properties": {
"datasource": {
"type": "Microsoft.ServiceBus/EventHub",
"properties": {
"serviceBusNamespace": "[variables('clientEventHubNamespace')]",
"sharedAccessPolicyName": "[variables('clientEventHubClientSharedAccessName')]",
"sharedAccessPolicyKey": "[listKeys(resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules', variables('clientEventHubNamespace'), parameters('clients')[copyIndex('outputs')].id, variables('clientEventHubClientSharedAccessName')), '2015-08-01').primaryKey]",
"eventHubName": "[parameters('clients')[copyIndex('outputs')].id]"
}
},
"serialization": {
"type": "Avro"
}
}
}
}
]
}
},
Thanks for reporting this and sorry for the inconvenience.
I just talked to the ARM team, we had an issue when copyindex was inside the index tags eg 'array[copyindex()]'. It should be fixed now.
Let us know how it goes.
Thanks,
JS - Azure Stream Analytics

Resources