fun with bluetooth

why?

progressive 
 web apps

pwa’s are great !

full screen offline support add to home screen push notifications

location camera sensors network full screen
offline support
add to home screen push notifications

network full screen
offline support
location camera sensors add to home screen push notifications

ethernet 
 & wifi

wifi

zigbee? 


ethernet

runs a webserver use fetch or 
 xmlhttprequest

[{ "id":"001788fffe100491", "internalipaddress":"192.168.2.23", "macaddress":"00:17:88:10:04:91", "name":"Philips Hue" }, { "id":"001788fffe09a168", "internalipaddress":"192.168.88.252" }, { https://www.meethue.com/api/nupnp 1

<root xmlns="urn:schemas-upnp-org:device-1-0"> <specVersion> <major>1</major> <minor>0</minor> </specVersion> <URLBase>http://192.168.2.23:80/</URLBase> <device> <deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType> <friendlyName>Philips hue (192.168.2.23)</friendlyName> <manufacturer>Royal Philips Electronics</manufacturer> <manufacturerURL>http://www.philips.com</manufacturerURL> http://192.168.2.23/description.xml 2

http://192.168.2.23/ api 
 {"devicetype": "hue_pwa#pixel_xl" } 3 [{"success":{"username": "........" }}] User presses physical button on the hub click save to local storage

4 { "1": { "state": { "on": true, "bri": 144, "hue": 13088, "sat": 212, "xy": [0.5128,0.4147], "ct": 467, "alert": "none", "effect": "none", http://192.168.2.23/api/........ /lights

http://192.168.2.23/api/......../lights/1/state 
 { "hue": 50000, "on": true, "bri": 200 } 5 [ {"success":{"/lights/1/state/bri":200}}, {"success":{"/lights/1/state/on":true}}, {"success":{"/lights/1/state/hue":50000}} ]

click click reload click

this does 
 not work !

https only http only no certificate 
 for you

= network use remote api’s ≠ access to local devices

hue remote api Also allow control from 
 outside the local network

We are currently preparing for release of this remote API which will initially be available to a limited number of partners. “ — Philips

We are currently preparing for release of this remote API which will initially be available to a limited number of partners. “ — Philips two years ago very not yet

fun with bluetooth problems local networks

fun with bluetooth

bluetooth sucks

classic bluetoot h the reason everybody 
 hates bluetooth bluetoot h low energy vs. control drones and other cool shit

bluetoot h low energy also known as BLE Bluetooth LE Bluetooth Smart Bluetooth 4

playbulb sphere playbulb

spherio bb-8

parrot mini drone

activity tracker

the boring theoretical stuff

central peripheral

central

generic attribute profile gatt, because gap was already taken

client server

central peripheral

§ i device information light multiple services per device

i device information battery flight control

i device information battery steering control

i device information battery heart rate

heart rate i device information battery

i device information battery heart rate

i device information manufacturer
model number serial number hardware revision firmware revision software revision ... multiple characteristics 
 per service

server service characteristic value array of objects object property value

services and characteristics are identified by uuid’s 16 bit or 128 bit

0x180A 0000 180A -0000-1000-8000-00805F9B34FB 16 bit 128 bit i device information

0x180 F 0000 180F -0000-1000-8000-00805F9B34FB 16 bit 128 bit battery

not recommended any UUID outside of the range 
 xxxxxxxx -0000-1000-8000-00805F9B34FB 16 bit 128 bit light steering control flight control still, everybody does this

i device information manufacturer
model number serial number hardware revision firmware revision software revision ...

i 0x180A 0x2A29
0x2A24 0x2A25 0x2A27 0x2A26 0x2A28 ... bad for readability, 
 good for saving bandwidth

read write write without response notify each characteristic supports
one or more of these

every value is an array of bytes no fancy datatypes, just bytes

pfew...

fun

with

bluetooth boring facts 
 about

fun with bluetooth

 web


 bluetooth

api

still not the fun part :-(

connecting to a device

navigator.bluetooth.requestDevice({ filters: [
{ namePrefix: 'PLAYBULB' }
], optionalServices: [ 0xff0f ] }) .then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) .then(characteristic => { return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ]) ); }) 1 we tell the browser what 
 kind of device we want

the user selects
the actual device

navigator.bluetooth.requestDevice({ filters: [
{ namePrefix: 'PLAYBULB' }
], optionalServices: [ 0xff0f ] }) .then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) .then(characteristic => { return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ]) ); }) 2 connect to the server

navigator.bluetooth.requestDevice({ filters: [
{ namePrefix: 'PLAYBULB' }
], optionalServices: [ 0xff0f ] }) .then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) .then(characteristic => { return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ]) ); }) 3 get the service

navigator.bluetooth.requestDevice({ filters: [
{ namePrefix: 'PLAYBULB' }
], optionalServices: [ 0xff0f ] }) .then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) .then(characteristic => { return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ]) ); }) 4 get the characteristic

writing data

navigator.bluetooth.requestDevice({ ... }) .then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) .then(c => { return c.writeValue( new Uint8Array([ 0x00, r, g, b ]) ); }) write some bytes

reading data

navigator.bluetooth.requestDevice({ ... })

.then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) .then(c => c .readValue()) .then(value => { let r = value.getUint8(1);
let g = value.getUint8(2); let b = value.getUint8(3); }) read some bytes

get notified of changes

navigator.bluetooth.requestDevice({ ... })

.then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc))

.then(c => { c.addEventListener('characteristicvaluechanged', e => { let r = e.target.value.getUint8(1);
let g = e.target.value.getUint8(2); let b = e.target.value.getUint8(3); }); c.startNotifications(); }) add event listener don't forget to start listening

things you need to know: • the webbluetooth api • promises • typed arrays duh!

browser support Chrome Opera Samsung 
 (behind flag) Servo 
 (soon)

browser support Chrome Opera Samsung 
 (behind flag) kinda works Servo 
 (soon) WebBLE 
 for iOS

custom
characteristics . wtf!

writing a value: function(r, g, b) { return new Uint8Array([ 0x00, r, g, b ]); }

reading a value: function(buffer) { return { 
 r: buffer.getUint8(1), 
 g: buffer.getUint8(2), 
 b: buffer.getUint8(3) 


} } writing to and reading 
 from the same characteristic

writing a value: function(r, g, b) { return new Uint8Array([

    0x01, g, 0x01, 0x00, 0x01, 


 b, 0x01, r, 0x01, 0x00



]); } reading the current 
 color is not possible

writing a value: 
 function(r, g, b) { var buffer = new Uint8Array([ 
 0xaa, 0x0a, 0xfc, 0x3a, 0x86, 0x01, 0x0d, 
 0x06, 0x01, r, g, b, 0x00, 0x00, 
 (Math.random() * 1000) & 0xff, 0x55, 0x0d 


]); for (var i = 1; i < buffer.length - 2; i++) { buffer[15] += buffer[i]; } return buffer; } reading the current 
 color is not possible

reading a value: add event listener

write a specific value

get the event with the color 1 2 3 service 0xffe0 
 characteristic 0xffe4 service 0xffe5 
 characteristic 0xffe9

demofinally the fun part

warning experimental technology 
 setting low expectations

warning wifi interference 
 lowering them even further

https://bulb.blue/tooth/ 
 https://github.com/NielsLeenheer/BluetoothBulb change the colour 
 of a lightbulb

https://bricks.blue/tooth/

https://github.com/NielsLeenheer/BluetoothRacer control a lego racer 
 using a gamepad use css animations to 
 define a path

https://webdr.one 
 https://github.com/poshaughnessy/web-bluetooth-parrot-drone control a drone 
 from your browser

https://pulse.blue/tooth/ 
 https://github.com/NielsLeenheer/Bluetooth Pulsefind out your 
 current heartbeat

physical web

battery lasts years beacon really small

broadcast the url 
 of a web app easy to open from 
 the home screen

coming soon automatic
web bluetooth 
 connection

taking it one step further

runs javascript physical web beacon supports 
 web bluetooth api has a button

peripheral 
 mode

central 
 mode

fun with bluetooth !

questions? @html5test