Web Bluetooth / GAP Characteristics (Async Await) Sample

Available in Chrome 55+ | View on GitHub | Browse Samples

The Web Bluetooth API lets websites discover and communicate with devices over the Bluetooth 4 wireless standard using the Generic Attribute Profile (GATT). It is currently partially implemented in Android M, Chrome OS, Linux, and Mac.

This sample illustrates the use of the Web Bluetooth API to read all GAP characteristics from a nearby Bluetooth Device. You may want to try this demo with the BLE Peripheral Simulator App from the Google Play Store and check out the GAP Characteristics (Promises) sample.

Note: The Reconnection Address characteristic is blacklisted and forbidden from being accessed.

Live Output


JavaScript Snippet

async function onButtonClick() {
  try {
    log('Requesting any Bluetooth Device...');
    const device = await navigator.bluetooth.requestDevice({
     // filters: [...] <- Prefer filters to save energy & show relevant devices.
        acceptAllDevices: true,
        optionalServices: ['generic_access']});

    log('Connecting to GATT Server...');
    const server = await device.gatt.connect();

    log('Getting GAP Service...');
    const service = await server.getPrimaryService('generic_access');

    log('Getting GAP Characteristics...');
    const characteristics = await service.getCharacteristics();

    for (const characteristic of characteristics) {
      switch (characteristic.uuid) {

        case BluetoothUUID.getCharacteristic('gap.appearance'):
          await readAppearanceValue(characteristic);
          break;

        case BluetoothUUID.getCharacteristic('gap.device_name'):
          await readDeviceNameValue(characteristic);
          break;

        case BluetoothUUID.getCharacteristic('gap.peripheral_preferred_connection_parameters'):
          await readPPCPValue(characteristic);
          break;

        case BluetoothUUID.getCharacteristic('gap.central_address_resolution_support'):
          await readCentralAddressResolutionSupportValue(characteristic);
          break;

        case BluetoothUUID.getCharacteristic('gap.peripheral_privacy_flag'):
          await readPeripheralPrivacyFlagValue(characteristic);
          break;

        default: log('> Unknown Characteristic: ' + characteristic.uuid);
      }
    }
  } catch(error) {
    log('Argh! ' + error);
  }
}

async function readAppearanceValue(characteristic) {
  const value = await characteristic.readValue();
  log('> Appearance: ' +
      getDeviceType(value.getUint16(0, true /* Little Endian */)));
}

async function readDeviceNameValue(characteristic) {
  const value = await characteristic.readValue();
  log('> Device Name: ' + new TextDecoder().decode(value));
}

async function readPPCPValue(characteristic) {
  const value = await characteristic.readValue();
  log('> Peripheral Preferred Connection Parameters: ');
  log('  > Minimum Connection Interval: ' +
      (value.getUint8(0) | value.getUint8(1) << 8) * 1.25 + 'ms');
  log('  > Maximum Connection Interval: ' +
      (value.getUint8(2) | value.getUint8(3) << 8) * 1.25 + 'ms');
  log('  > Slave Latency: ' +
      (value.getUint8(4) | value.getUint8(5) << 8) + 'ms');
  log('  > Connection Supervision Timeout Multiplier: ' +
      (value.getUint8(6) | value.getUint8(7) << 8));
}

async function readCentralAddressResolutionSupportValue(characteristic) {
  const value = await characteristic.readValue();
  const supported = value.getUint8(0);
  if (supported === 0) {
    log('> Central Address Resolution: Not Supported');
  } else if (supported === 1) {
    log('> Central Address Resolution: Supported');
  } else {
    log('> Central Address Resolution: N/A');
  }
}

async function readPeripheralPrivacyFlagValue(characteristic) {
  const value = await characteristic.readValue();
  const flag = value.getUint8(0);
  if (flag === 1) {
    log('> Peripheral Privacy Flag: Enabled');
  } else {
    log('> Peripheral Privacy Flag: Disabled');
  }
}

/* Utils */

function getDeviceType(value) {
  // Check out page source to see what valueToDeviceType object is.
  return value +
      (value in valueToDeviceType ? ' (' + valueToDeviceType[value] + ')' : '');
}