SlideShare a Scribd company logo
TODAY'S ADVENTURE
> Wearables & My Story
> Coding with BLE on iOS
> The importance of protocols
> Connection stability
> Testing with wearables
> Logging & monitoring
> Remote maintenance
> The End
WEARABLES
TODAY A WEARABLE WILL BE
> A piece of HW that sits somewhere on your body
> Easy to carry with you
> Provides useful data via sensors
> Uses BLE for data exchange with the outside world
> In need of an app to communicate with
> Custom: you know / have power on the internals
IOTMAYBE JUST A
SPECIAL CASE
WEARABLES
&
ME
BLE & IOS
CORE BLUETOOTH
The framework is an abstraction of the Bluetooth 4.0
specification for use with low energy devices. That said,
it hides many of the low-level details of the specification
from you, the developer, making it much easier for you to
develop apps that interact with Bluetooth low energy
devices.
— Apple Docs
CORE BORING!
!
PERIPHERAL
> Has data
> Advertises its presence
> It's our wearable
> CBPeripheral
PERIPHERAL
> It exposes services
> Services contain characteristics
> Characteristics allow data exchange
> You can define your own
CENTRAL
> Wants data
> Scans for advertising peripherals
> Connects to peripherals
> Explores services and characteristics
> Reads, writes, is notified by characteristics
> It's (part of) our app
> CBCentralManager
THE
BLUETOOTH
DANCE
1 - THE DANCE FLOOR
SCANNING
let central = CBCentralManager(delegate: self, queue: nil)
let serviceUUID = CBUUID(string: "ABC00001-A0B1-FFFF-1234-1A2B3DD11001")
// Set the delegate (someDelegate: CBCentralManagerDelegate)
central.delegate = someDelegate
// Start Scanning
central.scanForPeripherals(withServices: [serviceUUID], options: nil)
2 - POTENTIAL PARTNERS
DISCOVERY
var peripheral: CBPeripheral?
// CBCentralManagerDelegate discovery handler
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any], rssi RSSI: NSNumber) {
if thisIsMy(peripheral) { // Check before connecting
central.stopScan() // Please do!
self.peripheral = peripheral // Keep a strong ref!
// Step 3 here
}
}
3 - WANNA DANCE?
CONNECTION
// central: CBCentralManager
// peripheral: CBPeripheral
central.connect(peripheral, options: nil)
FAILURE HANDLER
// CBCentralManagerDelegate method
func centralManager(_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?) {
// Recovery
// Notify users
// ...
// Give up? !
}
CONNECTION HANDLER
// CBCentralManagerDelegate method
func centralManager(_ central: CBCentralManager,
didConnect peripheral: CBPeripheral) {
// Start dancing!
// !"
}
UNENCRYPTED CHARACTERISTICS
No BLE encryption on the device side
> You can interface with the device immediately
> It will go back to advertising mode when disconnected
from the app
> It will need a new scan to be found (or a direct
connection via UUID)
ENCRYPTED
CHARACTERISTICS
Manual interaction required
ENCRYPTED
CHARACTERISTICS
Saves pairing at the OS level
(see Bluetooth settings)
ENCRYPTED CHARACTERISTICS
> The device reconnects automatically to iOS
> You'll need to retrieve it from known peripherals:
let peripherals = central
.retrieveConnectedPeripherals(withServices: [serviceUUID])
ENCRYPTED CHARACTERISTICS
The pairing can be "delicate":
> You can't retrieve the device anymore
> You can't connect to the retrieved device
> You can't exchange data with the device
You can't solve this with code:
> Soft solution: kill your app, forget device
> Hard solution: restart your phone
AFTER CONNECTING
peripheral.discoverServices([serviceUUID])
peripheral.discoverCharacteristics([charUUID], for: service)
peripheral.setNotifyValue(true, for: characteristic)
// In your CBPeripheralDelegate
func peripheral(_ peripheral: CBPeripheral,
didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
if let data = characteristic.value { // data: Data
// Enjoy your data! !
}
}
WHAT NOW?
THOU SHALT HAVE A SHARED PROTOCOL
> Available services and characteristics
> Commands and command format
> Response format (how to parse bytes)
PROTOCOL EXAMPLE
// Command Characteristic
let charUUID = CBUUID(string: "ABC00001-A0B1-FFFF-1234-1A2B3DD11002")
let char: CBCharacteristic // We have already discovered this
// Available Commands
enum CommandId: UInt8 {
case test // 0
case readTemp // 1
case writeTemp // 2
}
// Issuing the Read Temperature command
let readTempData = Data(bytes: [CommandId.readTemp.rawValue])
peripheral.writeValue(readTempData, for: char, type: .withResponse)
PARSING THE RESPONSE
PARSING THE RESPONSE
// Inside didUpdateValueForCharacteristic handler
const uint8_t *data = (uint8_t *)[characteristic.value bytes];
uint8_t packetID = data[0];
if (packetID == TEMP_RESPONSE_ID) { // ID for the temperature response packet
uint32_t timestamp;
memcpy(&timestamp, &data[1], 4);
int8_t temperature;
memcpy(&temperature, &data[5], 1);
// Work with temp value & timestamp
}
OBJ-C? !
MESSING WITH THE PROTOCOL?
// V1
enum CommandId: UInt8 {
case test // 0
case readTemp // 1
case writeTemp // 2
}
// V2
enum CommandId: UInt8 {
case test // 0
case reset // 1 <=== NEW COMMAND HERE! !
case readTemp // 2
case writeTemp // 3
}
DEVICE RESET!
RECAP
> We know how to discover our custom wearable
> We know how to connect and pair it with iOS
> We know how to subscribe to its characteristics
> We know how to parse device data
> WE KNOW HOW TO DANCE! !"
CONNECTION STABILITY
CONNECTION STABILITY
> Your wearable device measures critical data
> It needs to be always connected
> The background is a completely different story:
For iOS apps, it is crucial to know whether your app is
running in the foreground or the background. An app must
behave differently in the background than in the foreground,
because system resources are more limited on iOS devices
BACKGROUND MODE
STATE PRESERVATION AND RESTORATION
let queue = DispatchQueue(label: "mySerialDispatchQueue")
let options = [CBCentralManagerOptionRestoreIdentifierKey:
"myCentralManagerIdentifier"]
let centralManager = CBCentralManager(delegate: self,
queue: queue,
options: options)
AS A RESULT...
> Your app will continue working in the background
> If your app is suspended, the system will track:
> the services it was scanning for
> the peripherals it was connected / connecting to
> the characteristics it was subscribed to
> Related BLE events will make the system relaunch your
app in the background
ERROR #1
ASSUMING APP RELAUNCH WILL ALWAYS WORK
If the users kills your app, there's no coming back from it
SOLUTION
✅ Let your users know
ERROR #2
ASSUMING THE BACKGROUND WILL JUST WORK
If the BLE connection is dropped in the background and the app gets suspended, it
won't be relaunched
SOLUTION
✅ Try to reconnect immediately
✅ If you need to do some processing, start a background task
UIApplication.shared
.beginBackgroundTask(expirationHandler: (() -> Void)?)
ERROR #3
ASSUMING YOU HAVE INFINITE TIME
"10 second" rule: each BLE event renews your background time for about 10
seconds.
SOLUTION
✅ Have your wearable ping your app more often than every 10 seconds
✅ Start a background task if you miss a packet
ERROR #4
TRUSTING IOS CHANGELOGS
iOS updates break the Bluetooth in subtle ways
SOLUTION
✅ TEST, TEST, TEST each iOS release
TESTING WITH
WEARABLES
BASIC TESTING
> Write your unit tests
> Do your TDD
> Automate your tests
> Maybe add some UI testing
> Use continuous integration
> Involve your QA engineer colleagues
...WITH WEARABLES?
> Focus on full system integration
> Involve all the components
> Track exactly what you're testing: HW revision, FW
version, OS, ...
> Have clearly defined test scenarios and store test
reports
> Sadly, the simulator won't work here
THE HUMAN SIMULATOR
YOU'RE NOT ALONE IN THIS
Make sure these people are your best friends:
> FW developer: custom FW, insight about the device...
> QA engineer: test scenarios, collecting reports...
> Your colleagues: will run around with you !
SAMPLE TEST SCENARIO
> Custom FW that simulates disconnections
> Move around the room, app in foreground, see what
happens
> Send the app to the background, see if it dies on you or
if it recovers the connection
> Check what happened (HW + SW)
> Repeat this on every FW / App / OS update!
LOGGING AND MONITORING
> NEVER forget about logging
> Remote logging (in the cloud)
> Via the app (no internet access on device)
> Session reconstruction from start to finish
A CASE SOLVED BY
LOGGING
REMOTE MAINTENANCE
REMOTE COMMANDS
// Note: this is only a partial implementation
enum RemoteCommandId: Int {
case ping = 0
case checkStatus = 1
case resetDevice = 2
// ...
}
REMOTE COMMANDS
struct RemoteCommand {
let id: RemoteCommandId
let delay: Int
let params: [String: Any]?
// ...
}
REMOTE COMMANDS
struct RemoteCommand {
// ...
static func parseRemoteCommand(userInfo: [AnyHashable : Any])
-> (Bool, RemoteCommand?) {
if let cmdIdInt = userInfo["command"] as? Int,
let cmdId = RemoteCommandId(rawValue: cmdIdInt) {
let delay = (userInfo["delay"] as? Int) ?? 0
let params = userInfo["parameters"] as? [String: Any]
let cmd = RemoteCommand(id: cmdId, delay: delay, params: params)
return (true, cmd)
}
return (false, nil)
}
SILENT NOTIFICATIONS
{
"aps" : {
"content-available" : 1
},
"command" : 1, // Check Status
"delay" : 0 // Now,
"parameters": [
// Your custom parameters
]
}
RECEIVING AND PARSING
let executor = RemoteExecutor()
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler:
@escaping (UIBackgroundFetchResult) -> Void) {
// Check if this is a remote command
let (isCommand, command) = RemoteCommand.parseRemoteCommand(userInfo: userInfo)
if isCommand {
executor.run(command: command)
}
completionHandler(.noData)
}
EXECUTING
// Note: this is only a partial implementation
class RemoteExecutor {
let peripheral: CBPeripheral
let char: CBCharacteristic
func run(command: RemoteCommand) {
switch command.id {
case .checkStatus:
// Turn command into Data
let cmdData = Data(bytes: [CommandId.checkStatus.rawValue])
peripheral.writeValue(cmdData, for: char, type: .withResponse)
default:
break
}
}
}
RECAP
> Know your BLE basics
> Use encrypted chars, but know that the iOS BLE stack can get stuck
> Don't be afraid to resort to ObjC
> Keep your connection stable, especially in the background
> Always test at the system-integration level
> Don't trust iOS updates
> Flood the cloud with logs
> Implement remote maintenance
THANK YOU!
ALBERTO GUARINO
@albeguarino

More Related Content

Similar to Alberto Guarino "When iPhones and Wearables Dance the Bluetooth Dance: Lessons Learned"

Parrot Drones Hijacking
Parrot Drones HijackingParrot Drones Hijacking
Parrot Drones Hijacking
Priyanka Aash
 
Itsp documentation quadcopter flight controller based on kalman filters
Itsp documentation   quadcopter flight controller based on kalman filtersItsp documentation   quadcopter flight controller based on kalman filters
Itsp documentation quadcopter flight controller based on kalman filters
Jyotirmaya Mahanta
 
Fault tolerance techniques tsp
Fault tolerance techniques tspFault tolerance techniques tsp
Fault tolerance techniques tsp
Pradeep Kumar TS
 
iOS Bluetooth Low Energy (BLE) Remote Robot Interface
iOS Bluetooth Low Energy (BLE) Remote Robot InterfaceiOS Bluetooth Low Energy (BLE) Remote Robot Interface
iOS Bluetooth Low Energy (BLE) Remote Robot Interface
Steve Knodl
 
Synack Shakacon OSX Malware Persistence
Synack Shakacon OSX Malware PersistenceSynack Shakacon OSX Malware Persistence
Synack Shakacon OSX Malware Persistence
Ivan Einstein
 
Smart homes using android
Smart homes using androidSmart homes using android
Smart homes using android
Droidcon Berlin
 
Taming event-driven software via formal verification
Taming event-driven software via formal verificationTaming event-driven software via formal verification
Taming event-driven software via formal verification
AdaCore
 
DEFCON 18- These Aren't the Permissions You're Looking For
DEFCON 18- These Aren't the Permissions You're Looking ForDEFCON 18- These Aren't the Permissions You're Looking For
DEFCON 18- These Aren't the Permissions You're Looking For
Michael Scovetta
 
Embedded software development using BDD
Embedded software development using BDDEmbedded software development using BDD
Embedded software development using BDD
Itamar Hassin
 
Android app (Presentation v2)
Android app (Presentation v2)Android app (Presentation v2)
Android app (Presentation v2)
Dhruv Parmar
 
Droidcon Turin 2015 - Android wear sdk introduction
Droidcon Turin 2015 - Android wear sdk introductionDroidcon Turin 2015 - Android wear sdk introduction
Droidcon Turin 2015 - Android wear sdk introduction
Michelantonio Trizio
 
Android wear SDK introduction
Android wear SDK introductionAndroid wear SDK introduction
Android wear SDK introduction
Tiziano Basile
 
A Computer Based Artificial Neural Network Controller with Interactive Audito...
A Computer Based Artificial Neural Network Controller with Interactive Audito...A Computer Based Artificial Neural Network Controller with Interactive Audito...
A Computer Based Artificial Neural Network Controller with Interactive Audito...
theijes
 
Backtrack Manual Part4
Backtrack Manual Part4Backtrack Manual Part4
Backtrack Manual Part4
Nutan Kumar Panda
 
WPSDK 7.1.1
WPSDK 7.1.1WPSDK 7.1.1
WPSDK 7.1.1
Matt Lacey
 
Configuring ee (enterprise extender) between two ibm system i systems tech ...
Configuring ee (enterprise extender) between two ibm system i systems   tech ...Configuring ee (enterprise extender) between two ibm system i systems   tech ...
Configuring ee (enterprise extender) between two ibm system i systems tech ...
jbharo
 
Positive Hack Days. Pavlov. Network Infrastructure Security Assessment
Positive Hack Days. Pavlov. Network Infrastructure Security AssessmentPositive Hack Days. Pavlov. Network Infrastructure Security Assessment
Positive Hack Days. Pavlov. Network Infrastructure Security Assessment
Positive Hack Days
 
Penetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utilityPenetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utility
IOSR Journals
 
11 background tasks and multitasking
11   background tasks and multitasking11   background tasks and multitasking
11 background tasks and multitasking
WindowsPhoneRocks
 
IoT: Internet of Things with Python
IoT: Internet of Things with PythonIoT: Internet of Things with Python
IoT: Internet of Things with Python
Lelio Campanile
 

Similar to Alberto Guarino "When iPhones and Wearables Dance the Bluetooth Dance: Lessons Learned" (20)

Parrot Drones Hijacking
Parrot Drones HijackingParrot Drones Hijacking
Parrot Drones Hijacking
 
Itsp documentation quadcopter flight controller based on kalman filters
Itsp documentation   quadcopter flight controller based on kalman filtersItsp documentation   quadcopter flight controller based on kalman filters
Itsp documentation quadcopter flight controller based on kalman filters
 
Fault tolerance techniques tsp
Fault tolerance techniques tspFault tolerance techniques tsp
Fault tolerance techniques tsp
 
iOS Bluetooth Low Energy (BLE) Remote Robot Interface
iOS Bluetooth Low Energy (BLE) Remote Robot InterfaceiOS Bluetooth Low Energy (BLE) Remote Robot Interface
iOS Bluetooth Low Energy (BLE) Remote Robot Interface
 
Synack Shakacon OSX Malware Persistence
Synack Shakacon OSX Malware PersistenceSynack Shakacon OSX Malware Persistence
Synack Shakacon OSX Malware Persistence
 
Smart homes using android
Smart homes using androidSmart homes using android
Smart homes using android
 
Taming event-driven software via formal verification
Taming event-driven software via formal verificationTaming event-driven software via formal verification
Taming event-driven software via formal verification
 
DEFCON 18- These Aren't the Permissions You're Looking For
DEFCON 18- These Aren't the Permissions You're Looking ForDEFCON 18- These Aren't the Permissions You're Looking For
DEFCON 18- These Aren't the Permissions You're Looking For
 
Embedded software development using BDD
Embedded software development using BDDEmbedded software development using BDD
Embedded software development using BDD
 
Android app (Presentation v2)
Android app (Presentation v2)Android app (Presentation v2)
Android app (Presentation v2)
 
Droidcon Turin 2015 - Android wear sdk introduction
Droidcon Turin 2015 - Android wear sdk introductionDroidcon Turin 2015 - Android wear sdk introduction
Droidcon Turin 2015 - Android wear sdk introduction
 
Android wear SDK introduction
Android wear SDK introductionAndroid wear SDK introduction
Android wear SDK introduction
 
A Computer Based Artificial Neural Network Controller with Interactive Audito...
A Computer Based Artificial Neural Network Controller with Interactive Audito...A Computer Based Artificial Neural Network Controller with Interactive Audito...
A Computer Based Artificial Neural Network Controller with Interactive Audito...
 
Backtrack Manual Part4
Backtrack Manual Part4Backtrack Manual Part4
Backtrack Manual Part4
 
WPSDK 7.1.1
WPSDK 7.1.1WPSDK 7.1.1
WPSDK 7.1.1
 
Configuring ee (enterprise extender) between two ibm system i systems tech ...
Configuring ee (enterprise extender) between two ibm system i systems   tech ...Configuring ee (enterprise extender) between two ibm system i systems   tech ...
Configuring ee (enterprise extender) between two ibm system i systems tech ...
 
Positive Hack Days. Pavlov. Network Infrastructure Security Assessment
Positive Hack Days. Pavlov. Network Infrastructure Security AssessmentPositive Hack Days. Pavlov. Network Infrastructure Security Assessment
Positive Hack Days. Pavlov. Network Infrastructure Security Assessment
 
Penetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utilityPenetrating Windows 8 with syringe utility
Penetrating Windows 8 with syringe utility
 
11 background tasks and multitasking
11   background tasks and multitasking11   background tasks and multitasking
11 background tasks and multitasking
 
IoT: Internet of Things with Python
IoT: Internet of Things with PythonIoT: Internet of Things with Python
IoT: Internet of Things with Python
 

More from IT Event

Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...
Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...
Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...
IT Event
 
Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"
Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"
Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"
IT Event
 
Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...
IT Event
 
Roman Romanovsky, Sergey Rak - "JavaScript в IoT "
Roman Romanovsky, Sergey Rak - "JavaScript в IoT "Roman Romanovsky, Sergey Rak - "JavaScript в IoT "
Roman Romanovsky, Sergey Rak - "JavaScript в IoT "
IT Event
 
Konstantin Krivlenia - "Continuous integration for frontend"
Konstantin Krivlenia - "Continuous integration for frontend"Konstantin Krivlenia - "Continuous integration for frontend"
Konstantin Krivlenia - "Continuous integration for frontend"
IT Event
 
Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"
Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"
Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"
IT Event
 
Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"
Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"
Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"
IT Event
 
Vladimir Grinenko - "Dependencies in component web done right"
Vladimir Grinenko - "Dependencies in component web done right"Vladimir Grinenko - "Dependencies in component web done right"
Vladimir Grinenko - "Dependencies in component web done right"
IT Event
 
Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"
IT Event
 
Aleksey Bogachuk - "Offline Second"
Aleksey Bogachuk - "Offline Second"Aleksey Bogachuk - "Offline Second"
Aleksey Bogachuk - "Offline Second"
IT Event
 
James Allardice - "Building a better login with the credential management API"
James Allardice - "Building a better login with the credential management API"James Allardice - "Building a better login with the credential management API"
James Allardice - "Building a better login with the credential management API"
IT Event
 
Fedor Skuratov "Dark Social: as messengers change the market of social media ...
Fedor Skuratov "Dark Social: as messengers change the market of social media ...Fedor Skuratov "Dark Social: as messengers change the market of social media ...
Fedor Skuratov "Dark Social: as messengers change the market of social media ...
IT Event
 
Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"
Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"
Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"
IT Event
 
Алексей Рагозин "Java и linux борьба за микросекунды"
Алексей Рагозин "Java и linux борьба за микросекунды"Алексей Рагозин "Java и linux борьба за микросекунды"
Алексей Рагозин "Java и linux борьба за микросекунды"
IT Event
 
Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"
Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"
Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"
IT Event
 
Наш ответ Uber’у
Наш ответ Uber’уНаш ответ Uber’у
Наш ответ Uber’у
IT Event
 
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
IT Event
 
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
Leonid Vasilyev  "Building, deploying and running production code at Dropbox"Leonid Vasilyev  "Building, deploying and running production code at Dropbox"
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
IT Event
 
Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...
Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...
Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...
IT Event
 
Mete Atamel "Resilient microservices with kubernetes"
Mete Atamel "Resilient microservices with kubernetes"Mete Atamel "Resilient microservices with kubernetes"
Mete Atamel "Resilient microservices with kubernetes"
IT Event
 

More from IT Event (20)

Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...
Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...
Denis Radin - "Applying NASA coding guidelines to JavaScript or airspace is c...
 
Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"
Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"
Sara Harkousse - "Web Components: It's all rainbows and unicorns! Is it?"
 
Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...
 
Roman Romanovsky, Sergey Rak - "JavaScript в IoT "
Roman Romanovsky, Sergey Rak - "JavaScript в IoT "Roman Romanovsky, Sergey Rak - "JavaScript в IoT "
Roman Romanovsky, Sergey Rak - "JavaScript в IoT "
 
Konstantin Krivlenia - "Continuous integration for frontend"
Konstantin Krivlenia - "Continuous integration for frontend"Konstantin Krivlenia - "Continuous integration for frontend"
Konstantin Krivlenia - "Continuous integration for frontend"
 
Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"
Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"
Illya Klymov - "Vue.JS: What did I swap React for in 2017 and why?"
 
Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"
Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"
Evgeny Gusev - "A circular firing squad: How technologies drag frontend down"
 
Vladimir Grinenko - "Dependencies in component web done right"
Vladimir Grinenko - "Dependencies in component web done right"Vladimir Grinenko - "Dependencies in component web done right"
Vladimir Grinenko - "Dependencies in component web done right"
 
Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"
 
Aleksey Bogachuk - "Offline Second"
Aleksey Bogachuk - "Offline Second"Aleksey Bogachuk - "Offline Second"
Aleksey Bogachuk - "Offline Second"
 
James Allardice - "Building a better login with the credential management API"
James Allardice - "Building a better login with the credential management API"James Allardice - "Building a better login with the credential management API"
James Allardice - "Building a better login with the credential management API"
 
Fedor Skuratov "Dark Social: as messengers change the market of social media ...
Fedor Skuratov "Dark Social: as messengers change the market of social media ...Fedor Skuratov "Dark Social: as messengers change the market of social media ...
Fedor Skuratov "Dark Social: as messengers change the market of social media ...
 
Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"
Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"
Андрей Зайчиков "Архитектура распределенных кластеров NoSQL на AWS"
 
Алексей Рагозин "Java и linux борьба за микросекунды"
Алексей Рагозин "Java и linux борьба за микросекунды"Алексей Рагозин "Java и linux борьба за микросекунды"
Алексей Рагозин "Java и linux борьба за микросекунды"
 
Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"
Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"
Volodymyr Lyubinets "Introduction to big data processing with Apache Spark"
 
Наш ответ Uber’у
Наш ответ Uber’уНаш ответ Uber’у
Наш ответ Uber’у
 
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
 
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
Leonid Vasilyev  "Building, deploying and running production code at Dropbox"Leonid Vasilyev  "Building, deploying and running production code at Dropbox"
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
 
Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...
Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...
Анатолий Пласковский "Миллионы карточных платежей за месяц, или как потерять ...
 
Mete Atamel "Resilient microservices with kubernetes"
Mete Atamel "Resilient microservices with kubernetes"Mete Atamel "Resilient microservices with kubernetes"
Mete Atamel "Resilient microservices with kubernetes"
 

Recently uploaded

Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Neo4j
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
Miro Wengner
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
Neo4j
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
LizaNolte
 
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Pitangent Analytics & Technology Solutions Pvt. Ltd
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
DanBrown980551
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
Edge AI and Vision Alliance
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
Hiroshi SHIBATA
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
christinelarrosa
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
Safe Software
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
ScyllaDB
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
Enterprise Knowledge
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
c5vrf27qcz
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
Jakub Marek
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
UiPathCommunity
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
Vadym Kazulkin
 

Recently uploaded (20)

Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
 
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
 

Alberto Guarino "When iPhones and Wearables Dance the Bluetooth Dance: Lessons Learned"

  • 1.
  • 2.
  • 3. TODAY'S ADVENTURE > Wearables & My Story > Coding with BLE on iOS > The importance of protocols > Connection stability > Testing with wearables > Logging & monitoring > Remote maintenance > The End
  • 5.
  • 6.
  • 7.
  • 8.
  • 9. TODAY A WEARABLE WILL BE > A piece of HW that sits somewhere on your body > Easy to carry with you > Provides useful data via sensors > Uses BLE for data exchange with the outside world > In need of an app to communicate with > Custom: you know / have power on the internals
  • 12.
  • 13.
  • 14.
  • 16. CORE BLUETOOTH The framework is an abstraction of the Bluetooth 4.0 specification for use with low energy devices. That said, it hides many of the low-level details of the specification from you, the developer, making it much easier for you to develop apps that interact with Bluetooth low energy devices. — Apple Docs
  • 18. PERIPHERAL > Has data > Advertises its presence > It's our wearable > CBPeripheral
  • 19. PERIPHERAL > It exposes services > Services contain characteristics > Characteristics allow data exchange > You can define your own
  • 20.
  • 21.
  • 22. CENTRAL > Wants data > Scans for advertising peripherals > Connects to peripherals > Explores services and characteristics > Reads, writes, is notified by characteristics > It's (part of) our app > CBCentralManager
  • 24. 1 - THE DANCE FLOOR
  • 25. SCANNING let central = CBCentralManager(delegate: self, queue: nil) let serviceUUID = CBUUID(string: "ABC00001-A0B1-FFFF-1234-1A2B3DD11001") // Set the delegate (someDelegate: CBCentralManagerDelegate) central.delegate = someDelegate // Start Scanning central.scanForPeripherals(withServices: [serviceUUID], options: nil)
  • 26. 2 - POTENTIAL PARTNERS
  • 27. DISCOVERY var peripheral: CBPeripheral? // CBCentralManagerDelegate discovery handler func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if thisIsMy(peripheral) { // Check before connecting central.stopScan() // Please do! self.peripheral = peripheral // Keep a strong ref! // Step 3 here } }
  • 28. 3 - WANNA DANCE?
  • 29. CONNECTION // central: CBCentralManager // peripheral: CBPeripheral central.connect(peripheral, options: nil)
  • 30.
  • 31. FAILURE HANDLER // CBCentralManagerDelegate method func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { // Recovery // Notify users // ... // Give up? ! }
  • 32.
  • 33. CONNECTION HANDLER // CBCentralManagerDelegate method func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { // Start dancing! // !" }
  • 34. UNENCRYPTED CHARACTERISTICS No BLE encryption on the device side > You can interface with the device immediately > It will go back to advertising mode when disconnected from the app > It will need a new scan to be found (or a direct connection via UUID)
  • 36. ENCRYPTED CHARACTERISTICS Saves pairing at the OS level (see Bluetooth settings)
  • 37. ENCRYPTED CHARACTERISTICS > The device reconnects automatically to iOS > You'll need to retrieve it from known peripherals: let peripherals = central .retrieveConnectedPeripherals(withServices: [serviceUUID])
  • 38. ENCRYPTED CHARACTERISTICS The pairing can be "delicate": > You can't retrieve the device anymore > You can't connect to the retrieved device > You can't exchange data with the device You can't solve this with code: > Soft solution: kill your app, forget device > Hard solution: restart your phone
  • 39. AFTER CONNECTING peripheral.discoverServices([serviceUUID]) peripheral.discoverCharacteristics([charUUID], for: service) peripheral.setNotifyValue(true, for: characteristic) // In your CBPeripheralDelegate func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { if let data = characteristic.value { // data: Data // Enjoy your data! ! } }
  • 41. THOU SHALT HAVE A SHARED PROTOCOL > Available services and characteristics > Commands and command format > Response format (how to parse bytes)
  • 42. PROTOCOL EXAMPLE // Command Characteristic let charUUID = CBUUID(string: "ABC00001-A0B1-FFFF-1234-1A2B3DD11002") let char: CBCharacteristic // We have already discovered this // Available Commands enum CommandId: UInt8 { case test // 0 case readTemp // 1 case writeTemp // 2 } // Issuing the Read Temperature command let readTempData = Data(bytes: [CommandId.readTemp.rawValue]) peripheral.writeValue(readTempData, for: char, type: .withResponse)
  • 44. PARSING THE RESPONSE // Inside didUpdateValueForCharacteristic handler const uint8_t *data = (uint8_t *)[characteristic.value bytes]; uint8_t packetID = data[0]; if (packetID == TEMP_RESPONSE_ID) { // ID for the temperature response packet uint32_t timestamp; memcpy(&timestamp, &data[1], 4); int8_t temperature; memcpy(&temperature, &data[5], 1); // Work with temp value & timestamp }
  • 46. MESSING WITH THE PROTOCOL? // V1 enum CommandId: UInt8 { case test // 0 case readTemp // 1 case writeTemp // 2 } // V2 enum CommandId: UInt8 { case test // 0 case reset // 1 <=== NEW COMMAND HERE! ! case readTemp // 2 case writeTemp // 3 }
  • 48. RECAP > We know how to discover our custom wearable > We know how to connect and pair it with iOS > We know how to subscribe to its characteristics > We know how to parse device data > WE KNOW HOW TO DANCE! !"
  • 50. CONNECTION STABILITY > Your wearable device measures critical data > It needs to be always connected > The background is a completely different story: For iOS apps, it is crucial to know whether your app is running in the foreground or the background. An app must behave differently in the background than in the foreground, because system resources are more limited on iOS devices
  • 52. STATE PRESERVATION AND RESTORATION let queue = DispatchQueue(label: "mySerialDispatchQueue") let options = [CBCentralManagerOptionRestoreIdentifierKey: "myCentralManagerIdentifier"] let centralManager = CBCentralManager(delegate: self, queue: queue, options: options)
  • 53. AS A RESULT... > Your app will continue working in the background > If your app is suspended, the system will track: > the services it was scanning for > the peripherals it was connected / connecting to > the characteristics it was subscribed to > Related BLE events will make the system relaunch your app in the background
  • 54. ERROR #1 ASSUMING APP RELAUNCH WILL ALWAYS WORK If the users kills your app, there's no coming back from it SOLUTION ✅ Let your users know
  • 55. ERROR #2 ASSUMING THE BACKGROUND WILL JUST WORK If the BLE connection is dropped in the background and the app gets suspended, it won't be relaunched SOLUTION ✅ Try to reconnect immediately ✅ If you need to do some processing, start a background task
  • 57. ERROR #3 ASSUMING YOU HAVE INFINITE TIME "10 second" rule: each BLE event renews your background time for about 10 seconds. SOLUTION ✅ Have your wearable ping your app more often than every 10 seconds ✅ Start a background task if you miss a packet
  • 58. ERROR #4 TRUSTING IOS CHANGELOGS iOS updates break the Bluetooth in subtle ways SOLUTION ✅ TEST, TEST, TEST each iOS release
  • 60. BASIC TESTING > Write your unit tests > Do your TDD > Automate your tests > Maybe add some UI testing > Use continuous integration > Involve your QA engineer colleagues
  • 61. ...WITH WEARABLES? > Focus on full system integration > Involve all the components > Track exactly what you're testing: HW revision, FW version, OS, ... > Have clearly defined test scenarios and store test reports > Sadly, the simulator won't work here
  • 63. YOU'RE NOT ALONE IN THIS Make sure these people are your best friends: > FW developer: custom FW, insight about the device... > QA engineer: test scenarios, collecting reports... > Your colleagues: will run around with you !
  • 64. SAMPLE TEST SCENARIO > Custom FW that simulates disconnections > Move around the room, app in foreground, see what happens > Send the app to the background, see if it dies on you or if it recovers the connection > Check what happened (HW + SW) > Repeat this on every FW / App / OS update!
  • 65. LOGGING AND MONITORING > NEVER forget about logging > Remote logging (in the cloud) > Via the app (no internet access on device) > Session reconstruction from start to finish
  • 66. A CASE SOLVED BY LOGGING
  • 68. REMOTE COMMANDS // Note: this is only a partial implementation enum RemoteCommandId: Int { case ping = 0 case checkStatus = 1 case resetDevice = 2 // ... }
  • 69. REMOTE COMMANDS struct RemoteCommand { let id: RemoteCommandId let delay: Int let params: [String: Any]? // ... }
  • 70. REMOTE COMMANDS struct RemoteCommand { // ... static func parseRemoteCommand(userInfo: [AnyHashable : Any]) -> (Bool, RemoteCommand?) { if let cmdIdInt = userInfo["command"] as? Int, let cmdId = RemoteCommandId(rawValue: cmdIdInt) { let delay = (userInfo["delay"] as? Int) ?? 0 let params = userInfo["parameters"] as? [String: Any] let cmd = RemoteCommand(id: cmdId, delay: delay, params: params) return (true, cmd) } return (false, nil) }
  • 71. SILENT NOTIFICATIONS { "aps" : { "content-available" : 1 }, "command" : 1, // Check Status "delay" : 0 // Now, "parameters": [ // Your custom parameters ] }
  • 72. RECEIVING AND PARSING let executor = RemoteExecutor() func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // Check if this is a remote command let (isCommand, command) = RemoteCommand.parseRemoteCommand(userInfo: userInfo) if isCommand { executor.run(command: command) } completionHandler(.noData) }
  • 73. EXECUTING // Note: this is only a partial implementation class RemoteExecutor { let peripheral: CBPeripheral let char: CBCharacteristic func run(command: RemoteCommand) { switch command.id { case .checkStatus: // Turn command into Data let cmdData = Data(bytes: [CommandId.checkStatus.rawValue]) peripheral.writeValue(cmdData, for: char, type: .withResponse) default: break } } }
  • 74. RECAP > Know your BLE basics > Use encrypted chars, but know that the iOS BLE stack can get stuck > Don't be afraid to resort to ObjC > Keep your connection stable, especially in the background > Always test at the system-integration level > Don't trust iOS updates > Flood the cloud with logs > Implement remote maintenance