これは、KIT Developer Advent Calendar 2017 13日目の記事です。
これに参加するのもこれが最後です。少し寂しいですね。
みなさん。こんにちは。306_sanです。最近流行りのスマートスピーカーで開発してみました。
自分はAmazon Echo dotを購入しました。余談ですがスマートスピーカーの強みって高性能なマイクでの音声認識だと思うのですが、Amazon Echoシリーズが全シリーズ7つのマイクアレイを搭載されており、廉価版であるdotでも高性能なマイクを使った音声認識が可能です(Google Homeと同等だと思ってます)。Google Home miniはマイクが一つしかないので検討してる方は一つの指標にしてもいいかもしれません。
さて、Google HomeではIFTTT→Slack→Rubyで受け取りでいろいろいじれます。
ex. https://youtu.be/8yT5PeZuWJ4
(※投稿者≠私)
しかし、これをAlexaでやろうとした時点では、どうもAlexaのスキルは各国で使えるかどうかの制限がかけられており、IFTTTやNode-Red経由(最近対応しました)では英語しか対応していないため、日本語でやるには自力でJSONを受け取って処理しないといけません。
幸いAlexaには公式開発チュートリアルがありますが、このチュートリアルはAWSがないとできないものとなっています。AWSはちょっと大学では使えないので、自力で頑張ってみたのが今回の記事です。チュートリアルを見ずに開発したので詳しいことはよくわかってないままです。コメントどしどしお待ちしております。
参考にした記事:https://www.slideshare.net/tanakataro4/rubyalexa
とりあえず開発に必要な物
- HTTPS環境とドメイン
- オレオレ証明書は開発用途ならいいみたいですが、本番はダメみたいです。
- 自分はサーバーを持っていないのでここで詰みました。
- 今回はngrokを使って無理やり通信してます。
- 導入は省略します。
- Ruby
- 今回はRuby2.3.4を使いました
- 開発用語の知識
- インテント、カスタムスロットなどスキル開発用語が出てきますがここでは詳しく説明しません。
それでは開発していきます。
目標として↑と同じ機能を持つスキルを開発します。
Alexa周り
まず、Amazonの開発者登録をします。
Alexa Skill Kitを選択します。 新しいスキルを追加するを選択します。 ここはお好みでJSONでインテントを記述します。インテントとはメソッドのようなものです。slotsというのはあとで説明するカスタムスロットです。
ここでカスタムスロットを作成します。ざっくりいうと引数のようなものです。今回はコーヒーの量を選択したいので量をカスタムスロットで作成して追加します。 発話とインテントをここで紐付けます。すべてのパターンを洗い出して書いておくといいかと思います。 保存して次へ進みます。 サービスエンドポイントをHTTPSにして、適当なドメインをここで書いておきます。(ngrokは立ち上がるたびにドメインが変わるのであとで編集します。) 真ん中を選択して、次に進みます。 ここまで来たらとりあえずAlexa周りの設定は完了です。 しかし自分の場合は、この状態でテストできなかったので、次の2つを適当に埋めてSkill Beta testingを有効化させて自分宛てに招待を送って、テストしています。Ruby周り
さて、次はバックエンドを書きます。がんばルビィ!(※筆者はラブライブ!(サンシャイン!!も)が大好きです)
gemとして素敵なSinatraベースの素敵なライブラリ「ralyxa」があるので、これを使います。
source "https://rubygems.org"
gem 'ralyxa'
gem 'sinatra'
んで、bundle installでよしなにします。
フォルダー階層はこんな感じにします
├── Gemfile
├── Gemfile.lock
├── intents
│ └── test.rb
├── server.rb
└── vendor
└── path
注意してほしいがintentsフォルダーで、この中に対応するインテントを書きます。
ファイル名は別に一致してなくても良いみたいですが、本番時のことを考えると同名にした方がいいかなと思います。
ここではtest.rbでまとめて受け取ります。
require 'bundler'
Bundler.require
post '/' do
Ralyxa::Skill.handle(request)
end
# coding: utf-8
intent "LaunchRequest" do
ask("こんばんは。コーヒーはいかがですか?")
end
intent "drip_coffee" do
p request.slot_value("size")
if request.slot_value("size").nil?
tell("わかりました。コーヒを淹れますね。")
else
tell("わかりました。コーヒーを#{request.slot_value("size")}に淹れますね。")
end
end
intent "SessionEndedRequest" do
respond("Hello World!")
end
こんな感じでかきかきします。askとtellはユーザーの応答を待つかどうかの違いです。書いてないインテントもありますが、これは動かすために必要なインテント(おまじない)になります。ドキュメントを参照してください。
bundle exec ruby server.rb -p 8080 -o 0.0.0.0
とりあえず、127.0.0.1:8080にアクセスしてサーバーがた立ち上がっている(おそらくエラー画面だけど)のをを確認します。
次に別のターミナルを開いてngrokを立ち上げます。ngorkはポート開放などができなくても中継サーバーがいい感じに外部に公開してくれるサービスです。その為セキュリティのリスクがありますので開発用途に使いましょう。
$ngrok http 127.0.0.1:8080
すると、
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Account 306san (Plan: Free)
Version 2.2.8
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://****.ngrok.io -> 127.0.0.1:8080
Forwarding https://****.ngrok.io -> 127.0.0.1:8080
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
となるのでこれでもう外部に公開されている状態になりました。httpsのURLを先程の開発者ポータルでも書き換えます。
書き換えて保存します。試しにテストページに飛んで試してみましょう。
良さそうです。あとは、招待メールを送ってスキルを有効化してechoで喋らせてみましょう。 Echoから呼び出す場合は「アレクサ、ほげほげを開いて」と発話すれば大丈夫です。まとめ
ralyxaを使えば、Rubyでスキル開発ができる。
ngrokを使えば、ポート開放しなくとも無理やり外部に公開できる。
サーバーなくとも無料でスキル開発ができる!!
最高!
rm mini3をポチったので次はスマートホーム化を目指します