diff --git a/index.bs b/index.bs index be05d99..8e15a42 100644 --- a/index.bs +++ b/index.bs @@ -3519,6 +3519,46 @@ Instances of {{BluetoothRemoteGATTCharacteristic}} are created with the Characteristic has been removed or otherwise invalidated. +
"not-expected""not-expected""not-expected""not-expected"readValue()
task=] on the [=Bluetooth task source=] given |global| to [=reject=]
|promise| with a "{{NotSupportedError}}" {{DOMException}} and abort
these steps.
- 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
- global task=] on the [=Bluetooth task source=] given |global| to
- [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
- abort these steps.
-
- Issue(188): Implementations may be able to avoid this {{NetworkError}},
- but for now sites need to serialize their use of this API and/or give
- the user a way to retry failed operations.
- 1. Use any combination of the sub-procedures in the [=Characteristic Value
- Read=] procedure to retrieve the value of |characteristic|.
- Handle errors as described in .
+ 1. If |global|'s [=Window/navigable=]'s
+ [=navigable/top-level traversable=]'s simulated Bluetooth adapter
+ is not empty, run the following steps:
+ 1. If [=this=].{{[[automatedCharacteristicReadResponse]]}} is not `"not-expected"`,
+ [=queue a global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}} and abort
+ these steps.
+ 1. [=Trigger a simulated characteristic event=] given |global|'s
+ [=Window/navigable=], [=this=].{{BluetoothRemoteGATTServer/device}},
+ |characteristic|, and `read`.
+ 1. Set [=this=].{{[[automatedCharacteristicReadResponse]]}} to `"expected"`,
+ and wait for it to change.
+ 1. Let |response| be [=this=].{{[[automatedCharacteristicReadResponse]]}}.
+ 1. Set [=this=].{{[[automatedCharacteristicReadResponse]]}} to `"not-expected"`.
+ 1. If |response| is not `0`, do the following sub-steps:
+ 1. [=Queue a global task=] on the [=Bluetooth task source=] given
+ |global| to [=reject=] |promise| with a "{{NetworkError}}"
+ {{DOMException}} and abort these steps.
+ 1. Otherwise, let |buffer| be a [=new=] {{ArrayBuffer}} containing
+ [=this=].{{[[automatedCharacteristicReadResponseData]]}}.
+ 1. Otherwise, run the following steps:
+ 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
+ global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
+ abort these steps.
+
+ Issue(188): Implementations may be able to avoid this {{NetworkError}},
+ but for now sites need to serialize their use of this API and/or give
+ the user a way to retry failed operations.
+ 1. Use any combination of the sub-procedures in the [=Characteristic Value
+ Read=] procedure to retrieve the value of |characteristic| and let |buffer|
+ be a [=new=] {{ArrayBuffer}} holding the retrieved value.
+ Handle errors as described in .
1. [=Queue a global task=] on the [=Bluetooth task source=] given |global|
to perform the following steps:
1. If |promise| is not in |gatt|.{{[[activeAlgorithms]]}}, [=reject=]
@@ -3621,8 +3683,7 @@ The readValue()
these steps.
1. If the sub-procedures above returned an error, [=reject=] |promise|
with that error and abort these steps.
- 1. Let |buffer| be a [=new=] {{ArrayBuffer}} holding the retrieved
- value, and assign a [=new=] {{DataView}} created with |buffer| to
+ 1. Assign a [=new=] {{DataView}} created with |buffer| to
[=this=].{{BluetoothRemoteGATTCharacteristic/value}}.
1. [=Fire an event=] named "{{characteristicvaluechanged}}" with its
{{Event/bubbles}} attribute initialized to `true` at [=this=].
@@ -3657,33 +3718,52 @@ the UA MUST perform the following steps:
1. Return a |gatt|-[=connection-checking wrapper=] around [=a new promise=]
|promise| and run the following steps [=in parallel=].
1. Assert: |response| is one of "required", "never", or "optional".
- 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
- global task=] on the [=Bluetooth task source=] given |global| to
- [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
- abort these steps.
-
- Issue(188): Implementations may be able to avoid this {{NetworkError}},
- but for now sites need to serialize their use of this API
- and/or give the user a way to retry failed operations.
- 1. Write |bytes| to |characteristic| by performing the
- following steps:
-
-
- - If |response| is "required"
- -
- Use the [=Write Characteristic Value=] procedure.
-
- - If |response| is "never"
- -
- Use the [=Write Without Response=] procedure.
-
- - Otherwise
- -
- Use any combination of the sub-procedures in the [=Characteristic
- Value Write=] procedure.
-
-
- Handle errors as described in .
+ 1. If |global|'s [=Window/navigable=]'s
+ [=navigable/top-level traversable=]'s simulated Bluetooth adapter
+ is not empty, run the following steps:
+ 1. If [=this=].{{[[automatedCharacteristicWriteResponse]]}} is not `"not-expected"`,
+ [=queue a global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}} and abort
+ these steps.
+ 1. [=Trigger a simulated characteristic event=] given |global|'s
+ [=Window/navigable=], [=this=].{{BluetoothRemoteGATTServer/device}},
+ |characteristic|, `write`, and |bytes|.
+ 1. Set [=this=].{{[[automatedCharacteristicWriteResponse]]}} to `"expected"`,
+ and wait for it to change.
+ 1. Let |response| be [=this=].{{[[automatedCharacteristicWriteResponse]]}}.
+ 1. Set [=this=].{{[[automatedCharacteristicWriteResponse]]}} to `"not-expected"`.
+ 1. If |response| is not `0`, do the following sub-steps:
+ 1. [=Queue a global task=] on the [=Bluetooth task source=] given
+ |global| to [=reject=] |promise| with a "{{NetworkError}}"
+ {{DOMException}} and abort these steps.
+ 1. Otherwise, run the following steps:
+ 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
+ global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
+ abort these steps.
+
+ Issue(188): Implementations may be able to avoid this {{NetworkError}},
+ but for now sites need to serialize their use of this API
+ and/or give the user a way to retry failed operations.
+ 1. Write |bytes| to |characteristic| by performing the
+ following steps:
+
+
+ - If |response| is "required"
+ -
+ Use the [=Write Characteristic Value=] procedure.
+
+ - If |response| is "never"
+ -
+ Use the [=Write Without Response=] procedure.
+
+ - Otherwise
+ -
+ Use any combination of the sub-procedures in the [=Characteristic
+ Value Write=] procedure.
+
+
+ Handle errors as described in .
1. Queue a global task on |global| using the [=Bluetooth task
source=] to perform the following steps:
1. If |promise| is not in |gatt|.{{[[activeAlgorithms]]}}, [=reject=]
@@ -3778,34 +3858,53 @@ notifications.
{{Navigator/bluetooth|navigator.bluetooth}}, [=queue a global task=]
on the [=Bluetooth task source=] given |global| to [=resolve=]
|promise| with [=this=] and abort these steps.
- 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
- global task=] on the [=Bluetooth task source=] given |global| to
- [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
- abort these steps.
-
- Issue(188): Implementations may be able to avoid this {{NetworkError}}, but
- for now sites need to serialize their use of this API and/or give the user a
- way to retry failed operations.
- 1. If the characteristic has a [=Client Characteristic Configuration=]
- descriptor, use any of the [=Characteristic Descriptors=] procedures to
- ensure that one of the Notification or Indication
- bits in |characteristic|'s [=Client Characteristic Configuration=]
- descriptor is set, matching the constraints in |characteristic|'s
- properties. The UA SHOULD avoid
- setting both bits, and MUST deduplicate
- value-change events if both bits are
- set. Handle errors as described in .
+ 1. If |global|'s [=Window/navigable=]'s
+ [=navigable/top-level traversable=]'s simulated Bluetooth adapter
+ is not empty, run the following steps:
+ 1. If [=this=].{{[[automatedCharacteristicSubscribeToNotificationsResponse]]}} is not `"not-expected"`,
+ [=queue a global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}} and abort
+ these steps.
+ 1. [=Trigger a simulated characteristic event=] given |global|'s
+ [=Window/navigable=], [=this=].{{BluetoothRemoteGATTServer/device}},
+ |characteristic|, and `subscribe-to-notifications`.
+ 1. Set [=this=].{{[[automatedCharacteristicSubscribeToNotificationsResponse]]}} to `"expected"`,
+ and wait for it to change.
+ 1. Let |response| be [=this=].{{[[automatedCharacteristicSubscribeToNotificationsResponse]]}}.
+ 1. Set [=this=].{{[[automatedCharacteristicSubscribeToNotificationsResponse]]}} to `"not-expected"`.
+ 1. If |response| is not `0`, do the following sub-steps:
+ 1. [=Queue a global task=] on the [=Bluetooth task source=] given
+ |global| to [=reject=] |promise| with a "{{NetworkError}}"
+ {{DOMException}} and abort these steps.
+ 1. Otherwise, let |success| to be `true`.
+ 1. Otherwise, run the following steps:
+ 1. If the UA is currently using the Bluetooth system, it MAY [=queue a
+ global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{NetworkError}}" {{DOMException}} and
+ abort these steps.
+
+ Issue(188): Implementations may be able to avoid this {{NetworkError}}, but
+ for now sites need to serialize their use of this API and/or give the user a
+ way to retry failed operations.
+ 1. If the characteristic has a [=Client Characteristic Configuration=]
+ descriptor, use any of the [=Characteristic Descriptors=] procedures to
+ ensure that one of the Notification or Indication
+ bits in |characteristic|'s [=Client Characteristic Configuration=]
+ descriptor is set, matching the constraints in |characteristic|'s
+ properties. The UA SHOULD avoid
+ setting both bits, and MUST deduplicate
+ value-change events if both bits are
+ set. Handle errors as described in .
-
- Note: Some devices have characteristics whose properties include the
- Notify or Indicate bit but that don't have a Client Characteristic
- Configuration descriptor. These non-standard-compliant characteristics
- tend to send notifications or indications unconditionally, so this
- specification allows applications to simply subscribe to their messages.
-
- 1. If the procedures were successful,
- {{Navigator/bluetooth|navigator.bluetooth}} to
- |characteristic|'s [=active notification context set=].
+
+ Note: Some devices have characteristics whose properties include the
+ Notify or Indicate bit but that don't have a Client Characteristic
+ Configuration descriptor. These non-standard-compliant characteristics
+ tend to send notifications or indications unconditionally, so this
+ specification allows applications to simply subscribe to their messages.
+
+ 1. If the procedures were successful, let |success| to be `true`.
+ 1. If |success| is `true`, add {{Navigator/bluetooth|navigator.bluetooth}} to|characteristic|'s [=active notification context set=].
1. [=Queue a global task=] on the [=Bluetooth task source=] given |global|
to perform the following steps:
1. If |promise| is not in |gatt|.{{[[activeAlgorithms]]}}, [=reject=]
@@ -3834,12 +3933,31 @@ promise promise and run the following steps in parallel:
{{InvalidStateError}} and abort these steps.
1. If characteristic's active notification context set
contains {{Navigator/bluetooth|navigator.bluetooth}}, remove it.
-1. If characteristic's active notification context set became
- empty and the characteristic has a Client Characteristic
- Configuration descriptor, the UA SHOULD use any of the Characteristic
- Descriptors procedures to clear the Notification and
- Indication bits in characteristic's Client
- Characteristic Configuration descriptor.
+ 1. If |global|'s [=Window/navigable=]'s
+ [=navigable/top-level traversable=]'s simulated Bluetooth adapter
+ is not empty, run the following steps:
+ 1. If [=this=].{{[[automatedCharacteristicUnsubscribeFromNotificationsResponse]]}} is not `"not-expected"`,
+ [=queue a global task=] on the [=Bluetooth task source=] given |global| to
+ [=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}} and abort
+ these steps.
+ 1. [=Trigger a simulated characteristic event=] given |global|'s
+ [=Window/navigable=], [=this=].{{BluetoothRemoteGATTServer/device}},
+ |characteristic|, and `unsubscribe-from-notifications`.
+ 1. Set [=this=].{{[[automatedCharacteristicUnsubscribeFromNotificationsResponse]]}} to `"expected"`,
+ and wait for it to change.
+ 1. Let |response| be [=this=].{{[[automatedCharacteristicUnsubscribeFromNotificationsResponse]]}}.
+ 1. Set [=this=].{{[[automatedCharacteristicUnsubscribeFromNotificationsResponse]]}} to `"not-expected"`.
+ 1. If |response| is not `0`, do the following sub-steps:
+ 1. [=Queue a global task=] on the [=Bluetooth task source=] given
+ |global| to [=reject=] |promise| with a "{{NetworkError}}"
+ {{DOMException}} and abort these steps..
+ 1. Otherwise, run the following steps:
+ 1. If characteristic's active notification context set became
+ empty and the characteristic has a Client Characteristic
+ Configuration descriptor, the UA SHOULD use any of the Characteristic
+ Descriptors procedures to clear the Notification and
+ Indication bits in characteristic's Client
+ Characteristic Configuration descriptor.
1. [=Queue a global task=] on the [=Bluetooth task source=] given [=this=]'s
[=relevant global object=] to [=resolve=] |promise| with [=this=].
@@ -5821,8 +5939,49 @@ bluetooth.SimulateCharacteristicResponseParameters = {
+The [=remote end steps=] with command parameters |params| are:
-Issue: TODO: Finish the algorithm of bluetooth.simulateCharacteristicResponse.
+1. Let |contextId| be |params|[`"context"`].
+1. Let |navigable| be the result of [=trying=] to [=get a navigable=] with |contextId|.
+1. Let |deviceAddress| be |params|[`"address"`].
+1. Let |simulatedBluetoothAdapter| be |navigable|'s simulated Bluetooth adapter.
+1. If |simulatedBluetoothAdapter| is empty, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |deviceMapping| be |simulatedBluetoothAdapter|'s simulated Bluetooth device mapping.
+1. If |deviceMapping|[|deviceAddress|] [=map/exists=], let |simulatedDevice| be |deviceMapping|[|deviceAddress|].
+ Otherwise, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |serviceMapping| be |simulatedDevice|'s simulated GATT service mapping.
+1. Let |serviceUuid| be |params|[`"serviceUuid"`].
+1. If |serviceMapping|[|serviceUuid|] [=map/exists=], let |simulatedService| be |serviceMapping|[|serviceUuid|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid argument=].
+1. Let |characteristicMapping| be |simulatedService|'s simulated GATT characteristic mapping.
+1. Let |characteristicUuid| be |params|[`"characteristicUuid"`].
+1. If |characteristicMapping|[|characteristicUuid|] [=map/exists=], let |simulatedGattCharacteristic|
+ be |characteristicMapping|[|characteristicUuid|].
+1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+1. Let |simulatedDeviceInstance| be the result of get the BluetoothDevice representing
+ |simulatedDevice| inside |navigable|'s active window's associated Navigator's
+ [=associated Bluetooth=].
+1. Let |promise| be |simulatedDeviceInstance|.{{[[context]]}}.{{Bluetooth/[[attributeInstanceMap]]}}[|simulatedGattCharacteristic|].
+1. Upon fulfillment of |promise| with |characteristic|, run the following steps:
+ 1. If |params|[`"type"`] is `read`, run the following steps:
+ 1. If |characteristic|.{{[[automatedCharacteristicReadResponse]]}} is `expected`,
+ set |characteristic|.{{[[automatedCharacteristicReadResponse]]}} to |params|[`"code"`] and
+ |characteristic|.{{[[automatedCharacteristicReadResponseData]]}} to [=a copy of the bytes held=]
+ by |params|[`"data"`].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+ 1. If |params|[`"type"`] is `write`, run the following steps:
+ 1. If |characteristic|.{{[[automatedCharacteristicWriteResponse]]}} is `expected`,
+ set |characteristic|.{{[[automatedCharacteristicWriteResponse]]}} to |params|[`"code"`].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+ 1. If |params|[`"type"`] is `subscribe-to-notifications`, run the following steps:
+ 1. If |characteristic|.{{[[automatedCharacteristicSubscribeToNotificationsResponse]]}} is `expected`,
+ set |characteristic|.{{[[automatedCharacteristicSubscribeToNotificationsResponse]]}} to |params|[`"code"`].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+ 1. If |params|[`"type"`] is `unsubscribe-from-notifications`, run the following steps:
+ 1. If |characteristic|.{{[[automatedCharacteristicUnsubscribeFromNotificationsResponse]]}} is `expected`,
+ set |characteristic|.{{[[automatedCharacteristicUnsubscribeFromNotificationsResponse]]}} to |params|[`"code"`].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=].
+ 1. Otherwise, return [=error=] with [=error code=] [=invalid argument=].
@@ -6041,7 +6200,25 @@ bluetooth.CharacteristicEventGeneratedParameters = {
-Issue: TODO: Finish the algorithm of bluetooth.characteristicEventGenerated.
+To trigger a simulated characteristic event given a [=navigable=] |navigable|, a {{BluetoothDevice}} |device|, a
+simulated GATT characteristic |characteristic|, string |type|, and an optional byte sequence |bytes|:
+
+1. Let |navigableId| be |navigable|'s [=navigable id=].
+1. Let |params| be a [=map=] matching the bluetooth.CharacteristicEventGeneratedParameters production and run
+ the following steps:
+ 1. Set |params|[`"context"`] to |navigableId|.
+ 1. Set |params|[`"address"`] to |device|.{{[[representedDevice]]}}'s address.
+ 1. Let |service| be the simulated GATT service containing |characteristic|.
+ 1. Set |params|[`"serviceUuid"`] to |service|'s UUID.
+ 1. Set |params|[`"characteristicUuid"`] to |characteristic|'s UUID.
+ 1. Set |params|[`"type"`] to |type|.
+ 1. If |type| is `write`, set |params|[`"data"`] to a [=new=] {{Uint8Array}} wrapping a [=new=] {{ArrayBuffer}} containing |bytes|.
+1. Let |body| be a [=map=] matching the bluetooth.CharacteristicEventGenerated production, with the
+ params field set to |params|.
+1. Let |relatedNavigables| be a [=/set=] containing |navigable|.
+1. For each |session| in the [=set of sessions for which an event is enabled=] given
+ "bluetooth.characteristicEventGenerated" and |relatedNavigables|:
+ 1. [=Emit an event=] with |session| and |body|.