Getting Physical
with Web Bluetooth
in the browser
Dan Jenkins
@dan_jenkins
@dan_jenkins
Dan Jenkins
@dan_jenkins
nimblea.pe
dan@nimblea.pe
@nimbleapeltd
Google Dev Expert
@dan_jenkins
Wouldn't it be
cool to interact
with real life
using JavaScript
In the Browser?
@dan_jenkins
Imagine
walking up to
something...
@dan_jenkins
And being
able to use it.
With the Web.
@dan_jenkins
Drones, BB8,
Fitbits, Adult toys...
Bluetooth Low
Energy
@dan_jenkins
Let's take a
step back
@dan_jenkins
What is this magic?
@dan_jenkins
Physical Web
@dan_jenkins
Web Bluetooth
@dan_jenkins
Getting
Physical
Physical
@dan_jenkins
Ever wished you could "click"
on things in real life and find
out more about them?
@dan_jenkins
Been
somewhere
that had
these?
@dan_jenkins
They're
everywhere!
@dan_jenkins
But there are
many other
places where
we want to
interact with
something
around us
@dan_jenkins
The Physical Web
@dan_jenkins
@dan_jenkins
@dan_jenkins
How do I use this magic?
@dan_jenkins
Seeing
Physical Web
Notifications
@dan_jenkins
Android or
iOS
@dan_jenkins
Android iOS
• Location & Bluetooth turned on

• Android "Nearby" enabled (default)
https://android.googleblog.com/2016/06/introducing-nearby-new-way-to-discover.html
• Bluetooth turned on

• Chrome Notifications enabled 

(Allow the Chrome widget in
Notification Center)
https://docs.pushmote.com/docs/how-to-enable-chromes-physical-web-extension-on-the-ios
@dan_jenkins
Android caveat
They've just rolled back to Chrome doing the Physical
Web notifications in latest Chrome for Android
https://goo.gl/MrAXUw
https://goo.gl/PMwBY2
@dan_jenkins
Android caveat
But that'll only be for 6 or so weeks...
@dan_jenkins
@dan_jenkins
Transmitting
Physical
Web URLs
@dan_jenkins
Beacons
@dan_jenkins
Apps
@dan_jenkins
Anything that can emit using
Bluetooth Low Energy
@dan_jenkins
What makes up the Physical Web?
@dan_jenkins
Eddystone
•
Open Message Format
•
Eddystone URLs have 18 bytes worth of data that
can be broadcast
•
https://developers.google.com/beacons/eddystone
@dan_jenkins
Chrome•
Chrome on iOS and Nearby on Android scans for BLE beacons with
Eddystone URLs
•
Chrome only supports HTTPS URLs
•
Chrome then sends those URLs up to Google's Proxy service
(does some extra magic)
•
The Proxy service then sends those URLs back to Chrome
•
Chrome/Nearby shows a notification
All of this doesn't work unless you have data & location turned on
@dan_jenkins
@dan_jenkins
And they're being used
today
@dan_jenkinshttp://www.proxama.com/news/proxama-partners-with-google-to-deliver-worlds-first-physical-web-experience-for-consumers/
@dan_jenkinshttp://www.proxama.com/news/proxama-partners-with-google-to-deliver-worlds-first-physical-web-experience-for-consumers/
@dan_jenkins
And there are beacons
here today
@dan_jenkins
And you don't have to
use Chrome to get
them
https://www.phy.net/physical-web-browsers/
@dan_jenkins
That's great for
linking the
Physical World
to your Phone
@dan_jenkins
BUT,
There's more...
@dan_jenkins
Web
Bluetooth
@dan_jenkins
Your browser can
connect to
Bluetooth Low Energy
(BLE) devices directly
@dan_jenkins
Using JavaScript, we
can now connect to
physical devices using
BLE and control them
@dan_jenkins
@dan_jenkins
BLE (not just toys)
45
@dan_jenkins
BLE (not just toys)
46
@dan_jenkins
BLE (okay... a fair few toys)
47
@dan_jenkins
Stepping back, what is BLE?
•
Low Bandwidth
•
Bluetooth v4 - Bluetooth Low Energy (0.3 Mbps)
•
Bluetooth v3 (54 Mbps)
•
A set of Standard Services
•
But you can also build your own services
@dan_jenkins
BLE GATT Server
Gatt Server
Custom ServiceBattery Service
Battery Level
Characteristic
Custom
Characteristic #1
Custom
Characteristic #1
@dan_jenkins
Let's take a look at the
Web Bluetooth API
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', boop);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function boop(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
var options = { filters: [{ services: ['heart_rate'] }] };
navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged', beep);
return characteristic.startNotifications();
})
.catch(error => { console.log(error); });
function beep(event) { console.log(event.target.value); }
@dan_jenkins
But what if the device was
broadcasting a URL
where it can be controlled
from?
@dan_jenkins
@dan_jenkins
Today, there's no way to
bypass that device
selection
Which kinda sucks
@dan_jenkins
But that's changing soon too
var referringDevice = navigator.bluetooth.referringDevice;
if (referringDevice) {
referringDevice.gatt.connect()
.then(server => { ... })
.catch(error => { console.log(error); });
}
@dan_jenkins
But that's changing soon too
var referringDevice = navigator.bluetooth.referringDevice;
if (referringDevice) {
referringDevice.gatt.connect()
.then(server => { ... })
.catch(error => { console.log(error); });
}
@dan_jenkins
Where can I play with Web
Bluetooth today?
In short.... Chrome/Chromium on...
Android
M & N
ChromeOS Linux
Android L with Chromium
OSX
(Chrome 53)
Windows (a little)
@dan_jenkins
But for more info...
https://goo.gl/rDu2UT
@dan_jenkins
And you have to enable it...
chrome://flags
@dan_jenkins
But there is a Google
Chrome Origin Trial ongoing
https://goo.gl/hzczDR
@dan_jenkins
And the Chrome team has
announced their intent to ship in 56
https://goo.gl/KMmjda
@dan_jenkins
Oh and only on
Localhost & HTTPS...
There are quite a few hoops!
@dan_jenkins
Loads of demos out there
https://webbluetoothcg.github.io/demos/
@dan_jenkins
And you can make your own peripherals
BBC micro:bit
Arduino
Tessel
Raspberry Pi 3
@dan_jenkins
Developing for Web
Bluetooth has become
easier.
@dan_jenkins
Unless you're
developing on
Windows... but that's
changing too
@dan_jenkins
Hardware with BLE is
cheap
@dan_jenkins
Your dev environment
just needs to have BLE
(Bluetooth 4)
@dan_jenkins
One last
demo
@dan_jenkins
Build things
with the Web
@dan_jenkins
There are less
and less
reasons to build
native apps
@dan_jenkins
goo.gl/7uAtkY
3 great Google I/O videos
about the Physical Web
and Web Bluetooth
@dan_jenkins
Thanks!
@dan_jenkins

Getting physical with web bluetooth in the browser hackference