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

Shuichi Tsutsumi: Practical Core Bluetooth in I...

Realm
June 16, 2016

Shuichi Tsutsumi: Practical Core Bluetooth in IoT & Wearable projects

In recent years, "IoT" or "Wearable" are one of buzzwords, so you might have interests in building hardware products. But learning how to develop electric circuits, mechanical systems or embedded systems etc. from zero is so difficult.

However, iOS developers can contribute to projects of hardware products with the knowledge of Core Bluetooth / Bluetooth Low Energy (BLE), even if they are not familiar with hardware layer.

In this session, you can learn the basics of Core Bluetooth / BLE (what it is, why we use it, and how it works), and practical knowledges to build apps for hardware products (how to design the apps, how to test without actual hardware prototypes, troubleshooting tips, and how the apps can be reviewed by Apple) which I learned through actual IoT/Wearable projects.

This would be interesting & understandable even if you are not familiar with or have no interests in Core Bluetooth because of the actual examples.

Bio: Shuichi is an iOS Freelancer who has developed many IoT related apps using Bluetooth Low Energy. He co-authored "iOS x BLE Core Bluetooth Programming" (2015) and authored "iOS Programming - Advanced 100 Recipes" (2013). He is the owner of popular OSS repositories such as iOS-9-Sampler, AnimatedTransitionGallery, and many more, ultimately totaling 15,000 stars.
Twitter: https://twitter.com/shu223

Realm

June 16, 2016
Tweet

More Decks by Realm

Other Decks in Technology

Transcript

  1. • Low energy • NOT compatible with Classic BT •

    Uses 2.4 GHz radio frequencies • Marketed by the Bluetooth SIG
  2. • Low energy • NOT compatible with Classic BT •

    Uses 2.4 GHz radio frequencies • Marketed by the Bluetooth SIG • etc…
  3. • Low energy • NOT compatible with Classic BT •

    Uses 2.4 GHz radio frequencies • Marketed by the Bluetooth SIG • etc…
  4. The API ‘Core Bluetooth’ is open for developers • API

    for Classic BT is NOT open. - Requires MFi certification.
  5. BLE is almost the ONLY way to enable iOS apps

    to communicate with external hardware without infrastructure or MFi.
  6. Moff Band Moff App Sensor Data BLE Connection Sensors -

    Gyroscope - Accelerometer Analyze sensor data
  7. Moff Band Moff App Sensor Data BLE Connection Sensors -

    Gyroscope - Accelerometer Analyze sensor data Recognize - Gesture - Posture
  8. Moff Band Moff App Sensor Data BLE Connection Sensors -

    Gyroscope - Accelerometer Analyze sensor data Recognize - Gesture - Posture Play sounds
  9. Scan Step 1. Scan Advertise : Search for nearby BLE

    devices centralManager.scanForPeripheralsWithServices(nil, options: nil)
  10. Scan Step 1. Scan Advertise Discover : Search for nearby

    BLE devices func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber!) { print(“Discovered a BLE device!”) }
  11. Scan Step 1. Scan Advertise Discover : Search for nearby

    BLE devices func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber!) { print(“Discovered a BLE device!”) } Central
  12. Scan Step 1. Scan Advertise Discover : Search for nearby

    BLE devices func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber!) { print(“Discovered a BLE device!”) } Peripheral Central
  13. Moff Service xx Service Step 3. Subscribe: Ready to receive

    data GATT = Generic Attribute Profile
  14. Moff Service xx Service Button Characteristic xx Characteristic Sensor Characteristic

    Step 3. Subscribe: Ready to receive data GATT = Generic Attribute Profile
  15. Moff Service xx Service Button Characteristic xx Characteristic Sensor Characteristic

    Subscribe (Request to be notified) Step 3. Subscribe: Ready to receive data GATT = Generic Attribute Profile
  16. Moff Service xx Service Button Characteristic xx Characteristic Sensor Characteristic

    Subscribe (Request to be notified) Step 3. Subscribe: Ready to receive data GATT = Generic Attribute Profile peripheral.setNotifyValue(true, forCharacteristic: c)
  17. Step 4. Notify Notify subscribers Moff Service Sensor Characteristic xxxx

    Characteristic Update the value func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { print(“Received sensor data!”) }
  18. Step 4. Notify Notify subscribers Moff Service Sensor Characteristic xxxx

    Characteristic Update the value func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { print(“Received sensor data!”) }
  19. BLE

  20. Group conversation system with VoIP - Detects the human voice

    - Cuts out all background noise → Can be used even in areas with poor coverage!
  21. GATT to send sensor data Foo Service Sensor Data Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Bar Service xx Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: acc x, acc y, acc z, gyro x, gyro y, gyro z (2bytes for each) xx Characteristic
  22. GATT to send sensor data Foo Service Sensor Data Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Bar Service xx Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: acc x, acc y, acc z, gyro x, gyro y, gyro z (2bytes for each) xx Characteristic
  23. GATT to send sensor data Foo Service Sensor Data Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Bar Service xx Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: acc x, acc y, acc z, gyro x, gyro y, gyro z (2bytes for each) xx Characteristic
  24. GATT to send sensor data Foo Service Sensor Data Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Bar Service xx Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: acc x, acc y, acc z, gyro x, gyro y, gyro z (2bytes for each) xx Characteristic
  25. GATT to send sensor data Foo Service Sensor Data Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Bar Service xx Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: acc x, acc y, acc z, gyro x, gyro y, gyro z (2bytes for each) xx Characteristic
  26. GATT to send sensor data Foo Service Sensor Data Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Bar Service xx Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: acc x, acc y, acc z, gyro x, gyro y, gyro z (2bytes for each) xx Characteristic
  27. GATT to send button interactions Foo Service Button Control Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: 0x01 or 0x00
  28. GATT to send button interactions Foo Service Button Control Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: 0x01 or 0x00
  29. GATT to send button interactions Foo Service Button Control Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: 0x01 or 0x00
  30. GATT to send button interactions Foo Service Button Control Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: 0x01 or 0x00 Button interactions
  31. GATT to send button interactions Foo Service Button Control Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: 0x01 or 0x00 Button interactions
  32. GATT to send button interactions Foo Service Button Control Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: 0x01 or 0x00 Button interactions
  33. GATT to send button interactions Foo Service Button Control Characteristic

    UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Notify Value: 0x01 or 0x00 Button interactions Y1VTIFE Y3FMFBTFE
  34. GATT for remote control Foo Service Remote Control Characteristic UUID:

    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Write Value: Horizontal (-100 ~ 100), Vertical (-100 ~ 100)
  35. GATT for remote control Foo Service Remote Control Characteristic UUID:

    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Write Value: Horizontal (-100 ~ 100), Vertical (-100 ~ 100)
  36. GATT for remote control Foo Service Remote Control Characteristic UUID:

    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Write Value: Horizontal (-100 ~ 100), Vertical (-100 ~ 100) values
  37. GATT for remote control Foo Service Remote Control Characteristic UUID:

    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Write Value: Horizontal (-100 ~ 100), Vertical (-100 ~ 100) values
  38. GATT for remote control Foo Service Remote Control Characteristic UUID:

    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties: Write Value: Horizontal (-100 ~ 100), Vertical (-100 ~ 100) values
  39. GATT for generic commands Electronic Stimulation Control Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

    Properties: Write Value: 1 byte 4 Commands: - Change the pulse frequency - Change the electric current - Right channels on/off - Left channels on/off
  40. GATT for generic commands Electronic Stimulation Control Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

    Properties: Write Value: 1 byte 4 Commands: - Change the pulse frequency - Change the electric current - Right channels on/off - Left channels on/off
  41. GATT for generic commands Electronic Stimulation Control Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

    Properties: Write Value: 1 byte High-order 2 bits - 00: Change the pulse frequency - 01: Change the electric current - 10: Left channels on/off - 11: Right channels on/off
  42. GATT for generic commands Electronic Stimulation Control Characteristic UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

    Properties: Write Value: 1 byte High-order 2 bits - 00: Change the pulse frequency - 01: Change the electric current - 10: Left channels on/off - 11: Right channels on/off
  43. How to define GATT 1. Create UUID for the service

    & characteristic $ uuidgen CEEA31BC-BEAC-4A78-B7ED-FC96B6254D4C
  44. How to define GATT 1. Create UUID for the service

    & characteristic 2. Define the properties (Read, Notify, Write, etc.) $ uuidgen CEEA31BC-BEAC-4A78-B7ED-FC96B6254D4C
  45. How to define GATT 1. Create UUID for the service

    & characteristic 2. Define the properties (Read, Notify, Write, etc.) Peripheral → Central: Notify 
 Central → Peripheral: Write $ uuidgen CEEA31BC-BEAC-4A78-B7ED-FC96B6254D4C
  46. How to define GATT 1. Create UUID for the service

    & characteristic 2. Define the properties (Read, Notify, Write, etc.) Peripheral → Central: Notify 
 Central → Peripheral: Write 3. Define the value format $ uuidgen CEEA31BC-BEAC-4A78-B7ED-FC96B6254D4C
  47. How to define GATT 1. Create UUID for the service

    & characteristic 2. Define the properties (Read, Notify, Write, etc.) Peripheral → Central: Notify 
 Central → Peripheral: Write 3. Define the value format Usually limited to 20 bytes $ uuidgen CEEA31BC-BEAC-4A78-B7ED-FC96B6254D4C
  48. Background behaviors on iOS • Very limited - Listening to

    music - Getting location data - Downloading data
  49. You would have to always keep the app in the

    foreground, while snowboarding!
  50. What functions can be used in the background? • Scanning

    peripherals • Connecting with peripherals
  51. What functions can be used in the background? • Scanning

    peripherals • Connecting with peripherals • Reading characteristics’ value
  52. What functions can be used in the background? • Scanning

    peripherals • Connecting with peripherals • Reading characteristics’ value • Writing characteristics’ value
  53. What functions can be used in the background? • Scanning

    peripherals • Connecting with peripherals • Reading characteristics’ value • Writing characteristics’ value • Receiving notifications
  54. What functions can be used in the background? • Scanning

    peripherals • Connecting with peripherals • Reading characteristics’ value • Writing characteristics’ value • Receiving notifications Almost all functions can be used even in the background!
  55. Limitations • Longer intervals for scanning • Must explicitly specify

    one or more services to scan • CBCentralManagerOptionShowPowerAlertKey option is ignored
  56. Limitations • Longer intervals for scanning • Must explicitly specify

    one or more services to scan • CBCentralManagerOptionShowPowerAlertKey option is ignored Resources - Core Bluetooth Programming Guide - Core Bluetooth Framework Reference (also in headers)
  57. State Preservation and Restoration The system takes over the BLE

    tasks even after the app is killed. - Preserves the state of the app’s central managers and continues the BLE tasks on their behalf.
  58. State Preservation and Restoration The system takes over the BLE

    tasks even after the app is killed. - Preserves the state of the app’s central managers and continues the BLE tasks on their behalf. - Relaunches the app into the background and calls the corresponding delegate method.
  59. State Preservation and Restoration The system takes over the BLE

    tasks even after the app is killed. - Preserves the state of the app’s central managers and continues the BLE tasks on their behalf. - Relaunches the app into the background and calls the corresponding delegate method. → The app can handle BLE events!
  60. • The app is killed by the system • The

    user pushes the button on the peripheral device
  61. • The app is killed by the system • The

    user pushes the button on the peripheral device • The system receives the notification
  62. • The app is killed by the system • The

    user pushes the button on the peripheral device • The system receives the notification • The app is relaunched in the BG and the delegate method is called.
  63. func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { print(“Received

    the characteristic data!”) } • The app is killed by the system • The user pushes the button on the peripheral device • The system receives the notification • The app is relaunched in the BG and the delegate method is called.
  64. func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { print(“Received

    the characteristic data!”) } • The app is killed by the system • The user pushes the button on the peripheral device • The system receives the notification • The app is relaunched in the BG and the delegate method is called. The app can process the button interaction!
  65. Implementation • Add an option when initializing the CBCentralManager object.

    let options = [ CBCentralManagerOptionRestoreIdentifierKey: "somekey" ] centralManager = CBCentralManager( delegate: self, queue: queue, options: options)
  66. Implementation • Implement the delegate method which is called when

    the app is restored. func centralManager(central: CBCentralManager, willRestoreState dict: [String : AnyObject]) { print("Restored") }
  67. Testing the restoration • Kill the app as if it

    was killed by the iOS kill(getpid(), SIGKILL);
  68. Did the HW prototypes exist when develop the apps? Projects

    HW prototypes existed? Moff YES WHILL NO BONX NO SmartDrive YES PLEN2 NO Music for the Deaf NO
  69. Emulator App • Develop another iOS app as the alternative

    to the peripheral device • Use CBPeripheralManager
  70. Emulator App • Develop another iOS app as the alternative

    to the peripheral device • Use CBPeripheralManager • Easier for iOS engineers
  71. =

  72. • Connection dropped • Can’t discover services or characteristics •

    Fail to write • Incorrect characteristic values
  73. • Connection dropped • Can’t discover services or characteristics •

    Fail to write • Incorrect characteristic values • Incorrect behaviors in the background
  74. • Connection dropped • Can’t discover services or characteristics •

    Fail to write • Incorrect characteristic values • Incorrect behaviors in the background • etc…
  75. Identify which side the problem is on Is the problem

    on the central side or on the peripheral side? → Compare with another iOS app like ‘LightBlue’
  76. Can’t find the peripheral • Scanning, but can’t find the

    peripheral device Scan but ‘didDiscover’ method isn’t called
  77. func centralManager( central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String :

    AnyObject], RSSI: NSNumber!) { print(advertisementData) } Filtered by iOS! → Can’t see all of the advertisement data
  78. func centralManager( central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String :

    AnyObject], RSSI: NSNumber!) { print(advertisementData) } Filtered by iOS! → Can’t see all of the advertisement data e.g. Can’t see the ‘Manufacture Data’ field of iBeacon
  79. Videos for review • Show how the app works with

    the peripheral device • Not need to be cool!
  80. Recap • What is Bluetooth Low Energy? • Basics of

    Core Bluetooth with an actual product
  81. Recap • What is Bluetooth Low Energy? • Basics of

    Core Bluetooth with an actual product • Practical Core Bluetooth with specific examples
  82. Recap • What is Bluetooth Low Energy? • Basics of

    Core Bluetooth with an actual product • Practical Core Bluetooth with specific examples - Defining GATT
  83. Recap • What is Bluetooth Low Energy? • Basics of

    Core Bluetooth with an actual product • Practical Core Bluetooth with specific examples - Defining GATT - Defining background behaviors
  84. Recap • What is Bluetooth Low Energy? • Basics of

    Core Bluetooth with an actual product • Practical Core Bluetooth with specific examples - Defining GATT - Defining background behaviors - Testing without HW prototypes
  85. Recap • What is Bluetooth Low Energy? • Basics of

    Core Bluetooth with an actual product • Practical Core Bluetooth with specific examples - Defining GATT - Defining background behaviors - Testing without HW prototypes - Troubleshooting
  86. Recap • What is Bluetooth Low Energy? • Basics of

    Core Bluetooth with an actual product • Practical Core Bluetooth with specific examples - Defining GATT - Defining background behaviors - Testing without HW prototypes - Troubleshooting - App Review
  87. private let centralManager = CBCentralManager() override func viewDidLoad() { super.viewDidLoad()

    centralManager.delegate = self } private var centralManager: CBCentralManager! override func viewDidLoad() { super.viewDidLoad() centralManager = CBCentralManager(delegate: self, queue: nil) } From To
  88. Thank you! Shuichi Tsutsumi - iOS Freelancer • Twitter: @shu223

    • GitHub: shu223 • Blog: https://medium.com/@shu223/ • Email: [email protected]