先日とあるプロジェクトでGASを使って予約フォームを作ったのですが、発生した不具合を解決できずになんとかごまかして乗り切りました。
「今度はGASを使わずにNode.jsでGmail/Googleスプレッドシートを操作する方法を試してみようかな、記事のネタにもなるし」と思っていたらのびすけさんにやられてしまい、ネタに困る事態に……。
そんな時echo dotがやっと届いたのでAlexaといちゃいちゃした様子を記録したいと思います。
なおAWSにあまり慣れてなく、Lambdaも初めてだったのでかなり細かめにキャプチャ取りながらまとめてみました。
動機
- 妻帯者エンジニア共通の課題は新しく手に入れたガジェットといちゃいちゃしていると背後に危険な視線を感じること
- 直談判は効果が薄いことが多い
- 第三者の仲裁(「旦那さんは頑張っているんですよ」的な)が効果的なことが多い
ということから第三者(Alexa)にかばってもらうことを考えました。天才的。
必要なもの
- echoシリーズなどAlexaがうごくもの
- Amazon Developerアカウント
- Amazon Web Servicesアカウント
- 嫁
3行まとめ
思いのほか長くなったので
- 公式ドキュメントを良く読もう、せめてこれは最初に
- あまりNode.jsっぽくない話になってしまいました
- Alexaで嫁は攻略できない
手順
大まかな流れとして
- AWS Lambdaにバックエンドを実装する
- Amazon Skills Kit(Skill開発ダッシュボード的なもの)でスキル登録とバックエンドへの紐付けなどを設定
- 実機テスト
という流れになります。
バックエンドの作成
バックエンドにはLambdaを使います。
関数の作成と設定

まずは 関数の作成 をクリック。

名前とロールを設定します。
Lambdaのロールについては適当にLamdba実行用のロールを作成しました。「カスタムロールの作成」を選択すると新しくロールを作成することが出来ます。

関数の作成 をクリックして進むと、トリガー設定の画面に移ります。何をトリガーにして処理を呼び出すのかを設定するようです。
今回はAlexaから呼び出したいので、Alexa Skills Kitを選択してください。

トリガーの設定画面が出てきますが、特に設定項目もないので追加をクリック。
クリックすると画面右上部の保存がオレンジ色になるのでクリックして設定を保存してください。

続けて関数本体の設定をするため中央上部の作成した関数名(ここではMyAppeaseSkill
)を選択してください。
コードエントリタイプは**.ZIPファイルをアップロード**を選択してください。
関数本体の実装
ここまで来たらローカルで関数本体の実装に移ります。
Node.jsはnodebrewなりnvmなりでv6.10を用意してください。
まずは作業場所を確保。
$ mkdir my-appease-skill
$ cd my-appease-skill
$ git init
$ npm init
Alexa SDKを使うので
$ npm install --save alexa-sdk
全体像はこんな感じ。
'use strict';
const Alexa = require('alexa-sdk');
// APP_ID : optionalらしくundefinedでも問題ないっぽい
const APP_ID = undefined;
//================
// alexaへのハンドラ登録
// ここは定型文で良さそう
//================
exports.handler = (event, context, callback) => {
const alexa = Alexa.handler(event, context);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
//================
// ハンドラ作成
// 入力したボイスメッセージに対応する実処理をここに実装する
//
// アロー関数使っていないのは呼び出し元で定義されるemit()関数を呼んでいるため
//================
const handlers = {
'LaunchRequest': function() {
// スキル呼び出し時の処理を実装する
// 「(呼び出し名)を開いて」で呼ばれる
// 別のインテントを呼び出したいときは
// this.emit('AppeaseIntent');
// のようにすると呼び出せます
const speechOutput = 'どうかしましたか?';
this.emit(':ask', speechOutput);
},
'AppeaseIntent': function () {
// ここにインテントごとの処理を実装する
const speechOutput = '旦那様は素晴らしい方です。こんな素晴らしい旦那様をお持ちになって奥様は幸せですね。';
this.emit(':tell', speechOutput);
},
//以下については基本機能なのでメッセージ内容を変える程度のほぼ定型文で良さそう
'AMAZON.HelpIntent': function () {
const speechOutput = '私に頼りたい時は「なだめて」と、終わりたい時は「ありがとう」と言ってください。どうしますか?';
const reprompt = 'どうしますか?';
this.emit(':ask', speechOutput, reprompt);
},
'AMAZON.CancelIntent': function () {
this.emit(':tell', 'さようなら、夫婦仲良く');
},
'AMAZON.StopIntent': function () {
this.emit(':tell', 'さようなら、夫婦仲良く');
}
};
ポイントはコメントに記載しましたが、結構カンタンに実装できるみたいです。
this.emit()
しているところで、第1引数に:ask
ハンドラを指定するとAlexaの応答後待ち受け状態に、:tell
ハンドラを指定すると応答後スキルを終了します。
詳細はこのあたりに書いてあるようですが、まだ試せていません。
:tellwithcard
でAlexaアプリの履歴にも表示できる様子(タイトルと通知本文の引数を2つ追加するみたい)。他にもバリエーションがある様子です。クラスメソッド様の記事でまとめられていました。
このソースコードindex.js
とパッケージディレクトリnode_modules
をLambdaに登録するためにZIPにまとめます。
実装を登録
再度Lambdaの設定画面に戻ります。

作成したZIPファイルをアップロードして、保存します。
保存したら動作確認のために隣のテストをクリックします。

テスト作成画面が出てくるので、イベントテンプレートにAlexa Start Session
を選択し、適当な名前で作成してください。

テストをクリックするとテストが実行されます。画面のような緑色の結果が出ればOKです。
Skillと紐付けるために右上のARNの値をコピーしておいてください。
スキルの作成

Amazon開発者コンソールからALEXAのメニューのAlexa Skills Kitを始めます。

新しいスキルを追加するをクリック。

- 言語は日本語
- スキル名は適当に
- 呼び出し名はスキルを起動するときに使う言葉
を設定して、保存をクリック。

保存をクリックすると、次へがクリックできるようになります。

対話モデルの設定では最初にこのスキルにどのような機能があるかを登録します。この機能1つ1つをインテントと呼びます。
インテントにはカスタムインテントと基本的な機能を用意した一般的標準インテントがあります。
とりあえず今回は以下の内容で設定します。
{"intents": [
{"intent": "AppeaseIntent"},
{"intent": "AMAZON.HelpIntent"},
{"intent": "AMAZON.StopIntent"},
{"intent": "AMAZON.CancelIntent"}
]}

次にサンプル発話の登録をします。ここでは呼び出し名に続けて呼びかける言葉(アクションと呼ばれれる)の登録をします。
出来る限り多くのバリエーションを登録することで融通の聞くコマンド入力ができるようになるようです。
形式としては起動するインテント + 半角空白 + アクション
の形式になります。
ここでは以下のように登録します。
AppeaseIntent なだめて
AppeaseIntent 嫁をなだめて
AppeaseIntent 助けて
AppeaseIntent 嫁に言ってやって
これで「アレクサ、大変だ助けて」みたいに呼べばかばってくれるようになりそうです。
入力したら、保存 → 次へをクリックします。

対話モデルの更新を行うと、しばらくモデルの構築処理が走ります。モデルの構築には数分かかるのでそのまま設定を進めていきます。

設定ではLambdaで作成した関数との紐付けを行います。コピーしたARNの値(arn:〜で始まる値)を設定してください。
入力したら保存 → 次へをクリックします。

ここまで来るとテストが行なえます。
発話入力欄に呼びかけるメッセージを入力して動作確認してみてください。
が、しかし実機で動作させる場合とは挙動が異なります。
サービスシュミレータでのテストはかなり楽観的だと思ってください。ここで期待するレスポンスが返ってきても実機での保証にはなりません。
ひとまず先に進みます。



公開情報を登録します。ここは適当な値で入力しておけば良いと思います。
公開する国と地域は日本語しか設定しないのであればJapan
に限定しておいたほうが良いかもしれないです。
スキルの説明もそれっぽく入力します。
サンプルフレーズには実際にどう呼びかければ使えるかを入力します。
そしてアイコンの登録も必須なので適当に108x108、512x512のアイコン画像を用意しておきましょう。

プライバシーとコンプライアンスの設定はそれぞれ適切に設定しておきましょう。
ただし、13歳未満の子供を対象にしたスキルはこのあと出て来るSkills Beta Testing機能が利用できないので注意が必要です。

ここまでの
- スキル情報
- 対話モデル
- 設定
- テスト
- 公開情報
- プライバシーとコンプライアンス
の全設定が完了するとSkills Beta Testing機能が使えるようになります。
これはスキルを一般公開せずにAlexa対応端末にスキルを適用する機能です。

テスターのメールアドレスを入力してテスターを追加をクリックします。

テスターが追加されるのでテストを開始をクリックします。

このような画面になればテストの準備はOKです。

このようなメールが指定したメールアドレスに送信されているので、日本の利用者であれば下のリンク先に遷移します。

Alexaの設定画面にいき、スキルをテストするかどうかの確認ダイアログが出ますので、もちろんスキルテストをクリック。

有効にするをクリックすればecho実機でテストが出来るようになります!
動かない!!
がしかし「アレクサ、大変だ助けて!」と呼びかけても「すみません、私にはわかりません」
アレクサに見捨てられた!
なんでだ? と思って調べたら公式サイトに「ユーザーによるカスタムスキルの呼び出し」というドキュメントを見つけました。
これによると「呼び出し名」と「アクション」は特定のルールに則っていないと有効ではないようです。
「(呼び出し名)を起動して(アクション)」というルールがあったので、試しに「アレクサ、大変だを起動して助けて」と呼びかけたら無事かばってくれました。
ぐぬぬ……思っていたのと違う。
まとめ
- スキルの作成自体は思っていたよりもカンタン
- 今回作った単発型のスキルだと特に
- 「ユーザーによるカスタムスキルの呼び出し」の内容を念頭に置かないと自然な起動呼びかけに設計できないので読み込み必須
他にもいろいろやれることがたくさんあるのでもっと触っていきたいですね。
カラーコードかるたの読み上げスキルとか作りたい。
で
嫁に向かってこれを使ったところ、
な感じでした。