たくさんハマりました。
メモメモ
micro:bitを買ってから色々といじってましたが、色んな所でハマったのでメモしておきます。
JavaScript Block EditorでBluetoothのブロックが見つからない
デフォルトで非表示という罠。
Web Bluetooth APIが使えるOS/ブラウザの組み合わせが意外と少ない
Chrome on Macは優秀。Safariが対応してなくてビビる。
BLEデバイスのスキャン
ページ上でユーザーアクションをトリガーに、ブラウザの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.
と言われてしまいます。acceptAllDevices
をtrue
にしてもいいですが、そうすると関係ない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は、そもそもキャラクタリスティックが見つかりませんでした。