ESP32をAlexa Gadgets Toolkitデバイスにしよう

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は、一般には以下のような流れです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/c129571e-742e-3448-62a5-ff3da344ed80.png)

今回はこのうち以下の流れだけです。（これ以外は、次回の投稿にあります。）
Alexa Gadgets Toolkitに定義済みの、wakeword(アレクサ、という呼びかけ)をひっかけて、LED点灯するところまでです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/e73bf07c-2be1-4a48-7091-47f3cf130d7f.png)

いつもの通り、Arduinoのコードは以下のGitHubに登録しておきました。

poruruba/AlexaGadget
　https://github.com/poruruba/AlexaGadget

※ソースコードの解説やカスタムスキル対応は次回の記事で。以下、続編
　[ESP32をAlexa Gadgets Toolkitデバイスにしよう：ソースコード解説](https://qiita.com/poruruba/items/1ad01eb93af2c00e0e5d)
　[ESP32をAlexa Gadgets Toolkitデバイスにしよう：カスタムスキル→Alexa Gadgetデバイスへの通知](https://qiita.com/poruruba/items/5c7cfbf36f4ed9ec001e)
　[ESP32をAlexa Gadgets Toolkitデバイスにしよう： Alexa Gadgetデバイス→カスタムスキルへの通知](https://qiita.com/poruruba/items/a15acf155e8c0f634925)

#Alexa Gadgetsデバイスの登録

まず最初に、Alexa Gadgetsデバイスの情報を登録して、IDを払い出します。
登録は、Alexa音声サービス開発者コンソールから行います。

Alexa音声サービス開発者コンソール
　https://developer.amazon.com/alexa/console/avs/home

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/35c8098b-d5ed-2292-0910-6d57747986fa.png)

製品 をクリックしたのち、「新しい商品を追加」をクリックします。

製品名等を登録します。何でも良いですが、とりあえず適当に以下で入力してみましょう。

・製品名：M5StickC
・製品ID：M5StickC
・製品タイプ：Alexaガジェット
・商品カテゴリ：コミュニケーションまたは通知の端末
・製品概要：テスト用
・この製品を商品として配信する予定ですか？：いいえ

登録が完了すると、「Amazon ID」と「Alexaガジェットのシークレット」が払い出されます。

ちょっと、フライングですが、以下にあるPythonコードを実行しておきます。

https://developer.amazon.com/ja-JP/docs/alexa/alexa-gadgets-toolkit/alexa-discovery-interface.html#AdditionalIdentification

```py:maketoken.py
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の形式で送られてくるバイナリをデコードしたり、バイナリにエンコードしたりするエンコーダを作成します。

以下の手順に従います。

https://developer.amazon.com/ja-JP/docs/alexa/alexa-gadgets-toolkit/bluetooth-le-handshake-sample.html

まず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書き込みやモニタしやすくするために、以下のようにポート番号を指定すると楽です。ポート番号は適宜変えてください。

```platformio.ini
[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の以下の部分のコメントアウトを外してください。

```c: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”とでもしておきましょうか。

https://developer.amazon.com/ja-JP/docs/alexa/alexa-gadgets-toolkit/alexa-discovery-interface.html#Endpoints

以下の文字列は何でも良いです。
【ファームウェアバージョン】
【モデル名】

上記をPlatformIOでコンパイルし、ESP32に書き込みます。
リブートがかかると、シリアルに「setup」という文字が表示されれば起動が完了です。

#動作確認

それでは、動かしてみましょう。
AndroidなどにAlexaアプリがインストールされている前提です。

起動後、左上のメニューボタンを押して、設定を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/96d81842-3066-6cfe-dd9c-56f2db27bab9.png)

次に「デバイスの設定」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/8a363282-7793-1344-d50a-3d6da4c40863.png)

そうすると、Echoデバイスが一覧で表示されているかと思いますので、つなげたいEchoデバイスを選択します。
それでは、Alexa Gadgetデバイスを登録しましょう。
それには、「AlexaGadgetをペアリング」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/478ebfee-a372-2ff2-2671-18f3cfd03ba7.png)

そうすると、BLEスキャンが始まり、「M5StickC」というのが見つかるはずです。
それを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/67cf3b34-4ca7-2c2a-9c01-b63ec0e96e7f.png)

めでたく、登録が完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/e6694ec8-458e-e6e6-68e7-81c4355dcfcc.png)

#Echoデバイスに問いかけてみる

おもむろに、Echoデバイスに、「アレクサ、今何時」と聞いてみましょう。
アレクサに話しかけている間、M5StickCのLEDが点灯しているのではないでしょうか。

#終わりに

ここまで来るのに疲れました。。。。
Arduinoのコードの解説は次回の記事でしたいと思います。

以下、参考にさせていただきました。
　[Alexaのカスタムスキルがガジェットと連携！ 〜Alexa Gadgets Toolkit の Custom Interfaces を試す〜](https://qiita.com/youtoy/items/472da6c009a5ee3407ea)

以上