diff --git a/index.bs b/index.bs index 7033eda..3039dee 100644 --- a/index.bs +++ b/index.bs @@ -1509,7 +1509,7 @@ spec: permissions interface BluetoothDevice { readonly attribute DOMString id; readonly attribute DOMString? name; - readonly attribute BluetoothRemoteGATTServer gatt; + readonly attribute BluetoothRemoteGATTServer? gatt; readonly attribute FrozenArray<UUID> uuids; Promise<void> watchAdvertisements(); @@ -1664,10 +1664,10 @@ spec: permissions Initialize result.watchingAdvertisements to `false`.
  • - Set result.gatt.{{BluetoothRemoteGATTServer/device}} to result. -
  • -
  • - Set result.gatt.{{BluetoothRemoteGATTServer/connected}} to `false`. + Initialize |result|.gatt to + a new {{BluetoothRemoteGATTServer}} instance with + its {{BluetoothRemoteGATTServer/device}} attribute initialized to |result| + and its {{BluetoothRemoteGATTServer/connected}} attribute initialized to `false`.
  • Add device's diff --git a/index.html b/index.html index 0f14c2f..bcf6699 100644 --- a/index.html +++ b/index.html @@ -2451,7 +2451,7 @@

    interface BluetoothDevice { readonly attribute DOMString id; readonly attribute DOMString? name; - readonly attribute BluetoothRemoteGATTServer gatt; + readonly attribute BluetoothRemoteGATTServer? gatt; readonly attribute FrozenArray<UUID> uuids; Promise<void> watchAdvertisements(); @@ -2539,8 +2539,9 @@

    If device has a partial or complete Bluetooth Device Name, set result.name to that string.
  • Initialize result.watchingAdvertisements to false. -
  • Set result.gatt.device to result. -
  • Set result.gatt.connected to false. +
  • Initialize result.gatt to + a new BluetoothRemoteGATTServer instance with + its device attribute initialized to result and its connected attribute initialized to false.
  • Add device’s advertised Service UUIDs to result@[[unfilteredUuids]].
  • If the Bluetooth cache contains @@ -2834,7 +2835,7 @@

    5.1. GATT Information Model

    -

    The GATT Profile Hierarchy describes how a GATT Server contains a hierarchy of Profiles, Primary Services, Included Services, Characteristics, and Descriptors.

    +

    The GATT Profile Hierarchy describes how a GATT Server contains a hierarchy of Profiles, Primary Services, Included Services, Characteristics, and Descriptors.

    Profiles are purely logical: the specification of a Profile describes the expected interactions between the other GATT entities the Profile contains, @@ -2855,7 +2856,7 @@

    Characteristics. The Included Services are references to other Services, and a single Service can be included by more than one other Service. - Services are known as Primary Services if they appear directly under the GATT Server, + Services are known as Primary Services if they appear directly under the GATT Server, and Secondary Services if they’re only included by other Services, but Primary Services can also be included.

    A Characteristic contains a value, which is an array of bytes, @@ -2992,11 +2993,11 @@

    5.2. BluetoothRemoteGATTServer

    -

    BluetoothRemoteGATTServer represents a GATT Server on a remote device.

    -
    interface BluetoothRemoteGATTServer {
    +     

    BluetoothRemoteGATTServer represents a GATT Server on a remote device.

    +
    interface BluetoothRemoteGATTServer {
       readonly attribute BluetoothDevice device;
       readonly attribute boolean connected;
    -  Promise<BluetoothRemoteGATTServer> connect();
    +  Promise<BluetoothRemoteGATTServer> connect();
       void disconnect();
       Promise<BluetoothRemoteGATTService> getPrimaryService(BluetoothServiceUUID service);
       Promise<sequence<BluetoothRemoteGATTService>>
    @@ -3004,21 +3005,21 @@ 

    -
    NOTE: BluetoothRemoteGATTServer attributes
    +
    NOTE: BluetoothRemoteGATTServer attributes

    device is the device running this server.

    connected is true while this instance is connected to this.device. It can be false while the UA is physically connected, - for example when there are other connected BluetoothRemoteGATTServer instances + for example when there are other connected BluetoothRemoteGATTServer instances for other global objects.

    When no ECMAScript code can - observe an instance of BluetoothRemoteGATTServer server anymore, + observe an instance of BluetoothRemoteGATTServer server anymore, the UA SHOULD run server.disconnect(). Because BluetoothDevice instances are stored in navigator.bluetooth.[[deviceInstanceMap]], this can’t happen at least until navigation releases the global object or closing the tab or window destroys the browsing context. Disconnecting on garbage collection ensures that the UA doesn’t keep consuming resources on the remote device unnecessarily.

    -

    Instances of BluetoothRemoteGATTServer are created with the internal slots +

    Instances of BluetoothRemoteGATTServer are created with the internal slots described in the following table:

    @@ -3058,7 +3059,7 @@

    Set this.connected to false.
  • Fire an event named gattserverdisconnected with its bubbles attribute initialized to true at this.device. -

    This event is not fired at the BluetoothRemoteGATTServer.

    +

    This event is not fired at the BluetoothRemoteGATTServer.

  • Let device be this.device@[[representedDevice]].
  • In parallel: if, for all BluetoothDevices deviceObj in the whole UA @@ -3066,9 +3067,9 @@

    device’s ATT Bearer.

    Algorithms need to fail if - their BluetoothRemoteGATTServer was disconnected while they were running, + their BluetoothRemoteGATTServer was disconnected while they were running, even if the UA stays connected the whole time - and the BluetoothRemoteGATTServer is subsequently re-connected before they finish. + and the BluetoothRemoteGATTServer is subsequently re-connected before they finish. We wrap the returned Promise to accomplish this.

    To create a gattServer-connection-checking wrapper around a Promise promise, the UA MUST:

      @@ -3570,7 +3571,7 @@

      Clear deviceObj.gatt@[[activeAlgorithms]].
    1. Fire an event named gattserverdisconnected with its bubbles attribute initialized to true at deviceObj. -

      This event is not fired at the BluetoothRemoteGATTServer.

      +

      This event is not fired at the BluetoothRemoteGATTServer.

    @@ -4919,7 +4920,7 @@

    I interface BluetoothDevice { readonly attribute DOMString id; readonly attribute DOMString? name; - readonly attribute BluetoothRemoteGATTServer gatt; + readonly attribute BluetoothRemoteGATTServer? gatt; readonly attribute FrozenArray<UUID> uuids; Promise<void> watchAdvertisements(); @@ -5567,10 +5568,10 @@

    #bluetoothremotegattserverReferenced in:

  • + + + + + + + +
    FieldInitial value
    {{BluetoothLEScan/filters}}|filters|
    {{BluetoothLEScan/keepRepeatedDevices}}|options|.keepRepeatedDevices
    {{BluetoothLEScan/active}}`true`
    +

  • +
  • + Request permission to use {name: {{"bluetooth-le-scan"}}}. + + Note: This may require that this algorithm was triggered by user activation. +
  • +
  • + If the result is {{"denied"}}, + reject |promise| with a {{NotAllowedError}} and abort these steps. +
  • +
  • + Add |scan| to navigator.bluetooth.{{[[activeScans]]}}. +
  • +
  • + Ensure the UA is scanning for BLE advertisements + in a mode that will receive at least + all advertisements matching any scan + in any {{[[activeScans]]}} set in the whole UA. +
  • +
  • + If the UA fails to start scanning, + remove |scan| from navigator.bluetooth.{{[[activeScans]]}}, + reject |promise| with one of the following errors, + and abort these steps: + +
    +
    The UA doesn't support scanning for advertisements
    +
    {{NotSupportedError}}
    + +
    Bluetooth is turned off
    +
    {{InvalidStateError}}
    + +
    Other reasons
    +
    {{UnknownError}}
    +
    +
  • +
  • + Resolve |promise| with |scan|. +
  • + + + +
    +

    Controlling a BLE scan

    + +
    +      [Constructor(BluetoothLEScanFilterInit init)]
    +      interface BluetoothLEScanFilter {
    +        readonly attribute UUID? serviceUUID;
    +        readonly attribute unsigned short? manufacturerData;
    +        readonly attribute UUID? serviceData;
    +      };
    +
    +      interface BluetoothLEScan {
    +        readonly attribute FrozenArray<BluetoothLEScanFilter> filters;
    +        readonly attribute boolean keepRepeatedDevices;
    +
    +        readonly attribute boolean active;
    +
    +        void stop();
    +      };
    +    
    + +
    +

    + {{BluetoothLEScan/stop()|BluetoothLEScan.stop()}} + stops a previously-requested scan. + Sites should do this as soon as possible to avoid wasting power. +

    +
    + +
    +

    + The BluetoothLEScanFilter(|init|) + constructor, when invoked MUST perform the following steps: +

    +
      +
    1. + Initialize all fields to `null`. +
    2. +
    3. + For each present member in |init|, + set `this`'s attribute with a matching identifier to the value of the member. + If the member's type is {{BluetoothServiceUUID}}, + pass its value through {{BluetoothUUID/getService()|BluetoothUUID.getService()}} + to get the value with which to initialize the attribute. + If any of these calls throw an exception, + propagate that exception from this constructor. +
    4. +
    +
    + +
    +

    + The stop() method, when invoked, + MUST perform the following steps: +

    +
      +
    1. Set this.{{BluetoothLEScan/active}} to `false`.
    2. +
    3. Remove `this` from navigator.bluetooth.{{[[activeScans]]}}.
    4. +
    5. + The UA SHOULD reconfigure or stop its BLE scan to save power + while still receiving any advertisements that + match any scan + in any {{[[activeScans]]}} set in the whole UA. +
    6. +
    +
    +
    + +
    +

    Permission to scan

    + +

    + The "bluetooth-le-scan" + powerful feature's + permission-related algorithms and types + are defined as follows: +

    +
    +
    permission descriptor type
    +
    +
    +          dictionary BluetoothLEScanPermissionDescriptor : PermissionDescriptor {
    +            // These match BluetoothLEScanOptions.
    +            sequence<BluetoothLEScanFilterInit> filters;
    +            boolean keepRepeatedDevices;
    +          };
    +        
    +
    + +
    permission result type
    +
    +
    +          interface BluetoothLEScanPermissionResult : PermissionStatus {
    +            attribute FrozenArray<BluetoothLEScan> scans;
    +          };
    +        
    +
    + +
    permission query algorithm
    +
    +

    + Given a {{BluetoothLEScanPermissionDescriptor}} |descriptor| + and a {{BluetoothLEScanPermissionResult}} |result|: +

    +
      +
    1. + Update |result|.{{PermissionStatus/state}} + to |descriptor|'s permission state. +
    2. +
    3. + If |result|.{{PermissionStatus/state}} is {{"denied"}}, + set |result|.scans to an empty {{FrozenArray}} + and abort these steps. +
    4. +
    5. + Update |result|.{{scans}} to + a new {{FrozenArray}} containing + the elements of navigator.bluetooth.{{[[activeScans]]}}. + +

      + Consider filtering the result to active scans that + match the fields of the descriptor. +

      +
    6. +
    +
    + +
    permission request algorithm
    +
    +

    + Given a {{BluetoothLEScanPermissionDescriptor}} |descriptor| + and a {{BluetoothLEScanPermissionResult}} |result|: +

    +
      +
    1. + Let |promise| be the result of + navigator.bluetooth.{{requestLEScan()|requestLEScan}}(|descriptor|). +
    2. +
    3. Wait for |promise| to settle.
    4. +
    5. + If |promise| rejected, throw the reason it rejected with, + and abort these steps. +
    6. +
    7. + Update |result|.status to + |descriptor|'s permission state. +
    8. +
    9. + Update |result|.scans to + a new {{FrozenArray}} whose single element is the value in |promise|. +
    10. +
    +
    + +
    + permission revocation algorithm +
    +
    +
      +
    1. + For each |activeScan| in navigator.bluetooth.{{[[activeScans]]}}, + call |activeScan|.{{stop()}}. +
    2. +
    +
    +
    +
    + + +
    +

    Event handling

    + +
    +

    Responding to advertising events

    + +
    +

    + When the UA receives an advertising event |event| + (consisting of an advertising packet and an optional scan response), + it MUST run the following steps: +

    +
      +
    1. + Let device be the Bluetooth device that sent the advertising event. +
    2. +
    3. + For each {{Bluetooth}} instance |bluetooth| in the UA, + queue a task on + |bluetooth|'s relevant settings object's responsible event loop + to do the following sub-steps: +
        +
      1. + Let |scans| be the set of + {{BluetoothLEScan}}s in |bluetooth|.{{[[activeScans]]}} + that match |event|. +
      2. +
      3. If |scans| is empty, abort these sub-steps.
      4. +
      5. + Get the `BluetoothDevice` representing |device| inside |bluetooth|, + with the following modification to the algorithm, + and let |deviceObj| be the result. + +

        + If there is no entry in + storage.{{BluetoothPermissionStorage/allowedDevices}} + for |device|, + then initialize |result|.{{BluetoothDevice/id}} to + a per-origin ID + that's stable until the user revokes + their permission for this origin to scan, + and initialize |result|.{{BluetoothDevice/gatt}} to `null`. +

        + +

        + Make this more rigorous once [[Permissions]] is in shape. +

        +
      6. +
      7. + Add each {{BluetoothLEScan}} in |scans| + to |deviceObj|.{{[[returnedFromScans]]}}. +
      8. +
      9. + Fire an `advertisementreceived` event + for |event| at |deviceObj|. +
      10. +
      +
    4. +
    +
    + +
    +

    + An advertising event |event| + matches a {{BluetoothLEScan}} |scan| + if the following steps return `match`: +

    +
      +
    1. + If |event| doesn't match + any filter in |scan|.{{BluetoothLEScan/filters}}, + return `no match`. +
    2. +
    3. + If |scan|.{{BluetoothLEScan/keepRepeatedDevices}} is `false`, + there is a {{BluetoothDevice}} |device| that + represents the same Bluetooth device as the one that sent |event|, + and |device|.{{[[returnedFromScans]]}} includes |scan|, + the UA MAY return `no match`. +
    4. +
    5. Return `match`.
    6. +
    +
    + +
    +

    + An advertising event |event| + matches + a {{BluetoothLEScanFilter}} |filter| + if all of the following conditions hold: +

    +
      +
    • + If |filter|.serviceUUID is non-`null`, + it is equal to a Service UUID in |event|. +
    • +
    • + If |filter|.manufacturerData is non-`null`, + it is equal to the Company Identifier Code + in some Manufacturer Specific Data in |event|. +
    • +
    • + If |filter|.serviceData is non-`null`, + it is the 128-bit UUID representation of the UUID + in some Service Data in |event|. +
    • +
    +
    +
    +
    + +
    +

    Changes to existing interfaces

    + +

    + Instances of {{Bluetooth}} additionally have the following internal slots: +

    + + + + + + + + + + + +
    Internal SlotInitial ValueDescription (non-normative)
    \[[activeScans]] + An empty set of {{BluetoothLEScan}} instances. + + The contents of this set will have {{BluetoothLEScan/active}} equal to `true`. +
    + +

    + Instances of {{BluetoothDevice}} additionally have the following internal slots: +

    + + + + + + + + + + + +
    Internal SlotInitial ValueDescription (non-normative)
    \[[returnedFromScans]] + An empty set of {{BluetoothLEScan}} objects. + + Used to implement {{BluetoothLEScanOptions/keepRepeatedDevices}}. +
    +
    + +
    +

    Terminology and conventions

    + +

    + This specification uses a few conventions and several terms from other specifications. + This section lists those and links to their primary definitions. +

    + +

    + When an algorithm in this specification uses a name defined in this or another specification, + the name MUST resolve to its initial value, + ignoring any changes that have been made to the name in the current execution environment. + For example, when the {{Bluetooth/requestLEScan()}} algorithm says to call + |options|.filters.map(filter=>new + {{BluetoothLEScanFilter/BluetoothLEScanFilter()|BluetoothLEScanFilter}}(filter)), + this MUST apply the + {{Array.prototype.map}} algorithm defined in [[ECMAScript]] + with |options|.services as its this parameter and + the algorithm defined at {{BluetoothLEScanFilter/BluetoothLEScanFilter()}} + as its callbackfn parameter, + regardless of any modifications that have been made to window, + Array, Array.prototype, Array.prototype.map, + Function, Function.prototype, + BluetoothLEScanFilter, or other objects. +

    + +
    +
    [[!BLUETOOTH42]]
    +
    +
      +
    1. Architecture & Terminology Overview +
        +
      1. General Description +
          +
        1. Overview of Bluetooth Low Energy Operation + (defines advertising events) +
        2. +
        +
      2. +
      +
    2. +
    3. Core System Package [BR/EDR Controller volume] +
        +
      1. Host Controller Interface Functional Specification +
          +
        1. HCI Commands and Events +
            +
          1. Informational Parameters +
              +
            1. Read BD_ADDR Command
            2. +
            +
          2. +
          3. Status Parameters +
              +
            1. + Read RSSI Command +
            2. +
            +
          4. +
          +
        2. +
        +
      2. +
      +
    4. +
    5. Core System Package [Host volume] +
        +
      1. Service Discovery Protocol (SDP) Specification +
          +
        1. Overview +
            +
          1. Searching for Services +
              +
            1. UUID + (defines UUID aliases and + the algorithm to compute the 128-bit UUID represented + by a UUID alias) +
            2. +
            +
          2. +
          +
        2. +
        +
      2. +
      3. Generic Access Profile +
          +
        1. Profile Overview +
            +
          1. Profile Roles +
              +
            1. Roles when Operating over an LE Physical Transport +
                +
              1. Broadcaster Role
              2. +
              3. Observer Role
              4. +
              5. Peripheral Role
              6. +
              7. Central Role
              8. +
              +
            2. +
            +
          2. +
          +
        2. +
        3. User Interface Aspects +
            +
          1. Representation of Bluetooth Parameters +
              +
            1. Bluetooth Device Name (the user-friendly name) +
            2. +
            3. Class of Device
            4. +
            +
          2. +
          +
        4. +
        5. Idle Mode Procedures — BR/EDR Physical Transport +
            +
          1. Device Discovery Procedure
          2. +
          +
        6. +
        7. Operational Modes and Procedures — LE Physical Transport +
            +
          1. Broadcast Mode and Observation Procedure +
              +
            1. Observation Procedure
            2. +
            +
          2. +
          3. Discovery Modes and Procedures +
              +
            1. General Discovery Procedure
            2. +
            3. Name Discovery Procedure
            4. +
            +
          4. +
          5. Connection Modes and Procedures
          6. +
          +
        8. +
        9. Security Aspects — LE Physical Transport +
            +
          1. Privacy Feature
          2. +
          3. Random Device Address +
              +
            1. Static Address
            2. +
            3. Private address +
                +
              1. + Resolvable Private Address Resolution Procedure +
              2. +
              +
            4. +
            +
          4. +
          +
        10. +
        11. Advertising Data and Scan Response Data Format
        12. +
        13. Bluetooth Device Requirements +
            +
          1. Bluetooth Device Address (defines BD_ADDR) +
              +
            1. Bluetooth Device Address Types +
                +
              1. Public Bluetooth Address
              2. +
              +
            2. +
            +
          2. +
          +
        14. +
        +
      4. +
      5. Attribute Protocol (ATT) +
          +
        1. Protocol Requirements +
            +
          1. Basic Concepts +
              +
            1. Attribute Type
            2. +
            3. Attribute Handle
            4. +
            5. Long Attribute Values
            6. +
            +
          2. +
          3. Attribute Protocol Pdus +
              +
            1. Error Handling +
                +
              1. Error Response
              2. +
              +
            2. +
            +
          4. +
          +
        2. +
        +
      6. +
      7. Generic Attribute Profile (GATT) +
          +
        1. Profile Overview +
            +
          1. Configurations and Roles + (defines GATT Client and GATT Server) +
          2. +
          3. + Profile Fundamentals, + defines the ATT Bearer +
          4. +
          5. Attribute Protocol +
              +
            1. Attribute Caching
            2. +
            +
          6. +
          7. GATT Profile Hierarchy +
              +
            1. Service
            2. +
            3. Included Services
            4. +
            5. Characteristic
            6. +
            +
          8. +
          +
        2. +
        3. Service Interoperability Requirements +
            +
          1. Characteristic Definition +
              +
            1. Characteristic Declaration +
                +
              1. Characteristic Properties
              2. +
              +
            2. +
            3. Characteristic Descriptor Declarations +
                +
              1. Characteristic Extended Properties
              2. +
              3. Client Characteristic Configuration
              4. +
              +
            4. +
            +
          2. +
          +
        4. +
        5. GATT Feature Requirements — defines the + GATT procedures. +
            +
          1. Primary Service Discovery +
              +
            1. Discover All Primary Services
            2. +
            3. Discover Primary Service by Service UUID
            4. +
            +
          2. +
          3. Relationship Discovery +
              +
            1. Find Included Services
            2. +
            +
          4. +
          5. Characteristic Discovery +
              +
            1. Discover All Characteristics of a Service
            2. +
            3. Discover Characteristics by UUID
            4. +
            +
          6. +
          7. Characteristic Descriptor Discovery +
              +
            1. Discover All Characteristic Descriptors
            2. +
            +
          8. +
          9. Characteristic Value Read
          10. +
          11. Characteristic Value Write
          12. +
          13. Characteristic Value Notification
          14. +
          15. Characteristic Value Indications
          16. +
          17. Characteristic Descriptors +
              +
            1. Read Characteristic Descriptors
            2. +
            3. Read Long Characteristic Descriptors
            4. +
            5. Write Characteristic Descriptors
            6. +
            7. Write Long Characteristic Descriptors
            8. +
            +
          18. +
          19. Procedure Timeouts
          20. +
          +
        6. +
        7. GAP Interoperability Requirements +
            +
          1. BR/EDR GAP Interoperability Requirements +
              +
            1. Connection Establishment
            2. +
            +
          2. +
          3. LE GAP Interoperability Requirements +
              +
            1. Connection Establishment
            2. +
            +
          4. +
          +
        8. +
        9. Defined Generic Attribute Profile Service +
            +
          1. Service Changed
          2. +
          +
        10. +
        +
      8. +
      9. Security Manager Specification +
          +
        1. Security Manager +
            +
          1. Security in Bluetooth Low Energy +
              +
            1. Definition of Keys and Values, + defines the + Identity Resolving Key + (IRK) +
            2. +
            +
          2. +
          +
        2. +
        +
      10. +
      +
    6. +
    7. Core System Package [Low Energy Controller volume] +
        +
      1. Link Layer Specification +
          +
        1. General Description +
            +
          1. Device Address +
              +
            1. Public Device Address
            2. +
            3. Random Device Address +
                +
              1. Static Device Address
              2. +
              +
            4. +
            +
          2. +
          +
        2. +
        3. Air Interface Protocol +
            +
          1. Non-Connected States +
              +
            1. Scanning State +
                +
              1. Passive Scanning
              2. +
              +
            2. +
            +
          2. +
          +
        4. +
        +
      2. +
      +
    8. +
    +
    +
    [[!BLUETOOTH-SUPPLEMENT6]]
    +
    +
      +
    1. Data Types Specification +
        +
      1. Data Types Definitions and Formats +
          +
        1. Service UUID
        2. +
        3. Local Name
        4. +
        5. Manufacturer Specific Data
        6. +
        7. TX Power Level
        8. +
        9. Service Data
        10. +
        11. Appearance
        12. +
        +
      2. +
      +
    2. +
    +
    +
    +
    diff --git a/scanning.html b/scanning.html new file mode 100644 index 0000000..3ff93e5 --- /dev/null +++ b/scanning.html @@ -0,0 +1,2848 @@ + + + + + Web Bluetooth Scanning + + + + + + + + + + +
    +

    +

    Web Bluetooth Scanning

    +

    Draft Community Group Report,

    +
    +
    +
    This version: +
    https://webbluetoothcg.github.io/web-bluetooth/scanning.html +
    Issue Tracking: +
    GitHub +
    Inline In Spec +
    Editor: +
    See contributors on GitHub +
    Participate: +
    Join the W3C Community Group +
    Fix the text through GitHub +
    public-web-bluetooth@w3.org (archives) +
    IRC: #web-bluetooth on W3C’s IRC +
    +
    +
    +
    + +
    +
    +

    Abstract

    +
    +

    This document describes an API to scan for nearby Bluetooth Low Energy devices in real time.

    +
    +

    Status of this document

    +
    +

    This specification was published by the Web Bluetooth Community Group. + It is not a W3C Standard nor is it on the W3C Standards Track. + + Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. + + Learn more about W3C Community and Business Groups.

    +

    Changes to this document may be tracked at https://github.com/WebBluetoothCG/web-bluetooth/commits/gh-pages.

    +

    If you wish to make comments regarding this document, please send them to public-web-bluetooth@w3.org (subscribe, archives).

    +

    +
    +
    + +
    +
    +

    1. Introduction

    +

    This section is non-normative.

    +

    Bluetooth Low Energy (BLE) allows devices to broadcast advertisements to nearby observers. + These advertisements can contain small amounts of data + of a variety of types defined in [BLUETOOTH-SUPPLEMENT6].

    +

    For example, a beacon might announce that it’s next to a particular museum exhibit + and is advertising with 1mW of power, + which would let nearby observers know their approximate distance to that exhibit.

    +

    This specification extends [web-bluetooth] to allow websites to + receive these advertisements from nearby BLE devices, + with the user’s permission.

    +
    +

    1.1. Examples

    +
    + +

    To discover what iBeacons are nearby and measure their distance, + a website could use code like the following:

    +
    function recordNearbyBeacon(major, minor, pathLossVs1m) { ... }
    +let myBeaconUuid = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
    +
    +navigator.bluetooth.requestLEScan({
    +  filters: [{manufacturerData: 0x004C}],
    +  options: {
    +    keepRepeatedDevices: true,
    +  }
    +}).then(() => {
    +  navigator.bluetooth.addEventListener('advertisementreceived', event => {
    +    let appleData = event.manufacturerData.get(0x004C);
    +    if (appleData.byteLength != 23 ||
    +        appleData.getUint16(0, false) !== 0x0215) {
    +      // Isn’t an iBeacon.
    +      return;
    +    }
    +    let uuidArray = new Uint8Array(appleData.buffer, 2, 16);
    +    for (let i = 0; i < 16; i++) {
    +      if (uuidArray[i] != myBeaconUuid[i]) {
    +        // Not my class of beacon.
    +        return;
    +      }
    +    }
    +    let major = appleData.getUint16(18, false);
    +    let minor = appleData.getUint16(20, false);
    +    let txPowerAt1m = -appleData.getInt8(22);
    +    let pathLossVs1m = txPowerAt1m - event.rssi;
    +
    +    recordNearbyBeacon(major, minor, pathLossVs1m);
    +  });
    +})
    +
    +
    +
    +
    +
    +

    2. Privacy considerations

    +

    This section is non-normative.

    +

    The ambient advertisements in a user’s area are unlikely to directly include GPS coordinates, + but are likely to contain unique identifiers + that could be manually correlated with particular physical locations + or with particular other people. + Given that, the user needs to give permission + before a website gets access to nearby advertisements.

    +

    If a user has already given a site permission to know their location, + it might be ok to implicitly grant access to BLE advertisements. + However, BLE advertisements give away + strictly less location information than full [geolocation-api] access, + so UAs should allow users to grant that intermediate level of access.

    +

    BLE advertisements are usually fully public, + since they’re broadcast unencrypted on 2.4GHz radio waves. + However, it’s possible that a user would + have a device broadcast private information in a radio-shielded room. + This is probably an inappropriate use for BLE advertisements, + but might argue for requiring explicit permission to scan, + rather than inferring it from having permission to get a geolocation.

    +
    +
    +

    3. Security considerations

    +

    This section is non-normative.

    +

    Because this API doesn’t write anything, + there are few if any security implications. + A device in a shielded room might broadcast security-sensitive information, + but we don’t have any actual attack scenarios for that.

    +
    +
    +

    4. Scanning for BLE advertisements

    +
    dictionary BluetoothLEScanFilterInit {
    +  BluetoothServiceUUID serviceUUID;
    +  unsigned short manufacturerData;
    +  BluetoothServiceUUID serviceData;
    +};
    +
    +dictionary BluetoothLEScanOptions {
    +  required sequence<BluetoothLEScanFilterInit> filters;
    +  boolean keepRepeatedDevices = false;
    +};
    +
    +partial interface Bluetooth {
    +  [SecureContext]
    +  Promise<BluetoothLEScan> requestLEScan(BluetoothLEScanOptions options);
    +};
    +
    +
    +
    NOTE: requestLEScan() summary
    +

    navigator.bluetooth.requestLEScan(options) starts scanning for BLE advertisements, + asking the user for permission if they haven’t yet granted it.

    +

    Because this could show a prompt, + it can only be called from a user gesture + and requires a secure context.

    +

    Advertising events that match a BluetoothLEScanFilter in an active BluetoothLEScan cause advertisementreceived events to be dispatched + to the sending BluetoothDevice. + A filter matches if the advertisement includes data equal to each present member. + Usually, you’ll only include one member in each filter.

    +

    Normally scans will discard + the second and subsequent advertisements from a single device + to save power. + If you need to receive them, + set keepRepeatedDevices to true. + Note that setting keepRepeatedDevices to false doesn’t guarantee you won’t get redundant events; + it just allows the UA to save power by omitting them.

    +
    +
    +

    The requestLEScan(options) method, + when invoked, MUST return a new promise promise and run the following steps in parallel:

    +
      +
    1. Let filters be options.filters.map(filter=>new BluetoothLEScanFilter(filter)). + If this throws an exception, reject promise with that exception and abort these steps. +
    2. + Let scan be a new BluetoothLEScan instance + whose fields are initialized as in the following table: + + + + + + + +
      Field + Initial value +
      filters + filters +
      keepRepeatedDevices + options.keepRepeatedDevices +
      active + true +
      +
    3. + Request permission to use {name: "bluetooth-le-scan"}. +

      Note: This may require that this algorithm was triggered by user activation.

      +
    4. If the result is "denied", + reject promise with a NotAllowedError and abort these steps. +
    5. Add scan to navigator.bluetooth.[[activeScans]]. +
    6. Ensure the UA is scanning for BLE advertisements + in a mode that will receive at least + all advertisements matching any scan + in any [[activeScans]] set in the whole UA. +
    7. + If the UA fails to start scanning, + remove scan from navigator.bluetooth.[[activeScans]], reject promise with one of the following errors, + and abort these steps: +
      +
      The UA doesn’t support scanning for advertisements +
      NotSupportedError +
      Bluetooth is turned off +
      InvalidStateError +
      Other reasons +
      UnknownError +
      +
    8. Resolve promise with scan. +
    +
    +
    +

    4.1. Controlling a BLE scan

    +
    [Constructor(BluetoothLEScanFilterInit init)]
    +interface BluetoothLEScanFilter {
    +  readonly attribute UUID? serviceUUID;
    +  readonly attribute unsigned short? manufacturerData;
    +  readonly attribute UUID? serviceData;
    +};
    +
    +interface BluetoothLEScan {
    +  readonly attribute FrozenArray<BluetoothLEScanFilter> filters;
    +  readonly attribute boolean keepRepeatedDevices;
    +
    +  readonly attribute boolean active;
    +
    +  void stop();
    +};
    +
    +
    +
    NOTE: BluetoothLEScan members
    +

    BluetoothLEScan.stop() stops a previously-requested scan. + Sites should do this as soon as possible to avoid wasting power.

    +
    +
    +

    The BluetoothLEScanFilter(init) constructor, when invoked MUST perform the following steps:

    +
      +
    1. Initialize all fields to null. +
    2. For each present member in init, + set this's attribute with a matching identifier to the value of the member. + If the member’s type is BluetoothServiceUUID, + pass its value through BluetoothUUID.getService() to get the value with which to initialize the attribute. + If any of these calls throw an exception, + propagate that exception from this constructor. +
    +
    +
    +

    The stop() method, when invoked, + MUST perform the following steps:

    +
      +
    1. Set this.active to false. +
    2. Remove this from navigator.bluetooth.[[activeScans]]. +
    3. The UA SHOULD reconfigure or stop its BLE scan to save power + while still receiving any advertisements that match any scan + in any [[activeScans]] set in the whole UA. +
    +
    +
    +
    +

    4.2. Permission to scan

    +

    The "bluetooth-le-scan" powerful feature’s + permission-related algorithms and types + are defined as follows:

    +
    +
    permission descriptor type +
    +
    dictionary BluetoothLEScanPermissionDescriptor : PermissionDescriptor {
    +  // These match BluetoothLEScanOptions.
    +  sequence<BluetoothLEScanFilterInit> filters;
    +  boolean keepRepeatedDevices;
    +};
    +
    +
    permission result type +
    +
    interface BluetoothLEScanPermissionResult : PermissionStatus {
    +  attribute FrozenArray<BluetoothLEScan> scans;
    +};
    +
    +
    permission query algorithm +
    +

    Given a BluetoothLEScanPermissionDescriptor descriptor and a BluetoothLEScanPermissionResult result:

    +
      +
    1. Update result.state to descriptor’s permission state. +
    2. If result.state is "denied", + set result.scans to an empty FrozenArray and abort these steps. +
    3. + Update result.scans to + a new FrozenArray containing + the elements of navigator.bluetooth.[[activeScans]]. +

      Consider filtering the result to active scans that + match the fields of the descriptor.

      +
    +
    permission request algorithm +
    +

    Given a BluetoothLEScanPermissionDescriptor descriptor and a BluetoothLEScanPermissionResult result:

    +
      +
    1. Let promise be the result of navigator.bluetooth.requestLEScan(descriptor). +
    2. Wait for promise to settle. +
    3. If promise rejected, throw the reason it rejected with, + and abort these steps. +
    4. Update result.status to descriptor’s permission state. +
    5. Update result.scans to + a new FrozenArray whose single element is the value in promise. +
    +
    permission revocation algorithm +
    +
      +
    1. For each activeScan in navigator.bluetooth.[[activeScans]], + call activeScan.stop(). +
    +
    +
    +
    +
    +

    5. Event handling

    +
    +

    5.1. Responding to advertising events

    +
    +

    When the UA receives an advertising event event (consisting of an advertising packet and an optional scan response), + it MUST run the following steps:

    +
      +
    1. Let device be the Bluetooth device that sent the advertising event. +
    2. + For each Bluetooth instance bluetooth in the UA, queue a task on bluetooth’s relevant settings object’s responsible event loop to do the following sub-steps: +
        +
      1. Let scans be the set of BluetoothLEScans in bluetooth.[[activeScans]] that match event. +
      2. If scans is empty, abort these sub-steps. +
      3. + Get the BluetoothDevice representing device inside bluetooth, + with the following modification to the algorithm, + and let deviceObj be the result. +

        If there is no entry in storage.allowedDevices for device, + then initialize result.id to + a per-origin ID + that’s stable until the user revokes + their permission for this origin to scan, + and initialize result.gatt to null.

        +

        Make this more rigorous once [Permissions] is in shape.

        +
      4. Add each BluetoothLEScan in scans to deviceObj.[[returnedFromScans]]. +
      5. Fire an advertisementreceived event for event at deviceObj. +
      +
    +
    +
    +

    An advertising event event matches a BluetoothLEScan scan if the following steps return match:

    +
      +
    1. If event doesn’t match any filter in scan.filters, + return no match. +
    2. If scan.keepRepeatedDevices is false, + there is a BluetoothDevice device that + represents the same Bluetooth device as the one that sent event, + and device.[[returnedFromScans]] includes scan, + the UA MAY return no match. +
    3. Return match. +
    +
    +
    +

    An advertising event event matches a BluetoothLEScanFilter filter if all of the following conditions hold:

    +
      +
    • If filter.serviceUUID is non-null, + it is equal to a Service UUID in event. +
    • If filter.manufacturerData is non-null, + it is equal to the Company Identifier Code + in some Manufacturer Specific Data in event. +
    • If filter.serviceData is non-null, + it is the 128-bit UUID representation of the UUID + in some Service Data in event. +
    +
    +
    +
    +
    +

    6. Changes to existing interfaces

    +

    Instances of Bluetooth additionally have the following internal slots:

    + + + + + +
    Internal Slot + Initial Value + Description (non-normative) +
    [[activeScans]] + An empty set of BluetoothLEScan instances. + The contents of this set will have active equal to true. +
    +

    Instances of BluetoothDevice additionally have the following internal slots:

    + + + + + +
    Internal Slot + Initial Value + Description (non-normative) +
    [[returnedFromScans]] + An empty set of BluetoothLEScan objects. + Used to implement keepRepeatedDevices. +
    +
    +
    +

    7. Terminology and conventions

    +

    This specification uses a few conventions and several terms from other specifications. + This section lists those and links to their primary definitions.

    +

    When an algorithm in this specification uses a name defined in this or another specification, + the name MUST resolve to its initial value, + ignoring any changes that have been made to the name in the current execution environment. + For example, when the requestLEScan() algorithm says to call options.filters.map(filter=>new BluetoothLEScanFilter(filter)), + this MUST apply the Array.prototype.map algorithm defined in [ECMAScript] with options.services as its this parameter and + the algorithm defined at BluetoothLEScanFilter() as its callbackfn parameter, + regardless of any modifications that have been made to window, Array, Array.prototype, Array.prototype.map, Function, Function.prototype, BluetoothLEScanFilter, or other objects.

    +
    +
    [BLUETOOTH42] +
    +
      +
    1. + Architecture & Terminology Overview +
        +
      1. + General Description +
          +
        1. Overview of Bluetooth Low Energy Operation + (defines advertising events) +
        +
      +
    2. + Core System Package [BR/EDR Controller volume] +
        +
      1. + Host Controller Interface Functional Specification +
          +
        1. + HCI Commands and Events +
            +
          1. + Informational Parameters +
              +
            1. Read BD_ADDR Command +
            +
          2. + Status Parameters +
              +
            1. Read RSSI Command +
            +
          +
        +
      +
    3. + Core System Package [Host volume] +
        +
      1. + Service Discovery Protocol (SDP) Specification +
          +
        1. + Overview +
            +
          1. + Searching for Services +
              +
            1. UUID (defines UUID aliases and + the algorithm to compute the 128-bit UUID represented by a UUID alias) +
            +
          +
        +
      2. + Generic Access Profile +
          +
        1. + Profile Overview +
            +
          1. + Profile Roles +
              +
            1. + Roles when Operating over an LE Physical Transport +
                +
              1. Broadcaster Role +
              2. Observer Role +
              3. Peripheral Role +
              4. Central Role +
              +
            +
          +
        2. + User Interface Aspects +
            +
          1. + Representation of Bluetooth Parameters +
              +
            1. Bluetooth Device Name (the user-friendly name) +
            2. Class of Device +
            +
          +
        3. + Idle Mode Procedures — BR/EDR Physical Transport +
            +
          1. Device Discovery Procedure +
          +
        4. + Operational Modes and Procedures — LE Physical Transport +
            +
          1. + Broadcast Mode and Observation Procedure +
              +
            1. Observation Procedure +
            +
          2. + Discovery Modes and Procedures +
              +
            1. General Discovery Procedure +
            2. Name Discovery Procedure +
            +
          3. Connection Modes and Procedures +
          +
        5. + Security Aspects — LE Physical Transport +
            +
          1. Privacy Feature +
          2. + Random Device Address +
              +
            1. Static Address +
            2. + Private address +
                +
              1. Resolvable Private Address Resolution Procedure +
              +
            +
          +
        6. Advertising Data and Scan Response Data Format +
        7. + Bluetooth Device Requirements +
            +
          1. + Bluetooth Device Address (defines BD_ADDR) +
              +
            1. + Bluetooth Device Address Types +
                +
              1. Public Bluetooth Address +
              +
            +
          +
        +
      3. + Attribute Protocol (ATT) +
          +
        1. + Protocol Requirements +
            +
          1. + Basic Concepts +
              +
            1. Attribute Type +
            2. Attribute Handle +
            3. Long Attribute Values +
            +
          2. + Attribute Protocol Pdus +
              +
            1. + Error Handling +
                +
              1. Error Response +
              +
            +
          +
        +
      4. + Generic Attribute Profile (GATT) +
          +
        1. + Profile Overview +
            +
          1. Configurations and Roles + (defines GATT Client and GATT Server) +
          2. Profile Fundamentals, + defines the ATT Bearer +
          3. + Attribute Protocol +
              +
            1. Attribute Caching +
            +
          4. + GATT Profile Hierarchy +
              +
            1. Service +
            2. Included Services +
            3. Characteristic +
            +
          +
        2. + Service Interoperability Requirements +
            +
          1. + Characteristic Definition +
              +
            1. + Characteristic Declaration +
                +
              1. Characteristic Properties +
              +
            2. + Characteristic Descriptor Declarations +
                +
              1. Characteristic Extended Properties +
              2. Client Characteristic Configuration +
              +
            +
          +
        3. + GATT Feature Requirements — defines the GATT procedures. +
            +
          1. + Primary Service Discovery +
              +
            1. Discover All Primary Services +
            2. Discover Primary Service by Service UUID +
            +
          2. + Relationship Discovery +
              +
            1. Find Included Services +
            +
          3. + Characteristic Discovery +
              +
            1. Discover All Characteristics of a Service +
            2. Discover Characteristics by UUID +
            +
          4. + Characteristic Descriptor Discovery +
              +
            1. Discover All Characteristic Descriptors +
            +
          5. Characteristic Value Read +
          6. Characteristic Value Write +
          7. Characteristic Value Notification +
          8. Characteristic Value Indications +
          9. + Characteristic Descriptors +
              +
            1. Read Characteristic Descriptors +
            2. Read Long Characteristic Descriptors +
            3. Write Characteristic Descriptors +
            4. Write Long Characteristic Descriptors +
            +
          10. Procedure Timeouts +
          +
        4. + GAP Interoperability Requirements +
            +
          1. + BR/EDR GAP Interoperability Requirements +
              +
            1. Connection Establishment +
            +
          2. + LE GAP Interoperability Requirements +
              +
            1. Connection Establishment +
            +
          +
        5. + Defined Generic Attribute Profile Service +
            +
          1. Service Changed +
          +
        +
      5. + Security Manager Specification +
          +
        1. + Security Manager +
            +
          1. + Security in Bluetooth Low Energy +
              +
            1. Definition of Keys and Values, + defines the Identity Resolving Key (IRK) +
            +
          +
        +
      +
    4. + Core System Package [Low Energy Controller volume] +
        +
      1. + Link Layer Specification +
          +
        1. + General Description +
            +
          1. + Device Address +
              +
            1. Public Device Address +
            2. + Random Device Address +
                +
              1. Static Device Address +
              +
            +
          +
        2. + Air Interface Protocol +
            +
          1. + Non-Connected States +
              +
            1. + Scanning State +
                +
              1. Passive Scanning +
              +
            +
          +
        +
      +
    +
    [BLUETOOTH-SUPPLEMENT6] +
    +
      +
    1. + Data Types Specification +
        +
      1. + Data Types Definitions and Formats +
          +
        1. Service UUID +
        2. Local Name +
        3. Manufacturer Specific Data +
        4. TX Power Level +
        5. Service Data +
        6. Appearance +
        +
      +
    +
    +
    +
    +
    +

    Conformance

    +

    Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. + The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” + in the normative parts of this document + are to be interpreted as described in RFC 2119. + However, for readability, + these words do not appear in all uppercase letters in this specification.

    +

    All of the text of this specification is normative + except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

    +

    Examples in this specification are introduced with the words “for example” + or are set apart from the normative text with class="example", like this:

    +
    This is an example of an informative example.
    +

    Informative notes begin with the word “Note” + and are set apart from the normative text with class="note", like this:

    +

    Note, this is an informative note.

    +
    + +

    Index

    +

    Terms defined by this specification

    + +

    Terms defined by reference

    + +

    References

    +

    Normative References

    +
    +
    [BLUETOOTH-SUPPLEMENT6] +
    Supplement to the Bluetooth Core Specification Version 6. 14 July 2015. URL: https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=302735 +
    [BLUETOOTH42] +
    BLUETOOTH SPECIFICATION Version 4.2. 2 December 2014. URL: https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 +
    [ECMAScript] +
    ECMAScript Language Specification. URL: https://tc39.github.io/ecma262/ +
    [HTML] +
    Ian Hickson. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/ +
    [Permissions] +
    Mounir Lamouri; Marcos Caceres. The Permissions API. 7 April 2015. WD. URL: https://w3c.github.io/permissions/ +
    [PROMISES-GUIDE] +
    Domenic Denicola. Writing Promise-Using Specifications. 16 February 2016. Finding of the W3C TAG. URL: https://www.w3.org/2001/tag/doc/promises-guide +
    [RFC2119] +
    S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
    [WEB-BLUETOOTH] +
    Jeffrey Yasskin. Web Bluetooth. Draft Community Group Report. URL: https://webbluetoothcg.github.io/web-bluetooth/ +
    [WebIDL-1] +
    Cameron McCormack; Boris Zbarsky. WebIDL Level 1. 8 March 2016. CR. URL: https://heycam.github.io/webidl/ +
    +

    Informative References

    +
    +
    [GEOLOCATION-API] +
    Andrei Popescu. Geolocation API Specification. 28 May 2015. PER. URL: http://dev.w3.org/geo/api/spec-source.html +
    [SECURE-CONTEXTS] +
    Mike West. Secure Contexts. 18 July 2016. WD. URL: https://w3c.github.io/webappsec-secure-contexts/ +
    +

    IDL Index

    +
    dictionary BluetoothLEScanFilterInit {
    +  BluetoothServiceUUID serviceUUID;
    +  unsigned short manufacturerData;
    +  BluetoothServiceUUID serviceData;
    +};
    +
    +dictionary BluetoothLEScanOptions {
    +  required sequence<BluetoothLEScanFilterInit> filters;
    +  boolean keepRepeatedDevices = false;
    +};
    +
    +partial interface Bluetooth {
    +  [SecureContext]
    +  Promise<BluetoothLEScan> requestLEScan(BluetoothLEScanOptions options);
    +};
    +
    +[Constructor(BluetoothLEScanFilterInit init)]
    +interface BluetoothLEScanFilter {
    +  readonly attribute UUID? serviceUUID;
    +  readonly attribute unsigned short? manufacturerData;
    +  readonly attribute UUID? serviceData;
    +};
    +
    +interface BluetoothLEScan {
    +  readonly attribute FrozenArray<BluetoothLEScanFilter> filters;
    +  readonly attribute boolean keepRepeatedDevices;
    +
    +  readonly attribute boolean active;
    +
    +  void stop();
    +};
    +
    +dictionary BluetoothLEScanPermissionDescriptor : PermissionDescriptor {
    +  // These match BluetoothLEScanOptions.
    +  sequence<BluetoothLEScanFilterInit> filters;
    +  boolean keepRepeatedDevices;
    +};
    +
    +interface BluetoothLEScanPermissionResult : PermissionStatus {
    +  attribute FrozenArray<BluetoothLEScan> scans;
    +};
    +
    +
    +

    Issues Index

    +
    +
    Consider filtering the result to active scans that + match the fields of the descriptor.
    +
    Make this more rigorous once [Permissions] is in shape.
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file