micro:bitとWeb Bluetoothで始める!ブラウザからのIoT制御入門

子ども向けのレクチャーとしてmicro:bitを使用していますが、IoT系のハッカソンなどでは、複雑になってくるとmicro:bitからRaspberryPiへの変更を余儀なくされることもあります。ただ、micro:bitは電池駆動ができることで、身につけるものにもつけられるといった利点もあり、なんとか活かせないかなと思っていました。ESP32でもいいのですが…、メンバーにエンジニアがいないというときには難易度が上がるのが問題です。

そこで、今回はWeb Bluetoothを使用してmicro:bitとシリアル通信を行い、micro:bitのセンサーや機能をを用いるといったことができないかを実験してみました。

1. micro:bitWeb Bluetoothを使用したシリアル通信の方法

micro:bitWeb Bluetoothの概要

ご存知の方もいるかと思いますが、micro:bitは教育用に開発された小型のコンピュータボードで、様々なセンサーやLEDディスプレイ、無線通信機能を搭載しています。実はこのBluetooth機能を利用することで、スマートフォンやパソコンなど他のデバイスと通信することもできます。

また、Web Bluetooth APIは、Webブラウザから直接Bluetooth対応デバイスに接続し、データのやり取りを行うための技術です。従来はネイティブアプリケーションでしか実現できなかったBluetooth通信が、Webアプリケーションでも可能になりました。これにより、プラットフォームに依存しない形でmicro:bitと通信するアプリケーションを開発できます。

必要な環境・機材

今回使用しているのは以下の環境・機材となります。

ハードウェア

  • micro:bit(V2)
  • USB ケーブル(micro:bitのプログラミング用)
  • WindowsPC(MacLinuxでも可能だと思います)

ソフトウェア

  • Google Chromeを推奨します。(Microsoft EdgeなどのWeb Bluetooth APIをサポートするブラウザでも大丈夫だと思います)
  • MakeCode Editormicro:bitのプログラミング環境)

2. micro:bitBluetooth機能について

UART(シリアル通信)サービスについて

micro:bitは、Bluetooth Low Energy(BLE)規格を採用していて、様々なBLEサービスを提供しています。今回はUART(Universal Asynchronous Receiver/Transmitter)サービスを使用します。テキストデータや数値データを双方向で送受信することが可能です。

UARTサービスは、以下のような特徴を持っています。

  • 双方向通信:送信(TX)と受信(RX)の2つの特性(Characteristic)を持ち、データの送受信が可能
  • テキストベース:主にテキスト形式でデータをやり取り(バイナリデータも扱えます)
  • 標準的:多くのBluetooth対応デバイスで採用されている

micro:bitUARTサービスで使用するUUIDは以下の通りです。このUUIDを使用してサービスの有効化を行います。

項目 UUID
サービスUUID 6e400001-b5a3-f393-e0a9-e50e24dcca9e
送信特性UUID(micro:bitからデータを受信) 6e400002-b5a3-f393-e0a9-e50e24dcca9e
受信特性UUID(micro:bitへデータを送信) 6e400003-b5a3-f393-e0a9-e50e24dcca9e

また、今回の通信では、データの区切りとして改行コード(\n)が使用します。これはmicro:bitから送信されるデータは通常、末尾に改行コードが付加されているためです。同様に、micro:bitへデータを送信する際も、改行コードを付けることでデータの区切りを明確します。

Bluetoothの有効化

micro:bitBluetooth機能を使用するには、プログラムでBluetoothを有効化する必要があります。MakeCodeでは、【拡張機能】から【Bluetooth】を追加することで、Bluetooth関連のブロックが使用可能になります。

MakeCodeでのBluetooth拡張機能の追加手順:

  1. MakeCode Editorを開く(https://makecode.microbit.org/
  2. 【新しいプロジェクト】をクリック、プロジェクトに名前をつけてください。
  3. 画面左側の【拡張機能】をクリック
  4. 検索ボックスにbluetoothと入力
  5. 表示されたbluetooth拡張機能をクリック

これにより、Bluetoothカテゴリが追加され、UART関連のブロックが使用できるようになります。

Bluetooth拡張機能には、今回は主に以下のブロックを使用します。

ブロック名 機能
Bluetooth UARTサービス UARTサービスを有効化
Bluetooth 接続されたとき Bluetoothの接続時の処理
Bluetooth 接続が切断されたとき Bluetoothの切断時の処理
UARTで1行書き出す テキストをUART経由で送信、改行コードを末尾に付与
UARTで受信したとき 区切り文字 UART経由でデータを受信したときのトリガ処理
UART次のいずれかの文字の手前まで受信 UART経由でデータを受信したときの処理

これらのブロックを使用して、簡単にmicro:bitとブラウザ間での通信プログラムを作成することができます。

3. micro:bit側のプログラミング

MakeCodeブロックプログラミングによる実装

MakeCodeを使って、micro:bit側のUART通信プログラムを作成します。今回は以下の機能を実装していきます。

  • ボタンA/Bが押されたときに対応するデータを送信(micro:bit→ブラウザ)
  • 左右の傾きを検知して送信(micro:bit→ブラウザ)
  • テキストコマンドを受信してLEDの表示を制御(ブラウザ→micro:bit

手順1: 基本設定

まず、Bluetooth UARTサービスを初期化します。

このブロックにより、micro:bitBluetooth機能とUARTサービスが有効になります。プログラムの最初に配置してください。

手順2: ボタン入力の送信

ボタンA/Bが押されたときにテキストを送信するブロックを追加します。

ここで重要なのは、送信データの末尾に改行コード\nを付けることです。これにより、受信側でデータの区切りを認識できます。今回のブロックでは自動的に改行コードをつけて送信をしてくれます。

手順3: 傾きの検出と送信

加速度センサーを使って、micro:bitの傾きを検出し送信します。

この例では、左右の傾きを検出していますが、必要に応じて前後の傾き(Y軸)や揺れ(Z軸)も検出できます。

手順4: コマンド受信処理

受信したテキストに応じてLEDを制御するブロックを追加します。

また、このブロックは、特定のコマンドを受信したときに対応する処理を行います。

  • led:on → テキストをスクロール表示し、LEDをすべて点灯、受信テキストを送信側へ返す
  • led:off → テキストをスクロール表示し、LEDをすべて消灯、受信テキストを送信側へ返す ‐ その他文字列 → テキストをスクロール表示し、受信テキストを送信側へ返す

ソースコード

ブロックプログラムではそのまま共有ができないので、MakecodeのUIでブロックからPythonコード変換して以下のコードをペースとすれば同じものが作成出来ます。

micro:bit‐ブラウザ間でWebBluetoothのUart通信を行うサンプルプログラム

4. Web側の実装

Web Bluetooth APIの基本

Web Bluetooth APIは、Webページから直接Bluetoothバイスに接続し、通信するためのJavaScript APIです。以下に基本的な使用ステップを説明します。

1. デバイスの要求と接続

Bluetooth接続は、ユーザーのアクションから開始する必要があり、セキュリティ上の理由から自動接続はできないようになっています。接続後特定のサービスと特性(Characteristic)にアクセスします。

      // 接続ボタンのクリックイベント
      async function onConnectButtonClick() {
        try {
          addLog('Bluetoothデバイスをリクエスト中...');
          device = await navigator.bluetooth.requestDevice({
            filters: [
              { services: [UUID_UART_SERVICE] },
              { namePrefix: "BBC micro:bit" },
            ],
          });

          addLog(`デバイス「${device.name}」を選択しました`);
          
          // 切断イベントを監視
          device.addEventListener('gattserverdisconnected', onDisconnected);

          addLog('GATTサーバーに接続中...');
          const server = await device.gatt.connect();
          
          addLog('UARTサービスを取得中...');
          const service = await server.getPrimaryService(UUID_UART_SERVICE);
          
          addLog('Characteristic(受信用)を取得中...');
          txCharacteristic = await service.getCharacteristic(UUID_TX_CHAR_CHARACTERISTIC);
          await txCharacteristic.startNotifications();
          txCharacteristic.addEventListener('characteristicvaluechanged', handleNotifications);
          addLog('受信の通知を開始しました');
          
          addLog('Characteristic(送信用)を取得中...');
          rxCharacteristic = await service.getCharacteristic(UUID_RX_CHAR_CHARACTERISTIC);
          addLog('送信の準備ができました');
          
          updateConnectionStatus(true);
        } catch (error) {
          addLog(`エラーが発生しました: ${error}`, 'error');
          console.error('接続エラー:', error);
        }
      }

※重要な命名規則についての注意点:

Bluetooth UARTサービスでは、「TX」と「RX」の名称はデバイス側(micro:bit側)から見た方向で名付けられています。これが混乱を招くことがあります。

  • TX Characteristic (UUID_TX_CHAR_CHARACTERISTIC):

    • micro:bitの「送信(Transmit)」特性
    • Webアプリケーションからは「受信」用に使用
    • 変数名は txCharacteristic だが、ブラウザ側では受信処理に使用
  • RX Characteristic (UUID_RX_CHAR_CHARACTERISTIC):

    • micro:bitの「受信(Receive)」特性
    • Webアプリケーションからは「送信」用に使用
    • 変数名は rxCharacteristic だが、ブラウザ側では送信処理に使用
特性 UUID micro:bitから見た意味 Webアプリ側の用途
TX 6e400002-... micro:bitが送信(TX) Webアプリが「受信」
RX 6e400003-... micro:bitが受信(RX) Webアプリが「送信」

この命名規則はBLEの標準に従っており、ペリフェラル(デバイス側)の視点に基づいています。コードを書く際は、この点に注意してください。

2. 通知の開始(データ受信)

バイスからのデータを受信するには、通知を開始する必要があります。

      function handleNotifications(event) {
        try {
          const value = event.target.value;
          const inputValue = new TextDecoder().decode(value).replace(/\r?\n/g, '');
          
          // 受信データの種類に応じた処理
          let logMessage = '';
          switch (inputValue) {
            case "buttonA":
              logMessage = `受信: Aボタンが押されました`;
              break;
            case "buttonB":
              logMessage = `受信: Bボタンが押されました`;
              break;
            case "left":
              logMessage = `受信: 左に傾きました`;
              break;
            case "right":
              logMessage = `受信: 右に傾きました`;
              break;
            default:
              // 数値データかどうか確認
              const numValue = parseInt(inputValue);
              if (!isNaN(numValue)) {
                logMessage = `受信: センサ値 ${numValue}`;
              } else {
                logMessage = `受信: ${inputValue}`;
              }
          }
          
          addLog(logMessage, 'received');
          console.log(logMessage);
        } catch (error) {
          addLog(`受信エラー: ${error}`, 'error');
          console.error('受信エラー:', error);
        }
      }

3. データの送信

バイスにデータを送信するには、writeValueメソッドを使用します。

      async function sendMessage() {
        if (!rxCharacteristic) {
          addLog('送信できません: デバイスが接続されていません', 'error');
          return;
        }

        const message = messageInput.value.trim();
        if (message === '') {
          return;
        }

        try {
          // 改行コードを追加してテキストをUint8Arrayに変換
          const encoder = new TextEncoder();
          const data = encoder.encode(message + '\n');
          
          // データ送信
          await rxCharacteristic.writeValue(data);
          addLog(`送信: ${message}`, 'sent');
          
          // 入力フィールドをクリア
          messageInput.value = '';
        } catch (error) {
          addLog(`送信エラー: ${error}`, 'error');
          console.error('送信エラー:', error);
        }
      }

4. ソースコード(HTMLの全体像)

開始時は【micro:bit接続】ボタンをクリックし、対象となるmicto:bitを選択してください。※事前に機器同士のペアリングを行う必要があります。

WebBluetoothを使用してHTMLからmicro:bitにUart通信を行う

5. 注意点

Web Bluetooth APIを使用する際には、いくつかの重要な注意点があります。この章では、実装時に直面する可能性のある制限事項や問題点について説明します。

Web Bluetooth APIのセキュリティ制限

Web Bluetooth APIは、セキュリティ上の理由から、特定の条件下でのみ動作します:

1. HTTPS または localhost 環境のみで動作

Web Bluetooth APIは、以下の環境でのみ使用可能です: - HTTPSで提供されるWebサイト(セキュアな接続) - ローカルホスト(localhost)環境

通常のHTTP環境では、セキュリティ上の理由からWeb Bluetooth APIは利用できません。これは、悪意あるサイトがユーザーのBluetoothバイス不正アクセスするリスクを防ぐための制限です。

実装方法

  • 開発時は localhost を使用する(直接HTMLファイルをブラウザで開いてもOK)
  • 本番環境では必ずHTTPS上で提供する
  • GitHubページなどの無料のHTTPSホスティングサービスも利用可能

以下のコードを用いれば、簡易なチェックが可能です

// 安全でない環境での簡易チェック
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
  alert('**Web Bluetooth API**はHTTPSまたはlocalhost環境でのみ動作します。');
}

2. ユーザーアクションが必要

セキュリティ上の理由から、Bluetooth接続はユーザーのアクション(クリックなど)から直接開始する必要があります。ページ読み込み時の自動接続などはできません。

// 正しい使用法
connectButton.addEventListener('click', onConnectButtonClick);

// 間違った使用法(動作しない)
window.onload = onConnectButtonClick; // ❌

3. ブラウザの互換性

Web Bluetooth APIはすべてのブラウザでサポートされているわけではありません。以下を参照してください。

github.com

サポートされていないブラウザ:

アプリケーションを開発する場合にはブラウザの互換性をチェックし、警告表示することをお勧めします。

6. おわりに

この基本的な通信の仕組みをつかうことで様々な応用も考えられます。

micro:bitWeb Bluetooth APIを使用したシリアル通信が可能になりました。これによって特別なアプリケーションをインストールすることなく、Webブラウザから直接micro:bitと通信することができます🤗また、プラットフォームに依存しない点も嬉しいですね😊