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」が表示されます。