Getting physical with web bluetooth in the browser

68
Getting Physical with Web Bluetooth in the browser Dan Jenkins @dan_jenkins

Transcript of Getting physical with web bluetooth in the browser

Gett ing Physical with Web Bluetooth

in the browserDan Jenkins

@dan_jenkins

@dan_jenkins

Dan Jenkins@dan_jenkins

nimblea.pe

[email protected]

@nimbleapeltd

@dan_jenkins

Gett ing 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

DEMO

@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

@dan_jenkins

@dan_jenkins

How do I use this magic?

@dan_jenkins

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

@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

So all of this doesn't work unless you have data!

@dan_jenkins

@dan_jenkins

When you add in Progressive Web Apps,

your reason for having a Native app dwindles

@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

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

DEMO(S)

@dan_jenkins

BLE (not just toys)

32

@dan_jenkins

BLE (not just toys)

33

@dan_jenkins

BLE (okay... a fair few toys)

34

@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 ServerGatt 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 toovar referringDevice = navigator.bluetooth.referringDevice;

if (referringDevice) { referringDevice.gatt.connect() .then(server => { ... }) .catch(error => { console.log(error); }); }

@dan_jenkins

But that's changing soon toovar 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)

@dan_jenkins

But for more info...

https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md

@dan_jenkins

And you have to enable it... chrome://flags

@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

In the past 2 months developing for Web

Bluetooth has become easier

@dan_jenkins

Unless you're developing on

Windows...

@dan_jenkins

Hardware with BLE is cheap

@dan_jenkins

And you don't need to use ChromeOS or

Android now

@dan_jenkins

Physical Web & Web Bluetooth

Some beacons now run a GATT server inside them

They run a "Eddystone URL Configuration Service"

@dan_jenkins

Physical Web & Web Bluetooth

http://cf.physical-web.org (redirects to a HTTPS url)

@dan_jenkins

Build th ings 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

@dan_jenkins

We're hiring Developers!Remote / Node.js / JavaScript / VoIP /

WebRTC / Other Cool Sh*t