この記事は、富士通システムズウェブテクノロジー Advent Calendarの1日目の記事です。会社として参加することを決めた僕の役目は、以降の人たちのハードルを下げることと信じて、記事を書いてます。
(お約束)本記事の掲載内容は私自身の見解であり、所属する組織を代表するものではありません。
Alexa Gadget Toolkitとは
Alexa Gadget Toolkit(AGT)は2019年9月に発表された、AmazonのスマートスピーカーであるEchoデバイスと連携づけて動作させるガジェット(周辺機器)を開発するためのキットとなります。デバイスにAlexaのスマートスピーカー機能を組み込むAlexa Voice Service(AVS)とは異なり、ガジェットはあくまでEchoデバイスの子機として動作し、デバイス連携による多様な機能提供を狙ったものとなります。
同じようなガジェットの分野ではLINEがLINE Thingsとして2018年11月に発表していますので、そこから約1年遅れで登場した、ということになります(LINE ThingsはスマートスピーカーでなくLINE Botと連携して使うガジェットですが)。当初はベータ版として米国、英国、ドイツでのみ利用可能でしたが、11月にはAlexaが販売されている全15か国(日本を含む)で利用可能となりました。
AGTでできること
AGTでは、EchoデバイスとガジェットをBluetooth接続でペアリングします。それにより、ペアリングしたEchoデバイスからの指示をガジェットに伝えたり、ガジェットからの応答をスキルが受け取ることができるようになります。(下図はAlexa公式ページから引用)

Echoデバイスとガジェットの間の通信インタフェースには、大きく2種類があります。ウェイクワードの検出やタイマーなど数種類の定義済みインターフェースと、様々な指示やデータ交換ができるカスタムインターフェースです。定義済みインターフェースはEchoデバイス・Alexa音声サービス(クラウド)とガジェットが直接連携し、スキルは介在できません。スキルを含めた連携アプリケーションを実現したいなら、カスタムインターフェース一択になります。
AGTを使ってみる
ここからはAGTを実際に使ってみることにします。以下は、下記記事を参考にしました。ありがとうございます。
Alexaのカスタムスキルがガジェットと連携! 〜Alexa Gadgets Toolkit の Custom Interfaces を試す〜
この先は、自分が試す中で詰まったポイントを押さえながら、書いています。
ガジェットの登録
開発するガジェットは事前にAmazonへの製品登録が必要です。登録はAmazon開発者ポータルから実施します。Alexaスキル(ASK)の開発者は同じアカウントでログインできます。未登録の場合はAmazon.co.jpアカウントを使って、無料で登録できます。登録時の注意点としては「Amazon.co.jpとAmazon.comで同じメールアドレスを使っている場合、パスワードを異なるものにする」こと。パスワードが同じだと、ログイン時にAmazon.comの開発者ポータルに優先的に登録されてしまい、Amazon.co.jpの開発者ポータルが使えなくなります。
ログインしたら「Alexa」→右上メニューから「Alexa Voice Service」→「製品」→「製品を作成する」の順で選択し、製品の登録画面を表示します。登録画面での設定項目は下記の通り。
- 製品名:Echo本体とのペアリング時に表示されるガジェット名となります。全角・半角文字が使えます。
- 製品ID:システム内で用いるIDで、半角英字・数字・アンダーバーのみ使えます。
- 製品タイプ:「Alexaガジェット」を選択してください。
- 以下、製品カテゴリー以降は適当なものを設定してください(サンプルのため)。
登録が終わると「Amazon ID」と「Amazonガジェットのシークレット」の2種類のコードが発行されます。これはガジェットのサンプルコード実行時に使用します。
ガジェットの準備(ハードウェア)
AGTには、Raspberry Pi(RPi)を使ってToolkitの機能を試すためのサンプルが用意されていますので、これを使います。RPiはPCとUSB接続してのセットアップも可能ですが、モニタ・キーボード・マウスを接続してセットアップするほうが簡単です。自分はRaspberry Pi Zero WH、モニタ、USBハブ、USB接続のキーボードとマウスを使いました。また、無線LAN環境が必要です。

RPiにRaspbian OSの最新版、Busterをインストールします。サンプルのページにはBusterの一つ前のバージョン、Stretchと記載がありますが、Busterで大丈夫でした。インストールにはNOOBS3.2.1を使いました。PCでzipファイルを展開、microSDカードにコピーし、RPiに取り付けて起動し、画面からRaspbianを選択することでインストールできます。
初回起動時のOS設定で無線LAN設定を行います。一旦DHCPで接続になりますが、後で固定IPアドレスへと変更します。TextEditorを使い、/etc/dhcpcd.confに下記の記述を追加することで変更できます。
interface wlan0
static ip_address=192.168.xx.xx/24 #RPiに付与する固定アドレス
static routers=192.168.xx.x #無線ルータのアドレス
static domain_name_servers=192.168.xx.x #上と同じで可
次にOSのメニューバー右側にあるBluetoothのアイコンを右クリックし、削除します。これが残っていると、Echoデバイスとのペアリングの際の障害になりますので、必ず削除してください。

ここまでの設定を反映するため、RPiを再起動します。
ガジェットの準備(ソフトウェア)
次にサンプルコードをダウンロードします。ここから先は、RPiでコンソールを開くか、同じ無線LAN上のPCからSSHでリモート接続し、/home/piフォルダに移動している前提とします。
git cloneでサンプルコードをダウンロードします。
git clone https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples.git
サンプルを使うためのセットアップを実施します。
cd Alexa-Gadgets-Raspberry-Pi-Samples
sudo bash ./setup.sh
実行時にAmazon IDとAmazonガジェットのシークレットの入力を要求されますので、先程ガジェットの登録時に発行されたコードを入力します。

セットアップには数十分かかります。また、500MBほどのダウンロードが発生しますので注意が必要です。セットアップが終了すると再起動を促されますので、再起動してください。
Echoデバイスとガジェットのペアリング
Echoデバイスとガジェット(RPi)をBluetoothでペアリングします。必要なのは下記の通り。
- Echoデバイス:ガジェット対応のEchoデバイスであること。RPiと同一の無線LANネットワーク上にあること。また、電源ONはにしておく。
- スマホのAlexaアプリ:Echoデバイスに画面がない場合、ペアリングに必要。
まず、RPiのコンソール上でサンプルコードを実行します。
cd /home/pi/Alexa-Gadgets-Raspberry-Pi-Samples/src/examples/wakeword
python3 wakeword_gadget.py
実行すると、ペアリング時にスマホに表示されるBluetoothデバイス名が「GadgetXXX」の形式で表示されます。

次に、Echoデバイスからペアリングの設定を行います。ここでは、画面のないEcho Dotを使用する場合の、スマホのAlexaアプリからの設定例を示します。
Alexaアプリを起動したら、メニュー左の「設定」→「Echo・Alexa」→使用するEcho Dot→ワイヤレス内「Bluetoothデバイス」→「新しいデバイスをペアリング」の順で選択し、ペアリング先の検索画面を表示します。ペアリング先として先程表示されたBluetoothデバイス名が表示されたら、それを選択します。「(製品名)をペアリングしました」のダイアログが表示されたら、ペアリング成功です。

ペアリングのテスト
ペアリングができたかどうかの確認を行います。ガジェット側で実行しているサンプルコードは、Echoデバイスに対するウェイクワード(「Alexa、~して」の「Alexa」)の発話を検知してガジェットに接続したLEDを点灯・消灯させるものです。ここではLEDを接続せず、RPiコンソール画面で確認する方法を示します。
Echoデバイスに「Alexa、明日の天気を教えて」と発話します。すると、RPiコンソールに下記のように表示されます。1行目は「Alexa」と発話した時、2行目は「明日の~」を発話した時に表示されます。

このサンプルコードには定義済みインターフェースの「ウェイクワードの検出」が実装されており、Echoデバイスでウェイクワードの発話・続きの発話を認識した際にペアリングされたガジェットへ通知を発行するようになっています。
ソースコードを見てみる
サンプルコード(wakeword_gadget.py)のなかを見てみると、案外シンプルでした。初期化などを除いた、主なコードはこれだけ。
class WakewordGadget(AlexaGadget):
...(省略)... def on_alexa_gadget_statelistener_stateupdate(self, directive): for state in directive.payload.states: if state.name == 'wakeword': if state.value == 'active': logger.info('Wake word active - turn on LED') LED.on() elif state.value == 'cleared': logger.info('Wake word cleared - turn off LED') LED.off()
もひとつ、同じフォルダにあるiniファイル(wakeword_gadget.ini)も見てみます。
[GadgetSettings] amazonId = YOUR_GADGET_AMAZON_ID alexaGadgetSecret = YOUR_GADGET_SECRET [GadgetCapabilities] Alexa.Gadget.StateListener = 1.0 - wakeword
定義済みインタフェースのひとつ、Alexa.Gadget.StateListenerを使うためには、iniファイル内に使用するインタフェースと種類(本例ではウェイクワード発話の通知)を宣言し、プログラム本体でAlexaGadgetクラスを継承し、宣言したインタフェースに対応したコールバック関数を定義しておけば良いようです。なんてシンプルなのかしら。
本記事では定義済みインタフェースのサンプルだけを試しましたが、時間があればカスタムインターフェースのサンプルも試そうと思います。ちょっと見た感じ、Alexaスキルの日本語対応をしないとダメそうだけど。
ピンバック: Alexa Gadget Toolkitを試してみた件(その2) – ぼっちの王国