Web Bluetooth API で toio を 6台同時に制御する

toio の BLE経由での制御について、Node.js ＋ noble を使ったプログラムを試しに作って、以下の記事を書きました。以下の記事の中でも、この記事のタイトルにある 6台同時制御をやっていたりします。

●あらためて noble でガジェットを扱う話に着手する： toio と micro:bit を複数混在させてスキャン、toio の複数制御（6台分） - Qiita
　https://qiita.com/youtoy/items/15a743d692f348327ff9

そして、上記の記事のプログラムを書いている時、ふと「以前、何度も使っていた Web Bluetooth API で toio を同時制御していた時、そのソースを改変して同時制御の台数を増やしても 3〜4台までしか扱えない状態だったけれど、あれは実装の問題では？」という考えが頭をよぎりました。

そして、以前から実装していた Web Bluetooth API を使った toio の複数台の処理のプログラムを書き直して、6台同時に動かせるかを試しました。結論から言うと、以下のように　6台同時制御に成功しました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">自宅にある <a href="https://twitter.com/hashtag/toio?src=hash&amp;ref_src=twsrc%5Etfw">#toio</a> 6台の同時制御シリーズ、第2弾。<br><br>「6台同時接続＆全てに同じモーター制御を適用」という実装を Web Bluetooth API を使って書きました（実行はブラウザ上）。<br><br>以前、何度も書いていたプログラムの実装を見直してたらできてしまった（今までの実装だと、同時に 3〜4台までだった）。 <a href="https://t.co/NUFRVPEqhV">pic.twitter.com/NUFRVPEqhV</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1386360362883182602?ref_src=twsrc%5Etfw">April 25, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ちなみに、台数が 6台になってるのは、単純に自分が持っている台数が 6台だから、という理由です。

## 実装内容
ソースコード全体は、以下になります。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Web Bluetooth API による複数同時接続</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.css"/>
  </head>
  <body>
    <section class="section">
      <div class="container">
        <h1 class="title">操作用ボタン</h1>
        <div class="buttons" style="margin-top: 1.5rem">
          <button class="button is-success is-light" type="button" onclick="onStartButtonClick()">接続</button>
          <button class="button is-info is-light" type="button" onclick="onButton02Click()">一斉動作</button>
        </div>
      </div>
    </section>

    <script>
      const TOIO_SERVICE_UUID = "10b20100-5b3b-4571-9508-cf3efcd7bbae";
      const MOTOR_CHARACTERISTIC_UUID = "10b20102-5b3b-4571-9508-cf3efcd7bbae";
      const motorBuf = new Uint8Array([0x02, 0x01, 0x01, 0x32, 0x02, 0x02, 0x32, 0x78,]);

      let myCharacteristics = [];

      async function onStartButtonClick() {
        let serviceUuid = TOIO_SERVICE_UUID;

        try {
          console.log("Requesting Bluetooth Device...");
          const device = await navigator.bluetooth.requestDevice({
            filters: [{ services: [serviceUuid] }],
          });
          console.log("Connecting to GATT Server...");
          const server = await device.gatt.connect();
          console.log("Getting Service...");
          const service = await server.getPrimaryService(serviceUuid);
          console.log("Getting Characteristic...");
          const characteristic = await service.getCharacteristic(
            MOTOR_CHARACTERISTIC_UUID
          );
          myCharacteristics.push(characteristic);
          console.log(myCharacteristics.length);
        } catch (error) {
          console.log("Argh! " + error);
        }
      }

      async function onButton02Click() {
        if (myCharacteristics.length !== 0) {
          for (const element of myCharacteristics) {
            console.log("write");
            await element.writeValue(motorBuf);
          }
        }
      }
    </script>
  </body>
</html>
```

HTML の部分はボタンを 2つ作っていて、接続処理用のものとモーター制御用のものです。
接続用ボタンは使い回しをする形で、1個を繰り返し使うことで 6台分の接続処理を行えます（1台ずつ手動でつないでいく流れ）。もう 1つのモーター制御用のボタンは、ボタンが押された時点でつながっている全ての toio のモーター制御を行います。

モーター制御用のバイナリデータは、toio の通信仕様のモーターの部分にある「時間指定付きモーター制御」を使っています。また、toio関連の UUID 2つも、以下の仕様に掲載されているものです。
　●モーター · toio™コア キューブ 技術仕様
　　https://toio.github.io/toio-spec/docs/assets/motor_cube_direction.svg

その他の部分は、過去に書いた記事でも使ったノウハウを利用しています。
　●toio を Web Bluetooth API で制御（「通知・読み出し・書き込み」を行う） - Qiita
　　https://qiita.com/youtoy/items/791905964d871ac987d6
　●toio を音で制御してみた（Audio用の Teachable Machine でベルやタンバリンの音を機械学習） - Qiita
　　https://qiita.com/youtoy/items/37f70bb4ce630e6cbd92

## まとめ
Web Bluetooth API でも 6台同時に制御するというのができたので、Node.js実装のものとは違った活用法を見つけられればと思います。

## 【追記】 音の機械学習・機械学習による手の認識との組み合わせ
その後、Teachable Machine を使った音の機械学習と組み合わせたもの、MediaPipe Hands による手の認識と組み合わせたものを作ったりしました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">5/1・2 に行われた <a href="https://twitter.com/hashtag/%E5%AD%90%E3%81%A9%E3%82%82%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%91%E3%83%BC%E3%82%AF?src=hash&amp;ref_src=twsrc%5Etfw">#子どもプログラミングパーク</a> の中の企画「モノとつながる楽しいプログラミング（トーク＆デモ）」でデモを行った仕組み。<br>声を合図に <a href="https://twitter.com/hashtag/toio?src=hash&amp;ref_src=twsrc%5Etfw">#toio</a> 6台を一斉に動作させるものだったのですが、動画を公開してなかったのでツイート。<br>※ <a href="https://twitter.com/hashtag/TeachableMachine?src=hash&amp;ref_src=twsrc%5Etfw">#TeachableMachine</a> による音の機械学習を組み合わせ <a href="https://t.co/KC0lCCZxwu">pic.twitter.com/KC0lCCZxwu</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1389306314069733376?ref_src=twsrc%5Etfw">May 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">カメラで認識した指の動き（2本の指の距離の大きさ）を使って、 <a href="https://twitter.com/hashtag/toio?src=hash&amp;ref_src=twsrc%5Etfw">#toio</a> 6台の回転動作の ON/OFF を制御する、ちょっとしたお試し！<br><br>技術的には、以前から個別で使っていた 2つ<br>「手の認識： <a href="https://twitter.com/hashtag/MediaPipe?src=hash&amp;ref_src=twsrc%5Etfw">#MediaPipe</a> Hands の <a href="https://twitter.com/hashtag/TensorFlowJS?src=hash&amp;ref_src=twsrc%5Etfw">#TensorFlowJS</a> 実装（ブラウザで動くもの）、toio の制御： Web Bluetooth API」です。 <a href="https://t.co/gN4DoKKgDf">pic.twitter.com/gN4DoKKgDf</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1389266337181036545?ref_src=twsrc%5Etfw">May 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>