Web Bluetooth API と Web Serial API を使用すると、ウェブアプリはそれぞれ Bluetooth Low Energy(BLE)デバイスとシリアル デバイスと通信できます。多くのウェブ デベロッパーがすでにこれらの API を活用して大きな成果を上げていますが、Bluetooth Classic デバイスのサポートも求められています。
Web Serial API は、デスクトップ版 Chrome 117 の シリアルポート プロファイル(SPP)など、ペア設定された Bluetooth Classic デバイスの RFCOMM サービスとの通信をサポートするようになりました。これにより、ウェブ デベロッパーとユーザーの両方に新しい可能性が開かれます。以下に、この機能のメリットを享受できるデバイスをいくつか示します。
- Google Pixel Buds Pro などのワイヤレス イヤホンは、RFCOMM を使用して音声設定とファームウェア アップデートを管理します。
- モバイル POS システムは、Bluetooth SPP を使用してレシート プリンタと通信します。
- 家畜の RFID タグリーダーは、Bluetooth SPP を使用して動物の移動を記録します。
Bluetooth RFCOMM プロトコル
90 年代後半にタイムスリップしましょう。Palm Pilot をホルダーに置くだけで、翌日のカレンダーが同期されます。ワイヤレスで充電できたら便利ですよね。この新しい「Bluetooth」技術により、煩雑なコードをすべて排除できます。ワイヤレスは未来の技術です。問題は 1 つだけです。既存のすべてが RS-232 ケーブルで接続するように設計されています。そのため、Bluetooth は無線通信(RFCOMM)プロトコルを使用して、既存のすべてのソフトウェアとハードウェアにそのインターフェースを提供します。
現在でも、RFCOMM サービスは新規および既存のハードウェアで広く使用されています。これにより、これまで Bluetooth Low Energy では満たせなかった特定のレイテンシと帯域幅の要件を満たすことができます。そのため、Google は、シリアル デバイスに接続するための API である Web Serial と Bluetooth を統合し、メーカーが Bluetooth Low Energy に移行し、デベロッパーが代わりに Web Bluetooth API を使用できるようになるまで、これらのレガシー RFCOMM サービスへのアクセスを可能にしました。
Web Serial API の変更
パソコン版 Chrome 117 以降では、ウェブ デベロッパーは Web Serial API を使用して RFCOMM サービス経由でペア設定された Bluetooth Classic デバイスと確実に通信できるようになりました。これは、Web Serial API の次の更新によって可能になりました。
- Chrome で、標準化された Bluetooth 従来型シリアル ポート プロファイルを使用してシリアル インターフェースを公開する、ペア設定された Bluetooth デバイスが列挙されるようになりました。
- エミュレートされたシリアルポート経由でオペレーティング システムがデバイスノードを作成していない場合でも、Chrome がシリアル インターフェースと通信できるようになりました。
- Chrome は、RFCOMM シリアル インターフェースを公開するシリアルポート以外のサービスと通信できるようになりました(非標準のサービスクラス ID をご覧ください)。
Web Serial API の使用方法については、シリアルポートへの読み取りと書き込みをご覧ください。この記事では、Bluetooth に関する基本的な知識があることを前提として、Bluetooth 経由のシリアル通信の変更について説明します。
フィルタを指定せずに navigator.serial.requestPort()
を呼び出すと、Bluetooth 以外のシリアルポート、すでにマッピングされている Bluetooth シリアルポート、標準化された Bluetooth Classic シリアルポート プロファイルによって提供される未マッピングのシリアルポートを選択できます。
// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();
ほとんどのデバイスは、標準化された Bluetooth Classic シリアル ポート プロファイルを通じて SPP ベースの通信を公開していますが、一部のデバイスはカスタム RFCOMM ベースのサービスを使用しています。これらのデバイスのサービスクラス ID は、標準の Bluetooth UUID 範囲外です。
次の例に示すように、これらのカスタム RFCOMM ベースのサービスにアクセスするには、allowedBluetoothServiceClassIds
リストを navigator.serial.requestPort()
に渡す必要があります。
const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef";
// Prompt user to select any serial port.
// Access to the custom Bluetooth RFCOMM service above will be allowed.
const port = await navigator.serial.requestPort({
allowedBluetoothServiceClassIds: [myBluetoothServiceUuid],
});
Chrome は音声や動画などの Bluetooth Classic サービスをサポートしていないため、Bluetooth SIG ベースの UUID を使用するすべてのサービスクラス ID(つまり、末尾が「-0000-1000-8000-00805f9b34fb」のすべての UUID)は、シリアルポート プロファイル ID を除きブロックされます。
また、navigator.serial.requestPort()
を呼び出すときに bluetoothServiceClassId
フィルタキーを使用して、サービスクラス ID で識別されたフィルタされた Bluetooth シリアルポートのリストをユーザーに表示することもできます。下記の例をご覧ください。
const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef";
// Prompt the user to select Bluetooth serial ports with
// the custom Bluetooth RFCOMM service above.
const port = await navigator.serial.requestPort({
allowedBluetoothServiceClassIds: [myBluetoothServiceUuid],
filters: [{ bluetoothServiceClassId: myBluetoothServiceUuid }],
});
シリアルポートが Bluetooth デバイスの一部である場合、port.getInfo()
の呼び出しによって返されるシリアルポート情報には、ポートが接続されている RFCOMM チャネルに関連付けられたサービスクラス ID を含む新しい bluetoothServiceClassId
キーが含まれています。シリアルポートがマッピングされている場合は、「00001101-0000-1000-8000-00805f9b34fb」または短縮形式の 0x1101 を返します。
const { bluetoothServiceClassId } = port.getInfo();
ユースケースの例: Google Pixel Buds Pro を操作する
Google Pixel Buds Pro ウェブ コンパニオン アプリは、ウェブブラウザを搭載した任意のデバイスから Google Pixel Buds Pro を操作できる新しいウェブアプリです。プログレッシブ ウェブアプリ技術を使用して構築されているため、即時読み込みが可能です。必要に応じて、他のオペレーティング システム アプリと一緒にインストールすることもできます。
このアプリは、Web Serial API を使用して Google Pixel Buds Pro と通信します。これにより、アクティブ ノイズ コントロール、イコライザー、装着検知、ファームウェア アップデートなど、Google Pixel Buds Pro のさまざまな設定をユーザーが操作できるようになります。
Google Pixel Buds Pro ウェブ コンパニオン アプリをお試しいただくには、ChromeOS デバイスで mypixelbuds.google.com にアクセスしてください(他のプラットフォームは近日提供予定)。
リソース
謝辞
レビューを送信していただいた Reilly Grant 様、Thomas Steiner 様、Ben Morss 様、Vincent Scheib 様に感謝いたします。