Tech Blog of Beatrobo, Inc.

Web Bluetooth API で BLE デバイスにブラウザから接続する

| Comments

こんばんは。 Beatrobo竹井です。

この記事は Bluetooth Low Energy Advent Calendar 2015 の20日目の記事です。

先日 JavaScriptでIoT !! JS Board Shibuya #6 LTナイト! に行った際に Web Bluetooth API の存在を知りました。

この Web Bluetooth API を利用すれば、ブラウザだけで Web サービスと BLE デバイスとがコミュニケーションできるようになるというわけです。

以前開発していた konashi-js-sdk では、ブラウザ上の JS で BLE デバイスとコミュニケーションを実現するため、BLE と通信する Native 側とブラウザ内の JS とが双方向にコミュニケーションできるカスタム WebView を作り、それを konashi.js アプリの中に埋め込んでいました。

それが Web Bluetooth API だと特別なアプリのインストールいらずで、普通のブラウザ上で konashi.js 相当のことができるようになります。

今回は、Web Bluetooth API の現状を整理しつつ、Web Bluetooth API を使って Proximity Profile デバイスとコミュニケーションする JS を作って見ようと思います。

コードは https://github.com/hideyuki/proximity-profile-with-web-bluetooth-api に実行可能な状態で置いています。

Web Bluetooth API の調査

現在、Web Bluetooth API は W3C に Draft として上がっています。この Draft にはサンプルコードもたくさん記載されています。

また、最新情報などは以下から取得できます。

そして Web Bluetooth API の実装状況はこちら。全体的には、やっと実装が始まってる & 実装すら始まっていないという感じです。

主要なブラウザの対応状況を見ていきましょう。

Chrome

Android 6 以上だと v48で GATT Notifications 以外はすべて実装されているようです。Mac OS X の Chromeだと Discovery のみ。

Mac OS X Chrome はまだアクティブではないようで、Android Chrome のほうをまず実装してからとなるようです。

ついでに、Windows, Linux はまだ実装も始まっていない状況です。

Firefox

Bug 1204396 – [meta] Align our GATT API with W3C spec にあるように、Firefox OS での実装が進んでいるようですが、歴史的経緯で W3C の Web Bluetooth API とは異なっているようです。

Windows Edge

実装ステータスはこちら。優先度は低でまだ評価中という段階のようです。

ということで

今回は Nexus5 の Android 6 で Web Bluetooth API にトライしてみましょう。

Android Chrome Dev で Web Bluetooth API を使う

現在の Android Chrome の Dev版 のバージョンは 49 です。

v48 だと characteristicvaluechanged イベントが発火しないようなのですが、v49 でも発火せず Notify はまだ使えない。残念。ということで今回は Read/Write ができるChracteristics を持つ Service を触っていきましょう。

Chrome で Web Bluetooth API を有効にするには、以下のフラグページで Web Bluetooth API を有効にする必要があります。

1
chrome://flags/#enable-web-bluetooth

BLE デバイスをお持ちでない方は、Androidアプリの BLE Peripheral Simulator か、iOSアプリの LightBlue Explorer をもう一台のスマホにインストールすることで、スマホ自体が仮想BLEデバイス (Peripheral) として振る舞ってくれるのでオススメです。

Proximity デバイスと通信!

今回は私の開発用iPhoneに LightBlue Explorer をインストールし、仮想 Proximity デバイスを作って Android Chrome Dev の Web Bluetooth API を使って通信させてみます。

本題に入る前に、Proximity Profile の整理をさくっと。

(余談ですが、Profile や Service の詳細を調べたいときは、developer.bluetooth.org の GATT Specifications > Profiles や、GATT Specifications > Services を見ると一目瞭然です!)

Proximity Profile (PXP)

Bluetooth Developer Portal: GATT Specifications > Profiles > Proximity

Proximity Profile は「近接」という単語の通り、デバイスとの距離をベースにアラートを生成するプロファイルで、スマートフォンの置き忘れなどのアプリケーションを作成する時に搭載されるものです。

この Proximity Profile には 以下の3つの Serices が定義されています。

Link Loss Service (org.bluetooth.service.link_loss)

Bluetooth Developer Portal: GATT Specifications > Services > Link Loss

接続が切れた時にアラートを鳴らすかの設定を行う Service です。Read/Write 可能な alert_level という Characteristic を持っています。

Immediate Alert Service (org.bluetooth.service.immediate_alert)

Bluetooth Developer Portal: GATT Specifications > Services > Immediate Alert

すぐさまアラートを鳴らせる Service です。WriteWithoutResponse のみ可能な alert_level という Characteristic を持っています。

Tx Power Service (org.bluetooth.service.tx_power)

Bluetooth Developer Portal: GATT Specifications > Services > Tx Power

BLE の送信パワーを読める Service です。Read のみ可能な tx_power_level という Characteristic を持っています。

ブラウザ(BLEのセントラル)側のコード例

BLE のセントラル側の一般的な処理の流れは以下です(ペアリングはややこしいので省きます)。

  • ① デバイスのスキャン
  • ② デバイスに接続
  • ③ デバイスの Services 情報を取得
  • ④ ③で得た Services の Characteristics 情報を取得
  • ⑤ Characteristics を操作する

現状の Web Bluetooth API はこれ以上のことはできなさそうなので、今回はこの①〜⑤を実装してみましょう。

以下、コードです。ES6ですのでご注意を。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// ① デバイスのスキャン
navigator.bluetooth.requestDevice({
  filters: [{
    services: [
      'link_loss',
      'immediate_alert',
      'tx_power'
    ]
  }]
})
  .then(device =>{
    // ② デバイス見つかったので、接続する
    return device.connectGATT();
  })
  .then(server =>{
    // ③ デバイスに接続できたので、そのデバイスのServiceを調べる
    return Promise.all([
      server.getPrimaryService('link_loss'),
      server.getPrimaryService('immediate_alert'),
      server.getPrimaryService('tx_power')
    ]);
  })
  .then(services =>{
  // ④ Serviceを全部調べたので、次はサービスに紐づくCharacteristicsを調べる
    return Promise.all([
      services[0].getCharacteristic('alert_level'),
      services[1].getCharacteristic('alert_level'),
      services[2].getCharacteristic('tx_power_level')
    ]);
  })
  // Discovered characteristics
  .then(characteristics =>{
      // ⑤ 全部の Chracteristics をゲット
      // あとはその Characteristics を Read/Writeしていく
  })
  .catch(error =>{
    // エラー時はここにくる
    console.log(error);
  });

.then (Promises)=> などは ES6 (ES2015) で新しく定義されている文法です。 ES6 に関しては Learn ES2015 がわかりやすいです。

注意点としては、https 上でしか Web Bluetooth API が動作しないようですので、オレオレ証明書を作ってローカルサーバでも https ができるようにしておくのが良いでしょう。

デモ

このような Proximity の Services/Characteristics を表示する JS/HTML を作成してみました。

https://proximity-web-bluetooth-api.herokuapp.com/

動作ムービーです。

Link Loss Service の alert_level の Read/Write はもちろんのこと、Proximity デバイス側から Link Loss Service の alert_level を書き換えてから、ブラウザから Read してもちゃんと反映されています。Characteristics の Read/Write は普通にできていますね。

Immediate Alert Service の alert_level Characteristic は WriteWithoutResponse なのですが、writeValue() だとエラーが出てしまうので Immediate Alert Service は非表示にしています。

開発Tips

Android Chrome のリモートデバッグ

現状の Web Bluetooth API だと、基本的には Android Chrome 上でした動作しないので、Android上で動作確認を行いながら開発を進めていくことになります。そんな時は、Android Chrome のリモートデバッグ機能を使うと、PCのChrome DevTools 上で Android の Chrome 上のページをデバッグできるようになり、とても楽です。

リモートデバッグのやり方は Remote Debugging on Android with Chrome が詳しいです。

Mac から Android Chrome へのポートフォワード

リモートデバッグ関連ですが、Mac 上で動作しているサーバ(JS などを https でホストしている)に Android から簡単にアクセスさせるために方法としてポートフォワードがいい感じです。ポートフォワードなら、Mac の IP を調べたり、同じ LAN 内にいなくても開発が進めることができます。設定は Chrome の DevTools から可能です。

まだ不安定。だが期待はできる!

実装自体もまだ始まったばかりの Web Bluetooth API。とても不安定です。実際に開発している最中でも、同じデバイス名が2つ出てきたり、まったく接続できなくなったりします。その時はブラウザを再起動してやればまた正常に動きますのでご安心を。

あと1年くらいすれば Android Chrome は落ち着きそうな感じ。あとは他のブラウザが追従してくるか…

すでに、Chrome の Extension 領域では chrome.bluetooth が利用可能ですので、OSX や Windows のChrome への実装もそう遠くない未来に実現するでしょう。

ブラウザ上でハードウェアとコミュニケーションができる API があることによって、ハードウェアと連動するWebページなど、今までの Web をより拡張したものができるかもしれません。今後も引き続き BLE 情報はウォッチしつつ、何かおもしろいプロダクトが作れればと思います。

BLE 好きな方、遊びにおいで!

アルバイトや正社員のエンジニア募集中です!

BLEが好きな方、ハードが好きな方。ぜひ弊社の代々木オフィスに遊びに来て語り合いましょう!

@HideyukiTakei もしくは、hide@beatrobo.com までご連絡頂ければ大歓迎いたします。

Comments