ブラウザ(JavaScript)でマイクロビットとBLE!

IoT

こんにちは、ECF Techブログ
担当 Michiです。

今回はマイクロビットとブラウザ(JavaScript)を使ったBLE接続を行なってみたいと思います。

はじめに

Web Bluetooth API

Web Bluetooth APIというものを使います。かなり以前からあったようなのですが、しばらくWindows上のブラウザでは対応していなかった時期がありました。Windows上のChromeブラウザでも動作するようになったそうなので、今回はその実験プログラムです。

Web Bluetooth APIのブラウザごとの対応状況などについては、Web Bluetooth Community Groupの「Implementation Status」ページでご確認ください。

Web Bluetooth APIの仕様については、Web Bluetooth Draft Community Groupのレポート(英文)が参考になるかと思います。

記事の概要と想定読者

本記事ではとりあえず接続ができた。というサンプルプログラムの提供に留めます。BLE(Bluetooth Low Energy)の基本的な内容については、こちら(当ブログ記事)をご覧ください。

サンプル内のコードにコメントを記載する形で説明をさせて頂いています。JavaScriptの基本的なコードが読める方が対象になっております。ご了承ください。

プログラムの内容

  • スタートボタンでマイクロビットとブラウザを接続し、ボタン状況の通知を開始します。
  • マイクロビットでAやBのボタンが押された際にその状況を検知し、ブラウザに上のように表示します。
  • ストップボタンで通知を終了します。

サンプルコード

<!DOCTYPE html>

<html>
    <head>
        
    </head>
    <body>
        Bluetooth接続サンプル
        <input type="button" value="スタート" onclick="pushStart()" />
        <input type="button" value="ストップ" onclick="pushStop()" />
        <div id="buttonA">
        </div>
        <div id="buttonB">
        </div>
        <script>
            let charaA, charaB;
            function hello(){
                console.log("hello");
            }
            function pushStart(){
                console.log("pushStart");
                //microbit ボタンサービスのUUIDを直入れ
                let buttonUuid =  "E95D9882-251D-470A-A062-FA1922DFA9A8";
                let AButtonUuid = "E95DDA90-251D-470A-A062-FA1922DFA9A8";
                let BButtonUuid = "E95DDA91-251D-470A-A062-FA1922DFA9A8";
                //デバイスの取得
                navigator.bluetooth.requestDevice(
                    //デバイスにフィルターかけて、マイクロビットだけが見えるようにできる
                    //ようですが上手くいかなかったので、とりあえず全デバイスを許可
                    //{filters: [{services:[buttonUuid.toLowerCase()]}] }
                    {acceptAllDevices:true,optionalServices:[buttonUuid.toLowerCase()]}
                ).then(         //デバイス取得できたら
                    device => {
                        console.log('Connecting micro:bit');
                        return device.gatt.connect();
                    }
                ).then(         //接続できたら
                    server => {
                        console.log('Getting Service');
                        return server.getPrimaryService(buttonUuid.toLowerCase());
                    }
                ).then(         //サービスが取得できたら
                    service => {
                        console.log('Getting Characteristics');
                        //2つのcharacteristicsの取得を待つ
                        return Promise.all([
                            //characteristicsの取得(Aボタン用)
                            service.getCharacteristic(AButtonUuid.toLowerCase())
                            .then(chara => {
                                //停止できるようにグローバルに保持
                                charaA = chara;
                                //通知サービスを開始
                                chara.startNotifications();
                                //リスナー関数の設定
                                chara.addEventListener('characteristicvaluechanged',listenerButtonA);
                            }
                            ),
                            //characteristicsの取得(Bボタン用)
                            service.getCharacteristic(BButtonUuid.toLowerCase())
                            .then(chara => {
                                //停止できるようにグローバルに保持
                                charaB = chara;
                                //通知サービスを開始
                                chara.startNotifications();
                                //リスナー関数の設定
                                chara.addEventListener('characteristicvaluechanged',listenerButtonB);
                            }
                            )
                        ]);
                    }
                )
                .catch(
                    error => {
                        //途中でエラー発生したらエラー出力
                        console.log('sorry Error!');
                        console.log(error.code);
                        console.log(error.message);
                        console.log(error.name);
                    }
                )
            }
            //通知停止
            function pushStop(){
                if( charaA ){
                    //通知の停止
                    charaA.stopNotifications().then(() => {
                        //リスナーの解放
                        charaA.removeEventListener('characteristicvaluechanged',listenerButtonA);
                        console.log("stop notification");
                    });
                }
                if( charaB ){
                    //通知の停止
                    charaB.stopNotifications().then(() => {
                        //リスナーの解放
                        charaB.removeEventListener('characteristicvaluechanged',listenerButtonB);
                        console.log("stop notification");
                    });
                }
            }
            
            //Aボタン用リスナ
            function listenerButtonA(event){
                let chara = event.target;
                //valueがDataViewオブジェクトになっている。microbit仕様によると値は
                //UINT8で提供されるので、その情報で取得
                let message = 'Aボタンが' + getStatus( chara.value.getUint8(0) );
                document.getElementById('buttonA').innerHTML = message;
            }
            //Bボタン用リスナ
            function listenerButtonB(event){
                let chara = event.target;
                let message = 'Bボタンが' + getStatus( chara.value.getUint8(0) );
                document.getElementById('buttonB').innerHTML = message;
            }
            //ボタンの状態を判別し文字列を返す
            function getStatus( value ){
                switch(value){
                   case 0:
                        return '離されました';
                   case 1:
                        return '押されました';
                   break;
                   case 2:
                        return '長押しされました';
                   break;
                }
            }
        </script>
    </body>
</html>

プログラム概要説明

マイクロビットのBLE仕様については、Lancaster Universityの下のドキュメントをご確認ください。
マイクロビット BLEのプロファイル

マイクロビットのボタンサービスでは、2つのキャラクタリスティクス(やり取り可能な情報)を取得できます。それぞれAボタンが押された状況Bボタンが押された状況の2つです。

この2つの値の通知をリスナー関数で受け取るように設定し、その値を判断してブラウザ表示を動的に変更しています。

動作方法

マイクロビットのプログラムの準備

マイクロビットのプログラムは下のようになります。

Bluetoothのブロックは次の手順で使う事ができます。
1.「高度なブロック」から「拡張機能」を使う

  1. Bluetoothを選択

  2. ピンクのボタンをクリック

また、プログラムをマイクロビットに保存する場合は右の歯車から「プロジェクトの設定」を選んで、下の図のように変更しておいてください。どの端末からでもマイクロビットに接続できる設定です。

動かしてみよう

本プログラムをブラウザで開き、「スタート」ボタンを押します。

下の画面が出るのでペア設定を押します。すると「接続済み」になると思います。

コンソールログがしばらく出ます。「Getting Characteristics」が出たところで準備OKです。

AボタンやBボタンを押します。

おわりに

本日はここまでとさせていただきます。最後までご覧いただきありがとうございました。

マイクロビットがブラウザと接続されたことで、また新しい楽しみ方が広がりそうです。VRとまではいきませんが、リアルと画面をつなげるゲームなんか作っていけたら面白いなと思っています。

今後も違うサービスを使ったサンプルを作っていければと思っていますので、ぜひまたご覧ください。


合同会社イー・シー・エフでは、子ども向けプログラミングなどの教育講座を実施しています。プログラミング教室の案内や教育教材の情報は、下記よりご確認ください。

ECFエデュケーション
タイトルとURLをコピーしました