Androidのメモとか

ポキオの日記です。今日も遅延してない。

micro:bitをWeb Bluetooth APIで通信するときにハマったポイント

たくさんハマりました。

micro:bit Web Bluetooth API

メモメモ

micro:bitを買ってから色々といじってましたが、色んな所でハマったのでメモしておきます。

JavaScript Block EditorでBluetoothのブロックが見つからない

デフォルトで非表示という罠。

relativelayout.hatenablog.com

Web Bluetooth APIが使えるOS/ブラウザの組み合わせが意外と少ない

Chrome on Macは優秀。Safariが対応してなくてビビる。

github.com

BLEデバイスのスキャン

Web Bluetooth

ページ上でユーザーアクションをトリガーに、ブラウザのBLEデバイスリスト画面をnavigator.bluetooth.requestDevice()で表示させることで、特定のBLEデバイスと接続し通信するわけですが。

  navigator.bluetooth.requestDevice({
    filters: [
      { services: [LED_SERVICE] },
      { namePrefix: "BBC micro:bit" }
    ]
  })

結論から言うと、こんな感じで書くとうまく動作しました。ここで、LED_SERVICEというのは、サービスのUUIDで、

// micro:bit LEDサービス
const LED_SERVICE = "e95dd91d-251d-470a-a062-fa1922dfa9a8";

こんな感じです。

例えば、servicesを指定しないと、

SecurityError: Origin is not allowed to access any service. Tip: Add the service UUID to 'optionalServices' in requestDevice() options. https://goo.gl/HxfxSQ

セキュリティ観点でブラウザに怒られてしまい、機器リストには表示されるものの、いざ接続してRead/Writeしようとすると失敗してしまいます。

  navigator.bluetooth.requestDevice({
    filters: [
      { services: [LED_SERVICE] }
    ]
  })

じゃあservicesだけならいいのかと思うと、そういうわけでなく、これだとデバイスをうまく見つけられません。

  navigator.bluetooth.requestDevice({
    services: [LED_SERVICE]
  })

むしゃくしゃしてこういう書き方をしてしまうと、

TypeError: Failed to execute 'requestDevice' on 'Bluetooth': Either 'filters' should be present or 'acceptAllDevices' should be true, but not both.

と言われてしまいます。acceptAllDevicestrueにしてもいいですが、そうすると関係ないBLEデバイスも機器リストに表示されてしまい、見づらくなってしまいます。servicesでサービスを指定しつつ、名前のprefixでフィルターするには、

  navigator.bluetooth.requestDevice({
    filters: [
      { services: [LED_SERVICE] },
      { namePrefix: "BBC micro:bit" }
    ]
  })

やっぱりこういう書き方がジャスティスっぽいです。filtersで条件をつなげていくといい感じにANDでフィルターしてくれます。

サービス、キャラクタリスティックのUUIDや仕様がわからない

ここの情報を信じて実装しました。

Bluetooth Developer Studio - Profile Report

ちなみに、先程のLEDサービスのUUIDは、プロファイルの仕様書上はE95DD91D251D470AA062FA1922DFA9A8と書かれていますが、このままJavaScriptのコードに書いてしまうとエラーになってしまいました。ちゃんとハイフンを入れてあげて、e95dd91d-251d-470a-a062-fa1922dfa9a8みたいな感じで書いてあげなければ行けません。キャラクタリスティックのUUIDも同様です。

一部未実装?だったり、セキュリティ的にアクセスできないキャラクタリスティックがある

先程のプロファイルの仕様書では、Device Informationというサービスがあり、

  • Model Number String
  • Serial Number String
  • Hardware Revision String
  • Firmware Revision String
  • Manufacturer Name String

という5つのキャラクタリスティックがあるようですが、実際にアクセスしてみると、Serial Number Stringは

SecurityError: getCharacteristic(s) called with blocklisted UUID. https://goo.gl/4NeimX

セキュリティ的にアクセスが封じられているようです。また、Hardware Revision StringとManufacturer Name Stringは、そもそもキャラクタリスティックが見つかりませんでした。

「Androidのメモとか」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。

このブログは個人的なメモ書きであったり、考えを書く場所であります。執筆者の所属する団体や企業のコメントや意向とは無関係であります。また、このブログは必ずしも正しいことが書かれているとは限らず、誤字脱字や意図せず誤った情報を載せる場合がありえます。それが原因で読者が不利益を被ったとしても、執筆者はいかなる責任も負いません。ありがとうございます。