ビジュアルプログラミング（MIT App Inventor）で開発した Androidアプリから #toio の制御を行う（BLE用の拡張機能を利用）

## はじめに
ビジュアルプログラミングで Androidアプリが開発できる MIT App Inventor（以下、App Inventor と記載）に関する記事で、BLE通信を使った #toio の制御を行う話です。
**（【2021/3/9追記】 iPhone・iPad用のコンパニオンアプリが出ました）**

### 以前作ったもの
App Inventor に関し、最近は以下の記事に書いた「音の機械学習や音声合成を使うアプリ」を試しに作っていました。

- [ビジュアルプログラミングの MIT App Inventor を用いた音の機械学習を利用する Androidアプリ開発【後編：アプリ実装】 - Qiita](https://qiita.com/youtoy/items/b241809c93e8fcef0e26)
- [ビジュアルプログラミングで Androidアプリ開発ができる「MIT App Inventor」を試す（ボタンを押したら音声でしゃべるアプリを作る） - Qiita](https://qiita.com/youtoy/items/93f7c786ff9d664d3032)

## App Inventor で BLEを使う
App Inventor で BLE を使うには、以下の拡張機能のページに掲載された「BluetoothLE（BluetoothLE.aix）」を読み込んで使う必要があります。

●MIT App Inventor Extensions
　https://mit-cml.github.io/extensions/
![MIT_App_Inventor_Extensions_BLE.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/9845f200-bf92-b87a-ac7d-9f08f02fda72.jpeg)

なお、冒頭に掲載していた 2つの記事のうち、音の機械学習を行う内容だったほうは、ここに掲載されている「PersonalAudioClassifier」を読み込んで作っています。

## アプリを作る
今回は前回書いた記事と同様、MIT公式のバージョンではなく日本語化プロジェクトの日本語版を使って作っています。

アプリを作る細かな手順は今回は省略してますので、それに関する補足などは冒頭で掲載していた以下の記事をご参照ください
> ●ビジュアルプログラミングで Androidアプリ開発ができる「MIT App Inventor」を試す（ボタンを押したら音声でしゃべるアプリを作る） - Qiita
> 　https://qiita.com/youtoy/items/93f7c786ff9d664d3032

それでは、、手順の大まかな内容のみ書いていきます。

### 画面のデザインを編集する
プロジェクトを新規作成し、拡張機能の「BluetoothLE.aix」を読み込んでください。
拡張機能の読み込みは、左側のメニューの一番下にある「エクステンション」の中の「Import extension」から行います。
![拡張の読み込み.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/14c85f0b-3e79-5141-018b-2c945ae76dc9.jpeg)

拡張機能を読み込んだら、以下のようにコンポーネントを配置します。
![画面の編集.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/32f53339-cfc6-c904-6359-42e3c853f149.jpeg)

ここで、上記の画面を作るために行った内容を、少し補足します。
画面上に配置したものは、画面の上から置いた順に書いていくと以下のとおりです。「ボタン」の 4つ・3つのまとまりのものは、「横並び」の中に入るように配置します。

* 「レイアウト の 横並び」
   * 「ユーザーインターフェース の ボタン」 × 4つ
* 「レイアウト > 横並び」
   * 「ユーザーインターフェース の ボタン」 × 3つ
* 「ユーザーインターフェース の ラベル」
* 「ユーザーインターフェース の リストビュー」
* 「エクステンション の BluetoothLE」 ※ 画面上には表示されません
* 「センサー の 加速度センサー」 ※ 画面上には表示されません

そして、上記のボタンやラベルの名前・表示するテキストなどを、以下の対応関係になるように設定しています。

* 「横並び」： （変更なし）
   * 「ボタン」： スキャン
   * 「ボタン」： スキャン停止
   * 「ボタン」： 接続
   * 「ボタン」： 切断
* 「横並び」： （変更なし）
   * 「ボタン」： 音を鳴らす
   * 「ボタン」： LED点灯
   * 「ボタン」： LED消灯
* 「ラベル」： ステータス
* 「リストビュー」： BLEリスト
* 「BluetoothLE」： （変更なし）
* 「加速度センサー」： （変更なし）

なお上記の画面作成について、2つ目の「横並び」以外の部分は、以下の公式チュートリアルの内容を見て作った構成です。
> ●App Inventor + IoT: Basic Bluetooth Connection Setup
　> http://iot.appinventor.mit.edu/assets/tutorials/MIT_App_Inventor_Basic_Connection.pdf

### プログラムを作る
今回作ったプログラムは、以下のとおりです。
![プログラムの内容.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/44255371-e750-2bf5-f360-3d8de3574700.jpeg)

ここで、プログラムの内容を少し補足していきます。
このプログラムで 11個のブロックの固まりがあるのですが、その中の 7つは以下の公式チュートリアルを見て作ったものです。
> ●App Inventor + IoT: Basic Bluetooth Connection Setup
　> http://iot.appinventor.mit.edu/assets/tutorials/MIT_App_Inventor_Basic_Connection.pdf

具体的には、以下のブロックです（※ 上の画像とは、並びを少し変えています）。
![スキャンや接続などの処理.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/772bc4ba-987d-b1e8-ea67-eb81ad8fe9b9.jpeg)

これらのブロックは、以下の動作を行わせるためのものです。

* 「スキャン」ボタンが押されたらデバイスのスキャンを行って、見つかったデバイスの情報をリストビューに表示
* 「スキャン停止」ボタンが押されたらデバイスのスキャンを止める
* リストビューに表示されたデバイスを選んだ状態で、「接続」ボタンを押したらデバイスへの接続を行う
* 「切断」ボタンが押されたら、デバイスとの接続を切る

また、上記の動作に合わせて、画面のラベルの表示を変えたり、リストビューが不可視になるかどうかを制御していたりします。

ここからは、デバイスとの接続が行われた状態で動作させるブロックについて補足します。
それに該当するのが以下のブロックです（※ 上の画像とは、並びを少し変えています）。
![接続後に行わせる処理.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/6ac87f0c-f966-3236-1466-628da840ba90.jpeg)

4つあるブロックの固まり全てで、最初にデバイスとの接続が行われているかをチェックしています。そして、接続済みであれば、以下の動作が行われるようにしています。

* 「ボタン： 音を鳴らす」が押されたら、特定の音を鳴らす
* 「ボタン： LED点灯」が押されたら、LED を特定の色で点灯させる
* 「ボタン： LED消灯」が押されたら、LED を消灯される
* スマホが揺さぶられたら、特定の音を鳴らす（加速度センサーで揺れを検知）

そして、それぞれの処理で「WriteBytes」の処理を行う部分で、2つの UUID や値などを設定しています。
2つの UUID は、以下の toio の仕様が書いてあるページのものを使います。

▼ サービスの UUID が書いてある部分（4つのブロックの固まり共通で使っているもの）
　●通信概要 · toio™コア キューブ 技術仕様
　　https://toio.github.io/toio-spec/docs/ble_communication_overview
![service_uuid.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/179b1bc4-b065-6bd8-d883-71d6b299dedf.jpeg)

▼ 音を鳴らす処理の Characteristic UUID が書いてある部分
　●サウンド · toio™コア キューブ 技術仕様
　　https://toio.github.io/toio-spec/docs/ble_sound
![sound_uuid.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/657b7434-b701-801b-12f8-0e71123f4950.jpeg)

▼ ランプを点灯・消灯させる処理の Characteristic UUID が書いてある部分
　●ランプ · toio™コア キューブ 技術仕様
　　hhttps://toio.github.io/toio-spec/docs/ble_light
![ランプ_uuid.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/7c32afe9-b03f-a08c-76e1-9544d3841528.jpeg)

そして、特定の音を鳴らしたり、特定の色でランプを点灯させたり、その指示を出すための値の指定も、同様に上記の仕様に書かれたものを使っています。
例えば、「ボタン： 音を鳴らす」が押された時の処理は、以下を見て設定しています。
![音を鳴らす時の値の指定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/789eecf3-2716-cd14-e882-79d375257fdb.jpeg)

ブロックの中でいうと、以下の赤枠で囲んだ部分です。
![音を鳴らす処理1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/7409e6c2-efe7-f5f9-781e-34bff180fe0c.jpeg)
音量について、仕様で最大音量 `0xFF` というのが 16進数で書かれていますが、それを上記のブロックで指定する場合、置くべきブロックは数値となるようでした。そこで、10進数にした値の `255` を使っています。
さらに、複数の値を指定するには、リストを使って複数の数値を設定すれば良いようでした。

## 動作している様子
上記の手順を進めて作ったアプリを、実際に動かしてみると以下のようになります。
動画で出ている部分の前にスキャンと toio への接続をすませており、この動画では音を鳴らしたりランプを制御したりする部分をご覧いただけるようにしています。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">ビジュアルプログラミング（MIT App Inventor）による Androidアプリでの BLE利用。<a href="https://twitter.com/hashtag/toio?src=hash&amp;ref_src=twsrc%5Etfw">#toio</a> への接続後、ボタンを押して音を鳴らしたり、ボタン押下でのランプの点灯/消灯をやって、最後にスマホを振ったら音が鳴る、という動作をさせた様子の動画。 <a href="https://t.co/3mO2xAVB9o">pic.twitter.com/3mO2xAVB9o</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1368574123199197195?ref_src=twsrc%5Etfw">March 7, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 終わりに
今回、App Inventor とその拡張機能を使い、BLE通信を使った #toio との接続・制御を行いました。
そして、掲載していた動画の内容のとおり、無事に動作させることができました。

今後は、toio から値を受け取る処理の実装も試すことができたらと思います。

### 気になる点
今回は使ってない部分で気になるところがあり、具体的には toio で値をやりとりする仕様の中で 2バイトを使って 255より大きい値を扱うところ（例えば、専用マットの位置座標を扱うところ）です。
今回のような数値を指定する形で、エンディアンを考慮した意図通りのバイトオーダーになるか・それを簡単に扱えるか、という点なのですが、そのあたりは今後確かめていこうと思っています。