Niels Leenheer Fun with Bluetooth Summer. Sea. JavaScript.

Niels Leenheer t s e t 5 l m t h @ Fun with Bluetooth Summer. Sea. JavaScript.

why?

progressive web apps

pwa’s ! are great

but…

bluetooth

bluetooth s k c su

classic bluetooth y d o b y r h e t v o e o t n e o u s l a b e s r e e t a th h

classic bluetooth vs. control dr on es and oth bluetooth low energy er cool shi t

bluetooth low energy also known as B l Bluetooth Smar t uetooth LE B l u e t o o t h 4 BLE

bluetooth low energy also known as B l Bluetooth Smar t uetooth LE B l u e t o o t h 4 and 5 BLE

10 million bluetooth devices shipping every day

e n o h p e l i b mo

computer

r o t i n o m e s o c u l g d n a h s ’ y d o b e som

activity tracker

e r e h p u b y a l p s lb b l u b y a pl

8 b b o i r e sph

e n o r d i n i m t o r par

r e n n i p s fidget

the boring theoretical stuff

central peripheral

central

generic attribute profile

generic attribute profile ?

generic attribute profile c e b , t t a g a w p a g e s u a n e k a t y d a e r s al

central peripheral client server

§ i device information light e c i v e d r e p s e c i v r e s e l p i t l u m

i device information battery flight control

i device information battery steering control

i device information battery heart rate

i device information battery heart rate

i device information battery heart rate

i device information manufacturer model number serial number hardware revision firmware revision software revision … s c i t s i r e t c a r a h c e l e p c i i t v l r u e s m r pe

server service characteristic value array of objects object property value

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

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

battery 16 bit 128 bit 0x180F 0000180F-0000-1000-8000-00805F9B34FB

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

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

i 0x180A 0x2A29 0x2A24 0x2A25 0x2A27 0x2A26 0x2A28 … b good fo ad for rea r saving dability bandwi , dth

s t r o p p u s c i t s i r e t e c s a e r h a t h f c o h e c r a o e m r o one read write write without response notify

every value is an array of bytes s e t y b st d y c n a f no u j , s e p y t a t a

pfew…

s t c a f g n i t r u o o b Fun b a with Bluetooth

Fun with Bluetooth

web bluetooth still not t he fun pa r :-( t api

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)) t a h w r e s w o r b e h t l l e t e w t n a w e w e c i v e d f o d n i k .then(characteristic => { return characteristic.writeValue(

s t c e l e s r e s u e th al device u t c a the

navigator.bluetooth.requestDevice({ filters: [ { namePrefix: ‘PLAYBULB’ } ], optionalServices: [ 0xff0f ] }) .then(device => { …. }) .then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) m o pr e r a s ise 7 1 0 2 so

let device = await 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(

let server = await device.gatt.connect()); conn r e v r e s e h t o ect t

let service = await server.getPrimaryService(0xff0f)); .then(characteristic => { return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ); }) ]) e c i v r e s e h t t e g

let characteristic = await service.getCharacteristic(0xfffc)); c i t s i r e t c a r a h c e h t t e g{ => .then(characteristic return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ); }) ])

writing data

characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ); ]) w s e t y b e m o s e rit

reading data

let value = await characteristic.readValue(); let r = value.getUint8(1); let g = value.getUint8(2); let b = value.getUint8(3); d er a s e t y b e m so

get notified of changes

characteristic.addEventListener( ‘characteristicvaluechanged’, e => { let r = e.target.value.getUint8(1); let g = e.target.value.getUint8(2); let b = e.target.value.getUint8(3); } ); r e n e t s i l ent v e d d a characteristic.startNotifications(); don’t forget to star t listen ing

things you need to know: • the webbluetooth api • promises (or async await) • typed arrays d ! h u

browser support Chrome Edge (Chromium) Samsung Servo (soon)

browser support Chrome Edge (Chromium) Samsung Servo (soon) iOS

browser support Chrome Edge (Chromium) Samsung Servo (soon) iOS

browser support a d n i k Chrome Edge (Chromium) Samsung s k r o w Servo WebBLE (soon) for iOS

and…

and… npm install node-web-bluetooth

and… npm install cordova-plugin-webbluetooth

and… espruino m m 8 2 x 18

custom characteristics wtf!

function(r, g, b) { return new Uint8Array([ 0x00, r, g, b } function(buffer) { return { r: buffer.getUint8(1), g: buffer.getUint8(2), b: buffer.getUint8(3) } } ]);

function(r, g, b) { return new Uint8Array([ 0x01, g, 0x01, 0x00, 0x01, b, 0x01, r, 0x01, 0x00 ]); }

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; }

function(r, g, b, position) { let buffer = new Uint8Array([ 0x07, 0x02, position + 1, r, g, b ]); return buffer; }

function(r, g, b, position) { let buffer = new Uint8Array([ 0x58, r, g, b, 0x01, position ]); …

function(r, g, b, position) { let buffer = new Uint8Array([ 0x58, r, g, b, 0x01, position ]); let payload = new Uint8Array(buffer.length + 4); payload[0] = payload.length - 2; payload[1] = payload.length - 2 >>> 8; payload.set(buffer, 2); let checksum = payload.reduce((a, b) => a + b, 0); payload[payload.length - 2] = checksum; payload[payload.length - 1] = checksum >>> 8;

message[m] = 0x03; message[m + 1] = 0x06; m += 2; } else { message[m] = payload[i]; m++; } } message[0] = 0x01; message[message.length - 1] = 0x02; return message; }

adafruit bluetooth sniffer

log all bluetooth packets on your phone o t b d a e g s o l u e d h n t a nsfer a r t

o t k r a h s a e t r a i d w e e h s u k at t o o l

decompiling the apk t ’ n o d ! e n o y n a l l e t

finally t he fun p ar t demo

warning experimental technology w o l g n i sett s n o i t a t c e exp

warning wifi interference r e h t r u f n e v e m e h t g n i lower

Fun with Bluetooth

questions? @htm l5test