【スマートスピーカー 2019】 Alexa（Echo）がガジェットと連携！ 〜 Espalexa編 〜（2019/12/4）

この記事は 「[スマートスピーカー Advent Calendar 2019]( https://qiita.com/advent-calendar/2019/smart-speaker )」の 4日目の記事です。

以前、[Alexa のカスタムスキルとガジェットを連携させる仕組み]( https://developer.amazon.com/ja/docs/alexa-gadgets-toolkit/custom-interface.html )を試して [Qiitaの記事]( https://qiita.com/youtoy/items/472da6c009a5ee3407ea )に書きましたが、**それとは別の仕組みを使ったガジェット連携**もやってみたことがありました。
今回は、その内容について仕組みの部分などを記事にしてみます。

ちなみに、以前書いたカスタムスキルとガジェットの連携に関する記事について、URLは下記になります。
　**[●Alexaのカスタムスキルがガジェットと連携！ 〜Alexa Gadgets Toolkit の Custom Interfaces を試す〜 - Qiita]( https://qiita.com/youtoy/items/472da6c009a5ee3407ea )**
　　https://qiita.com/youtoy/items/472da6c009a5ee3407ea

## はじめに

最初に、今回の記事の内容について、動作させた時の様子を掲載してみます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">試したいと思いつつ、積み残していたネタを1つ消化！<br><br>動画の内容は先日試した Alexa Gadgets Toolkit ではなく、 <a href="https://twitter.com/hashtag/M5StickC?src=hash&amp;ref_src=twsrc%5Etfw">#M5StickC</a> ＋ <a href="https://twitter.com/hashtag/Espalexa?src=hash&amp;ref_src=twsrc%5Etfw">#Espalexa</a> で実現してます。<a href="https://twitter.com/Norio_Delux?ref_src=twsrc%5Etfw">@Norio_Delux</a> さんが Qiitaの記事に書かれていた内容（先日 <a href="https://twitter.com/hashtag/IoTLT?src=hash&amp;ref_src=twsrc%5Etfw">#IoTLT</a> でも話されてたもの）に、さらに micro:bit周りの仕組みを追加してます。 <a href="https://t.co/1aBnnde9Gh">pic.twitter.com/1aBnnde9Gh</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1186667069556658176?ref_src=twsrc%5Etfw">October 22, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

この動画でやっていることは「Alexa に話しかけることで、車を前後に動かす」というものです。
スマートスピーカーと micro:bitを搭載した車のデバイスとが、連携した形になっています。

ここで両者をつなぐメインの部分に使っているのが「[Espalexa]( https://github.com/Aircoookie/Espalexa )」というものになります。
　●GitHub - Aircoookie/Espalexa: Alexa voice control for ESP8266/ESP32 (including brightness and color!)
　　https://github.com/Aircoookie/Espalexa

当初は、Twitter上で複数の方が個別に情報をツイートされていたのを見かけていたものの、すぐには手をつけずにいたものでした。

そんな中、下記の @norippy_i さんの記事が公開されてソースコードも記載されていたので、記事の公開後に内容を使わせていただきつつ、今回の内容のものを作ってみました。
　●M5StickCをAlexa連携デバイス化する - Qiita
　　https://qiita.com/norippy_i/items/d8456e3c84432e279754

以下では、"**上記の記事の内容を引用・参照しつつ、自分で追加した部分を説明しつつ**"、という形で書いていきます。

## 元にした記事の内容

### 仕組みの説明など

今回の内容の元になっている @norippy_i さんの記事で紹介されていた例は、以下になります。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">教えてもらったespalexaライブラリを使って、改めてM5StickCのAlexa連携デバイス化をやってみた。<br>前回のらON,OFFだけだったけど、今回は明るさの0~255が送れるし、RGBもそれぞれ送れるので、より細かな処理ができる！<a href="https://twitter.com/hashtag/alexa?src=hash&amp;ref_src=twsrc%5Etfw">#alexa</a> <a href="https://twitter.com/hashtag/M5StickC?src=hash&amp;ref_src=twsrc%5Etfw">#M5StickC</a> <a href="https://t.co/Nu886lsWf6">pic.twitter.com/Nu886lsWf6</a></p>&mdash; norippy@Hardware&amp;Alexa skillやってます (@Norio_Delux) <a href="https://twitter.com/Norio_Delux/status/1179009607198359552?ref_src=twsrc%5Etfw">October 1, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

この仕組みに関する部分を、記事から抜粋して引用してみます。

> 動画のやり方は、M5StickCをAlexa連携デバイスとしてAlexaアプリに登録して動かしています。
・・・
Alexa連携デバイスと認識されていると、Alexaアプリにある定型アクションを使えるようになるので、・・・
開発自体もとても簡単で、EspalexaというライブラリをM5StickCに書き込んで、WiFiに接続するだけです。
実際に使ってみてわかりましたが。Phillips社のHueのエミュレートをしているようです。

この抜粋した説明で、おおよその内容はつかめるかと思います。

### 試してみたこと

最初に試したことは、記事に書いてある内容そのまま、です。
丁寧に書かれているので、主要な部分の内容をなぞっていくことで、 @norippy_i さんの記事にあったとおりの動作させることができました。

#### なぞった手順
- [(準備)開発環境]( https://qiita.com/norippy_i/items/d8456e3c84432e279754#%E6%BA%96%E5%82%99%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83 )
    - 1.ライブラリの追加
    - 3.サンプルコードをベースに、コードを変更してみる
    - 4.Alexaアプリを使ってデバイスの登録を行う。
    - 6.定型アクションを登録して、音声で操作してみる

## オリジナルの部分を追加

自分は何を試そうかと考えたとき、声で「何かを動かしたり、見た目に変化が起きる何かをやったり」ということをやろうと思いました。
一方、できるだけ元のものを使いつつ、ソースコードの修正・追加は最小限にして、サクッと試せたら良いな、と考えました。

動き等をだす部分は、自宅にあるもので手軽に使えて有用なものとして「[micro: Maqueen]( https://www.dfrobot.com/product-1783.html?search=ROB0148 )」があったため、これを組み合わせることにしました。
<img width="600" alt="20191122163107.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/65e21ac6-5c96-95a6-1530-fa57d3f8e44d.jpeg">
余談ですが、こちらはコスパの良さ（価格に対しての利用可能な機能や、自分が関わる活動での利用頻度の多さ）の観点で、今月最初のアドベントカレンダー用に書いた下記の記事にて、今年のベストバイに選んだものだったりします。
　●【ベストバイガジェット2019】個人的には費用対効果が抜群： micro: Maqueen（2019/12/1） - 技術とエンタメと、その他・・・
　　https://yo-to.hatenablog.com/entry/20191201/1575157520

話を戻して、ここから概要などを記載していきます。

### M5StickC と micro: Maqueen の連携部分や構成

全体のデバイスの構成としては
　Alexa（Echo） -> M5StickC（＋ Espalexa） -> micro:bit① -> micro:bit②（＋ micro: Maqueen）
となっています。

以下は動画からキャプチャした画像ですが、その中の赤枠の部分を見ていただくと分かるように、M5StickC と micro: Maqueen は有線で接続しています。
<img width="324" alt="スクリーンショット_2019_12_02_1_51.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/38d8cd97-c597-b9db-6c09-abc778920a40.jpeg">
先ほどのデバイスの構成に、間の通信部分を補足した全体構成は、以下のとおりです。
　Alexa（Echo） --[Bluetooth]--> M5StickC（＋ Espalexa） --[シリアル通信（有線）]--> micro:bit① --[micro:bitの無線機能]--> micro:bit②（＋ micro: Maqueen）

**元の内容からの変更を最小限にしつつ、手軽に目的を実現するため**に、デバイス間通信では有線のシリアル通信を活用するのが良さそうに思い、このような構成で進めてみました。
最終的に、追加・修正したソースコードは少なく済んだと思います。

### micro:bit②（micro: Maqueen）の動作部分
micro:bit のプログラミングには、[Microsoft MakeCode for micro:bit](https://makecode.microbit.org/?lang=ja)を使っています。

micro: Maqueenを動かす部分は、以下のシンプルな内容です。
micro:bit①との無線通信を行うセットアップの処理があり、さらに、micro:bit①から2種類の文字列（前進・後退の制御用）のどちらかを受け取ったときに、前進・後退をするためにモーターを制御する処理のみです。
<img width="856" alt="スクリーンショット_2019_12_02_2_59.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/64944b8d-2e00-aaee-d6a0-7083e8cc7338.jpeg">

ここで設定している無線グループの番号や、条件文の部分で指定している、無線経由で受信した文字列の指定部分の内容は適当で良いですが、この次に出てくるmicro:bit①のプログラムのものと一致させるようにしてください。

### micro:bit①の動作部分
micro:bit②と同様に、[Microsoft MakeCode for micro:bit](https://makecode.microbit.org/?lang=ja) でのプログラミングを行います。

<img width="854" alt="スクリーンショット_2019_12_02_3_04.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/fc1acbfd-1547-6ede-322f-3fb52bfbf4a7.jpeg">

細かく見ると、LEDの表示部分の処理などもありますが、必要なメインの処理は「無線通信を行うセットアップ処理、シリアル通信のためのセットアップ処理、シリアル通信経由で特定の文字列を受け取ったら micro:bit②へ無線で文字列を飛ばす処理」となります。
見ていただくと分かるとおり、それほど複雑な処理は必要としない構成です。

上記のとおり、ここで設定している無線グループの番号や、無線経由で送信するよう指定した文字列は、前に出てきたmicro:bit②のプログラムのものと、一致させるようにしてください。
また、シリアル通信経由で受け取る文字列で、条件文で指定している文字列は、この後の Espalexa の処理で記載するものと一致させるようにしてください。

### Espalexa の処理の書きかえ部分
Espalexa のソースについて、ほとんどが @norippy_i さんの記事に書かれたもの（「元記事の[3.サンプルコードをベースに、コードを変更してみる](https://qiita.com/norippy_i/items/d8456e3c84432e279754#3%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)」の部分）と共通です。

付け加えた内容は以下の部分のみです。

A)元のソースコードの `void setup()` の中の前半に、以下を追加。

```C
  // Rx:0  Tx:26
  Serial2.begin(115200, SERIAL_8N1, 0, 26);
```

B）元のソースコードの `void brightnessChanged(uint8_t brightness)` の中の後半に以下を追加。

```C
  if(brightness == 78) {
    // 30%の明るさ
    Serial2.write("fff,");
  } else if(brightness == 179) {
    // 70%の明るさ
    Serial2.write("bbb,");
```
シリアル通信で送る文字列や、条件文で設定している明るさの度合いは、適当に決めただけで変えてしまって大丈夫です。

また、元のソースの下記の部分を、ご自身が利用される無線LAN の SSID とパスワードを指定するのを忘れないよう、ご注意ください。

```C
// Change this!!
const char* ssid = "your ssid";
const char* password = "your password";
```

### Alexaアプリでの定型アクションの設定
デバイス側のプログラムは一通り揃ったので、後は Alexaアプリの定型アクションの設定を残すのみです。

ここでは、車を前進させるときに話しかけるフレーズと、後退させるときに話しかけるフレーズの2つを設定しました。
![IMG_1574.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/958c9086-117f-cd23-c29a-6da423219acd.jpeg)

そして、それぞれのフレーズに紐付けて、連携デバイス（Espalexa のプログラムを書き込んだ M5StickC）の明るさを変えるよう設定します。上記で Espalexa のソースコードを書きかえた部分、2つのうち B）のほうの条件文で設定した明るさの度合いを使います（※ 今回の例では「30%の明るさ」と「70%の明るさ」を使ってます）。
![IMG_1575.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/dbbdf37d-61b3-5fa4-296a-6de2451508ff.jpeg)

後は、ここで設定したフレーズで、定型アクションを実行させればOKです！

### 動作について（過去の記事のものとの比較）

以上により、Expalexaを使ったガジェット連携を行うことができ、冒頭にも載せた動画の内容を実現できました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">試したいと思いつつ、積み残していたネタを1つ消化！<br><br>動画の内容は先日試した Alexa Gadgets Toolkit ではなく、 <a href="https://twitter.com/hashtag/M5StickC?src=hash&amp;ref_src=twsrc%5Etfw">#M5StickC</a> ＋ <a href="https://twitter.com/hashtag/Espalexa?src=hash&amp;ref_src=twsrc%5Etfw">#Espalexa</a> で実現してます。<a href="https://twitter.com/Norio_Delux?ref_src=twsrc%5Etfw">@Norio_Delux</a> さんが Qiitaの記事に書かれていた内容（先日 <a href="https://twitter.com/hashtag/IoTLT?src=hash&amp;ref_src=twsrc%5Etfw">#IoTLT</a> でも話されてたもの）に、さらに micro:bit周りの仕組みを追加してます。 <a href="https://t.co/1aBnnde9Gh">pic.twitter.com/1aBnnde9Gh</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1186667069556658176?ref_src=twsrc%5Etfw">October 22, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

なお、過去の記事で書いた「Alexa Gadgets Toolkit の Custom Interfaces」を試した記事は、[ GitHub に公開されていたサンプル「Color Cycler Gadget」]( https://github.com/alexa/Alexa-Gadgets-Raspberry-Pi-Samples/tree/master/src/examples/colorcycler )を試してみた、という内容でしたが、その後、今回の記事と同じ方針で micro: Maqueen と組み合わせるものも試作したりしました。

時系列的には、シリアル通信でガジェット間を連携させることをやったのは下記が先で、それを今回の記事の内容にも用いた、という流れでした。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">Alexaのカスタムスキルのガジェット連携、とりあえず版ですが micro:bitやLEDテープ・車型の小型ロボを組み合わせてみました！<br>Alexaスキルから車の発進を制御して、<br>また、車の超音波センサで障害物を検知したかどうかによって、スキルの最後のセリフやLEDテープの光る色が変わるようにしてみました。 <a href="https://t.co/OIBPAZwD1P">pic.twitter.com/OIBPAZwD1P</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1181266669504618496?ref_src=twsrc%5Etfw">October 7, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## さいごに

以前、Qiitaの記事に書いた「Alexa Gadgets Toolkit の Custom Interfaces」とは異なる仕組みで、ガジェット連携を行ってみました。
今回の内容は、定型アクションを使った内容になるので、ここ最近、購入したばかりの [Echo Flex]( https://www.amazon.co.jp/dp/B07PGX7GC9 ) の[モーションセンサー]( https://www.amazon.co.jp/dp/B07VF43BG1/ )と組み合わせて何かできないかな、と思ったりしました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">玄関のコンセントに設置！ <a href="https://t.co/KGgnfa9xFD">https://t.co/KGgnfa9xFD</a> <a href="https://t.co/mDMdWCP6Ws">pic.twitter.com/mDMdWCP6Ws</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1196460416005595136?ref_src=twsrc%5Etfw">November 18, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>