ESP32とAWSIoTとAlexaを繋げてみた(AlexaとDynamoDB編)


AlexaとDynamoDBを繋ごう

AlexaとDynamoDBを繋ぐためには
Alexa skillからLmabda関数を呼び起こし
Lambda関数からDynamoDB上のデータを取得します

Alexaのスキルを作ろう

登録の方法などは省略しますスキル一覧>スキルの作成を選択します
名前は適当に決めましょう次にスキルのテンプレートを選択しますがカスタムとします
開発画面に入りました!

最初に呼び出し名を決めましょう。

この呼び出し名をAlexaに話しかけるとスキルを開いてくれます。

とりあえず気温を取れるようにしたいのでこんな感じのインテントを作ります
インテントとは設定したワードを聞き取ると起動するやつです。
このインテントがLambda関数の呼び出しをします。

Lambda関数を作ろう

Alexaで何かするにはAlexaスキルからLambda関数を呼び起こしLambda関数でAlexaを操作するというような感じになってます
Lambda>関数>関数の作成
と進み、設計図からalexa-skill-kit-sdk-factskillを選択します

LambdaからAlexaスキルとDynamoDBに接続するためのロールを作ります

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "dax:*",
                "lambda:*",
                "dynamodb:*",
                "logs:CreateLogGroup",
                "logs:PutLogEvents",
                "a4b:*"
            ],
            "Resource": "*"
        }
    ]
}

Alexaのエンドポイントを設定してあげよう

Lambdaにトリガーを設定します。左からAlexa Skill Kitを選択し

一度AlexaSkillコンソールに戻りエンドポイントを設定してあげます。
スキルIDをコピーしてLambdaのAlexa Skill kitトリガーに設定してあげます。

次はLambdaの右上あたりにあるARNをコピーして
デフォルトの地域に設定してあげます。エンドポイントの保存が完了したらエンドポイントの設定は完了です!

Lambda関数でDynamoDBにアクセスしよう

こんな感じのDBになっているとします

index.js
const Alexa = require('alexa-sdk');
const AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
const SKILL_NAME = 'SensAlexa';
const HELP_MESSAGE = '欲しいデータを教えてください';
const HELP_REPROMPT = '何か手伝いますか?';
const STOP_MESSAGE = 'さようなら';

const handlers = {
    'LaunchRequest': function () {
    this.emit(':ask');
    },

    'gettempreture': function () {
        var speechOutput = "";
        let self = this;
        const params = {
            TableName: "BME280", // DynamoDBのテーブル名
            ExpressionAttributeNames: {
                '#clientid': 'client_id' //lambda関数内で処理する変数に
            },
            ExpressionAttributeValues: {
                ':id': 'ESP-32-1'  //検索するID
            },
            KeyConditionExpression: '#clientid = :id', //client_id=idだったら
            ScanIndexForward: false, // 昇順か降順か(デフォルトはtrue=昇順)
            Limit: 1 // 取得するデータ件数
        };
        docClient.query(params, function(err, data){
            if(err){
                speechOutput = "気温が取得できませんでした"
            }else{
                data.Items.forEach(function(value, index){
                speechOutput = "今の気温は" + value.tempreture + "です";
                });
            }
            self.response.speak(speechOutput);
            self.emit(':responseReady');
        })
    },
    'AMAZON.HelpIntent': function () {
        const speechOutput = HELP_MESSAGE;
        const reprompt = HELP_REPROMPT;

        this.response.speak(speechOutput).listen(reprompt);
        this.emit(':responseReady');
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':responseReady');
    },
    'AMAZON.StopIntent': function () {
        this.emit(':responseReady');
    },
};


exports.handler = function (event, context) {
    const alexa = Alexa.handler(event, context);
    // To enable string internationalization (i18n) features, set a resources object.;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

最終的にこんな感じになりました。AWS.DynamoDB.DocumentClient();については調べてみてください

テストしてみよう

Alexaスキルをビルドし、テストへ移りましょう

取得できました!!!完成!!!

LambdaからHTTPゲットリクエスト投げてESP32から直接もらったほうが早かったのではという話はなしにしましょう