Lorenzo Gonzalez Gascón
I'm teacher in computer Science in a high school, the high school is named "CIPFP Mislata" in Spain-Valencia-Mislata .
Lorenzo González
14/05/2024
Motivación
Alexa Skill
AWS Lambda
Creando un Alexa Skill
El problema
AWS API Gateway
AWS DynamoDB
AWS SQS
Juntando todo
Hay diversas formas pero ninguna es barata, segura, privada y versátil
+
Tipos de Skills
Skill: Aplicación que añade funciones personalizadas a Alexa
Alexa, enciende la bombilla
{
"directive": {
"header": {
"messageId": "74a44945-4b40-47dd-aaff-5050387ffcc9",
"namespace": "Alexa.PowerController",
"name": "TurnOn",
"payloadVersion": "3",
"correlationToken": "SUdTVEs6AAE6AAlNTM4LTdhYzQtNGE4Ni1iNGM0LWFhOGVjODJkMTNmYyJ9"
},
"endpoint": {
"scope": {
"type": "BearerToken",
"token": "Atz4vhHtITm3IF93x-1A_tGqtp2zXcd0677DIGS-yvq5jnokEYHFbdhPPnTExoFKTTQ"
},
"endpointId": "DEVICE-1",
"cookie": {}
},
"payload": {}
}
}
{
"event": {
"header": {
"namespace": "Alexa",
"name": "Response",
"messageId": "b0611318-483c-4625-8538-47401f04a2f0",
"correlationToken": "SUdTVEs6AAE6AAlNTM4LTdhYzQtNGE4Ni1iNGM0LWFhOGVjODJkMTNmYyJ9",
"payloadVersion": "3"
},
"endpoint": {
"scope": {
"type": "BearerToken",
"token": "Atz4vhHtITm3IF93x-1A_tGqtp2zXcd0677DIGS-yvq5jnokEYHFbdhPPnTExoFKTTQ"
},
"endpointId": "DEVICE-1"
},
"payload": {}
},
"context": {
"properties": [
{
"namespace": "Alexa.PowerController",
"name": "powerState",
"value": "ON",
"timeOfSample": "2024-05-06T09:12:47.019Z",
"uncertaintyInMilliseconds": 500
}
]
}
}
{
"event": {
"header": {
"namespace": "Alexa",
"name": "ErrorResponse",
"messageId": "b0611318-483c-4625-8538-47401f04a2f0",
"correlationToken": "SUdTVEs6AAE6AAlNTM4LTdhYzQtNGE4Ni1iNGM0LWFhOGVjODJkMTNmYyJ9",
"payloadVersion": "3"
},
"endpoint":{
"endpointId": "DEVICE-1"
},
"payload": {
"type": "FIRMWARE_OUT_OF_DATE",
"message": "El firmware del dispositivo es la versión 3.4 pero debe ser como mínimo la 4.1"
}
}
}
exports.handler = function (request, context) {
if (request.directive.header.namespace === 'Alexa.PowerController') {
const endpointId=request.directive.endpoint.endpointId;
if (request.directive.header.name === 'TurnOn') {
//Realizar la acción
return {} //Retornar un OK
}
if (request.directive.header.name === 'TurnOff') {
//Realizar la acción
return {} //Retornar un OK
}
}
}
Dispositivo inteligente a controlar
Directiva: Lo que queremos que haga el dispositivo
Uttertance: La frase que le decimos a Alexa
Interface: Agrupa varias directivas
Display Category: El tipo de dispositivo
Alexa.PowerController
TurnOn: Alexa, enciende la luz del comedor.
TurnOff: Alexa, apaga la luz del comedor.
Alexa.ColorController
SetColor: Alexa, pon la luz del comedor en azul.
Alexa.BrightnessController
SetBrightness: Alexa, establece el brillo del comedor al 50%
AdjustBrightness: Alexa, baja el brillo del comedor un 5%
Alexa.Discovery
Discover
Al activar el skills para saber que dispositivos hay
Alexa.Authorization
AcceptGrant
Autenticarse en el Skill
exports.handler = function (request, context) {
const response=hacerAlgo(request)
return response;
}
y poner los datos del "Security Profile" y viceversa
export const handler = async (request,context) => {
const wsRequest = JSON.parse(event.body);
connectionId=request.requestContext.connectionId
switch (request.requestContext.routeKey) {
case "$connect":
break;
case "$disconnect":
break;
case "$default":
break;
default:
break;
}
return {
statusCode: 200,
body: JSON.stringify("success")
};
}
connectionId:
Permite enviar y recibir datos del cliente de WebSockets
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
DynamoDBDocumentClient,PutCommand,UpdateCommand,DeleteCommand,
} from "@aws-sdk/lib-dynamodb";
const client = new DynamoDBClient({});
const dynamo = DynamoDBDocumentClient.from(client);
const tableName = "Conexiones";
let endpointId="DEVICE-1";
let connectionId="XPiAWf-9Dwe5oECHSw=";
//Insertar
await dynamo.send(new PutCommand({
TableName: tableName,
Item: {
endpointId:endpointId,
connectionId:connectionId
}
}));
//Leer
const dynamoDbResponse=await dynamo.send(new GetCommand({
TableName: tableName,
Key: {
endpointId: endpointId
}
}));
connectionId = dynamoDbResponse.Item.connectionId;
Al crear y cerrar la conexión, se guarda el connectionId en DynamoDB
Cuando llega una petición de Alexa , el Skill obtiene el connectionId de DynamoDB para poder enviar la petición por Websockets al dispositivo inteligente
import {
ApiGatewayManagementApiClient,
PostToConnectionCommand,
} from "@aws-sdk/client-apigatewaymanagementapi";
const url = "https://vkkogyu5555.execute-api.eu-west-1.amazonaws.com/production";
const apiClient = new ApiGatewayManagementApiClient({
endpoint: url,
});
async function sendToWebSocket(connectionId, data) {
return apiClient.send(new PostToConnectionCommand({
ConnectionId: connectionId,
Data: JSON.stringify(data, null, 2)
}));
}
const sqsClient = new SQSClient({});
const sqsQueueUrl = "https://sqs.eu-west-1.amazonaws.com/5555552080/AlexsaResponse.fifo";
//Enviar un mensaje
await sqsClient.send(new SendMessageCommand({
QueueUrl: sqsQueueUrl;,
MessageBody: {
"message":"Hola mundo"
},
MessageGroupId:"Alexa"
}));
//Recibir un mensaje
let sqsResponse = await sqsClient.send(new ReceiveMessageCommand({
QueueUrl: sqsQueueUrl,
MaxNumberOfMessages: 1,
WaitTimeSeconds:2
}));
La cola se usa para enviar la respuesta del dispositivo que está en la Lambda de WebSocket a la Lambda del Skill
Cuando el dispositivo se conecta por WebSocket al API Gateway , se guarda conexión en DynamoDB
El Skill de Alexa usa el identificador de la conexión para enviar el mensaje al dispositivo a través de API Gateway
Se una una cola para enviar la respuesta del dispositivo al Skill de Alexa
Es el tiempo que se tarda
desde que se da la orden a Alexa
hasta que se responde
¡Es el mayor problema
en un Skill!
Tiempo de
node_modules
En vez de usar el pequeño IDE de la función lambda , podemos programar en local y subir el código de AWS
Ventajas
aws lambda update-function-code --function-name AlexaSkill --zip-file fileb://../dist/lambda.zip
Subir el código a AWS
https://slides.com/logongas/alexa-skill-con-funciones-lambda
l.gonzalezgascon@edu.gva.es
By Lorenzo Gonzalez Gascón
I'm teacher in computer Science in a high school, the high school is named "CIPFP Mislata" in Spain-Valencia-Mislata .