Practical Core Bluetooth in IoT & Wearable projects @ AltConf 2016
- 16. • Low energy
• NOT compatible with Classic BT
• Uses 2.4 GHz radio frequencies
- 17. • Low energy
• NOT compatible with Classic BT
• Uses 2.4 GHz radio frequencies
• Marketed by the Bluetooth SIG
- 18. • Low energy
• NOT compatible with Classic BT
• Uses 2.4 GHz radio frequencies
• Marketed by the Bluetooth SIG
• etc…
- 19. • Low energy
• NOT compatible with Classic BT
• Uses 2.4 GHz radio frequencies
• Marketed by the Bluetooth SIG
• etc…
- 22. The API ‘Core Bluetooth’
is open for developers
• API for Classic BT is NOT open.
- Requires MFi certification.
- 23. BLE is almost the ONLY way
to enable iOS apps to communicate
with external hardware
without infrastructure or MFi.
- 28. Moff Band Moff App
BLE Connection
Sensors
- Gyroscope
- Accelerometer
- 29. Moff Band Moff App
Sensor Data
BLE Connection
Sensors
- Gyroscope
- Accelerometer
- 30. Moff Band Moff App
Sensor Data
BLE Connection
Sensors
- Gyroscope
- Accelerometer
Analyze sensor data
- 31. Moff Band Moff App
Sensor Data
BLE Connection
Sensors
- Gyroscope
- Accelerometer
Analyze sensor data
Recognize
- Gesture
- Posture
- 32. Moff Band Moff App
Sensor Data
BLE Connection
Sensors
- Gyroscope
- Accelerometer
Analyze sensor data
Recognize
- Gesture
- Posture
Play sounds
- 41. 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!”)
}
- 42. 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
- 43. 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
- 52. Moff Service
xx Service
Button Characteristic
xx Characteristic
Sensor Characteristic
Step 3. Subscribe: Ready to receive data
GATT = Generic Attribute Profile
- 53. 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
- 54. 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)
- 58. 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!”)
}
- 59. 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!”)
}
- 77. Group conversation system with VoIP
- Detects the human voice
- Cuts out all background noise
→ Can be used even in areas with poor coverage!
- 84. Music for the Deaf
Daito Manabe/Motoi Ishibashi/Teruoka Masaki/Shuichi Tsutsumi x SOUL FAMILY
- 85. Music for the Deaf
Daito Manabe/Motoi Ishibashi/Teruoka Masaki/Shuichi Tsutsumi x SOUL FAMILY
iPhone
- 86. Music for the Deaf
Daito Manabe/Motoi Ishibashi/Teruoka Masaki/Shuichi Tsutsumi x SOUL FAMILY
Electronic Stimulation DeviceiPhone
- 87. Music for the Deaf
Daito Manabe/Motoi Ishibashi/Teruoka Masaki/Shuichi Tsutsumi x SOUL FAMILY
Commands
Electronic Stimulation DeviceiPhone
- 88. Music for the Deaf
Daito Manabe/Motoi Ishibashi/Teruoka Masaki/Shuichi Tsutsumi x SOUL FAMILY
- 91. 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
- 92. 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
- 93. 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
- 94. 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
- 95. 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
- 96. 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
- 97. 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
- 98. 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
- 99. 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
- 100. 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
- 101. 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
- 102. 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
- 103. 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
0x01: Pushed
0x00: Released
- 104. 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)
- 105. 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)
- 106. 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
- 107. 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
- 108. 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
- 110. GATT for generic commands
Electronic Stimulation Control Characteristic
UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Properties: Write
Value: 1 byte
- 111. GATT for generic commands
Electronic Stimulation Control Characteristic
UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Properties: Write
Value: 1 byte
- 112. 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
- 113. 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
- 114. 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
- 115. 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
- 117. How to define GATT
1. Create UUID for the service & characteristic
- 118. How to define GATT
1. Create UUID for the service & characteristic
$ uuidgen
CEEA31BC-BEAC-4A78-B7ED-FC96B6254D4C
- 119. 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
- 120. 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
- 121. 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
- 122. 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
- 129. You would have to always keep the app
in the foreground, while snowboarding!
- 134. What functions can be used
in the background?
• Scanning peripherals
• Connecting with peripherals
- 135. What functions can be used
in the background?
• Scanning peripherals
• Connecting with peripherals
• Reading characteristics’ value
- 136. What functions can be used
in the background?
• Scanning peripherals
• Connecting with peripherals
• Reading characteristics’ value
• Writing characteristics’ value
- 137. What functions can be used
in the background?
• Scanning peripherals
• Connecting with peripherals
• Reading characteristics’ value
• Writing characteristics’ value
• Receiving notifications
- 138. 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!
- 145. Limitations
• Longer intervals for scanning
• Must explicitly specify one or more services to scan
• CBCentralManagerOptionShowPowerAlertKey option is
ignored
- 146. 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)
- 147. If the app in the background
is killed by the system…
- 151. 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.
- 152. 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.
- 153. 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!
- 156. • The app is killed by the system
• The user pushes the button on the
peripheral device
- 157. • The app is killed by the system
• The user pushes the button on the
peripheral device
• The system receives the notification
- 158. • 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.
- 159. 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.
- 160. 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!
- 162. Implementation
• Add an option when initializing the
CBCentralManager object.
let options = [
CBCentralManagerOptionRestoreIdentifierKey: "somekey"
]
centralManager = CBCentralManager(
delegate: self,
queue: queue,
options: options)
- 163. Implementation
• Implement the delegate method which is called when
the app is restored.
func centralManager(central: CBCentralManager,
willRestoreState dict: [String : AnyObject])
{
print("Restored")
}
- 167. 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
- 182. Emulator App
• Develop another iOS app as the
alternative to the peripheral
device
• Use CBPeripheralManager
- 183. Emulator App
• Develop another iOS app as the
alternative to the peripheral
device
• Use CBPeripheralManager
• Easier for iOS engineers
- 196. • Connection dropped
• Can’t discover services or characteristics
• Fail to write
• Incorrect characteristic values
- 197. • Connection dropped
• Can’t discover services or characteristics
• Fail to write
• Incorrect characteristic values
• Incorrect behaviors in the background
- 198. • Connection dropped
• Can’t discover services or characteristics
• Fail to write
• Incorrect characteristic values
• Incorrect behaviors in the background
• etc…
- 199. 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’
- 200. Can’t find the peripheral
• Scanning, but can’t find the peripheral device
- 201. Can’t find the peripheral
• Scanning, but can’t find the peripheral device
Scan
- 202. Can’t find the peripheral
• Scanning, but can’t find the peripheral device
Scan
but ‘didDiscover’
method isn’t called
- 204. Can’t find the peripheral
• Scan with another iOS app
Scan
Discovered peripherals
- 235. Videos for review
• Show how the app works with the peripheral device
• Not need to be cool!
- 241. Recap
• What is Bluetooth Low Energy?
• Basics of Core Bluetooth with an actual product
- 242. Recap
• What is Bluetooth Low Energy?
• Basics of Core Bluetooth with an actual product
• Practical Core Bluetooth with specific examples
- 243. Recap
• What is Bluetooth Low Energy?
• Basics of Core Bluetooth with an actual product
• Practical Core Bluetooth with specific examples
- Defining GATT
- 244. 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
- 245. 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
- 246. 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
- 247. 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
- 256. private var centralManager: CBCentralManager!
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
From
- 257. 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
- 259. Thank you!
Shuichi Tsutsumi - iOS Freelancer
• Twitter: @shu223
• GitHub: shu223
• Blog: https://medium.com/@shu223/
• Email: shuichi0526@gmail.com