AlexaスキルとAWS Lambda, Slackを使って我が家の買いもの管理を便利にした話
やったこと
ライフハックです。Alexaに買うものを伝えるとSlackの買い物チャンネルに伝えたものが追加されるシステムを作りました。 仕組みとしてはシンプルで、Alexaに「〇〇を追加して」と伝えると、Alexaのスキル、AWS Lambdaの関数が呼び出されSlackのチャンネルに〇〇がポストされるというものです。
買い物管理
同居人と生活をするにあたって、買いもの、特に洗剤やシャンプーなど日用品類の買い物管理をどうしようかという話題がありました。「XXを買っておいて」「〇〇はもう買ったんだっけ?」というコミュニケーションは仕事などで疲れているときにはコストが高いですし、買い忘れが発生して喧嘩する、みたいなのも避けたい。なんとかいい感じに解決したい、という思いを二人共モヤモヤ抱えていました。
ちなみに「Alexaで全部注文しちゃえばいいじゃん」というのはなしで。そういう案もあったのですが、お互い家にいない時間が多くマンションに宅配ボックスもないためボツとなりました。あくまでどちらかが買い物をしなきゃいけないという状況に対する取り組みが今回の記事です。
この課題を解決すべく、まずはSlackに買い物チャンネルを作り必要なものはそこにポストして管理する、というルールを決めました。やることは簡単で
- 買わなきゃいけないものがあったらその名前を書いてポストする
- ポストされたものを買ったら「済」スタンプをつける
というものです。 ルールを決めたことで「誰が何をいつ買ったか」が明確になり、お互い暮らしていく中で非常にストレスのない買いもの生活が送れるようになりました。
Alexaを用いた買うもの投稿機能
上記のルールで買いものの管理は便利になったものの、別の課題が出てきました。 それは「買わなきゃいけないものは日常生活をしている中でふと現れる」ということです。食器洗い、洗濯、掃除といった家事に取り組んでいる最中に「あれ買わなきゃ」と思っても、やっている最中にスマホを取り出してSlackに投稿するのは面倒だし(そもそも家事の途中は手が空いていないことの方が多い)、一段落ついた頃には忘れてしまうことだってあります。
そう、「Slackに買うものを投稿する」の自体がそもそもハードルが高いのです。
そこで、Alexaが代わりにSlackへの投稿をしてくれる簡単なアプリケーションを作成することにしました。声で伝えるのであれば手が埋まっていてもできるし、思いついたその場で登録しやすいですよね。 今回はAWS Lambdaと簡単なAlexaスキルを作成してVoice UIでの買い物登録を実現させました。
システム構成
最初に載せた図の再掲ですが。
ユーザがスキルを呼び出し、Alexaに向かって話しかけます。その発話から必要な情報(今回は「買うもの」)が取り出され、AWS Lambdaに登録した関数が呼び出されます。関数の実態はSlack APIを叩くだけのNode JSスクリプトです。Alexaから受け取った情報をもとにSlackの特定チャンネルにボットで投稿を行います。
Alexaスキルの作成
AlexaスキルはAmazon Alexaの開発者登録を行い、Alexa Developer Consoleから簡単に作成することができます。 アプリではインテントと呼ばれる発話意図を登録することで、特定のアクションを受け付けられるようになります。インテントには発話のパターンが登録でき、各発話パターンの中に「スロット」と呼ばれる枠を用意することで、「{りんご}を追加して」「{みかん}を追加して」といった発話によって変化する単語を入れることが可能になります。
今回は「買うもの」に当たる部分を{things}
という形でスロットにしました。また、買うものを追加する時に言うであろういくつかの発話パターンを登録します。
AWS Lambdaへの関数登録
AWS Lambdaには上述したように、Alexaスキルから連携される情報を受け取りSlackに投稿する関数を登録します。デフォルトのインテントや、定義したインテントを受け取るHandlerを定義することで、Alexaから連携される発話に対する処理を記述できます。
下記に買いものの処理をする部分のコードを載せます。let things = this.event.request.intent.slots[SLOT_NAME].value;
の箇所が、実際にAlexaスキルから連携されているスロットを受け取っているところです。
※ SDKのバージョンが古いため、最新バージョンだとこの書き方では動かないかもしれません。
// Slack Webhook URL const WEBHOOK_URI = process.env.WEBHOOK_URI; // Alexaから受け取るスロット const SLOT_NAME = 'things'; const handlers = { ... // 買いものリスト追加処理 'ToBuyIntent': function () { let func = this; // thingsスロット(=買うもの)を取得 let things = this.event.request.intent.slots[SLOT_NAME].value; // Alexaの発話 const speechOutput = things + 'ですね。わかりました。'; func.response.speak(speechOutput); func.emit(':responseReady'); // Slackに投稿するためのパラメータ let options = { method: 'POST', uri: WEBHOOK_URI, body: { text: things }, json: true, headers: { 'content-type': 'application/json', } }; // Slackに投稿 requestPromise(options).then(function(body) { }).catch(function(err) { console.log(err); func.response.speak('エラーが発生しました'); func.emit(':responseReady'); }); }, ... }; exports.handler = function (event, context, callback) { const alexa = Alexa.handler(event, context, callback); alexa.APP_ID = APP_ID; alexa.registerHandlers(handlers); alexa.execute(); };
苦戦した部分
あとはAlexaスキルのエンドポイントにAWS Lambdaの関数を登録し、Alexaで呼び出す際のスキル名を設定すれば完成となります。
が、ここで一つ罠がありました。 買い物リストなんていうありふれた機能はすでにAlexaにデフォルトスキルとして実装されているのです。
最初、スキル名を「買い物リスト」としいたんですが、そうすると自作したスキルではなくデフォルトのスキルが呼び出されてしまうのです。これでは使えない。。。
スキル名は「アレクサ、<今日の星占い(スキル名)>を開いて双子座の運勢を占って」のようにAlexaへの指示の中に織り交ぜて使われます。そのため、発話にいれて違和感のあるスキル名や極端に長いスキル名などは設定したくありません。 デフォルトのスキルが呼び出されず、かつAlexaへの呼びかけとして不自然じゃないスキル名を検討した結果、以下のようになりました。
これだ!!
「Alexa、スラックを開いてゴミ袋を追加して」
きっちりとSlackに投稿されています。これならまあ及第点でしょう。やったね。
まとめ
AlexaスキルとAWS Lambdaを使って買いもの管理を便利にしてみました。 やはり音声による入力というのは手入力よりはるかにストレスがないらしく、もはやスマホでSlackを開いて買うものを投稿するという場面はほとんど見なくなりました。こういったライフハックを積み重ねて生活をどんどん便利にしていきたいですね。
資料とか
GitHub - IshinFUKUOKA/waht-i-buy: Alexa skill's application posting message to slack channel