Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Fun with Bluetooth @ DomoticaGrunn

Fun with Bluetooth @ DomoticaGrunn

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.

Niels Leenheer

November 01, 2017
Tweet

More Decks by Niels Leenheer

Other Decks in Technology

Transcript

  1. fun with
    bluetooth

    View Slide

  2. bluetooth
    sucks

    View Slide

  3. classic bluetooth
    the reason everybody 

    hates bluetooth
    bluetooth low energy
    vs.
    control drones and other cool shit

    View Slide

  4. bluetooth low energy
    also known as
    BLE
    Bluetooth LE
    Bluetooth Smart
    Bluetooth 4

    View Slide

  5. playbulb sphere
    playbulb

    View Slide

  6. spherio bb-8

    View Slide

  7. parrot mini drone

    View Slide

  8. activity tracker

    View Slide

  9. the boring theoretical stuff

    View Slide

  10. central peripheral

    View Slide

  11. central

    View Slide

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

    View Slide

  13. central peripheral
    client server

    View Slide

  14. §
    i device information
    light
    multiple services per device

    View Slide

  15. i device information
    battery
    flight control

    View Slide

  16. i device information
    battery
    steering control

    View Slide

  17. i device information
    battery
    heart rate

    View Slide

  18. heart rate
    i device information
    battery

    View Slide

  19. i device information
    battery
    heart rate

    View Slide

  20. i device information
    manufacturer
    model number
    serial number
    hardware revision
    firmware revision
    software revision
    ...
    multiple characteristics 

    per service

    View Slide

  21. server
    service
    characteristic
    value
    array of objects
    object
    property
    value

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  25. 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

    View Slide

  26. i device information
    manufacturer
    model number
    serial number
    hardware revision
    firmware revision
    software revision
    ...

    View Slide

  27. i 0x180A
    0x2A29
    0x2A24
    0x2A25
    0x2A27
    0x2A26
    0x2A28
    ...
    bad for readability, 

    good for saving bandwidth

    View Slide

  28. read
    write
    write without response
    notify
    each characteristic supports
    one or more of these

    View Slide

  29. every value is an array of bytes
    no fancy datatypes, just bytes

    View Slide

  30. pfew...

    View Slide

  31. View Slide

  32. fun with
    bluetooth
    boring facts

    about

    View Slide

  33. fun with
    bluetooth

    View Slide

  34. web

    bluetooth
    api
    still not the fun part
    :-(

    View Slide

  35. connecting to a device

    View Slide

  36. 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

    View Slide

  37. the user selects
    the actual device

    View Slide

  38. 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

    View Slide

  39. 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

    View Slide

  40. 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

    View Slide

  41. writing data

    View Slide

  42. 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

    View Slide

  43. reading data

    View Slide

  44. 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

    View Slide

  45. get notified of changes

    View Slide

  46. 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

    View Slide

  47. things you need to know:
    • javascript

    • the webbluetooth api
    • promises
    • typed arrays duh!

    View Slide

  48. browser support
    Chrome Opera Samsung

    (behind flag)
    Servo

    (soon)

    View Slide

  49. browser support
    Chrome Opera Samsung

    (behind flag)
    kinda works
    Servo

    (soon)
    WebBLE

    for iOS

    View Slide

  50. and...
    npm install node-web-bluetooth

    View Slide

  51. and... the puck.js

    View Slide

  52. command-

    line
    tools Oh, come on!
    (linux)

    View Slide

  53. hcitool lescan

    LE Scan ...
    82:4C:4B:17:AC:E6 PLAYBULB sphere
    11:75:58:1B:52:85 TimeBox-mini-light
    D9:97:A2:35:42:2C BB-422C
    D5:72:4A:3F:C2:1F Puck.js c21f
    scan for 

    ble devices

    View Slide

  54. gatttool --device=82:4C:4B:17:AC:E6 --characteristics


    handle = 0x0002, char properties = 0x20, 

    char value handle = 0x0003, 

    uuid = 00002a05-0000-1000-8000-00805f9b34fb

    handle = 0x0028, char properties = 0x06, 

    char value handle = 0x0029, 

    uuid = 0000fffc-0000-1000-8000-00805f9b34fb
    handle = 0x004a, char properties = 0x02, 

    char value handle = 0x004b, 

    uuid = 00002a50-0000-1000-8000-00805f9b34fb
    get a list 

    of all 

    characteristics

    View Slide

  55. gatttool --device=82:4C:4B:17:AC:E6 

    --char-read --handle=0x0029


    Characteristic value/descriptor: 00 00 00 ff
    reading the value 

    of a characteristic

    View Slide

  56. gatttool --device=82:4C:4B:17:AC:E6 

    --char-write --handle=0x0029 --value=0000ff00

    writing the value 

    of a characteristic

    View Slide

  57. custom
    characteristics.
    wtf!

    View Slide

  58. 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

    View Slide

  59. 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

    View Slide

  60. 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

    View Slide

  61. 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

    View Slide

  62. adafruit

    bluetooth 

    sniffer

    View Slide

  63. View Slide

  64. View Slide

  65. demo
    finally the fun part

    View Slide

  66. warning
    experimental technology

    setting low expectations

    View Slide

  67. warning
    wifi interference

    lowering them even further

    View Slide

  68. View Slide

  69. https:/
    /bluetooth.rocks/lightbulb

    https:/
    /github.com/NielsLeenheer/BluetoothBulb
    change the colour 

    of a lightbulb

    View Slide

  70. https:/
    /bluetooth.rocks/racer
    https:/
    /github.com/NielsLeenheer/BluetoothRacer
    control a lego racer 

    using a gamepad
    use css animations to 

    define a path

    View Slide

  71. https:/
    /bluetooth.rocks/drone

    https:/
    /github.com/poshaughnessy/web-bluetooth-parrot-drone
    control a drone 

    from your browser

    View Slide

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

    View Slide

  73. https:/
    /bluetooth.rocks/pulse

    https:/
    /github.com/NielsLeenheer/BluetoothPulse
    find out your 

    current heartbeat

    View Slide

  74. fun with
    bluetooth
    !

    View Slide

  75. questions?
    @html5test

    View Slide