fun with bluetooth

bluetooth s k c su

classic bluetooth vs. 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 t e th ha 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

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

8 b b o i r e h p s

e n o r d i n parrot mi

activity tracker

the boring theoretical stuff

central peripheral

central

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

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 mu

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 e s mu r e p

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 flight c this not recommended 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 each one or more read write write without response notify

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

pfew…

s t c a f g n i r o b t u o ab fun with bluetooth

fun with bluetooth

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

connecting to a device

1 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 we t t n a w e w e c i v e d f o d kin .then(characteristic => { return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ); }) ])

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

2 navigator.bluetooth.requestDevice({ filters: [ { namePrefix: ‘PLAYBULB’ } ], optionalServices: [ 0xff0f ] }) .then(device => device.gatt.connect()) .then(server => server.getPrimaryService(0xff0f)) .then(service => service.getCharacteristic(0xfffc)) r e v r e s e h t o t t c e conn .then(characteristic => { return characteristic.writeValue( new Uint8Array([ 0x00, r, g, b ); }) ])

3 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 ); }) e c i v r e s get the ])

4 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 ); }) ]) c i t s i r e t c a r a h c e h get t

writing data

w s e t y b e m o s rite 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 ); }) ])

reading data

e m o s d er a s e t y b 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); })

get notified of changes

add r e n e t s i l t n e ev 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(); }) don’t forget to star t listen ing

things you need to know: • javascript • the webbluetooth api • promises • typed arrays d ! h u

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

browser support a d kin Chrome Opera s k r o w Samsung Servo WebBLE (behind flag) (soon) for iOS

and… npm install node-web-bluetooth

and… the puck.js

(linux) commandline tools Oh, com e on!

hcitool lescan r o f n a c s vices e d ble LE Scan … 82:4C:4B:17:AC:E6 11:75:58:1B:52:85 D9:97:A2:35:42:2C D5:72:4A:3F:C2:1F PLAYBULB sphere TimeBox-mini-light BB-422C Puck.js c21f

gatttool —device=82:4C:4B:17:AC:E6 —characteristics get a list o f character all istics handle char uuid handle char uuid handle char uuid = 0x0002, char properties = 0x20, value handle = 0x0003, = 00002a05-0000-1000-8000-00805f9b34fb = 0x0028, char properties = 0x06, value handle = 0x0029, = 0000fffc-0000-1000-8000-00805f9b34fb = 0x004a, char properties = 0x02, value handle = 0x004b, = 00002a50-0000-1000-8000-00805f9b34fb

gatttool —device=82:4C:4B:17:AC:E6 —char-read —handle=0x0029 Characteristic value/descriptor: 00 00 00 ff reading t h of a char e value acteristic

gatttool —device=82:4C:4B:17:AC:E6 —char-write —handle=0x0029 —value=0000ff00 e u l a v e h t g n c i i t t i s wr characteri of a

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) } } fro g n i d a e r d n a o t g writin c i t s i r e t c a r a h c e m a s e h t m

writing a value: function(r, g, b) { return new Uint8Array([ 0x01, g, 0x01, 0x00, 0x01, b, 0x01, r, 0x01, 0x00 ]); } t n e r r u c e h t g n i read e l b i s s o p t o n s i r colo

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; } t n e r r u c e h t g n i read e l b i s s o p t o n s i r colo

reading a value: 0 e f f x 0 e c servi 4 e f f x 0 c i t s i r e t c a char 1 write a specific value 2 get the event with the color 3 add event listener service 0xffe5 characteristic 0xffe 9

adafruit bluetooth sniffer

finally t he fun p ar t demo

warning experimental technology w o l g n i t set s n o i t a t c e p x e

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

change the colour of a lightbulb https://bluetooth.rocks/lightbulb https://github.com/NielsLeenheer/BluetoothBulb

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

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

pixel matrix display https://bluetooth.rocks/pixel

find out your current heartbeat https://bluetooth.rocks/pulse https://github.com/NielsLeenheer/BluetoothPulse

fun with bluetooth !

questions? @htm l5test