Alaxaには、Alexa Gadgets Toolkit という、Echoデバイス(スマートスピーカ)と連携できるAlaxa Gadgetを作れるSDKがあります。
Alexa Gadgets Toolkit
https://developer.amazon.com/ja-JP/docs/alexa/alexa-gadgets-toolkit/understand-alexa-gadgets-toolkit.html
Webでは、ラズパイを使った例が複数あったのですが、BLEのプロトコルも提示されているので、ESP32で実現しようと思います。
Alexa Gadgetsデバイスになれば、いろんなことができるのですが、まずは単純なところから。
今回は、「アレクサ、今何時?」といつもの問いかけをしている間、勝手にLEDが点灯するようなAlexa Gadgetsを作ってみたいと思います。
本来であれば、AlexaのスキルからAlexa Gadgetsデバイスに指示を出したり、Alexa Gadgetsからスキルにイベントを伝達できたりするのですが、それは次回で。
ESP32として、M5StickCを使いました。
開発環境は、PlatfomIOです。おそらくArduinoIDEでも大丈夫だと思います。
Alexa Gadgetsは、一般には以下のような流れです。
今回はこのうち以下の流れだけです。(これ以外は、次回の投稿にあります。)
Alexa Gadgets Toolkitに定義済みの、wakeword(アレクサ、という呼びかけ)をひっかけて、LED点灯するところまでです。
いつもの通り、Arduinoのコードは以下のGitHubに登録しておきました。
poruruba/AlexaGadget
https://github.com/poruruba/AlexaGadget
※ソースコードの解説やカスタムスキル対応は次回の記事で。以下、続編
ESP32をAlexa Gadgets Toolkitデバイスにしよう:ソースコード解説
ESP32をAlexa Gadgets Toolkitデバイスにしよう:カスタムスキル→Alexa Gadgetデバイスへの通知
ESP32をAlexa Gadgets Toolkitデバイスにしよう: Alexa Gadgetデバイス→カスタムスキルへの通知
#Alexa Gadgetsデバイスの登録
まず最初に、Alexa Gadgetsデバイスの情報を登録して、IDを払い出します。
登録は、Alexa音声サービス開発者コンソールから行います。
Alexa音声サービス開発者コンソール
https://developer.amazon.com/alexa/console/avs/home
製品 をクリックしたのち、「新しい商品を追加」をクリックします。
製品名等を登録します。何でも良いですが、とりあえず適当に以下で入力してみましょう。
・製品名:M5StickC
・製品ID:M5StickC
・製品タイプ:Alexaガジェット
・商品カテゴリ:コミュニケーションまたは通知の端末
・製品概要:テスト用
・この製品を商品として配信する予定ですか?:いいえ
登録が完了すると、「Amazon ID」と「Alexaガジェットのシークレット」が払い出されます。
ちょっと、フライングですが、以下にあるPythonコードを実行しておきます。
import hashlib
def generate_token(device_id, device_token):
hash_object = ( hashlib.sha256(bytes(device_id, 'utf-8') + bytes(device_token, 'utf-8')) )
hex_dig = hash_object.hexdigest()
return bytes(hex_dig, 'utf-8')
token = generate_token("【Amazon ID】", "【Alexaガジェットのシークレット】")
print(token)
【Amazon ID】と【Alexaガジェットのシークレット】のところを置き換えてください。
〉python maketoken.py
b’XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX’
ここで生成されたのがデバイストークンで、あとで使います。
これで、準備OKです。
#プロトコルバッファのコンパイル
EchoデバイスとはBLEで通信するのですが、通信プロトコルは、proto3と呼ばれるProtocolBufferという形式でバイナリ化されて送信されてきます。
Echoデバイスと通信するパラメータは、このproto3の形式で定義されており、その定義ファイルをダウンロードします。
Alexa Gadgets Embedded Sample Code
https://github.com/alexa/Alexa-Gadgets-Embedded-Sample-Code
proto3の形式で送られてくるバイナリをデコードしたり、バイナリにエンコードしたりするエンコーダを作成します。
以下の手順に従います。
まずnanopbダウンロードします。
https://jpa.kapsi.fi/nanopb/download/
ここで注意が必要です。必ず、v0.3系を選んでください。v0.4系では動きません。私はこれではまりました。。。本日時点では、v0.3.9.6が最後でした。
nanopb-0.3.9.6-windows-x86.zip をダウンロードしておきます。
また生成するエンコーダはWindowsではなくESP32で動かすので、nanopb-0.3.9.6.tar.gz もダウンロードしておきます。
展開後、以下のフォルダに移動します。
C:\XXXX\Alexa-Gadgets-Embedded-Sample-Code-master\ConnectionHelpers\BLE\Handshake
compile_nanos.batを開き、以下の部分PROTO_COMPILE_PATHをnanopbのWindows版の実行ファイルのある場所に変更します。
set PROTO_COMPILE_PATH=C:\XXXX\nanopb-0.3.9.6-windows-x86\nanopb-0.3.9.6-windows-x86\generator-bin\
そして、そのバッチファイルがあるフォルダで、実行します。
そうすると、*.pb.c
と*.pb.h
のファイルが出来上がっているはずです。
次に、こっちのフォルダに移動します。
C:\XXXX\Alexa-Gadgets-Embedded-Sample-Code-master\AlexaGadgetsProtobuf\examples
同様に、compile_nanos.bat の中のPROTO_COMPILE_PATHを修正します。
バッチファイルを実行する前に、するべきことがあります。
以下の4つのファイルの中で、namespaceという変数を定義しているところがあります。
・directiveHeader.options/.proto
・eventHeader.options/.proto
この部分をnamespaccに変更します。c言語としてコンパイルする分には問題ないのですが、C++としてコンパイルするときに予約語であるためエラーとなってしまうためです。回避方法がわからなかったため、暫定策として上記のように名前を変更しました。
バイナリ変換時には、変数名は関係ないので大丈夫です。
例:
変更前
string namespace = 1;
変更後
string namespacc = 1;
それでは、さきほどのバッチファイルがあるフォルダで実行します。そうすると、たくさんのファイルが出来上がります。
*.pb.c
と*.pb.h
というのができているかと思います。
これで準備OKです。
#PlatformIOのプロジェクト作成
とりあえず、プロジェクト名に「AlexaGadget」として、Boardに「M5Stick-C」、Frameworkに「Arduino」を選択し、プロジェクトを作成します。
あと、ROM書き込みやモニタしやすくするために、以下のようにポート番号を指定すると楽です。ポート番号は適宜変えてください。
[env:m5stick-c]
platform = espressif32
board = m5stick-c
framework = arduino
upload_port = COM6
monitor_port = COM6
次に、先ほど作った2つのフォルダにあるファイル「*.pb.c
/*.pb.h
」をコピーしてきます。main.cppがある\srcフォルダが良いです。加えて、
C:\XXXX\Alexa-Gadgets-Embedded-Sample-Code-master\ConnectionHelpers\BLE\Handshake
にある、common.hもコピーしておきます。
次に、nanopb-0.3.9.6.tar.gz を展開して出てくる以下のファイルもコピーしてきます。
・pb.h
・pb_common.c/.h
・pb_decode.c/.h
・pb_encode.c/.h
あと、pb.hの以下の部分のコメントアウトを外してください。
#define PB_FIELD_16BIT 1
最後に、main.cppを以下に置き換えます。
ソースが長くなってしまったので、GitHubを見てください。
https://github.com/poruruba/AlexaGadget/blob/master/AlexaGadget/src/main.cpp
以下の部分は、これまで出てきたかと思いますので、それぞれに合わせて書き換えてください。
【AmazonID】
【Alexaガジェットのシークレット】
【製品ID】
【デバイストークン】
以下は、お使いになるESP32に合わせてください。
【ESP32のBLEのMacAddress】
以下の部分は補足します。
【ガジェットの識別子】
以下に記載がありますが、endpointIdの部分です。とりあえず、” G090RD108032071X”とでもしておきましょうか。
以下の文字列は何でも良いです。
【ファームウェアバージョン】
【モデル名】
上記をPlatformIOでコンパイルし、ESP32に書き込みます。
リブートがかかると、シリアルに「setup」という文字が表示されれば起動が完了です。
#動作確認
それでは、動かしてみましょう。
AndroidなどにAlexaアプリがインストールされている前提です。
起動後、左上のメニューボタンを押して、設定を選択します。
次に「デバイスの設定」を選択します。
そうすると、Echoデバイスが一覧で表示されているかと思いますので、つなげたいEchoデバイスを選択します。
それでは、Alexa Gadgetデバイスを登録しましょう。
それには、「AlexaGadgetをペアリング」を選択します。
そうすると、BLEスキャンが始まり、「M5StickC」というのが見つかるはずです。
それを選択します。
めでたく、登録が完了です。
#Echoデバイスに問いかけてみる
おもむろに、Echoデバイスに、「アレクサ、今何時」と聞いてみましょう。
アレクサに話しかけている間、M5StickCのLEDが点灯しているのではないでしょうか。
#終わりに
ここまで来るのに疲れました。。。。
Arduinoのコードの解説は次回の記事でしたいと思います。
以下、参考にさせていただきました。
Alexaのカスタムスキルがガジェットと連携! 〜Alexa Gadgets Toolkit の Custom Interfaces を試す〜
以上