Pro Yearly is on sale from $80 to $50! »

Fun with Bluetooth @ Halfstack

Fun with Bluetooth @ Halfstack

Time for the browser to get physical. With WebBluetooth the browser can actually take control of all kinds of physical devices in the real world like lightbulbs, robots and even drones. This talk will teach you the basics that you need to get started and will show you some more advanced topics like building your own Bluetooth devices using just JavaScript.

De023a9aff4c7a5ede3a81e8c76f17b5?s=128

Niels Leenheer

November 17, 2017
Tweet

Transcript

  1. fun with bluetooth

  2. why?

  3. progressive 
 web apps

  4. pwa’s are great !

  5. but...

  6. but...

  7. None
  8. bluetooth

  9. bluetooth sucks

  10. classic bluetooth the reason everybody 
 hates bluetooth bluetooth low

    energy vs. control drones and other cool shit
  11. bluetooth low energy also known as BLE Bluetooth LE Bluetooth

    Smart Bluetooth 4
  12. playbulb sphere playbulb

  13. spherio bb-8

  14. parrot mini drone

  15. activity tracker

  16. the boring theoretical stuff

  17. central peripheral

  18. central

  19. generic attribute profile

  20. generic attribute profile ?

  21. generic attribute profile gatt, because gap was already taken

  22. central peripheral client server

  23. § i device information light multiple services per device

  24. i device information battery flight control

  25. i device information battery steering control

  26. i device information battery heart rate

  27. heart rate i device information battery

  28. i device information battery heart rate

  29. i device information manufacturer model number serial number hardware revision

    firmware revision software revision ... multiple characteristics 
 per service
  30. server service characteristic value array of objects object property value

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

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

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

  34. not recommended any UUID outside of the range
 xxxxxxxx-0000-1000-8000-00805F9B34FB 16

    bit 128 bit light steering control flight c still, everybody does this
  35. i device information manufacturer model number serial number hardware revision

    firmware revision software revision ...
  36. i 0x180A 0x2A29 0x2A24 0x2A25 0x2A27 0x2A26 0x2A28 ... bad

    for readability, 
 good for saving bandwidth
  37. read write write without response notify each characteristic supports one

    or more of these
  38. every value is an array of bytes no fancy datatypes,

    just bytes
  39. pfew...

  40. None
  41. fun with bluetooth boring facts
 about

  42. fun with bluetooth

  43. web
 bluetooth api still not the fun part :-(

  44. connecting to a device

  45. 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
  46. the user selects the actual device

  47. 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
  48. 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
  49. 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
  50. writing data

  51. 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
  52. reading data

  53. 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
  54. get notified of changes

  55. 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
  56. things you need to know: • the webbluetooth api •

    promises • typed arrays duh!
  57. browser support Chrome Opera Samsung
 (behind flag) Servo
 (soon)

  58. browser support Chrome Opera Samsung
 (behind flag) kinda works Servo


    (soon) WebBLE
 for iOS
  59. and... npm install node-web-bluetooth

  60. and... the puck.js

  61. custom characteristics. wtf!

  62. 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
  63. 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
  64. 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
  65. writing a value: 
 function(r, g, b, position) { let

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

    buffer = new Uint8Array([ 0x58, r, g, b, 0x01, position ]); ...
  67. writing a value: 
 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; let extra = payload.filter(value => {

  68. message[m] = 0x03; message[m + 1] = 0x05; m +=

    2; } else if (payload[i] === 0x03) { 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; }
  69. adafruit
 bluetooth 
 sniffer

  70. decompiling 
 the apk don't tell anyone!

  71. demo finally the fun part

  72. warning experimental technology
 setting low expectations

  73. warning wifi interference
 lowering them even further

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

    lightbulb
  76. https:/ /bluetooth.rocks/pixel draw pixel art on 
 a led matrix

    display
  77. https:/ /bluetooth.rocks/racer https:/ /github.com/NielsLeenheer/BluetoothRacer control a lego racer 
 using

    a gamepad use css animations to 
 define a path
  78. https:/ /bluetooth.rocks/drone
 https:/ /github.com/poshaughnessy/web-bluetooth-parrot-drone control a drone 
 from your

    browser
  79. https:/ /bluetooth.rocks/printer print on a receipt printer

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

  81. fun with bluetooth !

  82. questions? @html5test