Niels Leenheer
Fun with Bluetooth Summer. Sea. JavaScript.
Slide 2
Niels Leenheer
t s e t 5 l m t h @
Fun with Bluetooth Summer. Sea. JavaScript.
Slide 3
why?
Slide 4
progressive web apps
Slide 5
pwa’s
!
are great
Slide 6
but…
Slide 7
bluetooth
Slide 8
bluetooth
s k c su
Slide 9
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
Slide 10
classic bluetooth vs.
control dr on
es and oth
bluetooth low energy
er cool shi
t
Slide 11
bluetooth low energy also known as
B l Bluetooth Smar t uetooth LE B l u e t o o t h 4 BLE
Slide 12
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
Slide 13
10 million bluetooth devices shipping every day
Slide 14
e n o h p e l i b mo
Slide 15
computer
Slide 16
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
Slide 17
activity tracker
Slide 18
e r e h p
u b y a l p
s lb
b l u b y a pl
Slide 19
8 b b o i r e sph
Slide 20
e n o r d i n i m t o r par
Slide 21
r e n n i p s fidget
Slide 22
the boring theoretical stuff
Slide 23
central
peripheral
Slide 24
central
Slide 25
generic attribute profile
Slide 26
generic attribute profile
?
Slide 27
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
Slide 28
central
peripheral
client
server
Slide 29
§
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
Slide 30
i
device information
battery
flight control
Slide 31
i
device information
battery
steering control
Slide 32
i
device information
battery
heart rate
Slide 33
i
device information
battery
heart rate
Slide 34
i
device information
battery
heart rate
Slide 35
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
Slide 36
server service characteristic value
array of objects object property value
Slide 37
services and characteristics are identified by uuid’s 16 bit or 1 28 bit
Slide 38
i
device information
16 bit 128 bit
0x180A 0000180A-0000-1000-8000-00805F9B34FB
Slide 39
battery
16 bit 128 bit
0x180F 0000180F-0000-1000-8000-00805F9B34FB
Slide 40
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
Slide 41
i
device information
manufacturer model number serial number hardware revision firmware revision software revision …
Slide 42
i
0x180A 0x2A29 0x2A24 0x2A25 0x2A27 0x2A26 0x2A28 …
b good fo ad for rea r saving dability bandwi , dth
Slide 43
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
Slide 44
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
Slide 45
pfew…
Slide 46
Slide 47
s t c a f g n i t r u o o b Fun b a with
Bluetooth
Slide 48
Fun with Bluetooth
Slide 49
web bluetooth still not t he fun pa r
:-(
t
api
Slide 50
connecting to a device
Slide 51
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(
Slide 52
s t c e l e s r e s u e th al device u t c a the
Slide 53
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 server = await device.gatt.connect());
conn
r e v r e s e h t o ect t
Slide 56
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
Slide 57
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 ); })
])
Slide 58
writing data
Slide 59
characteristic.writeValue( new Uint8Array([ 0x00, r, g, b );
])
w
s e t y b e m o s e rit
Slide 60
reading data
Slide 61
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
Slide 62
get notified of changes
Slide 63
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
Slide 64
things you need to know: • the webbluetooth api • promises (or async await) • typed arrays
d
! h u
Slide 65
browser support
Chrome
Edge (Chromium)
Samsung
Servo (soon)
Slide 66
browser support
Chrome
Edge (Chromium)
Samsung
Servo (soon)
iOS
Slide 67
browser support
Chrome
Edge (Chromium)
Samsung
Servo (soon)
iOS
Slide 68
browser support a d n i k
Chrome
Edge (Chromium)
Samsung
s k r o w
Servo
WebBLE
(soon)
for iOS
Slide 69
and…
Slide 70
and…
npm install node-web-bluetooth
Slide 71
and…
npm install cordova-plugin-webbluetooth
Slide 72
and… espruino
m m 8 2 x 18
Slide 73
custom characteristics
wtf!
Slide 74
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) } }
]);
Slide 75
function(r, g, b) { return new Uint8Array([ 0x01, g, 0x01, 0x00, 0x01, b, 0x01, r, 0x01, 0x00 ]); }
Slide 76
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; }
Slide 77
function(r, g, b, position) { let buffer = new Uint8Array([ 0x07, 0x02, position + 1, r, g, b ]); return buffer; }
Slide 78
function(r, g, b, position) { let buffer = new Uint8Array([ 0x58, r, g, b, 0x01, position ]); …
Slide 79
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;