Bluetooth discovery

by stopsatgreen

HTML

<form>
  <input id="optionalServices" list="services" placeholder="BL services, e.g. generic_access, 0x1234" type="text">
  <button>Discover services</button>
</form>

JavaScript

function onBtnClick() {
	let services = document.getElementById('optionalServices').value.split(/, ?/).map(s => s.startsWith('0x') ? parseInt(s) : s).filter(s => s && BluetoothUUID.getService);
  console.log('Requesting Bluetooth devices...');
  navigator.bluetooth.requestDevice({
  	filters: anyDevice(),
    optionalServices: services
  }).then(device => {
  	console.log('NAME: ', device.name);
    console.log('SERVICES: ', device.uuids.join('\n' + ' '.repeat(20)));
    console.log('Connecting to GATT Server...');
    return device.gatt.connect();
  }).then(server => {
  	console.log('Getting services...');
    return server.getPrimaryServices();
  }).then(services => {
  	console.log('Getting characteristics...');
    let queue = Promise.resolve();
    services.forEach(service => {
    	queue = queue.then(_ => service.getCharacteristics().then(characteristics => {
      	console.log('SERVICE: ', service.uuid);
        characteristics.forEach(characteristic => {
        	console.log('CHARACTERISTIC: ', characteristic.uuid + ' ' + getSupportedProperties(characteristic));
        });
      }));
    });
    return queue;
  }).catch(error => {
  	console.log('ERROR: ', error);
  });
}

function getSupportedProperties(characteristic) {
	let supportedProperties = [];
  for (const p in characteristic.properties) {
  	if (characteristic.properties[p] === true) {
    	supportedProperties.push(p.toUpperCase());
    }
  }
  return '[' + supportedProperties.join(', ') + ']';
}

function anyDevice() {
	return Array.from('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').map(c => ({namePrefix: c})).concat({name: ''});
}

var btn = document.querySelector('button');
btn.addEventListener('click', onBtnClick);