KEMBAR78
Getting physical with web bluetooth in the browser | PDF
Getting Physical
with Web Bluetooth
in the browser
Dan Jenkins
@dan_jenkins
Dan Jenkins
@dan_jenkins
nimblea.pe
dan@nimblea.pe
@nimbleapeltd
Getting
Physical
Physical
Ever wished you could "click"
on things in real life and find
out more about them?
Been
somewhere
that had
these?
They're
everywhere!
But there are
many other
places where
we want to
interact with
something
around us
The Physical Web
How do I use this magic?
Eddystone
•
Open Message Format
•
A few different parts to Eddystone but all we care about here is
Eddystone URL format
•
Eddystone URLs have 18 bytes worth of data that can be broadcast
•
Eddystone is supported by over 30 vendors
•
Eddystone is also compatible with iBeacon
•
https://developers.google.com/beacons/eddystone
Chrome
•
Chrome on iOS and 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 shows a notification
So all of this doesn't work unless you have data!
When you add in
Progressive Web Apps,
your reason for having a
Native app
dwindles
And they're being used
today
http://www.proxama.com/news/proxama-partners-with-google-to-deliver-worlds-first-physical-web-experience-for-consumers/
http://www.proxama.com/news/proxama-partners-with-google-to-deliver-worlds-first-physical-web-experience-for-consumers/
And there are beacons
here today
BUT,
There's more...
Web
Bluetooth
Your browser can
connect to
Bluetooth Low Energy
(BLE) devices directly
Using JavaScript, we
can now connect to
physical devices using
BLE and control them
BLE (not just toys)
25
BLE (not just toys)
26
BLE (okay... a fair few toys)
27
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
BLE GATT Server
Gatt Server
Custom ServiceBattery Service
Battery Level
Characteristic
Custom
Characteristic #1
Custom
Characteristic #1
Let's take a look at the
Web Bluetooth API
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
Today, there's no way to
bypass that device
selection
Which kinda sucks
But that's changing soon too
var referringDevice = navigator.bluetooth.referringDevice;
if (referringDevice) {
referringDevice.gatt.connect()
.then(server => { ... })
.catch(error => { console.log(error); });
}
But that's changing soon too
var referringDevice = navigator.bluetooth.referringDevice;
if (referringDevice) {
referringDevice.gatt.connect()
.then(server => { ... })
.catch(error => { console.log(error); });
}
Where can I play with Web
Bluetooth today?
In short.... Chrome/Chromium on...
Android M & N ChromeOS Linux
But for more info...
https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md
And you have to enable it...
Oh and only on
Localhost & HTTPS...
There are quite a few hoops!
Loads of demos out there
https://webbluetoothcg.github.io/demos/
And you can make your own peripherals
BBC micro:bit
Arduino
Tessel
Raspberry Pi 3
But developing with
Web Bluetooth isn't
exactly easy right now...
If you have the required
devices then GREAT!
If you don't, it kinda
sucks...
DEMO
Well, this didn't go to plan...
Physical Web & Web Bluetooth
Some beacons now run a GATT server inside them
They run a "Eddystone URL Configuration Service"
Physical Web & Web Bluetooth
http://cf.physical-web.org (redirects to a HTTPS url)
Build things
with the Web
Less and less
reasons to
build
native apps
goo.gl/7uAtkY
3 great Google I/O videos
about the Physical Web
and Web Bluetooth
Thanks!
@dan_jenkins

Getting physical with web bluetooth in the browser

  • 1.
    Getting Physical with WebBluetooth in the browser Dan Jenkins @dan_jenkins
  • 2.
  • 3.
  • 4.
    Ever wished youcould "click" on things in real life and find out more about them?
  • 5.
  • 6.
  • 7.
    But there are manyother places where we want to interact with something around us
  • 8.
  • 11.
    How do Iuse this magic?
  • 12.
    Eddystone • Open Message Format • Afew different parts to Eddystone but all we care about here is Eddystone URL format • Eddystone URLs have 18 bytes worth of data that can be broadcast • Eddystone is supported by over 30 vendors • Eddystone is also compatible with iBeacon • https://developers.google.com/beacons/eddystone
  • 13.
    Chrome • Chrome on iOSand 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 shows a notification So all of this doesn't work unless you have data!
  • 15.
    When you addin Progressive Web Apps, your reason for having a Native app dwindles
  • 16.
  • 17.
  • 18.
  • 19.
    And there arebeacons here today
  • 20.
  • 21.
  • 22.
    Your browser can connectto Bluetooth Low Energy (BLE) devices directly
  • 23.
    Using JavaScript, we cannow connect to physical devices using BLE and control them
  • 25.
    BLE (not justtoys) 25
  • 26.
    BLE (not justtoys) 26
  • 27.
    BLE (okay... afair few toys) 27
  • 28.
    Stepping back, whatis 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
  • 29.
    BLE GATT Server GattServer Custom ServiceBattery Service Battery Level Characteristic Custom Characteristic #1 Custom Characteristic #1
  • 30.
    Let's take alook at the Web Bluetooth API
  • 31.
    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); }
  • 32.
    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); }
  • 33.
    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); }
  • 34.
    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); }
  • 35.
    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); }
  • 36.
    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); }
  • 37.
    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); }
  • 38.
    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); }
  • 39.
    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); }
  • 40.
    Today, there's noway to bypass that device selection Which kinda sucks
  • 41.
    But that's changingsoon too var referringDevice = navigator.bluetooth.referringDevice; if (referringDevice) { referringDevice.gatt.connect() .then(server => { ... }) .catch(error => { console.log(error); }); }
  • 42.
    But that's changingsoon too var referringDevice = navigator.bluetooth.referringDevice; if (referringDevice) { referringDevice.gatt.connect() .then(server => { ... }) .catch(error => { console.log(error); }); }
  • 43.
    Where can Iplay with Web Bluetooth today? In short.... Chrome/Chromium on... Android M & N ChromeOS Linux
  • 44.
    But for moreinfo... https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md
  • 45.
    And you haveto enable it...
  • 46.
    Oh and onlyon Localhost & HTTPS... There are quite a few hoops!
  • 47.
    Loads of demosout there https://webbluetoothcg.github.io/demos/
  • 48.
    And you canmake your own peripherals BBC micro:bit Arduino Tessel Raspberry Pi 3
  • 49.
    But developing with WebBluetooth isn't exactly easy right now...
  • 50.
    If you havethe required devices then GREAT!
  • 51.
    If you don't,it kinda sucks...
  • 52.
  • 53.
    Well, this didn'tgo to plan...
  • 60.
    Physical Web &Web Bluetooth Some beacons now run a GATT server inside them They run a "Eddystone URL Configuration Service"
  • 61.
    Physical Web &Web Bluetooth http://cf.physical-web.org (redirects to a HTTPS url)
  • 62.
  • 63.
    Less and less reasonsto build native apps
  • 64.
    goo.gl/7uAtkY 3 great GoogleI/O videos about the Physical Web and Web Bluetooth
  • 65.