Tales of
Web Bluetooth

@sandropaganotti

Device

Service

Characteristic

navigator.bluetooth.requestDevice({
  filters: [{
    services: [TOGGLE_LIGHT],
  }]
})
.then(device => 
  device.gatt.connect())
.then(server => 
  server.getPrimaryService(TOGGLE_LIGHT))
.then(service => 
  service.getCharacteristic(TOGGLE_LIGHT_CH))
.then(characteristic =>
  characteristic.readValue()
.then(value => 
  console.log((new DataView(value)).getUint8(0) 
    ? 'On' 
    : 'Off'
  )
);

Annoyances

  • not a standard (yet)
  • no discovery (yet)
  • only passive
  • connection only as a result of a direct user action
  • handling dropped connections
  • writing while another write is in process
  • connecting while another connection is in process
  • only some services / characteristics are standard 
// using JSGatt
var awox = new window.GATT.Device();
var toggle = awox.register(
  SET_LIGHT_SERVICE,
  SET_LIGHT_CHARACTERISTIC
); 

button.addEventListener(function(){
  // turn the light on
  toggle(new Uint8Array(1));
});

WebBluetooth + WebRTC =

Camera Color Picker

Camera

Dominant Color

Video

Canvas

Pixels

Bluetooth

// register color service
var awos = new window.GATT.Device();  
var color = awos.register(...);

// stream camera to a <video> element
window.navigator
  .mediaDevices
  .getUserMedia({audio: false, video: true})
  .then(function(stream) {
    video.srcObject = stream;
  });

// draw a <video> frame on a <canvas> 2d context
context.drawImage(video, 0, 0);
var pixels = context.getImageData(...).data;
// get the dominant color using lokesh/color-thief
var dominant = MMCQ.quantize(pixels, 2).palette()[0];
// send the color to the lamp
color(new Uint8Array(dominant));

WebBluetooth + WebSpeech =

Alexa

webSpeechRecognition

"on"-"off"

Bluetooth

// register toggle service
var awos = new window.GATT.Device();  
var toggle = awos.register(...);

// start recognition on button's click
var recognition = new window.webkitSpeechRecognition();
recognition.continuous = true;
button.addEventListener('click', function() {
  toggle(new Uint8Array([1])).then(function() {
    recognition.start();
  });  
});

// process the recognized text
recognition.addEventListener('result', function(e) {
  var text = e.results[e.resultIndex][0].transcript;
  if (/off/.test(text)) {
    toggle(new Uint8Array([0]));
  } //...
}); 

Print Battery Status Using

Notifications

characteristicvaluechanged

// get characteristic using the standard flow
characteristic.startNotifications().then(_ => {
  characteristic.addEventListener(
    'characteristicvaluechanged',
    handleNewValue // function
  );
});

// to stop
characteristic.stopNotifications().then(_ => {
  characteristic.removeEventListener(
    'characteristicvaluechanged',
    handleNewValue // function
  );
});
// this time service and characteristic are known
var phone = new window.GATT.Device();
var battery = phone.register(
  'battery_service', 'battery_level'
); 

// subscribe to the event
button.addEventListener('click', function() {
  battery.getCharacteristic().then(function(ch) {
    ch.startNotifications().then(function(){
      ch.addEventListener(
        'characteristicvaluechanged', printValue
      );
    });
  });
});

// update the progress bar
function printValue(event) {
  updateProgessBar(event.target.value.getUint8(0));
}

Bonus Round

Demo 2

Drone

kudos:

poshaughnessy/web-bluetooth-parrot-drone voodootikigod/node-rolling-spider

function directions() {
  move(new Uint8Array(MOVE_SEQUENCE(
    0,
    key.isPressed('W') ? 20 : (key.isPressed('S') ? -20 : 0),
    key.isPressed('D') ? 20 : (key.isPressed('A') ? -20 : 0),
    0
  ))).then(function() {
    if(!isLanding) {
      setTimeout(directions, 50);
    }
  });
}

takeoff.addEventListener('click', function() {
  performAuthenticationAndTakeOff()    
  .then(function() {
    setTimeout(directions, 50);
  });
});

land.addEventListener('click', function() {
  isLanding = true;
  handshake(new Uint8Array(LAND_SEQUENCE()));
});

Moar IoT

WebUSB

WebUSB supporting device

Chrome notification

pointing to a page in the device's manifest

navigator.usb.getDevices().then(devices => {
  devices.map(device => {
    console.log(device.productName);  
    console.log(device.manufacturerName);
  });
})

Thanks!

images from Flickr, credits to:

@pimthida, @qiaomeng, @lolwho, @!steevithak, @tylerlove, @peaches

Tales Of Web Bluetooth

By sandropaganotti

Tales Of Web Bluetooth

Slides for JSDay 2016

  • 2,657