This is Swift iOS app (built in XCode 6.1.1) is provided as an example for developers intested in the Kardia.io ecosystem. It is currently hard-coded to connect to and read data from RedBearLabs Blend Micro units that are loaded with the firmware recommended by the RedBearLabs website. We programmed these units to emit mock data that simulates a real ECG trace. This app connects the phone to the device and relays the data being emitted to the servers (node.js and python) at Kardia.io. The app also listens for and displays analysis coming back from the servers.
Clone the repo and open in XCode. Load the app onto your phone. The app will automatically connect to nearby BLE units with the appropriate service and characteristic UUIDs (see below) and begin streaming data to kardia.io. Analyzed data comes back to the app in real time. Any abnormal events (arrhythmia) will be recorded in the table view that can be accessed by swiping left or right. These events can be deleted by pulling them to the left.
The app looks for the service UUID 713D0000-503E-4C75-BA94-3148F18D941E which contains the characteristic UUID 713D0002-503E-4C75-BA94-3148F18D941E that corresponds to the data being emitted by the Arduino. These values are defined in the firmware for the Blend Micro linked on the RedBearLabs website.
Once the app connects to a BLE device (see below for a brief explanation), it registers a listener for changes in the status of the hardware's data characteristic. This data is interpreted as a float and passed to two callback functions. One adds it to a buffer of recent data points for rendering in the graph. The other emits it as a socket event. It is emitted as a JSON object with keys "amplitude" and "time" corresponding to the value received from the hardware and the ISO8601 time the socket event was emitted, respectively.
The app also listens for responses from the server, which are JSON objects that have "heartRate" (self-explanatory) and "statusCode" keys. The status code is looked up in a dictionary defined in ViewController.swift and translated into the main view as statusView.
We use the SocketIOClient library, which wraps the Objective-C library Socket Rocket. The following events are used:
We use the Swift-Linechart library to render the live ECG traces. It did not entirely meet our needs so we modified it as follows:
When the app registers a fresh abnormality, it records it in the arrhythmiaTimes global, which serves as the data source for the table view. "Fresh" in this case means an event is only recorded if the status being reported by the server changes to an abnormal event (in this case, arrhythmia) so that repeated arrhythmia events do not all get logged.
Please see the issues section of this repo.
Here is a good tutorial on connecting a BLE device to an iOS device using Swift. In brief, the app starts searching for Bluetooth peripherals that are advertising a specific service UUID. When one is found, it connects and looks for a specific characteristic UUID. If that is found, it begins listening to that data.
Any time the view needs updating, you have to run that code on the main (UI) thread. That's why you'll see blocks of code like this:
dispatch_async(dispatch_get_main_queue()) {
// UI-updating code goes here
}
Events are handled by the NSNotificationCenter - registering listeners and firing events is pretty self-explanatory. Here's a quick Swift : Javascript translation of terms:
Example:
foo.on('bar', doAThing)
becomes
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("doAThing"), name: "bar", object: nil)
Functions can have the same name as long as they have different parameters - this happens often with protocols.
Views can be created and constrained in either Main.storyboard or programmatically in code. This app uses a mixture of the two - the main view is all done in the latter style while the table view uses the former.