ちょっと話題の記事

Alexa に話しかけると名前と時刻を S3 に記録するカスタムスキルを作ってみた

2018.01.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

弊社では、情報セキュリティマネジメントシステム(ISMS)の一環としてオフィスから帰宅する際に最終退出者および最終退出時刻を紙の書類に記入しております。 紙の書類で運用していると、以下のような問題が発生することがあったため電子化・自動化したいという要望が大阪オフィス内で挙がりました。

  • 月が変わると、書類を印刷しないといけない
  • 書類を物理的に保管しないといけない
  • 記入忘れなど人為的なミスによる記入漏れ

上記の作業を、電子化・自動化するにあたり Alexa カスタムスキルを開発すれば便利なんじゃないか?という意見が上がったため Node.js 初学者である筆者が大阪オフィスメンバーと力を合わせてカスタムスキルを開発してみました。

作ってみた

Alexa カスタムスキルの作成自体が(ほぼ)初めてであるため、開発を開始するにあたって以下のドキュメントを参照しました。

開発トレーニングの「第1回 初めてのスキル開発」および「第2回 対話モデルと Alexa SDK」を試すことで、ふわっと作り方を理解することが出来ました。また、サンプルコードをベースに機能を追加する形でカスタムスキルを作成することが出来ました。 カスタムスキル開発当初のハマりポイントなどについては、オフィスメンバーである中安の記事が参考になると思います。

実際に書いたコードを、以下にご紹介します。

index.js

'use strict';
var Alexa = require('alexa-sdk');
var AWS = require('aws-sdk');
var moment = require('moment-timezone');
moment.tz.setDefault("Asia/Tokyo");

var APP_ID = undefined;
var HELP_MESSAGE = "終わりたい時は「おしまい」と言ってください。どうしますか?";
var HELP_REPROMPT = "どうしますか?";
var STOP_MESSAGE = "さようなら";

var s3 = new AWS.S3();
var dstBucket = process.env.S3_BUCKET_NAME;

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.APP_ID = process.env.ALEXA_APPLICATION_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
    'LaunchRequest': function () {
        this.emit('GetNewFactIntent');
    },
    'GetNewFactIntent': function () {
        if (this.event.request.dialogState !== 'COMPLETED'){
            this.emit(':delegate');
        } else {
            this.emit('EmployeeIntent');
        }
    },
    'AMAZON.HelpIntent': function () {
        var speechOutput = HELP_MESSAGE;
        var reprompt = HELP_REPROMPT;
        this.emit(':ask', speechOutput, reprompt);
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', STOP_MESSAGE);
    },
    'AMAZON.StopIntent': function () {
        this.emit(':tell', STOP_MESSAGE);
    },
    'EmployeeIntent': function () {
        var employee = this.event.request.intent.slots.Employee.value;
        var message = employee + 'さん、お疲れ様でした';
        var now = moment();
        var dstKey = now.format("YYYY/MM/DD/HH-mm-ss");
        var data = {
          date: now.format(),
          employee
        };
        var self = this;

        var params = {
          Bucket: dstBucket,
          Key: dstKey,
          Body: JSON.stringify(data),
          ContentType: 'application/json'
        };

        s3.putObject(params, function(err) {
          if(err){
            console.log(err);
          }else{
            console.log(params);
            self.emit(':tell', message);
          }
        });
    }
};

次に、Amazon 開発者コンソールのスキル情報と SKILL BUILDER をご紹介します。

こちらは、今回作成したカスタムスキル(クラスメソッド大阪)です。呼び出し名として、「オフィス閉店」と設定しています。

こちらは、コード上に登場していませんが ListOfEmployee という社員の名前をリストとして表しています。また、ひらがなで記載された白抜きのタグは synonym(同義語) と呼ばれています。synonym とは、カスタムスロットタイプ値の同義語とドキュメントにて説明されていることから、社員のあだ名(Alias)みたいなものと理解しています。

詳細については、公式ドキュメントを参照してください。

最後に、GetNewFactIntent の設定をご紹介します。こちらの設定は、先日大阪オフィスに来られていたSINさんのアドバイスに基づいて設定を行ったため、しっかり理解出来ていませんが GetNewFactIntent を呼び出した際に {Employee} に社員の名前が入力される必要があるという設定だと理解しています。もし、社員の名前がうまく聞き取れなかった場合 Prompts に設定された「お名前を教えてください」という言葉を Alexa がユーザーに投げかけ {Employee} に社員の名前が入力されるまで GetNewFactIntent が実行されるようです。

実際に作成したカスタムスキルの動作を、動画で御覧ください。

今回作成したカスタムスキルは、一般に公開するスキルではないため呼び出し名「オフィス閉店」の後に続く言葉として「を開いて」ではなく、「で」が利用できるようです。 そのため、「Alexa、オフィス閉店で◯◯帰ります。」と Amazon Echo Dot に話しかければ Alexa が聞き取ってくれた名前およびそのスキルが実行された時刻情報が json のデータとして S3 に保存されます。

実際に S3 へ保存されたデータは、以下のとおりです。

{"date":"2018-01-30T19:46:21+09:00","employee":"下田"}

後は、Amazon Echo Dot をオフィス出入り口付近に設置するだけですね。

さいごに

私は、自宅から大阪オフィスまで遠いため毎日出社するというわけではないのですが稀に出社して最終退出者になった時に、紙に記入する作業が非常に面倒だなと感じました。 そのため、可能であれば電子化(出来れば自動化)したいなと思い、素人ながらカスタムスキルを作成した次第です。サンプルコードをベースに作成したため、実際に作成したコード量はほとんどありませんが 作成したプログラムが実機で動いた際の感動はプライスレスでした。実運用に向けて、改善点は諸々ありますが大阪オフィスのメンバーで楽しく共同開発を進めたいなと考えています。

ではでは