Web Bluetoothを使ってSensorTagをScanするスクリプトを作成します。なお、Web Bluetooth APIの仕様については、「Web Bluetooth」を参照してください。「Implementation Status」に、OS、ブラウザ、各APIに対応したWeb Bluetoothの対応状況が記述されています。今回は、Windows10上でChromeを使って動作を確認します。

動作環境

  • windows10 Pro
  • Chrome バージョン: 80.0.3987.122
  • セキュリティのため SSL 通信できるHTTPサーバ

Windows10上でChromeを使ってBLE機器をアクセスするにはChromeの設定は必要ありませんが、Raspberry Piでは、WebBluetooth は有効になっていないため、まず WebBluetoothを使えるようにChromeの設定を変えます。

  • ブラウザで chrome://flags にアクセスして試験運用機能の画面を開きます
  • 項目「Experimental Web Platform features」を [有効] に切り替えてブラウザを再起動します

Web Bluetoothライブラリの作成

BLEデバイスのスキャンは navigator.bluetooth.requestDevice メソッドを使用します。requestDevice メソッドは、Promise を介して BluetoothDevice オブジェクトが取得できます。仕様とサンプルは「Bluetooth.requestDevice()」を参照してください。引数として、BLEデバイスのフィルター条件を指定します。次の例では、heart_rate サービスを保持するデバイスが検出されます。services の代わりに name を指定すれば、指示したデバイス名を持つデバイスが検出できます。

let options = {
  filters: [
    {services: ['heart_rate']},
    {services: [0x1802, 0x1803]},
    {services: ['c48e6067-5295-48d3-8d5c-0395f61792b1']},
    {name: 'ExampleName'},
    {namePrefix: 'Prefix'}
  ],
  optionalServices: ['battery_service']
}

navigator.bluetooth.requestDevice(options).then(function(device) {
  console.log('Name: ' + device.name);
  // Do something with the device.
})

Web Bluetoothライブラリは、「センサーデータをWeb Bluetooth APIで取得しよう!」で使用しているスクリプトをベースにして、次のようにクラス化しました。

  • 50行目のScanメソッドが呼ばれ、requestDeviceメソッドで BluetoothDevice オブジェクトを取得します。
  • 64行目で、コールバック関数「onScan」を呼びます。

bledevice.js

/* global Uint8Array, Promise */

class BleDevice {
//callBack

  constructor() {
    this.bluetoothDevice = null;
    this.service = null;
    this.dataCharacteristic = null;
    this.cmdcharacteristic = null;
    this.hashUUID = {};
    this.hashUUID_lastConnected;

    this.onScan = function (deviceName) {
      console.log("onScan");
    }

    this.onDisconnect = function () {
      console.log("onDisconnect");
    }

    this.onClear = function () {
      console.log("onClear");
    }

    this.onReset = function () {
      console.log("onReset");
    }

    this.onError = function (error) {
      console.log("onError");
    }
  }

  say() {
    console.log(this.nakigoe);
  }

//--------------------------------------------------
//setUUID
//--------------------------------------------------
  setUUID(name, serviceUUID, characteristicUUID) {

    console.log('Execute2 : setUUID');
    console.log(this.hashUUID);
    this.hashUUID[name] = {'serviceUUID': serviceUUID, 'characteristicUUID': characteristicUUID};
  }

//--------------------------------------------------
//scan
//--------------------------------------------------
  scan(uuid) {
    return (this.bluetoothDevice ? Promise.resolve() : this.requestDevice(uuid))
            .catch(error => {
              console.log('Error : ' + error);
              this.onError(error);
            });
  }

//--------------------------------------------------
//requestDevice
//--------------------------------------------------
  requestDevice(uuid) {
    console.log('Execute : requestDevice7');
    return navigator.bluetooth.requestDevice({
      acceptAllDevices: true,
      optionalServices: [this.hashUUID[uuid].serviceUUID]})
            .then(device => {
              this.bluetoothDevice = device;
              this.bluetoothDevice.addEventListener('gattserverdisconnected', this.onDisconnect);
              this.onScan(this.bluetoothDevice.name);
            });
  }

//--------------------------------------------------
//disconnect
//--------------------------------------------------
  disconnect() {
    if (!this.bluetoothDevice) {
      const error = "No Bluetooth Device";
      console.log('Error : ' + error);
      this.onError(error);
      return;
    }

    if (this.bluetoothDevice.gatt.connected) {
      console.log('Execute : disconnect');
      this.bluetoothDevice.gatt.disconnect();
    } else {
      const error = "Bluetooth Device is already disconnected";
      console.log('Error : ' + error);
      this.onError(error);
      return;
    }
  }

//--------------------------------------------------
//clear
//--------------------------------------------------
  clear() {
    console.log('Excute : Clear Device and Characteristic');
    this.bluetoothDevice = null;
    this.dataCharacteristic = null;
    this.onClear();
  }

//--------------------------------------------------
//reset(disconnect & clear)
//--------------------------------------------------
  reset() {
    console.log('Excute : reset');
    this.disconnect(); //disconnect() is not Promise Object
    this.clear();
    this.onReset();
  }

}

Web Bluetoothライブラリを使ったウェブページの作成

Web Bluetoothライブラリを使ったウェブページを次に示します。

  • Scanが終わると44行目に制御が移り、BLE装置名を表示します。
  • Scanボタンが押されると51行目に制御が移り、scanメソッドを呼びます。

index.html

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="description" content="BlueJelly">
    <meta name="viewport" content="width=640, maximum-scale=1.0, user-scalable=yes">
    <title>TomoSoft</title>
    <link href="https://fonts.googleapis.com/css?family=Lato:100,300,400,700,900" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="style.css">
    <script type="text/javascript" src="bledevice.js"></script>
  </head>

  <body>
    <h1> </h1>
    <div class="container">
      <div class="title margin">
        <p id="title">BLE Scan Sample</p>
      </div>

      <div class="contents margin">
        <button id="scan" class="button">Scan</button>
        <hr>
        <div id="device_name"> </div>
      </div>
    </div>
    <script>
    //--------------------------------------------------
    //Global変数
    //--------------------------------------------------
      var ble = new BleDevice();

    //--------------------------------------------------
    //ロード時の処理
    //--------------------------------------------------
      window.onload = function () {
        //UUIDの設定
        ble.setUUID("UUID1", "00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000");
      };

    //--------------------------------------------------
    //Scan後の処理
    //--------------------------------------------------
      ble.onScan = function (deviceName) {
        document.getElementById('device_name').innerHTML = deviceName;
      };

    //-------------------------------------------------
    //ボタンが押された時のイベント登録
    //--------------------------------------------------
      document.getElementById('scan').addEventListener('click', function () {
        ble.scan('UUID1');
      });

    </script>
  </body>
</html>

SensorTagのScan実施

作成したウェブページをhttpsサーバにアップロードし、Chromeを使ってアクセスします。Scanボタンを押すと、ダイアログが表示され検索が始まるので、SensorTagのボタンを押します。次のようにダイアログに「SensorTag」が表示されます。