M5Stackで始めるモノ作り・Alexa連携編

# 今回の概要
[前回](https://qiita.com/Reiji-Nishiyama/items/bb8f3961034d371ba56c)は土壌水分をモニターする部分を実装しました。今回で最終回となり、Alexaと連携してモニターした値を音声で教えてもらえるようにする部分と、Dashboardにモニターした値を表示する部分の実装を行います。
しかし、Alexaと連携する方法を調べる中でこれまで使用してきたmicropythonを諦め、Arduino IoT Cloudで実装することになります。

# Alexa連携方法
Alexaとの連携に関しては初めてで知識ゼロの所から今回はスタートしています。そのためここで示した方法以外にもオプションが必ず存在すると思いますので、ここでの内容は参考情報の一つ程度に捉えていただければと思います。

なお、今回はM5Stickc plusをAlexaと連携させる方法で調べています。Amazon公式の方法を見てみると[Amazon Developer](https://developer.amazon.com/ja-JP/alexa/devices/connected-devices/development-resources#echo-paired-alexa-gadgets-toolkit)にAlexaコネクテッドデバイス開発のオプションが一覧で整理されていました。ただ、別のSoCが必要となったりAmazon Developerアカウントの開設が必要になったりすることから今回はこれらの方法は見送りました。まぁ、開設すればいいだけなので掲載されているいくつかのAlexa連携方法については機会を見て試してみたいと思います。

### エミュレートする方法
[設計編](https://qiita.com/Reiji-Nishiyama/items/d06621c15402cd9cb0f8)では、当初自宅のAmazon Echoからローカルネットワークで直接デバイスを操作することを想定していました。これを実現する方法として、既存のAlexaコネクテッドデバイスをエミュレートする方法がネットに存在しています。BelkinのWeMosというデバイスとAmazon Echoとの通信を解析し、WeMos側の通信をエミュレートすることで、Alexaに開発したデバイスをあたかもWeMosとして認識させる方法になっています。元々は**Fauxmo**と呼ばれるプロジェクトから始まり、それがフォークされてC++など様々なプラットフォーム向けに実装され、その内micropython向けにポートされたのが**uPyEcho**となっています。

* uPyEcho
micropythonで動作可能なエミュレーション実装。
https://lemariva.com/blog/2017/10/micropython-wemos-and-amazon-echo-alexa

実際には使ってはいないのですが、内容を見てみるとON/OFFするようなデバイスしか開発出来なさそうです。今回開発するのはセンサーデバイスなので、ON/OFFではなくデータをAlexa側に送るタイプのデバイスになります。なのでこの方法は今回は見送りました。

### Alexa Connect Kit (ACK)を利用する方法
これを利用するにはACKモジュールなるものが搭載されたSoCが必要になるようです。なのでこれも見送ります。ちなみに、DIYで手軽に利用するにはESP32-PICO-V3-ZEROを入手するのが一番良さそうです。秋月電子で500円くらいで購入できます。ACKモジュールではAmazonが管理しているFWを実行するために存在しており、AlexaやACKマネージドサービスへの連携に関することは全てこのACKが担ってくれるため、ACKを使ったデバイス開発者はアプリケーションの開発のみに集中できるようになるとのこと。またエンドユーザーにおいては、Alexaに接続するためのストレスフリーなUXの高い設定体験を提供してくれるようです。話は変わりますが、某住宅設備メーカーのホームシステムはセットアップするだけで放り投げてしまいたくなる程意味不明な手順が多いペインフルな体験を約束してくれます。

* Alexa Connect KIT (ACK)
https://developer.amazon.com/ja-JP/docs/alexa/ack/how-alexa-connect-kit-works.html

### IoT Cloudサービスを利用する方法
当初のローカルネットワークで直接デバイスとAlexaを接続する方法ではなくなりますが、IoT Cloudサービスはセキュリティが確立されSDKで安全に導入できるので良さそうです。大手Public Cloud事業者はこうしたサービスを開発環境含め提供しています。Alexaとの連携を考慮すると、Amazonのサービスに統一しておいた方が余計な手間がかからず良さそうです。AWS印のM5Stack Core2 AWS IoTキットも販売されています。無印版との主な違いはセキュリティチップ搭載の有無ですが、[こちらの記事](https://qiita.com/Nabeshin/items/41756564e788ed41acb9)で無印のCore2でも利用できるようにする手順が紹介されています。
なお、AWS IoTとAlexaを連携するにはAlexaスキルの開発が必要になるかもしれません。
こちらについては別の機会に譲るとして、今回はM5Stackc plusで一番手軽に試すことができたArduino IoT Cloudを使用します。

# Arduino IoT CloudでAlexa連携とDashboard連携を行う
ほぼクリックだけでAlexa連携とデータ表示を全て叶えてくれたのがArduino IoT Cloudでした。もちろんアプリケーション部分の実装は必要ですが、Alexa連携とDashboardへの通信に関する部分は全てアプリケーションに沿った形で提供してくれます。
ただしAlexa連携については作成可能なAlexaコネクテッドデバイスが以下のタイプのデバイスに限定されます。
* **Colored Light** - bool and float (complex type).
* **Dimmed Light** - bool and float (complex type).
* **Television** - bool and int (complex type)
* **Contact Sensor** - bool
* **Light** - bool
* **Motion Sensor** - bool
* **Smart Plug** - bool
* **Switch** - bool
* **Temperature Sensor** - float

う〜ん、今回の土壌水分などというものはありません。。。
ここは妥協してfloat型の温度センサーの種別でコネクテッドデバイスを作ることにします。土壌水分モニターデバイスは１０段階のデータなので、０〜９℃のレンジでしか変化しません。またAlexaの回答も”〜度です”となりますが、良しとします。
まだ妥協しなければならないものがあります。Free planではデータの保持が1dayになっているため、履歴データの確認が出来なくなってしまいます。そして最後にもう一つ。Arduinoでの開発になるため、micropythonを諦めてArduino言語で作り直しが発生します。丸っと良しとします！

ということでArduino IoT Cloudで土壌水分モニターデバイスを実装し直し、Alexa連携とDashboard連携に必要なコードの埋め込みを行なって行きたいと思います。

## IoTデバイスとThingのセットアップ

##### リファレンス手順
公式ドキュメントにStep-by-stepでの詳しい手順が掲載されており、ほぼ迷うことなく設定することができましたので、そちらを参照して行なって行きます。ただ何点か注意を要する部分があるためその部分だけ詳しく記載するようにします。
* 設定に関する公式ドキュメント
https://docs.arduino.cc/arduino-cloud/tutorials/alexa-mkr-rgb-shield


##### Arduino IoT Cloudアカウント開設
アカウントの開設が必要です。既にArduinoのアカウントを持っている場合はそのまま利用可能です。

##### デバイスの登録
Arduino IoT Cloudページへ行きます。


`Devices`から`3rd Party device`を選択して`M5Stick-C`を選択します。デバイス名はなんでも構いません。登録すると`Device ID`と`Secret Key`が表示されますのでPDFで**ダウンロード**しておきます。デバイスがクラウドサービスに接続するにはこの**Secret Keyが必要になります。**
![スクリーンショット 41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481340/f605a1f9-dfff-6399-41cc-8c5cef80b967.png)

##### 温度センサータイプのThingの作成
ThingがAlexaでデバイスを検索登録する時に見える**モノ**になります。アプリケーション的にはデータへのアクセスポイントになっており、ここに読み書きするとデータがCloudと同期され、またCloudからThingを操作した場合にはリスナーを実装しておくことでその変化のイベントを受け取ることができます。

ではThingを作って行きます。
まず`Things`メニューから`ADD VARIABLE`をクリックし、名前を付けます。今回は土壌水分モニターデバイスなので`SoilMoisture`とします。

次にThingのタイプをプルダウンから選択します。
今回はAlexaのコネクテッドデバイスで温度センサータイプとするため、`Alexa compatible`を選択し、 `Temperature Sensor`を選択します。`Variable Update Policy`は今回どちらでもいいと思いますが`Periodically`としておきます。


![スクリーンショット 2023-01-22 16.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481340/30b22c97-19b1-d671-7c80-0e2e81e8701d.png)

##### Thingとデバイスの紐付け
次に`Associated Device`から作成したThingと登録したデバイスを紐づけます。


##### デバイスのネットワークとCredential設定
次に紐づけたデバイスのネットワーク設定を行います。ここで最初にデバイスを登録した時の`Secret Key`が必要になります。`Network`から自宅のWi-Fi APのSSIDとPassword、そして`Secret Key`を入力して設定します。

以上で必要な設定は完了です。設定が完了するとCloud側でThingのソースが自動生成され、thingProperties.hにI/Fが定義されているようですが、生成されたものがどうなっているのかは見ることができないようです。

## Thingへのアクセス
作成したThingへのアクセスは、生成されたSketchコードのコメントにある変数を参照することで行われます。今回の変数名は`soilMoisture`となっており、この変数にfloat値を代入するとCloud側に値が反映されることになります。つまり土壌水分量センサーからセンサー値を読み出し、それを１０段階の水分量レベルに変換し、それをsoilMoistureに代入するだけで、Alexa連携とDashboardへの表示が可能になります。とっても簡単です！！

なお、温度センサータイプのThingを作成した時にRead Onlyタイプとなっていましたが、これはクラウドからは操作できないことを意味しており、従ってこのThingの変更イベントは発生せずリスナーは不要です。もしRead/Writeタイプのデバイスの場合はon＋Thing名の関数、今回で言えば`onSoilMoisture`の関数を実装することで変更イベントを受け取ることができます。
データの同期やモニタリングについての具体的なコードは以下のドキュメントが参考になりました。
* Data Monitoring
https://docs.arduino.cc/cloud/iot-cloud/tutorials/cloud-environmental-data
* Variable Syncronisation
https://docs.arduino.cc/cloud/iot-cloud/tutorials/device-to-device

## Dashboardの作成
`Dashboards`メニューから作成を行います。
適当な名前を付け、`ADD`からウィジェットを選択して配置します。今回はゲージを選択し、最大値を9にしました。

最後にデータを表示したいThingを選択して紐付けを行ないます。
以上でDashboard作成は完了です。

ちなみに他の可視化サービスだと以下のようなものもあります。
* Ambient
https://ambidata.io
* looker studio
https://cloud.google.com/looker-studio?hl=ja

## Alexaでデバイスの検索と登録
次はスマホのAlexaアプリからAlexaにThingを登録して行きます。
これについても前述の公式ドキュメントに写真付きで手順が載っていますのでこちらに沿って行なっていきます。

まず、Arduino Skillをインストールし、完了するとデバイスの検索画面になるので検索を行います。
ここでデバイス検索に失敗するとこの画面に戻ることができません。そうなると、通常の検索画面から検索をしないといけなくなりますが、どのタイプのデバイスを選択すれば良いのか分かりません。試したところでは、`その他`のデバイスを選択し、`Wi-Fi`を選択してデバイスを検索したら検出することができました。試していませんが適当に選んでも大丈夫かもしれません。

# できあがり

![スクリーンショット 2023-01-22 17.54.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481340/95b7c2a7-680f-1273-eee0-beea83bfe8da.png)
う〜ん、温度だ。。。
![IMG_4548.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481340/dd345654-02b2-37de-f1fc-a760a8af5893.png)


# 最後に
今回の開発は妥協した点が多く、Alexa周りは見切り発車して実装開始してしまったのでプラットフォームの変更も発生してしまいました。また、Alexa連携周りが薄い内容で、Arduino IoT Cloudの解説みたいになってしまいました。機会を見つけてAWS IoT + Alexa Skills + M5Stackc plus + micropythonの組み合わせでAlexaコネクテッドデバイスが開発できないか試してみたいと思います。
（M5Stackc plus + micropythonはもう楽しめたし、この縛りは無くてもいいか。。。）