Web Bluetooth APIでBLE通信

2018.09.25

WebブラウザでBLE通信

今回はWeb Bluetooth APIを利用して、PCのWebブラウザとRaspberry Piの間でBLE通信をしてみたいと思います。

BLE通信とは

BLEとはBluetooth Low Energyの略で、Bluetoothのバージョン4.0以降のものを指します。
従来の規格に比べて、省電力かつ省コストで通信や実装を行うことができます。バージョン3.0以前のものとは互換性がありません。
有名なプロダクトだとAppleのibeaconにもこの規格が用いられています。
今回の検証を行うに当たって重要になるBLE通信のキーワードは以下になります。個別にご紹介していきます。

    • GATT
    • Service
    • Characteristic
    • Descriptor
    • セントラルとペリフェラル
  • リクエスト

GATT

「Generic Attribute Profile」の略で、 Bluetooth通信でデータを送受信する方法や形式が決められている規格です。これによって通信の規格が統一されているおかげで、異なるメーカーのBLEデバイス同士でも簡単に通信が行えるようになっています。

Service

Serviceとは、BLEデバイスに備わっている一つの機能のことです。
例えば、BLE対応スマートフォンなら現在のバッテリーの残量を測定するServiceなどがあります。公式のドキュメントにデフォルトで用意されている機能をそのまま利用することもできるし、オリジナルの機能を作成することもできます。Bluetooth通信でLEDを点滅させる機能などは公式には用意されていないため自作する必要があります。公式の機能の詳細はこちらのページから確認することができます。また、Serviceはデバイス間でやりとりすることのできるCharacteristicという値を保持することができます。

Characteristic

Characteristicとは、上記のServiceが扱う情報やデータのことです。
例えば、スマートフォンのバッテリー残量を測定できるServiceにおけるバッテリーの残量(%)がこれに当たります。Serviceはその機能に合わせてCharacteristicを複数保持することができ、このCharacteristicの情報を送受信することによってBluetoothデバイス間で通信を行います。

Descriptor

Characteristicが保持している値の一つで、そのCharacteristicの説明文や追加情報を記載することができます。今回はペリフェラル側で宣言されているCharacteristicのDescriptorをセントラル側から取得してみます。

セントラルとペリフェラル

Bluetooth通信において、操作する側のことを「セントラル」、操作される側のことを「ペリフェラル」と呼びます。
今回は、セントラルであるWebブラウザからWeb Bluetooth APIを介して、ペリフェラルであるRaspberry Piと通信する形になります。

リクエスト

Bluetooth通信では接続したデバイス間で以下の3つのリクエストを使うことができます。

  • Read
  • Write
  • Notify

Read

セントラルから、ペリフェラルで設定されたServiceのCharacteristicの値を取得する。

Write

セントラルから、ペリフェラルで設定されたServiceのCharacteristicの値に書き込みする。

Notify

ペリフェラルのタイミングで、セントラルへ値を送信し、セントラル側がそれを受信します。

Web Bluetooth APIとは

WebサイトからBLEデバイスに接続することができるapiです。
今まではスマートフォンなどのデバイスとBluetooth通信を行うにはネイティブアプリで実装する必要がありましたが、 このAPIを利用することによってWebブラウザ側のJavaScriptでBLE通信の実装が可能になります。
基本的に上記のBluetooth通信のお作法に沿って実装していくことができます。

通信のイメージ図

今回の実装における全体像のイメージは以下の通りです。

セントラルであるPCのWebブラウザから、ペリフェラルであるRaspberry PiのblenoのServiceが保持するCharacteristic情報にリクエストを飛ばしてアクセスします。

blenoとは

操作される側であるペリフェラル(今回はRaspberry Pi)側の実装にはNode.jsのモジュールの一つであるblenoを利用しています。blenoはBLE通信におけるペリフェラル実装用のモジュールで、JavaScriptファイルに記述してペリフェラルのデバイス上のNodeで実行します。デバイス間でやりとりするService、Characteristic情報の設定はここで行います。

実装の大まかな流れ

  1. ペリフェラルと接続
  2. Readリクエスト
  3. Writeリクエスト
  4. Notifyリクエスト
  5. Descriptorの読み込み

テスト環境の設定手順はこちらにまとめられています。

それでは実装に移っていきます。

1.ペリフェラルと接続

まずはペリフェラル側で、今回の通信に使用するServiceと、そのServiceが保持するCharacteristic情報の設定を行なっていきます。

ペリフェラル側(bleno)の実装

[app.js]

これで、ペリフェラル側でのService情報の準備ができました。

セントラル側(Web Bluetooth API)の実装

次に、ペリフェラルと接続するための準備をセントラルで行います。

[ble.js]

これでセントラルからペリフェラルをスキャンして接続する準備ができました。

接続

では接続してみます。
スキャンを開始すると以下のような画面が表示され、周囲のBLEデバイスをスキャンしています。今回はセントラル側でスキャンするUUIDとデバイス名を指定しているためRaspberry Piしか表示されていません。

デバイスをスキャンして選択し、ペア設定で接続することができました。

2.Readリクエスト

ペリフェラルと接続ができたら、いよいよ情報の送受信の準備を行なっていきます。
まずはセントラル側で、ペリフェラルにリクエストを送信するための準備を行います。Readした値が画面に表示されるように実装しています。

セントラル側の実装

[ble.js]

これで、セントラルからペリフェラルにReadリクエストを送信する準備ができました。

ペリフェラル側の実装

ペリフェラル側のbleno内ではセントラルからRead、Writeリクエストを受けたタイミングで処理を走らせることができます。デバック用にReadリクエストを受けたこととセントラルに送信した(読み取られた)値を出力するようにしてあります。

[app.js]

Readリクエスト実行

では、実際にReadリクエストを実行して、セントラルがペリフェラルの値を読み込めるか試してみます。

ペリフェラル側で設定したCharacteristicの値と同じものが取得できています。

3.Writeリクエスト

次は、セントラルからペリフェラルにWriteリクエストを送信し、ペリフェラルのCharacteristicが保持する値の中身を書き換えてみます。

セントラル側の実装

[ble.js]

セントラルからペリフェラルにWriteリクエストを送信する準備ができました。

ペリフェラル側の実装

ペリフェラル側では、セントラルから受け取ったWriteリクエストの内容をコンソールに出力します。

[app.js]

Writeリクエストしてみる

では実際にWriteリクエストを実行して、セントラルからペリフェラルに値を送信できるか試してみます。

ペリフェラル側のコンソール画面です。セントラルがWriteしたものと同じ文字列を取得できています。

4.Notifyリクエスト

今まではセントラル側のタイミングでReadやWriteリクエストが行われていましたが、Notifyリクエストを用いることによってペリフェラル側のタイミングでセントラルに値を送信することができます。

セントラル側の実装

[ble.js]

Notify通知を受け取ったら呼ばれるonRcvSensorData関数の設定がこちらです。

[ble.js]

ペリフェラルからNotify通知が送られてきたら、文字列に変換して画面に表示します。

ペリフェラル側の実装

ペリフェラル側からセントラルにNotify通知を送信する準備を行います。

[app.js]

Notify通知

実際にペリフェラル側からセントラル側にNotify通知をしてみます。

ペリフェラル側から送信されたNotify情報がセントラル側で取得できています。

5.Descriptorの読み込み

最後に、ペリフェラル側で設定されたDescriptor情報をセントラル側から読み込んでみます

セントラル側の実装

[ble.js]

Descriptorを取得

実際に、セントラル側でペリフェラル側のDescriptor情報を取得してみます。

ペリフェラル側で設定したDescriptor情報が取得できています。

ペリフェラル側ソースコード全文

[app.js]

セントラル側ソースコード全文

[index.html]
[ble.js]

セキュリティ上の懸念

BLEデバイス(ペリフェラル側)へ接続する際の認証はUUIDの一致で行われており、Webサイト(セントラル側)のJavaScriptソースでUUIDを宣言しておく必要があります。 もしも攻撃者がその場でWebサイトのJavaScriptソースからUUIDを盗み見て、そのIDを組み込んだ悪意のあるWebサイトからBLEデバイスにアクセスした場合、他の利用者の情報を盗み取られたり改ざんが行われる恐れがあります。 対策としては、データサーバーにUUIDを格納しておきJavaScriptファイルにはUUIDを直接記述しないことによって攻撃を行うための手間を増やす方法や、デバイスとの接続認証に個人のSNSのアカウントでのログイン認証を挟み込んで攻撃者を心理的に牽制する方法などが考えられますが、重要な個人情報を用いたサービスで用いるには不安が残るというのが現状のようです。

まとめ

今回は、Web Bluetooth APIを用いてWebブラウザとBLEデバイスのBLE通信をしてみました。
BLEデバイスが保持するServiceとCharacteristicの概念やRead、Write、Notifyリクエストの具体的な通信のイメージを掴めるかどうかがポイントではないかと思います。またWeb Bluetooth APIでは、BLEデバイスの電界強度を取得することもでき、WebブラウザからBLEデバイスとの距離も測ることができるようです。想像以上にWeb Bluetooth APIを使ってできることの幅は広そうです。