Fun with Bluetooth @ code.talks 2017

Fun with Bluetooth @ code.talks 2017

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

September 28, 2017
Tweet

Transcript

  1. fun with bluetooth

  2. why?

  3. progressive 
 web apps

  4. pwa’s are great !

  5. full screen offline support add to home screen push notifications

  6. full screen offline support location camera sensors network add to

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

    home screen push notifications
  8. ethernet 
 & wifi

  9. wifi

  10. zigbee?


  11. ethernet

  12. runs a webserver use fetch or 
 xmlhttprequest

  13. [{ "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
  14. <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</deviceT <friendlyName>Philips

    hue (192.168.2.23)</friendlyName> <manufacturer>Royal Philips Electronics</manufacturer> http://192.168.2.23/description.xml 2
  15. 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
  16. 4 { "1": { "state": { "on": true, "bri": 144,

    "hue": 13088, "sat": 212, "xy": [0.5128,0.4147], "ct": 467, "alert": "none", http://192.168.2.23/api/......../lights
  17. 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}}
  18. *click* *click* *reload* *click*

  19. this does 
 not work !

  20. https only http only no certificate 
 for you

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

  22. hue remote api Also allow control from 
 outside the

    local network
  23. We are currently preparing for release of this remote API

    which will initially be available to a limited number of partners. “ — Philips
  24. 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
  25. fun with bluetooth problems local networks

  26. fun with bluetooth

  27. bluetooth sucks

  28. classic bluetooth the reason everybody 
 hates bluetooth bluetooth low

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

    Smart Bluetooth 4
  30. playbulb sphere playbulb

  31. spherio bb-8

  32. parrot mini drone

  33. activity tracker

  34. the boring theoretical stuff

  35. central peripheral

  36. central

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

  38. central peripheral client server

  39. § i device information light multiple services per device

  40. i device information battery flight control

  41. i device information battery steering control

  42. i device information battery heart rate

  43. heart rate i device information battery

  44. i device information battery heart rate

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

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

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

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

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

  50. 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
  51. i device information manufacturer model number serial number hardware revision

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

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

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

    just bytes
  55. pfew...

  56. None
  57. fun with bluetooth boring facts
 about

  58. fun with bluetooth

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

  60. connecting to a device

  61. 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
  62. the user selects the actual device

  63. 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
  64. 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
  65. 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
  66. writing data

  67. 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
  68. reading data

  69. 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
  70. get notified of changes

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

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

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


    (soon) WebBLE
 for iOS
  75. custom characteristics. wtf!

  76. 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
  77. 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
  78. 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
  79. 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
  80. demo finally the fun part

  81. warning experimental technology
 setting low expectations

  82. warning wifi interference
 lowering them even further

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

    lightbulb
  85. https:/ /bricks.blue/tooth/ https:/ /github.com/NielsLeenheer/BluetoothRacer control a lego racer 
 using

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

    browser
  87. https:/ /pulse.blue/tooth/
 https:/ /github.com/NielsLeenheer/BluetoothPulse find out your 
 current heartbeat

  88. physical web

  89. battery lasts years beacon really small

  90. broadcast the url
 of a web app easy to open

    from 
 the home screen
  91. coming soon automatic web bluetooth
 connection

  92. taking it one step further

  93. runs javascript physical web beacon supports 
 web bluetooth api

    has a button
  94. peripheral
 mode

  95. central
 mode

  96. None
  97. fun with bluetooth !

  98. questions? @html5test