1. はじめに
このセクションは参考です。
Bluetoothは、機器間の短距離無線通信規格の1つです。クラシックBluetooth ( BR / EDR ) では、バイナリプロトコルの組を定義し、最大約24Mbpsの通信速度をサポートしています。 Bluetooth4.0 では Bluetooth Smart( BLE または LE ) と呼ばれる「省電力」モードが新たに導入されました。 通信速度は1Mbpsに制限されますが、ほとんどの時間は送信機の電源を切ったままにすることができます。 BLEでは、機能の大半を Generic Attribute Profile( GATT ) によるキー/バリューのペアで提供しています。
BLEでは、機器が行う複数の役割を定義しています。Broadcaster と Ovserver の役割 は、それぞれ送信専用、受信専用のアプリケーションです。 Peripheral の役割で動作するデバイスは接続を受信し、Central の役割で動作するデバイスは Peripheral 機器と接続できます。
Peripheral または Central の役割で動作しているデバイスは、GATT server のホストになることが可能で、サーバーは、Service、Characteristic、Descriptor という階層になっています。この階層について、詳しくは §5.1 GATT Information Model を参照してください。BLEトランスポートをサポートするよう設計されていますが、GATTプロトコルはBR/EDRトランスポートでも動作します。
本仕様書の初版では、Central の役割を持つUAで実行すれば、ウェブページが BR/EDR または LEコネクション 経由で GATT server と接続できます。本仕様書では BLUETOOTH42 の仕様書を引用しますが、Bluetooth 4.0 or 4.1 だけ実装したデバイス間通信もサポートする予定です。
1.1. サンプル
標準的な心拍数モニターを探索しデータを取り出すには、以下のようなコードをウェブサイトでは使用するでしょう:
let chosenHeartRateService = null; navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'], }] }).then(device => device.gatt.connect()) .then(server => server.getPrimaryService('heart_rate')) .then(service => { chosenHeartRateService = service; return Promise.all([ service.getCharacteristic('body_sensor_location') .then(handleBodySensorLocationCharacteristic), service.getCharacteristic('heart_rate_measurement') .then(handleHeartRateMeasurementCharacteristic), ]); }); function handleBodySensorLocationCharacteristic(characteristic) { if (characteristic === null) { console.log("Unknown sensor location."); return Promise.resolve(); } return characteristic.readValue() .then(sensorLocationData => { let sensorLocation = sensorLocationData.getUint8(0); switch (sensorLocation) { case 0: return 'Other'; case 1: return 'Chest'; case 2: return 'Wrist'; case 3: return 'Finger'; case 4: return 'Hand'; case 5: return 'Ear Lobe'; case 6: return 'Foot'; default: return 'Unknown'; } }).then(location => console.log(location)); } function handleHeartRateMeasurementCharacteristic(characteristic) { characteristic.addEventListener('characteristicvaluechanged', onHeartRateChanged); return characteristic.startNotifications(); } function onHeartRateChanged(event) { let characteristic = event.target; console.log(parseHeartRate(characteristic.value)); }
BluetoothRemoteGATTCharacteristic
の value
の中でストアされた DataView
を読み取るために heart_rate_measurement
ドキュメントの中で定義されている。
function parseHeartRate(data) { let flags = data.getUint8(0); let rate16Bits = flags & 0x1; let result = {}; let index = 1; if (rate16Bits) { result.heartRate = data.getUint16(index, /*littleEndian=*/true); index += 2; } else { result.heartRate = data.getUint8(index); index += 1; } let contactDetected = flags & 0x2; let contactSensorPresent = flags & 0x4; if (contactSensorPresent) { result.contactDetected = !!contactDetected; } let energyPresent = flags & 0x8; if (energyPresent) { result.energyExpended = data.getUint16(index, /*littleEndian=*/true); index += 2; } let rrIntervalPresent = flags & 0x10; if (rrIntervalPresent) { let rrIntervals = []; for (; index + 1 < data.byteLength; index += 2) { rrIntervals.push(data.getUint16(index, /*littleEndian=*/true)); } result.rrIntervals = rrIntervals; } return result; }
onHeartRateChanged()
はオブジェクトのように記録する:
{ heartRate: 70, contactDetected: true, energyExpended: 750, // Meaning 750kJ. rrIntervals: [890, 870] // Meaning .87s and .85s. }
もし心拍数モニターが energyExpended
をレポートすれば、ウェブアプリケーションは heart_rate_control_point
characteristic を書き換えることで、その値を 0 にリセットすることが出来る:
function resetEnergyExpended() { if (!chosenHeartRateService) { return Promise.reject(new Error('No heart rate sensor selected yet.')); } return chosenHeartRateService.getCharacteristic('heart_rate_control_point') .then(controlPoint => { let resetEnergyExpended = new Uint8Array([1]); return controlPoint.writeValue(resetEnergyExpended); }); }
2. セキュリティとプライバシーへの配慮
2.1. 強力なデバイスへのアクセス
ウェブサイトが requestDevice()
を用いてデバイスへアクセス要求する時、呼び出しで指定された GATT service の全てにアクセスできるようになります。UA は、どのデバイスを信用するか確認する前に、このサービスがウェブサイトに何の機能を与えるのか、ユーザーに通知しなければなりません。UA がまだ知らない service がリストにある場合、UA は、デバイスの完全なコントロールをこのサイトに与えることを想定し、リスクをユーザーに通知しなければなりません。また、UA はどのサイトが何のデバイスにアクセスするのか、をユーザは調べることができ、ペアリングを取り消すことができるようにもしなければなりません。
UA は、ユーザーがデバイスの全クラスをウェブサイトとペアリングできるようにしてはいけません。個別デバイス毎に同一 Bluetooth レベルの識別情報を送信するデバイスクラスを構成することが可能です。UA はこの種の偽装を検出する必要はなく、ユーザーに疑似デバイスをウェブサイトとペアリングさせてもかまいません。
この仕様はセキュアなコンテクストだけが Bluetoothデバイス( requestDevice )にアクセス可能であることを要求することによって、ユーザーがアクセスを承認したエンティティのみ実際にアクセスできることを保証します。
2.2. Trusted servers can serve malicious code
This section is non-normative.
ユーザがオリジンを信頼した場合であっても、オリジンのサーバや開発者は危険にさらされる可能性があります、あるいはオリジンのサイトはXSS攻撃に遭う脆弱性を持つこともありえます。いずれも、大切なデバイスに、悪質なコードへのアクセスをユーザが許可してしまうことにつながる可能性があります。オリジンは、XSS攻撃のリスクを低減するために、コンテンツセキュリティポリシィ( Content Security Policy, [CSP3])を定義する必要があります。しかし、これはサーバや開発者を危険にさらす手助けにはなりません。
§3.1 Permission API Integration によって提供されるページのリロード後に承諾されたデバイスを取得する機能は、このリスクを悪化させます。サイトが危険にさらされている間、ユーザが単に訪問した場合に、ユーザがアクセスを承諾する代わりに、攻撃者は以前に承諾されたデバイスを利用することができます。一方で、サイトがデバイスの横断的なページのリロードへのアクセスを保持できる場合に、サイトは、ユーザがより注意を払って見るようにするために、多くのパーミッションプロンプトを示す必要はありません。
2.3. デバイスへの攻撃
このセクションは参考です。
ウェブサイトからの通信によりデバイスのセキュリティモデルが破たんする場合があります。リモートデバイスの信頼できるオペレーティングシステムからのメッセージを受信するだけの仮定をしているからです。ヒューマンインターフェースデバイスは顕著な事例で、ウェブサイトへの通信を許可すれば、そのサイトでキーストロークを採取できるようになるでしょう。ウェブサイトの悪用を防止するため、本仕様書にはそのような脆弱な Service、Characteristic、Discriptor の blacklist が含まれています。
予期しないデータを無線で送信する脆弱性があるデバイスが多数あると本仕様書では想定しています。これまでは、デバイス一台ずつ攻撃する必要がありましたが、本APIを利用すれば大規模に攻撃することも可能です。本仕様書は、そのような攻撃を困難にする試みをいくつか採用しています。:
- デバイスクラスの代わりに個別デバイスをペアリングする際には、デバイスが悪用される前に少なくとも一回のユーザーアクションが必要になります。
- 包括的なバイトストリームアクセスではなく、GATT へのアクセスに制限すれば、悪意あるウェブサイトからのデバイスの大半のパーサーへのアクセスを拒否できます。一方、GATT の characteristic と descriptor の値はいまだにバイト配列で、デバイスが想定しない長さ、形式でセットされる可能性があります。UA は、できれば、これらの値を確認することが推奨されます。
- 本APIでは、ウェブサイトに Bluetooth のアドレス、署名データや暗号キー(キーと値の定義)を公開しません。この結果、無線で送信されるビットデータの予測が困難で、パケット・イン・パケット・インジェクション攻撃を阻止します。残念ながら、この方法は暗号化されたリンク上でのみ効果があり、BLEデバイス全てでサポートする必要はありません。
また、UA は、ユーザー保護のため、さらに対策を講じることも可能です:
- 悪意あるウェブサイトと脆弱なデバイスの一覧をウェブサービスで収集することができます。悪意あるウェブサイトから全デバイスへのアクセス、全ウェブサイトから脆弱なデバイスへのアクセスを UA で拒否できます。
2.4. Bluetooth デバイス識別子
このセクションは参考です。
各 Bluetooth ( BR/EDR )デバイスには、BD_ADDR と呼ばれる48ビットのユニークなMACアドレスがあります。各BLEデバイスにはPublic Device Address が少なくとも1つと Static Device Address が1つあります。Public Device Address は MACアドレスです。Static Device Address はリスタート毎に生成されるかもしれません。BR/EDR/LEデバイスは、( BD_ADDR を読み取るコマンドで指定された) BD_ADDRとPublic Device Address< は同一の値を使用します。
また、BLEデバイスには、ユニークな128ビットの IRK ( Identity Resolving Key )と呼ばれる鍵があり、ボンディングプロセス中に信頼されたデバイスに送信されます。永続的な識別子の漏えいを避けるため、BLEデバイスは、ランダムな 検証可能(Resolvable) または 検証不可能(Non-Resolvable) な Private Address を Static または Public Device Address の代わりに使用し、スキャンとアドバタイズすることが可能です。これらは周期的 (約15分毎)に生成されますが、ボンディングされたデバイスは、格納された IRK の中に検証可能なプライベートアドレスとマッチするものがあるか、 Resolvable Private Address Resolution Procedure を用いてのチェックが可能です。
また、各Bluetoothデバイスには、人間が読める形式の Bluetooth Device Name が定義されています。これらはユニークである保証はありませんが、デバイスタイプによっては多分ユニークでしょう。
2.4.1. リモート Bluetooth デバイスの識別子
このセクションは参考です。
ウェブサイトが永続的にデバイスIDを取得できる場合、周囲に存在するデバイスのカタログを作成という多大な努力を行えば、ユーザーの位置を発見するために使用できます。また、デバイスIDを使えば、異なる2つのウェブサイトに同じBluetoothデバイスでペアリングしているユーザーが同一ユーザーだと特定することも可能です。一方、 デバイスの身元を突き止めるために使用できる多数の GATT service が利用でき、この作業がさらに簡単になるよう、デバイスはカスタム GATT service を公開しています。
本仕様書では、ユーザは、スクリプトが単一のデバイスであると学習させようとしない場合、UA が異なるデバイス ID を単一のデバイスに使用することを提案し、ウェブサイトがデバイスアドレスを悪用するのを困難にしています。デバイスメーカーは、ユーザー追跡を助けるデバイスを設計できますが、ひと仕事が必要となります。
2.4.2. UA のBluetooth アドレス
このセクションは参考です。
BR/EDRモード または セキュリティ要件(Privacy Feature) なしでアクティブスキャニング中のLEモードでは、UA は永続的なIDを近隣のBluetooth無線にブロードキャストします。これは、周辺に敵意あるデバイスをばらまきやすくなり、 UA の追跡が簡単になります。2014年8月時点では、 セキュリティ要件(Privacy Feature) を実装したと文書化したプラットフォームはほとんどありません。従って、本仕様では推奨していますが、 これを使うことになるUA はほとんどなさそうです。本仕様では、ウェブサイトがスキャンを開始するにはユーザージェスチャーが必要で、スキャン頻度をいくらか少なくします。多くのプラットフォームでは、セキュリティ要件(Privacy Feature) を公開する方がもっと良いのでしょう。
3. デバイスの検索
dictionary BluetoothRequestDeviceFilter { sequence<BluetoothServiceUUID> services; DOMString name; DOMString namePrefix; }; dictionary RequestDeviceOptions { required sequence<BluetoothRequestDeviceFilter> filters; sequence<BluetoothServiceUUID> optionalServices = []; }; interface Bluetooth { [SecureContext] readonly attribute BluetoothDevice? referringDevice; [SecureContext] Promise<BluetoothDevice> requestDevice(RequestDeviceOptions options); }; Bluetooth implements EventTarget; Bluetooth implements BluetoothDeviceEventHandlers; Bluetooth implements CharacteristicEventHandlers; Bluetooth implements ServiceEventHandlers;
Bluetooth
members referringDevice
は、このページをユーザが開いて、そこからデバイスへのアクセスを提供することがあります。例えば、Eddystone ビーコンでは、UA は、ユーザが開くことができる URL をアドバライスするかもしれません。ビーコンを表す BluetoothDevice
は navigator.bluetooth.
を通じて利用できるようになります。referringDevice
requestDevice(options)
は、options.filters
のいずれのフィルターにマッチするデバイスへのオリジンアクセスを与えるよう、ユーザに求めます。フィルターにマッチするには、デバイスには以下が必要です:
- 該当メンバーが存在する場合、services リストにある全ての GATT service UUID をサポートすること。
- 該当メンバーが存在する場合、name と同じ名前があること。
- 該当メンバーが存在する場合、namePrefix で始まる名前があること。
ユーザがこのオリジンとペアリングするためにデバイスを選択した後で、options.filters
のいずれかのエレメントにある services
リスト、または options.optionalServices
にリストされている service で UUID を持つもの全部へのアクセスがオリジンに許可されます。
これは、開発者が名前だけでフィルターすれば、どんな service へアクセスするにも optionalServices
を使用しなければならないことを意味します。
UA が次のデバイスの近くにあるとしましょう:
Device | Advertised Services |
---|---|
D1 | A, B, C, D |
D2 | A, B, E |
D3 | C, D |
D4 | E |
D5 | <none> |
ウェブサイトが次のようにコールすると
navigator.bluetooth.requestDevice({ filters: [ {services: [A, B]} ] });
ユーザーにデバイスD1とD2を含んだダイアログが表示されます。ユーザーがD1を選択したら、ウェブサイトはサービスC、Dにはアクセスできません。ユーザーがD2を選択すれば、ウェブサイトはサービスEにはアクセスできません。
一方、ウェブサイトが次のようにコールすると
navigator.bluetooth.requestDevice({ filters: [ {services: [A, B]}, {services: [C, D]} ] });
ダイアログにはデバイスD1、D2、D3が含まれ、ユーザがD1を選択したら、ウェブサイトはサービスA、B、C、Dにアクセスできます。
optionalServices
は、ユーザーが見ているダイアログにデバイスも追加せず、ユーザーが選んだデバイスからどのサービスをウェブサイトが使用できるかに影響を与えます。
navigator.bluetooth.requestDevice({ filters: [ {services: [A, B]} ], optionalServices: [E] });
D1、D2を含み、D4を含まないダイアログを表示します。D4は必要なサービスが含まないからです。ユーザーがD2を選択した場合、最初の例とは異なり、ウェブサイトはサービスA、B、Eにアクセスできます。
ユーザがアクセスを許可した後にデバイスが変化しても、許可されたサービスは適用されます。例えば、ユーザーが前の requestDevice()
コールでD1を選択し、後でD1が新しいサービスEを追加した場合、serviceadded
イベントが開始され、ウェブページはサービスEをアクセスすることができます。
前の例で、デバイスが以下のように名前もアドバタイズしたとします:
Device | Advertised Device Name |
---|---|
D1 | First De… |
D2 | <none> |
D3 | Device Third |
D4 | Device Fourth |
D5 | Unique Name |
以下のテーブルには、navigator.bluetooth.requestDevice({filters: filters})
に渡された filters の値として、どのデバイスをユーザーが選択できるかを示しています。
filters | Devices | Notes |
---|---|---|
[{name: "Unique Name"}] | D5 | |
[{namePrefix: "Device"}] | D3, D4 | |
[{name: "First De"}, {name: "First Device"}] | <none> | D1 は地震の name の prefix のみをアドバタイズするので、name 全体とマッチさせようとすると失敗します。 |
[{namePrefix: "First"}, {name: "Unique Name"}] | D1, D5 | |
[{services: [C], namePrefix: "Device"}, {name: "Unique Name"}] | D3, D5 |
可能なデバイスを全て accept または reject するフィルターは TypeError
が発生します。
filters | Notes |
---|---|
[]
| フィルターリストが空であれば、デバイスを一切 accept しません。 |
[{}]
| フィルターリストが空であれば、デバイス全てを accept するので、これも許可されません。 |
[{namePrefix: ""}] | namePrefix がある場合、デバイスをフィルターするため空でないものとします。
|
Bluetooth
のインスタンスは、以下のテーブルで説明される内部スロットを用いて生成されます:
内部スロット | 初期値 | 説明(参考) |
---|---|---|
[[deviceInstanceMap]] | Bluetooth device から インスタンスへの空のマップ
| 1つのグローバルオブジェクト内で、各 Bluetooth デバイス を表す BluetoothDevice インスタンスはただ1つしかないことを保証します。
|
[[attributeInstanceMap]] | Bluetooth cache エントリー から Promise への空のマップ。
| この Promise は、BluetoothRemoteGATTService 、BluetoothRemoteGATTCharacteristic 、BluetoothRemoteGATTDescriptor のいずれかのインスタンスに resolve されます。
|
[[referringDevice]] | null
| Document がデバイスから開かれている場合、Document オブジェクトを初期化している間に BluetoothDevice にセットします。
|
navigator.bluetooth.referringDevice
を取得するには、[[referringDevice]]
を必ず返さなければなりません。
いくつかの UA は、ユーザが Bluetooth device に応答して navigate するブラウジングコンテキスト( browsing context )を引き起こすことを可能にします。 例えば、Eddystone ビーコンは、URLをアドバタイズした場合、 UA は、ユーザがこの URL に移動することを可能にします。 これが発生した場合、新しい Document
オブジェクトの初期化の一環として、UA は以下のステップを実行しなければなりません。:
- referringDevice を navigation を発生させたデバイスにします。
-
navigator.bluetooth
内部の referringDevice を表すBluetoothDevice
を取得し、referringDeviceObj を結果にします。 - 以前のステップで例外をスローした場合、以下のステップを中止します。
注記: これは、UA は、ユーザが referringDevice に現在の realm のアクセス件を承諾するであろうと推測していなかったことを意味します。例えば、ユーザはグローバルに GATT へのアクセスを拒否された可能性があります。
-
navigator.bluetooth@
を referringDeviceObj にセットします。[[referringDevice]]
以下のステップで match
が返された場合、Bluetooth device は filter#matches-a-filterReferenced in:3. Device Discovery (2) (3) にマッチします。:
filter.name
が存在し、device の Bluetooth Device Name が完全ではなく、filter.name
と一致しない場合、mismatch
を返します。filter.namePrefix
が存在し、device の Bluetooth Device Name が存在しないまたはfilter.namePrefix
で始まらない場合、mismatch
を返します。filter.services
の各 uuid に対して、デバイスが UUID uuid を持つプライマリ(含まれているのではなく)サービスのサポートを示しているアドバタイジングデータ、拡張要求応答( extended inquiry response ) または サービス検索応答( service discovery response ) を UAが受信していない場合、mismatch
を返します。match
を返します。
デバイスがアドバタイズする Service UUID のリストには、デバイスがサポートする全ての UUID が含まれない場合があります。アドバタイズされるデータは、リストが完全かどうか指定します。ウェブサイトは、近隣のデバイスがサポートはするがアドバタイズしない UUID をフィルターする場合、そのデバイスはユーザに提供されるデバイスリストには含まれていない可能性があります。サポートサービスの完全なリストを検索するため、UA はデバイスと接続する必要がありますが、無線性能の劣化や遅延が起こり得るため本仕様では要求していません。
requestDevice(options)
メソッドは、呼び出されると新しい promise promise を返し、同時に以下のステップを実行しなければなりません。:
-
options.
とfilters
options.
を渡しながら Bluetooth devices をリクエストし、devices を結果にします。optionalServices
- 以前のステップで例外をスローした場合、その例外とともに promise を reject し、以下のステップを中止します。
-
devices[0]
とともに promise を Resolve します。
Bluetooth devices をリクエストするには、BluetoothRequestDeviceFilter
のシーケンス、 filters、BluetoothServiceUUID
のシーケンス、および optionalServices が与えられると、UA は以下のステップを実行しなけれなばりません。:
このアルゴリズムの呼び出しは、最終的に複数のデバイスをリクエストできるようになりますが、今のところは単一のデバイスのみを返します。
- アルゴリズムがユーザの動作によって引き起こされていない場合は、
SecurityError
をスローし、以下のステップを中止します。 - service 名とエイリアスからただの UUID に引数を変換するために、以下のサブステップを実行します。:
filters.length === 0
の場合、TypeError
をスローし、以下のステップを中止します。- uuidFilters を新しい
Array
に、requiredServiceUUIDs を新しいSet
にします。 -
filters
の各 filter に対して、以下のサブステップを実行します:- filterの
services
、name
、namePrefix
メンバーがいずれも存在しない場合、TypeError
をスローし、以下のステップを中止します。 - canonicalizedFilter を
{}
にします。 -
filter.services
が存在する場合、以下のサブステップを実行します。:filter.services.length === 0
の場合、TypeError
をスローし、以下のステップを中止します。- services を
にします。Array.prototype.map
.call(filter.services,BluetoothUUID.getService
) BluetoothUUID.getService()
で例外が発生した場合、例外をスローし、ステップを中止します。- services の service のいずれかが blacklisted の場合、
SecurityError
をスローし、ステップを中止します。 canonicalizedFilter.services
を services にセットします。- services のエレメントを requiredServiceUUIDs に追加します。
-
filter.name
が存在する場合、以下のサブステップを実行します。-
filter.name
の UTF-8 encoding が248バイトを超える場合、TypeError
をスローし、以下のステップを中止します。248バイト は Bluetooth Device Name の UTF-8コードユニットの最大値です。
canonicalizedFilter.name
をfilter.name
にセットします。
-
-
filter.namePrefix
が存在する場合、以下のサブステップを実行します。filter.namePrefix.length === 0
またはfilter.namePrefix
の UTF-8 encoding が248バイトを超える場合、TypeError
をスローし、以下のステップを中止します。248バイト は Bluetooth Device Name の UTF-8コードユニットの最大値です。
canonicalizedFilter.namePrefix
をfilter.namePrefix
にセットします。
- canonicalizedFilter を uuidFilters にアペンドします。
- filterの
- optionalServiceUUIDs を
にします。Array.prototype.map
.call(optionalServices,BluetoothUUID.getService
) BluetoothUUID.getService()
で例外が発生した場合、例外をスローし、以下のステップを中止します。- optionalServiceUUIDs からblacklisted となっている UUID を削除します。
-
descriptor はこのようになります。
{ name: "bluetooth", filters: uuidFilters, optionalServices: optionalServiceUUIDs, }
- requiredServiceUUIDs を Service UUID の集合として持つデバイスをスキャンし、scanResult をその結果とします。
- uuidFilters でフィルターにマッチしない場合、デバイスを scanResult から削除します。
-
scanResult が空の場合であっても、descriptor に関連付けられた scanResult 内のデバイスのいずれかを選択するようにユーザを促し、device を結果にします。
UA は、uuidFilters にマッチしない、近隣のデバイスをユーザーが選択できる場合があります。
UA は、ユーザに書くデバイスの人間に可読な名前を表示する必要があります。例えば、この名前が使用不可の場合、UA の Bluetooth システムはプライバシーを有効にして実行するスキャンをサポートしていないため、UA は、ユーザが関心を示すことを許可します。また、名前を取得するために、プライバシーを無効にしてスキャンを実行する必要があります。
- device が
"denied"
の場合、[]
を返し、以下のステップを中止します。 -
device を選択することは、おそらく、ユーザが、少なくとも、現在の設定オブジェクト( current settings object ) の
"bluetooth"
の追加パーミッションデータ( extra permission data ) の許可されたデバイスリスト(allowedDevices
list ) に表示するようにしていることを示しています。そして、requiredServiceUUIDs と optionalServiceUUIDs の和集合内の全ての service を、すでに存在している任意の service に加えて、その許可されたデバイスリスト(allowedServices
)に表示するようにしていることを示しています。 - UA は device 内の全ての Service とともに Bluetooth cache を格納することができます。このステップでのエラーは無視します。
- device 内の コンテキストオブジェクト( context object )を表す
BluetoothDevice
を取得し、任意の例外を伝搬させ、deviceObj を結果とします。 [deviceObj]
を返します。
オプションの Service UUID のセット(デフォルトは全UUIDの集合)を用いてデバイスのスキャンをするには、UA は以下のステップを実行しなければなりません。:
- UA が最近デバイスをスキャンしたことがある場合、TODO: 時間の分量を確定させる。 現在のスキャン用の UUID のスーパーセットである UUID の集合を用いてスキャンしている場合、UAはそのスキャン結果を返し、ステップを中止することができます。
- nearbyDevices を Bluetooth device の集合とし、初期値は空です。
-
UA が LE トランスポートをサポートする場合、General Discovery Procedure を実行し、発見した Bluetooth device を nearbyDevices に追加します。UA はPrivacy Feature を有効にする必要があります。
passive scanning と Privacy Feature の両方で、ユニークかつ変更不可能なデバイスIDのリークを防止しています。どちらかを使用するよう UA に要求すべきですが、OS API にはどちらも公開するものがなさそうです。またBluetoothは passive scanning の使用が難しくなっています。Central デバイスが Observation Procedure をサポートする必要がないからです。
- UA が BR/EDR トランスポートをサポートする場合、Device Discovery Procedure を実行し、発見した Bluetooth device を nearbyDevices に追加します。
- result を Bluetooth device の集合とし、初期値は空です。
-
nearbyDevices の各 Bluetooth device device に対して以下のサブステップを実行します。:
- device の サポートされた物理トランスポート( supported physical transports )に LE が含まれ、その Bluetooth Device Name が部分的にしか存在しないまたは存在しない場合、UA は完全な名前を取得するために Name Discovery Procedure を実行する必要があります。
-
アドバタイズされた device の Service UUID が Service UUID の集合 と空でない共通部分がある場合、device を result に追加し、以下のサブステップを中止します。
BR/EDRデバイスについて、拡張問合せ応答( Extended Inquiry Response )で GATT と non-GATT services を区別する方法はありません。あるサイトが non-GATT service の UUID にフィルターする場合、ユーザーは、本APIが交信する方法を持たない
requestDevice
の結果としてデバイスを選択できる可能性があります。 -
UA は、device に接続し、Service UUID の集合にある全サービスを Bluetooth cache に格納 することができます。
device がサポートする物理トランスポート( supported physical transports ) に BR/EDR が含まれる場合、UA は standard GATT procedures に加え、キャッシュ格納時にサービス探索プロトコル( Service Discovery Protocol [Searching for Services] )を使用できます。
近隣の全デバイスに接続するサービス検索は、電力を消費し、Bluetooth無線の他の利用を遅くする可能性があります。デバイスに関心が期待できる何かの理由があれば、UA はあるデバイスの特別なサービスだけを検索をすべきです。
また UA は、開発者がこの特別な検索方法への依存を避けられるようにしなければなりません。例えば、開発者が以前あるデバイスに接続していれば、その UA はデバイスでサポートされるサービスをフルセットで知っています。そして、開発者が non-advertised UUID を用いてフィルターすれば、フィルターがユーザーのマシンでこのデバイスを除外しそうな場合でも、ダイアログにこのデバイスを含むことができます。このような場合、UA は、警告を出すかフィルターにマッチする時にアドバタイズされた service だけを含める、というオプションを開発者に提供できます。
- Bluetooth cache が Service UUID 集合に、UUID を持ったデバイス内部の known-present service を含んでいる場合、UA は device を result に追加できます。
- スキャンから result を返します。
3.1. Permission API Integration
この [permissions] API は、ウェブサイトが持っている権限を、ユーザやクエリーからリクエストするための統一的な方法を提供します。
サイトでは navigator.bluetooth.
の代替スペルとして requestDevice()
navigator.permissions.
を使用することができる。
request
({name: "bluetooth", ...})
navigator.permissions.request({ name: "bluetooth", filters: [{ services: ['heart_rate'], }] }).then(result => { if (result.devices.length > 1) { return result.devices[0]; } else { throw new DOMException("Chooser cancelled", "NotFoundError"); } }).then(device => { sessionStorage.lastDevice = device.id; });
サイトは、デバイスのセットへのアクセスを許可されたならば、リロード後にそれらのデバイスを取得するために navigator.permissions.
を使用することができます。query
({name: "bluetooth", ...})
navigator.permissions.query({ name: "bluetooth", deviceId: sessionStorage.lastDevice, }).then(result => { if (result.devices.length > 1) { return result.devices[0]; } else { throw new DOMException("Lost permission", "NotFoundError"); } }).then(...);
"bluetooth" の 強力な特徴である、パーミッションが関連するアルゴリズムおよびタイプは以下のように定義されています。:
- permission descriptor type
-
dictionary BluetoothPermissionDescriptor : PermissionDescriptor { DOMString deviceId; // These match RequestDeviceOptions. sequence<BluetoothRequestDeviceFilter> filters; sequence<BluetoothServiceUUID> optionalServices = []; };
- extra permission data type
-
BluetoothPermissionData
は以下のように定義されています。:dictionary AllowedBluetoothDevice { required DOMString deviceId; // An allowedServices of "all" means all services are allowed. required (DOMString or sequence<UUID>) allowedServices; }; dictionary BluetoothPermissionData { required sequence<AllowedBluetoothDevice> allowedDevices = []; };
AllowedBluetoothDevice
インスタンスは Bluetooth device を有する 内部スロット [[device]] を持っています。allowedDevices
の個別の要素は、異なる[[device]]
および、異なるdeviceId
を持っている必要があります。deviceId
は、サイトに、BluetoothDevice
インスタンスと同一インスタンスを表すBluetoothDevice
インスタンスの追跡を許可します、おそらく異なる realm です。 UA は、"bluetooth"
の extra permission data を返す時に、起こることまたは起きないことを、ユーザーが追跡しようとするかどうか、 を検討する必要があります。例えば、一般的に、ユーザは、それらが同じデバイスと対話していることを知っているため、2つの異なるオリジンを意図しません。また、ユーザは、クッキーをクリアした後に持続するユニークな識別子も意図しません。
- permission result type
-
interface BluetoothPermissionResult : PermissionStatus { attribute FrozenArray<BluetoothDevice> devices; };
- permission request algorithm
-
BluetoothPermissionDescriptor
options とBluetoothPermissionResult
status が与えられ、UA は以下のステップを実行しなければなりません。:- Bluetooth devices のリクエストでは
options.
とfilters
options.
を渡し、いずれの例外も伝搬させ、devices を結果とします。optionalServices
-
status.devices
を、devices の要素を含む新しいFrozenArray
にセットします。
- Bluetooth devices のリクエストでは
- permission query algorithm
-
BluetoothPermissionDescriptor
desc とBluetoothPermissionResult
status とともに"bluetooth" permission を問い合わせるためには、UAは以下のステップを実行しなければなりません。:- global を status と関連した global object とします。
-
status.
を desc の permission state にセットします。state
-
status.
がstate
"denied"
の場合、status.devices
を空のFrozenArray
にセットし、以下のステップを中止します。 - matchingDevices を新しい
Array
にします。 - data (
BluetoothPermissionData
) を、current settings object のために"bluetooth"
の extra permission data とします。 -
data.allowedDevices
の各 allowedDevice に対して、以下のサブステップを実行します。:-
desc.deviceId
がセットされ、allowedDevice.deviceId != desc.deviceId
の場合、次の allowedDevice に進みます。 -
desc.filters
がセットされ、allowedDevice@
が[[device]]
desc.filters
のフィルターとマッチしない場合、次の allowedDevice に進みます。 - 注記:
desc.optionalServices
フィールドは結果には影響しません。 -
global.navigator.bluetooth
内のallowedDevice@
を表す[[device]]
BluetoothDevice
を取得し、結果に matchingDevices を加えます。
-
-
status.devices
を、コンテンツが matchingDevices である新しいFrozenArray
にセットします。
- permission revocation algorithm
-
ユーザはデバイスを公開しないよう Bluetooth access を取り消すためには、UA は以下のステップを実行しなければなりません。:
- data (
BluetoothPermissionData
) を、current settings object のために"bluetooth"
の extra permission data とします。 - current realm の各
BluetoothDevice
instance deviceObj に対して、以下のサブステップを実行します。:-
data.
の中にallowedDevices
AllowedBluetoothDevice
allowedDevice がある場合、つまり:-
allowedDevice.
は[[device]]
deviceObj.
と 同一デバイスである。[[representedDevice]]
-
allowedDevice.
である。deviceId
=== deviceObj.id
deviceObj.
を[[allowedServices]]
allowedDevice.
に更新し、次の deviceObj に進みます。allowedServices
-
- そうでない場合、残りのステップを実行して、そのデバイスから deviceObj を切り離します。
-
deviceObj.gatt.
をコールします。disconnect()
注記: これは deviceObj で
gattserverdisconnected
イベントを開始させます。 -
deviceObj@
を[[representedDevice]]
null
にセットします。
-
- data (
4. デバイスの表現
UA は Bluetoothデバイスproperties をいくつかのレベルで追跡する必要があります。: グローバル、オリジン別、グローバルオブジェクト別
4.1. グローバル Bluetooth デバイスプロパティ
物理的な Bluetooth デバイスは、UA が受信していない可能性があるプロパティ群を持つことが保証される場合があります。ここでは、そのようなプロパティ群をオプションと記載します。
Bluetooth device には、以下のようなプロパティがあります。別途説明がない限り、オプションのプロパティは存在せず、シーケンスおよびマッププロパティは空です。それ以外のプロパティは、指定デフォルト値があるか、デバイス導入時点で決定されます。
- BR/EDR または LE のいずれか1つまたは両方を含んだサポートされた物理トランスポート( supported physical transports ) の集合。この集合は、通常、デバイスが検索されたトランスポート、および Advertising Data または Extended Inquiry Response の Flags Data Type により満たされます。
- 1種類以上の48ビットアドレス:Public Bluetooth Address、(ランダム) Static Address と 検証可能(resolvable) または 検証不可能(non-resolvable) な Private Address。
- オプションの128ビット IRK( Identity Resolving Key )。
- オプションの部分的または完全な Bluetooth Device Name。Shortened Local Name AD data が受信され、完全な名前が読み取られていない場合、デバイスには部分的な名前しかありません。Bluetooth Device Name は、UTF8としてエンコードされ、BOMアルゴリズムを使用しないUTF-8デコード を使用して、DOM文字列に変換されます。
- ATT Bearer,この上で全ての GATT 通信が発生します。 ATT Bearer は GAP Interoperability Requirements の接続確立(Connection Establishment) で説明されるプロシージャーにより生成されます。これは全く明らかではない方法 [BLUETOOTH42] で切断されます。
- Advertising Data または Extended Inquiry Response からのアドバタイズされた Service UUID のリスト。
- §5.1 GATT Information Model で説明される GATT 属性の階層
以下の場合に UA は2つの Bluetooth device が同一の Bluetooth デバイスと判断する必要があります。2つのデバイスの、Public Bluetooth Address、Static Address, Private Address, Identity Resolving Key のいずれかが同一の場合、あるいは、一方のデバイスのIRKと他方の検証可能な Private Address を使って Resolvable Private Address Resolution Procedure が成功した時に限り、同一のデバイスだと判断する必要があります。しかし、プラットフォームAPIでは、デバイスの同一性を決定する方法が文章化されていないので、UA は別のプロシージャを使用してもよいのです。
4.2. BluetoothDevice
BluetoothDevice
インスタンスは、特定の global object (あるいは、同等に、特定の Realm または Bluetooth
インスタンスに対して) の Bluetooth device を表しています。
interface BluetoothDevice { readonly attribute DOMString id; readonly attribute DOMString? name; readonly attribute BluetoothRemoteGATTServer gatt; readonly attribute FrozenArray<UUID> uuids; Promise<void> watchAdvertisements(); void unwatchAdvertisements(); readonly attribute boolean watchingAdvertisements; }; BluetoothDevice implements EventTarget; BluetoothDevice implements BluetoothDeviceEventHandlers; BluetoothDevice implements CharacteristicEventHandlers; BluetoothDevice implements ServiceEventHandlers;
BluetoothDevice
属性id は、UA が2つの Bluetooth 接続が同一デバイスであると判断できる程度にデバイスを識別することができます。また、id は、ユーザがスクリプトにその事項をスクリプトに公開したい程度にデバイスを識別することができます。
name は、人間が読める形式のデバイス名です。
gatt には、このデバイスの GATT services と通信する方法を与えます。
uuids
は、このデバイス上にあることがわかっている GATT service の UUID 群で、現在のオリジンがアクセスを許可されているもののリストです。
UA がこのデバイスからアドバタイズメントをスキャンしており、イベントを開始した場合、watchingAdvertisements は true です。
BluetoothDevice
インスタンスは、次のテーブルに記載された内部スロットを用いて作成されます。:
内部スロット | 初期値 | 説明(参考) |
---|---|---|
[[context]] | undefined
| この BluetoothDevice を返した BluetoothDevice .Bluetooth オブジェクト
|
[[representedDevice]] | undefined
| このオブジェクトが表している Bluetooth デバイス |
[[allowedServices]] | undefined
| 全てのサービスが許可されている "all" の場合は、オリジンのための、このデバイスの allowedServices リスト。例えば、UA は、そのオリジンに URL がそのオリジンにアドバタイズされた referringDevice 上の全てのサービスへのアクセスをオリジンに許可することができます。
|
[[unfilteredUuids]] | new
| このデバイスの GATT Server にあることが既知のサービスUUID。 UA が全サービス検索を実行していない場合、この集合は不完全であるかもしれません。 |
[[cachedAllowedServices]] | undefined
| [[filteredUuids]] が最後に実行された時点での [[allowedServices]] の値。
|
[[cachedUnfilteredUuids]] | undefined
| [[filteredUuids]] が最後に更新された時点での [[unfilteredUuids]] の値。
|
[[filteredUuids]] | undefined
| キャッシュされた uuids の値。[[cachedAllowedServices]] と [[allowedServices]] が等しい場合は、最新です。
|
Bluetooth
インスタンスの context 内部で Bluetooth device device を表す BluetoothDevice
を取得する representing#get-the-bluetoothdevice-representingReferenced in:3. Device Discovery5.3. BluetoothRemoteGATTService ためには、UA は以下のステップを実行しなければなりません。:
- device として 同一デバイスである context@
[[deviceInstanceMap]]
にキーが存在する場合、その値を返し、以下のステップを中止します。 - promise を新しい promise にします。
- device から context@
[[deviceInstanceMap]]
の promise へのマッピングを追加します。 - promise を返し、同時に以下のステップを実行します。
- data (
BluetoothPermissionData
) を current settings object による"bluetooth"
の extra permission data にします。 -
data.
の中から、allowedDevices
allowedDevice@
で、device として同一デバイスを検索します。そのようなオブジェクトが存在しない場合、[[device]]
SecurityError
をスローし、以下のステップを中止します。 -
data.
の中から、allowedDevices
allowedDevice@
で、device として同一デバイスを検索します。そのようなオブジェクトが存在しない場合、[[device]]
SecurityError
をスローし、以下のステップを中止します。 - device として同一デバイスである context@
[[deviceInstanceMap]]
にキーが無い場合、以下のサブステップを実行します。:- result を新しい
BluetoothDevice
のインスタンスとします。 - result のオプションのフィールド全てを
null
に初期化します。 -
result@
を context に初期化します。[[context]]
-
result@
を device に初期化します。[[representedDevice]]
- Initialize
result.id
をallowedDevice.
に初期化し、deviceId
result@
を[[allowedServices]]
allowedDevice.
に初期化します。allowedServices
- device が部分的または完全な Bluetooth Device Name を持つ場合、
result.name
にその文字列をセットします。 -
result.watchingAdvertisements
をfalse
に初期化します。 -
result.gatt.
を result に初期化します。device
-
result.gatt.
をconnected
false
に初期化します。 - device の アドバタイズされた Service UUIDs を
result@
に追加します。[[unfilteredUuids]]
- Bluetooth cache がデバイス内部の device の known-present サービスを含んでいる場合、これらのサービスに対する UUID群 を
result@
に追加します。[[unfilteredUuids]]
- device から context@
[[deviceInstanceMap]]
の result にマッピングを追加します。
- result を新しい
- キーが device として 同一デバイスである context@
[[deviceInstanceMap]]
の中の値を返します。
uuids
attribute を取得するには、以下のステップを実行しなければなりません。:
-
[[cachedAllowedServices]]
が[[allowedServices]]
と異なる、あるいは[[cachedUnfilteredUuids]]
が[[unfilteredUuids]]
と異なる場合、以下のステップを実行します。:[[cachedAllowedServices]]
に[[allowedServices]]
のコピーをセットします。-
[[cachedUnfilteredUuids]]
に[[unfilteredUuids]]
のコピーをセットします。 -
[[filteredUuids]]
に、以下の要素からなる新しいFrozenArray
をセットします。:[[allowedServices]]
が"all"
である場合[[unfilteredUuids]]
の全ての要素- そうでない場合
-
[[unfilteredUuids]]
と[[allowedServices]]
の共通部分
[[filteredUuids]]
を返します。
スキャンには電力が必要になるためウェブサイトは必要以上にアドバタイズメントを関しすることは避けてください。そして可能な限り早く電力の使用を停止する unwatchAdvertisements()
をコールする必要があります。
watchAdvertisements()
メソッドは、呼び出されると、新しい promise promise を返し、同時に以下のステップを実行しなければなりません。:
- UA は、このデバイスのアドバタイズメントをスキャンしていることを確認してください。UA は、同じデバイスの "重複した" アドバタイズメントを除外するべきではありません。
- UA がスキャンの有効化に失敗した場合は、次のいずれかのエラーとともに promise を reject し、以下のステップを中止します。:
- UA がアドバタイズメントのスキャンをサポートしていない場合
NotSupportedError
- Bluetooth がオフになっている場合
InvalidStateError
- それ意外の場合
UnknownError
-
以下のステップを実行するためにタスクをキューイングします。:
this.
をwatchingAdvertisements
true
にセットします。undefined
とともに promise を Resolve します。
unwatchAdvertisements()
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
this. watchingAdvertisements
をfalse
にセットします。- UA全体の中で
BluetoothDevice
にこれ以上watchingAdvertisements
にture
がセットされていない場合、UA はアドバタイズメントのスキャンを停止する必要があります。同様に、this
として同一デバイスを表すBluetoothDevice
のwatchingAdvertisements
にtrue
がこれ以上セットされていない場合、UA はこのデバイスのレポートを受信しないようにスキャンを再構成する必要があります。- UA全体の中で
4.2.1. Responding to Advertising Events
アドバタイズイベントが watchingAdvertisements
のセットとともに BluetoothDevice
に届くと、UA は "advertisementreceived
" を提供します。
interface BluetoothManufacturerDataMap { readonly maplike<unsigned short, DataView>; }; interface BluetoothServiceDataMap { readonly maplike<UUID, DataView>; }; [Constructor(DOMString type, BluetoothAdvertisingEventInit init)] interface BluetoothAdvertisingEvent : Event { readonly attribute BluetoothDevice device; readonly attribute FrozenArray<UUID> uuids; readonly attribute DOMString? name; readonly attribute unsigned short? appearance; readonly attribute byte? txPower; readonly attribute byte? rssi; readonly attribute BluetoothManufacturerDataMap manufacturerData; readonly attribute BluetoothServiceDataMap serviceData; }; dictionary BluetoothAdvertisingEventInit : EventInit { required BluetoothDevice device; sequence<(DOMString or unsigned long)> uuids; DOMString name; unsigned short appearance; byte txPower; byte rssi; Map manufacturerData; Map serviceData; };
BluetoothAdvertisingEvent
属性 uuids が Service の UUID をリストすることは、このアドバタイズメントが device
の GATT server をサポートしているということです。
name は device
のローカルネーム、またはそのプレフィックスです。
appearance は Appearance、org.bluetooth.characteristic.gap.appearance
characteristic によって定義される値の一つです。
txPower はデバイスがブロードキャストする時の送信電力で、単位はdBmで測定されます。この値は、this.txPower - this.rssi
により、パス損失を計算するために使用します。
rssi はデバイスパケットが受診された時の電力で、単位はdBmで測定されます。この値は、this.txPower - this.rssi
により、パス損失を計算するために使用します。
manufacturerData maps unsigned short
は、unsigned short
会社識別コード(Company Identifier Code) をDataView
にマップします。
デバイスを取得し、そこから iBeacon データを読み込むため、以下のコードを開発者は利用できます。このAPIは、現在のところ、ある manufacturer data をデバイスに要求する方法を提供していないことに注意してください。従って、ユーザーがこのデバイスを requestDevice
ダイアログの中で選ぶには、iBeacon は既知サービスに含むためにアドバタイズメントを循環させて必要があるでしょう。
var known_service = "A service in the iBeacon’s GATT server"; return navigator.bluetooth.requestDevice({ filters: [{services: [known_service]}] }).then(device => { device.watchAdvertisements(); device.addEventListener('advertisementreceived', interpretIBeacon); }); function interpretIBeacon(event) { var rssi = event.rssi; var appleData = event.manufacturerData.get(0x004C); if (appleData.byteLength != 23 || appleData.getUint16(0, false) !== 0x0215) { console.log({isBeacon: false}); } var uuidArray = new Uint8Array(appleData.buffer, 2, 16); var major = appleData.getUint16(18, false); var minor = appleData.getUint16(20, false); var txPowerAt1m = -appleData.getInt8(22); console.log({ isBeacon: true, uuidArray, major, minor, pathLossVs1m: txPowerAt1m - rssi}); });
iBeacon 形式のアドバタイズメントは、How do iBeacons work? (by Adam Warski) に由来しています。
UA は、(アドバタイジングパケットおよびオプションのスキャン応答からなる)アドバタイジングイベントを受信すると、以下のステップを実行する必要があります。:
- device を、アドバタイジングイベントを送信した Bluetooth device にします。
- UA の各
BluetoothDevice
deviceObj について、device が 同一デバイスであるようなdeviceObj@
には、以下のサブステップを実行するために、deviceObj の relevant settings object の responsible event loop に タスクをキューイングします。:[[representedDevice]]
-
deviceObj.
がwatchingAdvertisements
false
の場合、以下のサブステップを中止します。 - deviceObj のアドバタイズイベント に対して
advertisementreceived
を開始します。
-
BluetoothDevice
deviceObj の アドバタイズイベント adv に対して advertisementreceived
イベントを開始するために、UA は以下のステップを実行しなければなりません。:
-
event を以下のようにします。
{ bubbles: true, device: deviceObj, uuids: [], manufacturerData: new Map(), serviceData: new Map() }
- いずれの adv 内のパケットに対して received signal strength が利用可能の場合、
event.rssi
を dBm 単位でこの信号強度にセットします。 - adv のアドバタイズパケットとスキャン応答の各 AD structure に対して、AD タイプに応じて以下のステップから選択します。:
- Incomplete List of 16-bit Service UUIDs
- Complete List of 16-bit Service UUIDs
- Incomplete List of 32-bit Service UUIDs
- Complete List of 32-bit Service UUIDs
- Incomplete List of 128-bit Service UUIDs
- Complete List of 128-bit Service UUIDs
- Complete List of 16-bit Service UUIDs
- リストされた UUID を
event.uuids
にアペンドします。 - Shortened Local Name
- Complete Local Name
-
AD データにBOM 無しで UTF-8 デコードし、
event.name
を結果にセットします。注記: 私たちは、既存の API がこの情報を取得するために、生のアドバタイズメントを読み取ることを要求するため、name が完了したかどうか公開されていません。そして、私たちは、それが API にフィールドを追加する前に有用だという証拠をより多く求めています。
- Manufacturer Specific Data
- 16ビットの固有識別コードから manufacturer 固有のデータを含む
ArrayBuffer
へのマッピングをevent.manufacturerData
に追加します。 - TX Power Level
-
event.txPower
を AD data にセットします。 - Service Data - 16 bit UUID
- Service Data - 32 bit UUID
- Service Data - 128 bit UUID
- Service Data - 32 bit UUID
-
event.serviceData
a mapping from the UUID から サービスデータを含むArrayBuffer
へのマッピングをevent.serviceData
に追加します。 - Appearance
-
event.appearance
を AD data にセットします。 - そうでない場合
- 次の AD structure にスキップします。
- Incomplete List of 16-bit Service UUIDs
- deviceObj にて、その
isTrusted
属性をtrue
に初期化して、新たな
として初期化するイベントを開始します。BluetoothAdvertisingEvent
("advertisementreceived
", event)
BluetoothAdvertisingEvent
内の全フィールドは、初期化またはセットされた最後の値を返します。
BluetoothAdvertisingEvent(type, init) constructor は以下のステップを実行する必要があります。:
- event を、
uuids
、manufacturerData
、およびserviceData
メンバーを除いた DOM §3.4 Constructing events からのステップを実行した結果とします。 -
init.uuids
がセットされている場合、event.uuids
をinit.uuids.map(
の要素を含む新しいBluetoothUUID.getService
)FrozenArray
に初期化します。 そうでない場合は、event.uuids
を空のFrozenArray
に初期化します。 -
init.manufacturerData
内の各マッピングに対して:- code は
unsigned short
に変換されたキーとします。 - value は値とします。
- value が
BufferSource
でない場合、TypeError
をスローします。 - bytes を、value により保持されているバイトのコピー を含む read only ArrayBuffer にします。
- code から
event.manufacturerData@
の[[data]]
new DataView(bytes)
へのマッピングを追加します。
- code は
-
init.serviceData
内の各マッピングに対して:- key をキーにします。
- service は
BluetoothUUID.
をコールした結果にします。getService
(key). - value を値にします。
- value が
BufferSource
でない場合、TypeError
をスローします。 - bytes を、value により保持されているバイトのコピー を含む read only ArrayBuffer にします。
- service から
event.serviceData@
の[[data]]
new DataView(bytes)
へのマッピングを追加します。
- event を返します。
4.2.1.1. BluetoothManufacturerDataMap
次のテーブルで説明する内部スロットを使用して、BluetoothManufacturerDataMap
インスタンスが作成されます。:
内部スロット | 初期値 | 説明(参考) |
---|---|---|
[[data]] | new
| DataView に変換されているアドバタイズされた manufacturer data
|
BluetoothManufacturerDataMap
インスタンスの map entries は、
にあるエントリーです。[[data]]
4.2.1.2. BluetoothServiceDataMap
次のテーブルで説明する内部スロットを使用して、BluetoothServiceDataMap
インスタンスが作成されます。:
内部スロット | 初期値 | 説明(参考) |
---|---|---|
[[data]]
new
| DataView に変換されているアドバタイズされた service data
|
BluetoothServiceDataMap
インスタンスの map entries は、
のエントリー群です。[[data]]
5. GATT Interaction
5.1. GATT 情報モデル
GATT Profile Hierarchy は、どのように GATT Server が Profiles、Primary Service、Included Service、Characteristic、 Descriptor の階層を格納しているかを記述します。
Profile 群は純粋に論理的です。: Profile の仕様書には、その Profile を含む、他の GATT エンティティ群との間と期待されるインタラクションが記述されていますが、デバイスがどの Profile をサポートしているか問い合わせることはできません。
GATT Client 群は、GATT procedures の集合を使っているデバイス上の Services、Characteristics、Descriptors を検索してインタラクションすることが可能です。本仕様ではこれらを総称して Attribute群 と呼んでいます。 全ての Attributes には、UUID で識別される型があります。また、各 Attribute は GATT Server 上で同じ型を持つ他の Attributes と区別する、16ビット Attribute Handle を持っています。Attributes は、概念的には GATT Server 内で Attribute Handle により順位付けられています。プラットフォームインタフェースは、これらのエンティティ群をある順序で提供していますが、Attribute Handle の順序と一致することは保証しません。
Service には、Included Service群と Characteristic群のコレクションが含まれます。Included Service群は、他の Service 群への参照で、1つの Service を他の1つ以上の Service に含めることができます。Service群は、 GATT Server に直接現れる場合、Primary Services と呼ばれます。また、他の Service に含まれるだけで Primary Services にも含まれる可能性がある場合、Secondary Services と呼ばれます。
Characteristic には(バイトの配列である)値と、Descriptor群のコレクションを格納します。 Characteristic の properties によっては、GATT Client は、値の読み書きができ、また、値が変化した時に通知を受け取るよう登録ができます。
最後に、Descriptor は、Characteristic を記述したり構成する(これもバイトの配列である)値を格納します。
5.1.1. The Bluetooth cache
UA は、これまでにデバイス上で検索した Services、Characteristics、Descriptors の階層の Bluetooth cache を保持しなければなりません。UA は、同一デバイスをアクセスする複数のオリジン間でこのキャッシュを共有できます。キャッシュ内のエンティティは、known-present 、known-absent、あるいはunknownのいずれかが可能です。cache には、同一属性に対してエンティティを2つ格納してはいけません。キャッシュの各 known-present エンティティは、各 Bluetooth
インスタンスに対して Promise<
、BluetoothRemoteGATTService
>Promise<
、BluetoothRemoteGATTCharacteristic
>Promise<
のインスタンスがオプションで関連付けられています。BluetoothRemoteGATTDescriptor
>
例えば、ユーザーが serviceA.getCharacteristic(uuid1)
関数を、初期状態が空の Bluetooth cache でコールした場合、UA はUUIDプロシージャによって Discover Characteristics を仕様し、必要なキャッシュエントリ群を埋めます。返された Promise
を埋めるには Characteristic が1つだけ必要で、serviceA
の最初の Characteristic with UUID uuid1
は known-present で、その UUID を持つそれ以降の Characteristic 群は unknown のままです。そのため、この手続きは UA では早く終了します。ユーザが後で serviceA.getCharacteristics(uuid1)
をコールすれば、UA は Discover Characteristics by UUID procedure を再開または再スタートする必要があります。serviceA
だけが UUID uuid1
を持つ Characteristic を1つしか持たないことがわかった場合、
それ以降の Characteristic 群は known-absent になります。
Bluetooth cache 内の known-present エントリー群は順序付けられています。:Primary Service 群はデバイス内で、含まれている Services と Characteristics は Services 内で、Descriptors は Characteristics 内で、それぞれ、ある特定の順序で現れます。この順序は、デバイスのAttribute Handle 群の順序とマッチする必要がありますが、デバイスの順序が利用できない場合、UA は別の順序を使えます。
ある description とマッチするエントリーを Bluetooth cache に格納する#populate-the-bluetooth-cacheReferenced in:3. Device Discovery4.3. BluetoothDevice (2)5.1.1. The Bluetooth cache 場合、UA は以下のステップを実行しなければなりません。: 以下のステップはブロックされる可能性があることに注意してください。従って、このアルゴリズムを利用するには 並列に実行しなければなりません。
- [BLUETOOTH42] が規定する GATT procedures のいずれをシーケンスを用いて、キャッシュ内のマッチするエントリー全てを known-present または known-absent にすれば、十分な情報が返されるでしょう。§5.7 Error handling で記載されたようにエラーを処理します。
- 以前のステップでエラーが返された場合、このアルゴリズムからそのエラーを返してください。
ある description にマッチするエントリー群に対して、 BluetoothDevice
インスタンスの deviceObj に luetooth cache を問い合わせる#query-the-bluetooth-cacheReferenced in:5.1.2. Navigating the Bluetooth Hierarchy5.1.3. Identifying Services, Characteristics, and Descriptors には、UA は新しい promise promise の deviceObj.gatt
-connection-checking wrapper を返し、同時に以下のステップを実行しなければなりません。:
deviceObj.gatt.
の値がconnected
false
だった場合、NetworkError
で promise を reject し、以下のステップを中止します。- 記述とマッチするエントリーを Bluetooth cache に格納します。
- 以前のステップでエラーが返された場合、そのエラーで promise を reject し、以下のステップを中止します。
- エントリー群を、記述とマッチする known-present キャッシュエントリーのシーケンスにします。
- context を
deviceObj@
にします。[[context]]
- result を新しいシーケンスにします。
-
entries の各 entryに対して:
- entry が context@
[[attributeInstanceMap]]
のPromise<BluetoothGATT*>
インスタンスと関連付けられていない場合、エントリーが、Service, Characteristic, or Descriptor,に応じて、エントリーを表すBluetoothRemoteGATTService
representing entry, create aBluetoothRemoteGATTCharacteristic
representing entry, or create aBluetoothRemoteGATTDescriptor
representing entry を作成します。そして、エントリーから結果として得られた context@[[attributeInstanceMap]]
のPromise
へのマッピングを追加します。 - context@
[[attributeInstanceMap]]
のエントリーに関連したPromise<BluetoothGATT*>
インスタンスを result にアペンドします。
- entry が context@
- result の全エレメントを待っている結果を用いて、promise を resolve します。
5.1.2. Bluetooth 階層ナビゲーション
GetGATTChildren(attribute: GATT Attribute,
single: boolean,
uuidCanonicalizer: function,
uuid: optional (DOMString or unsigned int)
,
allowedUuids: optional ("all" or Array<DOMString>)
,
child type: GATT declaration type),
のために、UA 以下のステップを実行しなければなりません。:
- uuid が存在する場合、それを uuidCanonicalizer(uuid) にセットします。uuidCanonicalizer で例外がスローされた場合、その例外で promise を rejecte して返し、以下のステップを中止します。
- uuid が存在し、blacklisted されている場合、
SecurityError
でpromise を reject して返し、以下のステップを中止します。 -
deviceObj を attribute のタイプに応じて、以下のようにします。:
BluetoothDevice
attribute
BluetoothRemoteGATTService
attribute.
device
BluetoothRemoteGATTCharacteristic
attribute.
service
.device
-
以下の条件に合うエントリーを、
deviceObj
の Bluetooth cache に問い合わせします。:- attribute により表現されている Bluetooth エンティティ内部にあること。
- child type で記述された型を持っていること。
- uuid が存在する場合、uuid の UUID を有していること。
- allowedUuids が存在し、"all" でない場合に、allowedUuids に UUID があること。
- single フラグがセットされている倍、その中で最初であること。
-
以下の動作をする fulfillment handler を使用して、transforming promise の結果を返します。:
- 引数が空の場合、
NotFoundError
をスローします。 - そうでない場合で、single フラグがセットされている場合、この引数の最初(だけ)のエレメントを返します。
- そうでない場合、その引数を返します。
- 引数が空の場合、
5.1.3. Services、Characteristics、Descriptors の識別子
2つの Services、Characteristics、Descriptors a と b が 同一属性#same-attributeReferenced in:5.1.1. The Bluetooth cache5.1.3. Identifying Services, Characteristics, and Descriptors (2) (3)5.6.5. Responding to Service Changesかチェックする場合、 UA は a と b が 同一デバイスの中にあり、同一の Attribute Handle を持つことを判断する必要があります。 しかし、a と b が以下の条件のいずれかに適合する場合、同一属性とみなしてはいけない制約を持つ、UA が利用できる任意のアルゴリズムを使用することができます。:
- 両方が Services でも Characteristics でも Descriptors でもない。
- 両方が Services であるが、両方が、primary services または secondary services ではない。
- 異なる UUID を持っている。
- 親デバイスが同一デバイスではなく、親 Services または親 Characteristics が 同一属性ではない。
この定義は緩くなっています。Platform API 群は、同一性が Attribute Handle の等価性に基づくものなのかどうかを文章化しないまま、同一性の概念を公開しているからです。
Services、Characteristics、Descriptors を表現している x と y という2つの Javascript object に対して、x === y
は、Bluetooth cache に問い合わせをするアルゴリズムが新しいオブジェクトを作成し、キャッシュする方法に起因する、オブジェクトが 同一属性を表現するかどうかを返します。
5.2. BluetoothRemoteGATTServer
BluetoothRemoteGATTServer
は、リモートデバイス上の GATT Server を表します。
interface BluetoothRemoteGATTServer { readonly attribute BluetoothDevice device; readonly attribute boolean connected; Promise<BluetoothRemoteGATTServer> connect(); void disconnect(); Promise<BluetoothRemoteGATTService> getPrimaryService(BluetoothServiceUUID service); Promise<sequence<BluetoothRemoteGATTService>> getPrimaryServices(optional BluetoothServiceUUID service); };
BluetoothRemoteGATTServer
attributesdevice は、このサーバーを実行しているデバイスです。
このインスタンスが this.device
に接続されている間、connected は true です。UA が物理的に接続されている間で、例えば、他の global object 用に接続された他の BluetoothRemoteGATTServer
インスタンスがある場合には false になることがあります。
ECMAScript コードが、BluetoothRemoteGATTServer
server のインスタンスを観測できなくなった時、UA は server.
を実行する必要があります。
disconnect()
BluetoothDevice
インスタンスは navigator.bluetooth.
に格納されているので、ナビゲーションが global object を開放するか、タブまたはウィンドウを閉じ、 browsing context が破壊されるまで、少なくともこのようなことは起こりえないのです。
ガベージコレクション時に切断されますが、UA が必要もないのにリモートデバイスのリソースを消費し続けることがないことの保証になっています。[[deviceInstanceMap]]
次のテーブルで説明される内部スロットを使用して、BluetoothRemoteGATTServer
のインスタンスが作成されます。:
内部スロット | 初期値 | 説明(参考) |
---|---|---|
[[activeAlgorithms]] | new
|
このサーバの接続を用いた各アルゴリズムに対応する Promise を含みます。disconnect() は、実行中にこの realm が切断されたことがあったかアルゴリズムで判断できるよう、この集合を空にします。
|
connect()
メソッドは、呼び出されると、新しい promise promise を返し、同時に以下のステップを実行しなければなりません。:
this.device@
が[[representedDevice]]
null
の場合、NetworkError
で promise を reject し、以下のステップを中止します。this.device@
に ATT Bearer が無い場合、GAP Interoperability Requirements の「接続確立」で説明されるプロシージャを使って作成を試みます。[[representedDevice]]
- この試行が失敗したら、
NetworkError
で promise を reject し、以下のステップを中止します。 -
以下のサブステップを実行するためにタスクをキューイングします。:
this.device@
が[[representedDevice]]
null
の場合、NetworkError
で promise を reject し、以下のステップを中止します。this.connected
にtrue
をセットします。this
を使って promise を resolve します。
disconnect()
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
this.
がconnected
false
の場合、以下のステップを中止します。this@
をクリアします。[[activeAlgorithms]]
this.
をconnected
false
にします。-
this.
でdevice
bubbles
属性をtrue
に初期化して、gattserverdisconnected
という名前のイベントを開始します。このイベントは、
BluetoothRemoteGATTServer
では動作しません。 - device を
this.device@
にします。[[representedDevice]]
- 同時に:
deviceObj@
をデバイスとして 同一デバイスを持つ UA 全体の 全[[representedDevice]]
BluetoothDevice
sdeviceObj
に対して、deviceObj.gatt.
がconnected
false
である場合、UA は device の ATT Bearer を破壊する必要があります。
実行中に BluetoothRemoteGATTServer
が切断された場合、UA がずっと接続されており、終了前に BluetoothRemoteGATTServer
がその後再接続されたとしても、アルゴリズムは fail する必要があります。これを達成するため、返された Promise
のラッパーを作成します。
gattServer-connection-checking wrapper around a Promise
promise を作成するには、UA は以下のことが必要です。:
gattServer.connected
がtrue
の場合、promise にgattServer@
を追加します。[[activeAlgorithms]]
- transforming promise の結果を、以下のステップを実行する fulfillment ハンドラと rejection ハンドラと一緒に返します。:
- fulfillment handler
-
- promise が
gattServer@
にある場合、それを取り除き、最初の引数を返します。[[activeAlgorithms]]
- そうでない場合には、
NetworkError
をスローします。 gattServer はメインアルゴリズム実行中に切断されたからです。
- promise が
- rejection handler
-
- promise が
gattServer@
にある場合、それを取り除き、最初の引数を返します。[[activeAlgorithms]]
- そうでない場合には、
NetworkError
をスローします。 gattServer はメインアルゴリズム実行中に切断されたからです。
- promise が
getPrimaryService(service)
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
-
this.device@
が[[allowedServices]]
"all"
でなく、service がthis.device@
に無い場合、[[allowedServices]]
SecurityError
とともに promise を reject して返し、以下のステップを中止します。 - この値を返します。GetGATTChildren(attribute=
this.device
,
single=true,
uuidCanonicalizer=BluetoothUUID.getService
,
uuid=service
,
allowedUuids=this.device@
,[[allowedServices]]
child type="GATT Primary Service")
getPrimaryServices(service)
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
-
this.device@
が[[allowedServices]]
"all"
ではなく、service が存在し、this.device@
の中に無い場合、[[allowedServices]]
SecurityError
とともに promise を reject して返し、以下のステップを中止します。 - この値を返します。 GetGATTChildren(attribute=
this.device@
,[[representedDevice]]
single=false,
uuidCanonicalizer=BluetoothUUID.getService
,
uuid=service
,
allowedUuids=this.device@
,[[allowedServices]]
child type="GATT Primary Service")
5.3. BluetoothRemoteGATTService
BluetoothRemoteGATTService
は GATT Service 、つまり、デバイスの一部の振る舞いをカプセル化する characteristic 群のコレクションと他の Service 群との関係を表わしています。
interface BluetoothRemoteGATTService { readonly attribute BluetoothDevice device; readonly attribute UUID uuid; readonly attribute boolean isPrimary; Promise<BluetoothRemoteGATTCharacteristic> getCharacteristic(BluetoothCharacteristicUUID characteristic); Promise<sequence<BluetoothRemoteGATTCharacteristic>> getCharacteristics(optional BluetoothCharacteristicUUID characteristic); Promise<BluetoothRemoteGATTService> getIncludedService(BluetoothServiceUUID service); Promise<sequence<BluetoothRemoteGATTService>> getIncludedServices(optional BluetoothServiceUUID service); }; BluetoothRemoteGATTService implements EventTarget; BluetoothRemoteGATTService implements CharacteristicEventHandlers; BluetoothRemoteGATTService implements ServiceEventHandlers;
BluetoothRemoteGATTService
attributes device は GATT service が属するリモート peripheral を表している BluetoothDevice
です。
uuid は、service の UUID で、例えば、Heart Rate service に対しては '0000180d-0000-1000-8000-00805f9b34fb'
です。
isPrimary#dom-bluetoothremotegattservice-isprimaryReferenced in:5.1. GATT Information Model5.3. BluetoothRemoteGATTService は、この service のタイプが primary か secondary かを示します。
Service service を表す BluetoothRemoteGATTService
を作成する には、UA は新しい promise promise を返し、同時に以下のステップを実行しなければなりません。
- result を
BluetoothRemoteGATTService
の新しいインスタンスにします。 - service が現れるデバイスを表す
BluetoothDevice
を取得 し、device を結果とします。 - 以前のステップでエラーがスローされた場合、そのエラーとともに promise を reject し、以下のステップを中止します。
-
result.device
を device から初期化します。 result.uuid
を service の UUID から初期化します。- service が Primary Service の場合、
result.isPrimary
を true に初期化します。そうでない場合、result.isPrimary
を false に初期化します。 - result を使って promise を resolve します。
getCharacteristic(characteristic)
メソッドは、この Service の内部から Characteristic を取り出します。呼び出されると、次の値を返さなければなりません。
GetGATTChildren(attribute=this
,
single=true,
uuidCanonicalizer=BluetoothUUID.getCharacteristic
,
uuid=characteristic
,
allowedUuids=undefined
,
child type="GATT Characteristic")
getCharacteristics(characteristic)
メソッドは、この Service の内部から Characteristic のリストを取り出します。呼び出されると、次の値を返さなければなりません。
GetGATTChildren(attribute=this
,
single=false,
uuidCanonicalizer=BluetoothUUID.getCharacteristic
,
uuid=characteristic
,
allowedUuids=undefined
,
child type="GATT Characteristic")
getIncludedService(service)
メソッドは、この Service の内部から Included Service を取り出します。呼び出されると、次の値を返さなければなりません。
GetGATTChildren(attribute=this
,
single=true,
uuidCanonicalizer=BluetoothUUID.getService
,
uuid=service
,
allowedUuids=undefined
,
child type="GATT Included Service")
getIncludedServices(service)
メソッドは、この Service の内部から Included Service のリストを取り出します。呼び出されると、次の値を返さなければなりません。
GetGATTChildren(attribute=this
,
single=false,
uuidCanonicalizer=BluetoothUUID.getService
,
uuid=service
,
allowedUuids=undefined
,
child type="GATT Included Service")
5.4. BluetoothRemoteGATTCharacteristic
BluetoothRemoteGATTCharacteristic
は GATT Characteristic を表し、peripheral の service について詳細情報を提供する基本データエレメントです。
interface BluetoothRemoteGATTCharacteristic { readonly attribute BluetoothRemoteGATTService service; readonly attribute UUID uuid; readonly attribute BluetoothCharacteristicProperties properties; readonly attribute DataView? value; Promise<BluetoothRemoteGATTDescriptor> getDescriptor(BluetoothDescriptorUUID descriptor); Promise<sequence<BluetoothRemoteGATTDescriptor>> getDescriptors(optional BluetoothDescriptorUUID descriptor); Promise<DataView> readValue(); Promise<void> writeValue(BufferSource value); Promise<void> startNotifications(); Promise<void> stopNotifications(); }; BluetoothRemoteGATTCharacteristic implements EventTarget; BluetoothRemoteGATTCharacteristic implements CharacteristicEventHandlers;
BluetoothRemoteGATTCharacteristic
attributesservice は、この characteristic が属する GATT service です。
uuid は、characteristic の UUID で、例えば、Heart Rate Measurement であれば '00002a37-0000-1000-8000-00805f9b34fb'
です。
properties は、この characteristic のプロパティを保持します。
value は、現在キャッシュされている characteristic の値です。この値は、characteristic の値が notification や indication 経由で読み出されたり更新される場合に更新されます。
Characteristic characteristic を表す BluetoothRemoteGATTCharacteristic
を作成するには、UA が新しい promise promise を返し、同時に以下のステップを実行しなければなりません。
- result を
BluetoothRemoteGATTCharacteristic
の新しいインスタンスにします。 result.service
を、characteristic が現れる Service を表すBluetoothRemoteGATTService
インスタンスから初期化します。-
result.uuid
を characteristic の UUID から初期化します。 -
BluetoothCharacteristicProperties
インスタンスを Characteristic characteristic から作成し、propertiesPromise を結果とします。 - propertiesPromise が settle するまで待ちます。
- propertiesPromise が reject された場合、propertiesPromise で promise を resolve し、以下のステップを中止します。
result.properties
を propertiesPromise が fulfilled された値から初期化します。result.value
をnull
に初期化します。UA はresult.value
を新しいDataView
に初期化できます。このDataView
は、characteristic から直近に読み込まれた値(値が利用可能な場合)を格納する新しいArrayBuffer
のラッパーです。- result を使って promise を resolve します。
getDescriptor(descriptor)
メソッドは、この Characteristic の内部から Descriptor を取り出します。呼び出されると、次の値を返さなければなりません。
GetGATTChildren(attribute=this
,
single=true,
uuidCanonicalizer=BluetoothUUID.getDescriptor
,
uuid=descriptor
,
allowedUuids=undefined
,
child type="GATT Descriptor")
getDescriptors(descriptor)
メソッドは、この Characteristic の内部から Descriptor のリストを取り出します。呼び出されると、次の値を返さなければなりません。
GetGATTChildren(attribute=this
,
single=false,
uuidCanonicalizer=BluetoothUUID.getDescriptor
,
uuid=descriptor
,
allowedUuids=undefined
,
child type="GATT Descriptor")
readValue()
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
-
this.uuid
が 読み込みのブラックリストにある場合、SecurityError
で promise を reject して返し、以下のステップを中止します。 this.characteristic.service.device.gatt.
がconnected
false
の場合、reject された promise をNetworkError
で返し、以下のステップを中止します。- characteristic を、
this
が表している Characteristic にします。 -
新しい promise promise の
this.service.device.gatt
-connection-checking wrapper を返し、同時に以下のステップを実行します。:Read
ビットが characteristic の properties でセットされていない場合、NotSupportedError
で promise をreject し、以下のステップを中止します。- characteristic の値を取り出すためには、Characteristic Value Read プロシージャ無いのサブプロシージャの組み合わせを使用します。§5.7 Error handling で記載されたようにエラーをハンドリングします。
- 以前のステップでエラーが返さえれた場合、エラーとともに promise を reject し、以下のステップを中止します。
-
以下のステップを実行するためにタスクをキューインします:
- promise が
this.service.device.gatt@
の中に無い場合、[[activeAlgorithms]]
NetworkError
で promise を reject し、以下のステップを中止します。 - buffer を、取り出された値を保持する
ArrayBuffer
とし、new DataView(buffer)
をthis.value
に割り当てます。 -
ここで
bubbles
属性をtrue
に初期化して、characteristicvaluechanged
という名前の イベントを開始します。 -
this.value
を使って promsie をresolve します。
- promise が
writeValue(value)
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
this.uuid
が 書き込みのブラックリストにある場合、SecurityError
で promise を reject して返し、以下のステップを中止します。- characteristic を、
this
が表している Characteristic にします。 - bytes を、
value
により 保持されたバイトのコピー とします。 - bytes が 512 バイト(Long Attribute Values あたりの属性値の最大長)を超える場合、
InvalidModificationError
を使って promise を reject して返し、以下のステップを中止します。 -
this.service.device.gatt.
がconnected
false
の場合、NetworkError
で promise を reject して返し、以下のステップを中止します。 -
新しい promise promise の
this.service.device.gatt
-connection-checking wrapper を返し、同時に以下のステップを実行します。-
Write
、Write Without Response
、Authenticated Signed Writes
ビットのいずれも characteristic の properties で設定されていない場合、NotSupportedError
とともに promise を reject し、以下のステップを中止します。 - characteristic に bytes を書き込むには、Characteristic Value Write procedure 内のサブプロシージャの組み合わせを使用します。§5.7 Error handling で記載されたようにエラーをハンドリングします。
- 以前のステップでエラーが返さえれた場合、エラーとともに promise を reject し、以下のステップを中止します。
-
以下のステップを実行するためにタスクをキューイングします。:
- promise が
this.service.device.gatt@
に無い場合、[[activeAlgorithms]]
NetworkError
を使って promise を reject し、以下のステップを中止します。 -
this.value
を、bytes を格納する新しいArrayBuffer
のラッパーである、新しいDataView
にセットします。 -
undefined
を使って promise を resolve します。
- promise が
-
UA は、既知の GATT Characteristic の アクティブな notification のコンテキストセット( active notification context set#active-notification-context-setReferenced in:5.4. BluetoothRemoteGATTCharacteristic (2) (3) (4)5.6.4. Responding to Notifications and Indications )と呼ばれる Bluetooth
オブジェクト群の集合へのマッピングを保持しなければなりません。
既知の characteristic の集合は、notification に登録された各 Realm に対する navigator.bluetooth
オブジェクト群を格納しています。
startNotifications()
メソッド、呼び出されると、新しい promise promise を返し、同時に以下のステップを実行しなければなりません。notification の受信の詳細は §5.6.4 Responding to Notifications and Indications を参照してください。
this.uuid
が 読み込みのブラックリストにある場合、SecurityError
を使って promise を reject し、以下のステップを中止します。- characteristic を
this
が表している GATT Characteristic にします。 -
Notify
またはIndicate
ビットのいずれかが characteristic の properties でオンでない場合、NotSupportedError
を使って promise を reject し、以下のステップを中止します。 - characteristic の アクティブな notification のコンテキストセット( active notification context set )が
navigator.bluetooth
を含む場合、undefined
を使って promise を resolve し、以下のステップを中止します。 -
this.service.device.gatt.
がconnected
false
の場合、NetworkError
を使って promise を reject し、以下のステップを中止します。 - Characteristic Descriptors procedures を使用して、characteristic の Client Characteristic Configuration descriptor に
Notification
またはIndication
ビットの一つが確実にセットされ、characteristic の properties の制約と整合させてください。UA は、ビットを両方セットすることを避ける必要があり、両方のビットがセットされる場合は、value-change イベント群を分解しなければなりません。§5.7 Error handling で記載されたようにエラーをハンドリングします。 - 以前のステップでエラーが返さえれた場合、エラーとともに promise を reject し、以下のステップを中止します。
navigator.bluetooth
を characteristic のアクティブ notification コンテキストセット( active notification context set )に追加します。undefined
を使って promise をresolve します。
notification が有効になった後、結果の value-change event 群は、現在のマイクロタスクのチェックポイント( microtask checkpoint. )が終了するまで配送されません。この結果、開発者は結果の promise の .then
handler に、ハンドラを設定することができます。
stopNotifications()
メソッドは、呼び出されると、新しい promise promise を返し、同時に以下のステップを実行しなければなりません。:
- characteristic を
this
が表している GATT Characteristic にします。 - characteristic の アクティブな notification コンテキストセット( active notification context set ) に
navigator.bluetooth
が含まれる場合、削除してください。 - characteristic の アクティブな notification コンテキストセット( active notification context set ) が空になった場合、characteristic の Client Characteristic Configuration descriptor の
Notification
andIndication
ビットをクリアするために、UA は Characteristic Descriptors procedures を使用する必要があります。 -
undefined
で promise を resolve するために タスクをキューイングします。
promise を resolve するタスクをキューイングすれば、promise が resolve した後、notification の到着による value change events イベントがないことを保証できます。
5.4.1. BluetoothCharacteristicProperties
各 BluetoothRemoteGATTCharacteristic
は、characteristic properties を BluetoothCharacteristicProperties
オブジェクトを通して公開します。このプロパティ群は、characteristic で何のオペレーションが有効なのかを表しています。
interface BluetoothCharacteristicProperties { readonly attribute boolean broadcast; readonly attribute boolean read; readonly attribute boolean writeWithoutResponse; readonly attribute boolean write; readonly attribute boolean notify; readonly attribute boolean indicate; readonly attribute boolean authenticatedSignedWrites; readonly attribute boolean reliableWrite; readonly attribute boolean writableAuxiliaries; };
create a BluetoothCharacteristicProperties
インスタンスを Characteristic characteristic から作成するために、UA は新しい promise promise を返し、同時に以下のステップを実行しなければなりません。:
- propertiesObj を
BluetoothCharacteristicProperties
の新しいインスタンスにします。 - properties を characteristic のcharacteristic properties にします。
- propertiesObj 属性を properties の応答ビットから初期化します。:
Attribute Bit broadcast
Broadcast read
Read writeWithoutResponse
Write Without Response write
Write notify
Notify indicate
Indicate authenticatedSignedWrites
Authenticated Signed Writes -
characteristic properties の拡張プロパティビットがセットされていない場合、
propertiesObj.reliableWrite
とpropertiesObj.writableAuxiliaries
をfalse
に初期化します。そうでない場合、以下のステップを実行します。:-
characteristic に対する Characteristic Extended Properties descriptor を 発見し、その値を extendedProperties に読み込みします。§5.7 Error handling で記載されたようにエラーをハンドリングします。
Characteristic Extended Properties は、Characteristic に対して拡張往路パティが変更不可能であるかどうか明らかではありません。もしそうならば、UA はキャッシュを許可するようにすべきです。
- 以前のステップでエラーが返さえれた場合、エラーとともに promise を reject し、以下のステップを中止します。
-
propertiesObj.reliableWrite
を extendedProperties の Reliable Write ビットから初期化します。 -
propertiesObj.writableAuxiliaries
を extendedProperties の Writable Auxiliaries ビットから初期化します。
-
characteristic に対する Characteristic Extended Properties descriptor を 発見し、その値を extendedProperties に読み込みします。§5.7 Error handling で記載されたようにエラーをハンドリングします。
- propertiesObj を使って promise を resolve します。
5.5. BluetoothRemoteGATTDescriptor
BluetoothRemoteGATTDescriptor
は GATT Descriptor を表し、Characteristic の値についての詳細情報を提供します。
interface BluetoothRemoteGATTDescriptor { readonly attribute BluetoothRemoteGATTCharacteristic characteristic; readonly attribute UUID uuid; readonly attribute DataView? value; Promise<DataView> readValue(); Promise<void> writeValue(BufferSource value); };
BluetoothRemoteGATTDescriptor
attributescharacteristic は、この descriptor が属する GATT characteristic です。
uuid は characteristic descriptor の UUID です。例えば Client Characteristic Configuration descriptor であれば '00002902-0000-1000-8000-00805f9b34fb'
です。
value は descriptor に現在キャッシュされている値です。この値は、descriptor が読み出される時に更新されます。
Descriptor descriptor をす BluetoothRemoteGATTDescriptor
を作成するには、UA は新しい promise を返し、同時に以下のステップを実行しなければなりません。
- result を
BluetoothRemoteGATTDescriptor
の新しいインスタンスにします。 -
result.characteristic
を、descriptor が現れる Characteristic を表しているBluetoothRemoteGATTCharacteristic
インスタンスから初期化します。 -
result.uuid
を UUID の descriptor から初期化します。 -
result.value
をnull
に初期化します。UA は、result.value
を新しいDataView
に初期化できます。この DataView は、descriptor から直近に読み込まれた(値が利用可能な場合)を格納するArrayBuffer
のラッパーです。 - result を使って promise を resolve します。
readValue()#dom-bluetoothremotegattdescriptor-readvalueReferenced in:5.5. BluetoothRemoteGATTDescriptor
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
this.uuid
が 読み込みの blacklist にある場合、SecurityError
を使って promise を reject して返し、以下のステップを中止しなければなりません。this.characteristic.service.device.gatt.
がconnected
false
の場合、NetworkError
を使って promise を reject して返し、以下のステップを中止しなければなりません。- descriptor を
this
が表わしている Descriptor にします。 -
新しい promise promise の
this.characteristic.service.device.gatt
-connection-checking wrapper を返し、同時に以下のステップを実行しなければなりません。:- Read Characteristic Descriptors または Read Long Characteristic Descriptors サブプロシージャを用いて、descriptor の値を読みだしてください。§5.7 Error handling で記載されたようにエラーをハンドリングします。
- 以前のステップでエラーが返さえれた場合、エラーとともに promise を reject し、以下のステップを中止します。
-
以下のステップを実行するためにタスクをキューイングします。:
- promise が
this.characteristic.service.device.gatt@
の中に無い場合、[[activeAlgorithms]]
NetworkError
を使って promise を reject し、以下のステップを中止します。 - buffer を、読み出した値を保持する
ArrayBuffer
とし、new DataView(buffer)
をthis.value
に割り当てます。 -
this.value
を使って promise を resolve します。
- promise が
writeValue(value)
メソッドは、呼び出されると、以下のステップを実行しなければなりません。:
this.uuid
が 書き込みの blacklist にある場合、SecurityError
を使って promise を reject して返し、以下のステップを中止しなければなりません。- descriptor を
this
が表している Descriptor にします。 - bytes を、
value
により 保持されているバイトのコピー にします。 - bytes が 512バイト(Long Attribute Values あたりの属性値の最大長)を越える場合、
InvalidModificationError
とともに promise を reject して返し、以下のステップを中止します。 -
this.characteristic.service.device.gatt.
がconnected
false
の場合、NetworkError
とともに promise を reject して返し、以下のステップを中止します。 -
新しい promise promise の
this.characteristic.service.device.gatt
-connection-checking wrapper を返し、同時に以下のステップを実行します。- Write Characteristic Descriptors または Write Long Characteristic Descriptors サブプロシージャを用いて descriptor に bytes を書き込みます。§5.7 Error handling で記載されたようにエラーをハンドリングします。
- 以前のステップでエラーが返さえれた場合、エラーとともに promise を reject し、以下のステップを中止します。
-
以下のステップを実行するためにタスクをキューイングします。:
- promise が
this.characteristic.service.device.gatt@
に無い場合、[[activeAlgorithms]]
NetworkError
とともに promise を reject し、以下のステップを中止します。 -
this.value
を、bytes を含む新しいArrayBuffer
をラップする、新しいDataView
にセットします。 -
undefined
とともに promise を resolve します。
- promise が
5.6. イベント
5.6.1. Bluetooth ツリー
navigator.bluetooth
および BluetoothDevice
、BluetoothRemoteGATTService
、BluetoothRemoteGATTCharacteristic
、dBluetoothRemoteGATTDescriptor
インタフェースを実現しているオブジェクトは、Bluetooth tree と呼ばれるツリーに参加しています。
-
navigator.bluetooth
の children は、デバイスのnavigator.bluetooth
の関連する設定オブジェクト( relevant settings object )の"bluetooth"
の追加パーミッションデータ( extra permission data )の許可されたデバイス(allowedDevices
)リストを、不特定の順序で表すBluetoothDevice
オブジェクトです。 -
navigator.bluetooth
の children は、オリジンの許可されたデバイスマップ( allowed devices map )上のデバイスをある順序で表しているBluetoothDevice
オブジェクト群です。 -
BluetoothDevice
の children は、UUID がオリジンとデバイスの許可されたサービスリスト( allowed services list )にある GATT Server 上の Primary と Secondary Servicea> 群を表わしているBluetoothRemoteGATTService
オブジェクト群です。Primary サービスの順序は、Discover Service UUID による Primary Service プロシージャにより返さえる順序と一致しなければなりませんが、異なる UUID を持つ Secondary service 群と Primary service 群は、どんな順序でもかまいません。 -
BluetoothRemoteGATTService
の children は、Characteristic 群を表わしているBluetoothRemoteGATTCharacteristic
オブジェクト群です。characteristic 群の順序は、UUID による Discover Characteristics プロシージャにより返されると順序と一致しなければなりませんが、異なる UUID を持つ characteristic 群は、どんな順序でも構いません。 -
BluetoothRemoteGATTCharacteristic
の children は Discover All Characteristic Descriptors プロシージャで返される順序で Descriptor 群を表しているBluetoothRemoteGATTDescriptor
オブジェクト群です。
5.6.2. イベントタイプ
advertisementreceived
- アドバタイズイベントをそのデバイスから受信した時に
BluetoothDevice
上で開始されます。 gattserverdisconnected
- アクティブな GATT connection を失った時に
BluetoothDevice
上で開始されます。 servicechanged
-
BluetoothRemoteGATTService
リモートデバイスを発見して、Bluetooth tree に追加した直後に新しいBluetoothRemoteGATTService
で開始されます。 servicechanged
- 状態が変化した時に、
BluetoothRemoteGATTService
上で開始されます。サービスに追加またはサービスから削除される characteristic 群 および/または descriptor 群、およびリモートデバイスからの Service Changed インディケーションが含まれます。 serviceremoved
- デバイスから切断され、Bluetooth tree から削除される直前に
BluetoothRemoteGATTService
で開始されます。
5.6.3. 切断への応答
Bluetooth device device の ATT Bearer が(例えば、リモートデバイスが圏外に移動した、またはユーザが切断するプラットフォーム機能を使用したなどの理由で)失われた時、UA は、各 BluetoothDevice
deviceObj に対して、以下のステップを実行するために、deviceObj の関連する設定オブジェクト( relevant settings object’ )が責任を持つイベントループ( responsible event loop )にタスクをキューイングしなければなりません。:
-
deviceObj@
が device と同一デバイスでない場合、以下のステップを中止します。[[representedDevice]]
-
deviceObj.gatt.
が false の場合、以下のステップを中止します。connected
-
deviceObj.gatt.
にconnected
false
をセットします。 -
deviceObj.gatt@
をクリアします。[[activeAlgorithms]]
-
deviceObj
のbubbles
属性をtrue
に初期化して、gattserverdisconnected
という名前のイベントを開始します。このイベントは
BluetoothRemoteGATTServer
では開始されません。
5.6.4. Notifications と Indications への応答
UA が Bluetooth Characteristic Value Notification または Indication を受信した時、以下のステップを実行しなければなりません。:
-
Characteristic のアクティブな notification コンテキストセット( active notification context set )の中にある各 bluetoothGlobal に対して、以下のサブステップを実行するために、bluetoothGlobal のスクリプト設定オブジェクトのイベントループにタスクをキューイングします。:
- characteristicObject を、Characteristic を表している bluetoothGlobal をルートとする Bluetooth tree にある
BluetoothRemoteGATTCharacteristic
にセットします。 -
characteristicObject.service.device.gatt.
がconnected
false
の場合、以下のサブステップを中止します。 -
characteristicObject.value
を、Characteristic の新しい値を保持する新しいArrayBuffer
のラッパーである、新しいDataView
にセットします。 - characteristicObject で bubbles 属性を
true
に初期化してcharacteristicvaluechanged
という名前のイベントを開始します。
- characteristicObject を、Characteristic を表している bluetoothGlobal をルートとする Bluetooth tree にある
5.6.5. Service Changes への応答
Bluetooth Attribute Caching では、クライアントが Service、Characteristic、Descriptor に加えられた変更を追跡することが可能です。ウェブページで公開する目的でエンティティを検索する前に、UA は Service Changed characteristic からの Indication を(存在すれば)購読しなければなりません。UA が Service Changed characteristic の Indication を受信した場合、以下のステップを実行しなければなりません。:
- removedEntities を、Indication 前に UA が発見していた Service Changed characteristic により Indicate された範囲内のエンティティのリストとします。
- Primary Service Discovery、Relationship Discovery、Characteristic Discovery、Characteristic Descriptor Discovery プロシージャを使用して、Service Changed characteristic で indicate される範囲内の entity を再検索します。発見の結果が、以下で開始されるイベントに影響を与えないことが分かる場合は、UA は、indicate された範囲の全てまたは一部の検索をスキップできます。
- addedEntities を、前のステップで発見された entity のリストとします。
- 同じ定義を持つ entity が( Characteristic と Descriptor の値を無視して)removedEntities と addedEntities の両方に現れた場合、その entity を両方から削除します。
- changedServices を Service の集合(初期値は空)とします。
- 同一 Service が removedEntities と addedEntities の両方に現れた場合、その service を両方から削除し、changedServices に追加します。
- removedEntities と addedEntities の各 Characteristic と Descriptor について、オリジナルリストから削除し、その親 Service を changedServices に追加します。これ以降では、removedEntities と addedEntities は Service 群しか含んでいません。
-
addedEntities 内の Service が、これまでおこなった
getPrimaryService
、getPrimaryServices
、getIncludedService
、getIncludedServices
呼び出しから返されていない場合、service が呼び出し時点で存在していれば、UA は addedEntities からこの Service を削除できます。 - changedDevices を removedEntities、addedEntities、changedServices にある任意の Service を含む Bluetooth device のセットとします。
- changedDevices に接続された各
BluetoothDevice
deviceObj に対して、以下のステップを実行するために、global object が責任を持つイベントループ( responsible event loop )に タスクをキューイングします。:-
removedEntities の各 Service service に対して:
-
deviceObj@
の残りの Service が、service として同一 UUID を持たない場合、UUID を[[representedDevice]]
deviceObj@
から削除します。[[unfilteredUuids]]
- Service の UUID が
deviceObj@
にある場合、Service を表す[[allowedServices]]
BluetoothRemoteGATTService
でbubbles
属性をtrue
に初期化して、serviceremoved
という名前の イベントを開始します。 - この
BluetoothRemoteGATTService
を Bluetooth tree から削除します。
-
- addedEntities の 各 Service に対して、Service の UUID を
deviceObj@
に追加します。 Service の UUID が[[unfilteredUuids]]
deviceObj@
にある場合、この Service を表す[[allowedServices]]
BluetoothRemoteGATTService
を Bluetooth tree に追加し、BluetoothRemoteGATTService
でbubbles
属性をtrue
に初期化して、serviceadded
という名前の イベントを開始します。 - changedServices にある各 Service に対して、Service の UUID が
deviceObj@
にある場合、Service を表す[[allowedServices]]
BluetoothRemoteGATTService
でbubbles
属性をtrue
に初期化して、servicechanged
という名前のイベントを開始します。
-
removedEntities の各 Service service に対して:
5.6.6. IDL イベントハンドラ
[NoInterfaceObject] interface CharacteristicEventHandlers { attribute EventHandler oncharacteristicvaluechanged; };
oncharacteristicvaluechanged は characteristicvaluechanged
イベントタイプ用のイベントハンドラIDL属性( Event handler IDL attribute )です。
[NoInterfaceObject] interface BluetoothDeviceEventHandlers { attribute EventHandler ongattserverdisconnected; };
ongattserverdisconnected は gattserverdisconnected
イベントタイプ用のイベントハンドラIDL属性( Event handler IDL attribute )です。
[NoInterfaceObject] interface ServiceEventHandlers { attribute EventHandler onserviceadded; attribute EventHandler onservicechanged; attribute EventHandler onserviceremoved; };
onserviceadded は serviceadded
イベントタイプ用のイベントハンドラIDL属性( Event handler IDL attribute )です。
onservicechanged は servicechanged
イベントタイプ用のイベントハンドラIDL属性( Event handler IDL attribute )です。
onserviceremoved は serviceremoved
イベントタイプ用のイベントハンドラIDL属性( Event handler IDL attribute )です。
5.7. エラーハンドリング
本セクションでは、主に、システムエラーから Javascript エラー名へのマッピングを定義し、UA がいくつかのオペレーションをリトライできるようにします。リトライのロジックならびに可能性があるエラーの区別は、オペレーティングシステムに大きく制約を受けます。従って、この要件が現実を反映していない所は、ブラウザのバグではなく仕様バグである可能性が高いです。
UA が GATT procedure を用いてアルゴリズムでステップを実行したり、Bluetooth cache への問合せを処理したり(ここでは、この二つを「ステップ」と呼びます)、GATT procedure が Error Response
を返す場合、UA は以下のステップを実行しなければなりません。:
- procedure が タイムアウトする、または ATT Bearer ( Profile Fundamentals で記載) が存在しない、または何らかの理由で終了した場合、
NetworkError
を返し、以下のステップを終了します。 -
Error Code
によっては、以下の措置を行ってください。:Invalid Handle
Invalid PDU
Invalid Offset
Attribute Not Found
Unsupported Group Type
- これらのエラーコードは、プロトコルレイヤーで予想外の何かが発生したことを示しています。UA またはデバイスバグに可能性がありそうです。
NotSupportedError
を返します。 Invalid Attribute Value Length
-
InvalidModificationError
を返します。 Attribute Not Long
-
"Long" サブプロシジャを使用していないのにこのエラーコードを受信した場合は、デバイスのバグの可能性があります。このステップから
NotSupportedError
を返します。そうでない場合、"Long" サブプロシジャを使用しないでリトライします。書き込まれた値の長さからこれが不可能な場合、このステップから
InvalidModificationError
を返します。 Insufficient Authentication
Insufficient Encryption
Insufficient Encryption Key Size
- UA は、接続のセキュリティレベルを上げる必要があります。この試みが失敗する、または UA がこれより高度なセキュリティを提供していない場合は、このステップから
SecurityError
を返します。そうでない場合、新しく高度なセキュリティレベルで本ステップをリトライします。 Insufficient Authorization
-
SecurityError
を返します。 Application Error
- GATT procedure が Write である場合、このステップから
InvalidModificationError
を返します。そうでない場合、このステップからNotSupportedError
を返します。 Read Not Permitted
Write Not Permitted
Request Not Supported
Prepare Queue Full
Insufficient Resources
Unlikely Error
- Anything else
-
NotSupportedError
を返します。
6. UUIDs
typedef DOMString UUID;
UUID 文字列は128ビットの UUID [RFC4122] を表現します。有効な UUID は次の正規表現とマッチする文字列です。
the [ECMAScript] regexp /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
つまり、有効な UUID は小文字で、Bluetooth標準で定義されている16ビット/32ビットの短縮版は使用しません。本仕様書の関数と属性から返却されるUUID全ては、有効な UUID でなければなりません。
本仕様書の関数に、UUID または UUID 属性を含む辞書を型とする引数があり、UUID スロットに渡される引数が有効な UUID でない場合、関数は TypeError
とともに promise を reject して返し、他のステップを中止しなければなりません。
本標準では、16ビットまたは32ビットの Bluetooth UUID エイリアス を128ビット形式にマップする BluetoothUUID.canonicalUUID(alias)
関数を提供しています。
Bluetoothデバイス は、比較前に(属性タイプに記載されたように)16ビットまたは32ビットの UUID を 128ビットの UUID に変換する必要がありますが、全てのデバイスがそうしているわけではありません。このようなデバイスと相互運用するため、UA が (16-, 32-, または 128-ビット)形式のデバイスから UUID を受信した場合、その UUID の他のエイリアスを同一形式でデバイスに送り返さなければなりません。
6.1. 標準化された UUID
Bluetooth SIG は、UUID の [BLUETOOTH-ASSIGNED] に services、characteristics、descriptors および他のエンティティを識別するレジストリーを保持しています。本セクションでは、スクリプトがこれらの UUID を名前で検索する方法を提供し、各アプリケーションで複製を作らなくても済むようにします。
interface BluetoothUUID { static UUID getService((DOMString or unsigned long) name); static UUID getCharacteristic((DOMString or unsigned long) name); static UUID getDescriptor((DOMString or unsigned long) name); static UUID canonicalUUID([EnforceRange] unsigned long alias); }; typedef (DOMString or unsigned long) BluetoothServiceUUID; typedef (DOMString or unsigned long) BluetoothCharacteristicUUID; typedef (DOMString or unsigned long) BluetoothDescriptorUUID;
静的な BluetoothUUID.canonicalUUID(alias)
メソッドは、呼び出されると、16ビットまたは32ビット UUID エイリアスで表現された128ビットのUUIDを返さなければなりません。
このアルゴリズムは"00000000-0000-1000-8000-00805f9b34fb
"の上位32ビットをエイリアスのビットで置換するよう構成されています。例えば canonicalUUID(0xDEADBEEF)
であれば "deadbeef-0000-1000-8000-00805f9b34fb"
を返します。
BluetoothServiceUUID は16ビットまたは32ビット UUID エイリアス、つまり有効なUUID、[BLUETOOTH-ASSIGNED-SERVICES]の中で定義された名前を表しています。言い換えれば BluetoothUUID.getService()
で例外を発生させない値です。
BluetoothCharacteristicUUID は16ビットまたは32ビット UUID エイリアス、つまり有効な UUID 、[BLUETOOTH-ASSIGNED-CHARACTERISTICS] の中で定義された名前を表しています。言い換えれば BluetoothUUID.getCharacteristic()
で例外を発生させない値です。
BluetoothDescriptorUUID は16ビットまたは32ビット UUID エイリアス、つまり有効な UUID、[BLUETOOTH-ASSIGNED-DESCRIPTORS] の中で定義された名前を表しています。言い換えれば BluetoothUUID.getDescriptor()
で例外を発生させない値です。
ResolveUUIDName(name, assigned numbers table, prefix) を実行するためには、UA は以下のステップを実行しなければなりません:
- name が
unsigned long
の場合、BluetoothUUID.canonicalUUID
(name) を返し、以下のステップを中止します。 - name が有効な UUID の場合、name を返し、以下のステップを中止します。
prefix + "." + name
が 指定された番号テーブル に現れた場合、エイリアスを指定された番号にしてBluetoothUUID.canonicalUUID
(alias) を返します。- それ以外の場合は
SyntaxError
をスローします。
静的な BluetoothUUID.getService(name)
メソッドは、呼び出されると、ResolveUUIDName(name
, [BLUETOOTH-ASSIGNED-SERVICES], "org.bluetooth.service") を返さなければいけません。
静的な BluetoothUUID.getCharacteristic(name)
メソッドは、呼び出されると、ResolveUUIDName(name
, [BLUETOOTH-ASSIGNED-CHARACTERISTICS], "org.bluetooth.characteristic") を返さなければいけません。
静的な BluetoothUUID.getDescriptor(name)
メソッドは、呼び出されると、ResolveUUIDName(name
, [BLUETOOTH-ASSIGNED-DESCRIPTORS], "org.bluetooth.descriptor") を返さなければいけません。
returns BluetoothUUID.getService
("cycling_power")"00001818-0000-1000-8000-00805f9b34fb"
.
returns BluetoothUUID.getService
("00001801-0000-1000-8000-00805f9b34fb")"00001801-0000-1000-8000-00805f9b34fb"
.
throws a BluetoothUUID.getService
("unknown-service")SyntaxError
.
returns BluetoothUUID.getCharacteristic
("ieee_11073-20601_regulatory_certification_data_list
")"00002a2a-0000-1000-8000-00805f9b34fb"
.
returns BluetoothUUID.getDescriptor
("gatt.characteristic_presentation_format
")"00002904-0000-1000-8000-00805f9b34fb"
.
7. GATTブラックリスト
本仕様は、ウェブサイトがアクセス可能な GATT 属性 の集合を制限するために https://github.com/WebBluetoothCG/registries にあるブラックリストファイルに依存しています。
URLにあるブラックリストをパース した結果は、以下のアルゴリズムにより生成される、有効な UUID からトークンまたはエラーへのマップです:
- URLを取得し、そのコンテンツをボディとし、UTF-8 としてデコードします。
- lines は
'\n'
で分割された内容とします。 - result を空のマップにします。
-
lines の各 lineに対して、以下のサブステップを実行します:
- line が空行か、先頭文字が
'#'
の場合、次の行に進みます。 - line が 有効な UUID の場合、uuid をその UUID とし、token を "
exclude
" にします。 - line が 有効なUUID、スペース(U+0020)、そして "
exclude-reads
" または "exclude-writes
" のいずれかのトークンからなる場合、uuid をその UUID とし、token をそのトークンにします。 - そうでない場合は、エラーを返し、以下のステップを中止します。
- uuid がすでに result の中にある場合、エラーを返し、以下のステップを中止します。
- uuid から token へのマッピングを result に追加します。
- line が空行か、先頭文字が
- result を返します。
GATT blacklist は https://github.com/WebBluetoothCG/registries/blob/master/gatt_blacklist.txt にある ブラックリストをパース した結果です。 UA は定期的にブラックリストを再読み込みすべきですが、頻度は規定されていません。
GATT blacklist の値がエラーか、UUIDが GATT blacklist で "exclude
" にマップされる場合、UUID は ブラックリストに加えられます。#blacklistedReferenced in:3. Device Discovery (2)5.1.2. Navigating the Bluetooth Hierarchy
GATT blacklist の値がエラーか、UUIDが GATT blacklist で "exclude
" または "exclude-reads
" にマップされる場合、UUID は 読み出し用ブラックリストに加えられます。#blacklisted-for-readsReferenced in:5.4. BluetoothRemoteGATTCharacteristic (2)5.5. BluetoothRemoteGATTDescriptor
GATT blacklist の値がエラーか、UUIDが GATT blacklist で "exclude
" または "exclude-writes
" にマップされる場合、UUID は 書き込み用ブラックリストに加えられます。#blacklisted-for-writesReferenced in:5.4. BluetoothRemoteGATTCharacteristic5.5. BluetoothRemoteGATTDescriptor
8. ナビゲーションインターフェースの拡張
partial interface Navigator { readonly attribute Bluetooth bluetooth; };
9. 用語と規則
本仕様書は、規約と他の仕様書からの用語をいくつか使用します。本セクションでは、これらと主要な定義へのリンクをリストアップします。
Streams仕様書に刺激を受け、本仕様書では、オブジェクトの内部スロットを参照するため、「内部スロットxの [[y]]」という代わりに[[[ x@[[y]] ]]] という表記を使用します。
本仕様書で用いるアルゴリズムが、この仕様書または別の仕様書で定義される名前を用いる場合、その名前は初期値で解決され、現在の実行環境で名前に加えられたいかなる変更も無視しなければなりません。
例えば、requestDevice()
アルゴリズムが、
を呼び出す場合、パラメータとアルゴリズムは §6.1 Standardized UUIDs 内の Array.prototype.map
.call(filter.services, BluetoothUUID.getService
)BluetoothUUID.getService
で callbackfn
パラメータとして定義された、filter.services
を使って [ECMAScript] で定義された Array.prototype.map
アルゴリズムに適用されなければなりません。これはwindow
, Array
, Array.prototype
, Array.prototype.map
, Function
, Function.prototype
, BluetoothUUID
, BluetoothUUID.getService
またはその他のオブジェクトに加えられた修正とは関係ありません。
本仕様書では、WebIDLの FrozenArray
と同様の読み出し専用タイプを使用しています。
- 読み取り専用 ArrayBuffer には
ArrayBuffer
の値とインターフェースがあります。このコンテンツへの書き込みまたは転送を試みようとすることを除き、FrozenArray
のコンテンツへ書き込もうとした時と同じ影響があります。ArrayBuffer
でラッピングされたTypedArray
とDataView
にもこれは適用されます。
- [BLUETOOTH42]
-
-
Architecture & Terminology Overview
-
General Description
- Overview of Bluetooth Low Energy Operation (defines advertising events)
-
Communication Topology and Operation
-
Operational Procedures and Modes
-
BR/EDR Procedures
-
Inquiry (Discovering) Procedure
- Extended Inquiry Response
-
Inquiry (Discovering) Procedure
-
BR/EDR Procedures
-
Operational Procedures and Modes
-
General Description
-
Core System Package [BR/EDR Controller volume]
-
Host Controller Interface Functional Specification
-
HCI Commands and Events
-
Informational Parameters
- Read BD_ADDR Command
-
Status Parameters
- Read RSSI Command
-
Informational Parameters
-
HCI Commands and Events
-
Host Controller Interface Functional Specification
-
Core System Package [Host volume]
-
Service Discovery Protocol (SDP) Specification
-
Overview
-
Searching for Services
- UUID (defines UUID aliases and the algorithm to compute the 128-bit UUID represented by a UUID alias)
-
Searching for Services
-
Overview
-
Generic Access Profile
-
Profile Overview
-
Profile Roles
-
Roles when Operating over an LE Physical Transport
- Broadcaster Role
- Observer Role
- Peripheral Role
- Central Role
-
Roles when Operating over an LE Physical Transport
-
Profile Roles
-
User Interface Aspects
-
Representation of Bluetooth Parameters
- Bluetooth Device Name (the user-friendly name)
-
Representation of Bluetooth Parameters
-
Idle Mode Procedures — BR/EDR Physical Transport
- Device Discovery Procedure
- Operational Modes and Procedures — LE Physical Transport
-
Security Aspects — LE Physical Transport
- Privacy Feature
-
Random Device Address
- Static Address
-
Private address
- Resolvable Private Address Resolution Procedure
- Advertising Data and Scan Response Data Format (defines AD structure)
-
Bluetooth Device Requirements
-
Bluetooth Device Address (defines BD_ADDR)
-
Bluetooth Device Address Types
- Public Bluetooth Address
-
Bluetooth Device Address Types
-
Bluetooth Device Address (defines BD_ADDR)
-
Profile Overview
-
Attribute Protocol (ATT)
-
Protocol Requirements
-
Basic Concepts
- Attribute Type
- Attribute Handle
- Long Attribute Values
-
Attribute Protocol Pdus
-
Error Handling
- Error Response
-
Error Handling
-
Basic Concepts
-
Protocol Requirements
-
Generic Attribute Profile (GATT)
-
Profile Overview
- Configurations and Roles (defines GATT Client and GATT Server)
- Profile Fundamentals, defines the ATT Bearer
-
Attribute Protocol
- Attribute Caching
-
GATT Profile Hierarchy
- Service
- Included Services
- Characteristic
-
Service Interoperability Requirements
-
Characteristic Definition
-
Characteristic Declaration
- Characteristic Properties
-
Characteristic Descriptor Declarations
- Characteristic Extended Properties
- Client Characteristic Configuration
-
Characteristic Declaration
-
Characteristic Definition
-
GATT Feature Requirements — defines the GATT procedures.
- Primary Service Discovery
- Relationship Discovery
- Characteristic Discovery
-
Characteristic Descriptor Discovery
- Discover All Characteristic Descriptors
- Characteristic Value Read
- Characteristic Value Write
- Characteristic Value Notification
- Characteristic Value Indications
-
Characteristic Descriptors
- Read Characteristic Descriptors
- Read Long Characteristic Descriptors
- Write Characteristic Descriptors
- Write Long Characteristic Descriptors
- Procedure Timeouts
-
GAP Interoperability Requirements
-
BR/EDR GAP Interoperability Requirements
- Connection Establishment
-
LE GAP Interoperability Requirements
- Connection Establishment
-
BR/EDR GAP Interoperability Requirements
-
Defined Generic Attribute Profile Service
- Service Changed
-
Profile Overview
-
Security Manager Specification
-
Security Manager
-
Security in Bluetooth Low Energy
- Definition of Keys and Values, defines the Identity Resolving Key (IRK)
-
Security in Bluetooth Low Energy
-
Security Manager
-
Service Discovery Protocol (SDP) Specification
-
Core System Package [Low Energy Controller volume]
-
Link Layer Specification
-
General Description
-
Device Address
- Public Device Address
-
Random Device Address
- Static Device Address
-
Device Address
-
Air Interface Protocol
-
Non-Connected States
-
Scanning State
- Passive Scanning
-
Scanning State
-
Non-Connected States
-
General Description
-
Link Layer Specification
-
Architecture & Terminology Overview
- [BLUETOOTH-SUPPLEMENT6]
-
-
Data Types Specification
-
Data Types Definitions and Formats
- Service UUID Data Type
- Local Name Data Type
- Flags Data Type
- Manufacturer Specific Data
- TX Power Level
- Service Data
- Appearance
-
Data Types Definitions and Formats
-
Data Types Specification