One of the great things about Apple Watch is the personal health information provided by its sensors. Since launch, the Apple Watch has included a heart rate monitor. The most recent Series 4 version even includes the ability to perform an Electrocardiogram (ECG) right on your wrist. Given the power of that personalized information, I thought it would be great to explore a way to share that data with other users.
Let's build an app that allows team members to share their current pulse as it's measured on Apple Watch. Imagine the ability to see a real time dashboard of the heart rate of each member of a team. For instance, in a workout class, a dashboard could provide a quick view of how intense everyone is working out.
The full source code for this app (as well as more detailed instructions on how to get things set up) is on this GitHub repository. We'll cover the high level concepts here, but feel free to download the source and give it a whirl as well. You'll need a Mac with Xcode, an iPhone, an Apple Watch and an AWS Account.
AWS IoT provides a platform to connect billions of smart devices into Amazon Web Services. It uses MQTT, a machine-to-machine protocol that was designed as a lightweight publish and subscribe (PubSub) messaging transport. The model is widely used in the IoT space and provides a simple and secure way for low profile devices to connect and send data.
For this example app, I've chosen to use AWS for MQTT, but there are several other options as well. Eclipse Mosquitto is a popular open source MQTT broker. There are also lots of open source MQTT client implementations across many different platforms that you could use. Searching the Cocoapods repository for MQTT yields several different development libraries for Apple platforms.
Developing apps for Apple Watch has evolved over the past few years. Initially, Apple Watch apps were entirely tethered to the iPhone and couldn't do much independent of a paired iPhone. However, with the latest version of WatchOS and cellular versions of the device, the watch is becoming more and more independent. WatchOS has its own SDK and exposes its own set of capabilities that is a bit more limited than iOS. The watch can connect directly to the internet to send and receive information. However, WatchOS is not as widely supported as iOS among third party libraries.
For the purposes of this app, the Apple Watch would ideally connect directly over MQTT to AWS to post the latest heart rate updates. However, I could not find a readily available MQTT library that was supported on WatchOS that could be used to connect to the AWS IoT broker. There are a couple of implementations out there, but none that yet include the ability to securely connect over TLS, which is required by AWS. The AWSIoT pod itself supports iOS but not WatchOS currently. So rather than connect from Apple Watch directly, I decided to communicate via the tethered link to iPhone and use the paired iOS app to send the data over MQTT to AWS. The Apple Watch and iPhone use a combination of Bluetooth and Wifi to communicate.
In order to access heart rate data in the Apple Watch, we need an Apple Watch app. Apple Watch apps are developed as an extension of an iOS app. For privacy reasons, before we can access health data like pulse, we need to request permission. This request happens in the iOS app which grants appropriate access to both the iOS and WatchOS apps. I've incorporated this health data request into the settings screen of the iOS App. A system UI pops up when requesting permission. The app specifically asks for heart rate and the user must grant access for the app to successfully read the data.
Once we have access to the heart rate, we use the HealthKit API to request updates any time heart rate changes. I incorporated that functionality into a HealthDataManager class. It's worth noting that the heart rate sensor will periodically turn on during normal operation of the Watch, but it's not as frequent as during a workout when the watch is more actively monitoring pulse. In order to turn on the heart rate monitor and provide more frequent updates of the pulse data, I've incorporated a button that allows you to start and stop a workout in the watch app. If you've used the Workouts app in Apple Watch, you'll be familiar with the more elevated monitoring that is performed during a workout. (If you haven't used Workouts, you're missing out. It's a really great way to monitor heart rate, distance, calories, etc. during your workout.)
Apple provides an interface between WatchOS and iOS via the WatchKit Extension. The device can send and receive data via the WatchKit session that is established between devices. Once we have the Apple Watch app reading the heart rate data, we simply send those data points to the iPhone via the session. You can take a look at the functionality for sending the data in the Watch Extension InterfaceController and receiving in the SessionHandler class.
The native libraries for connecting to AWS services from iOS have been wrapped into the AWS Amplify umbrella that Amazon announced this past fall. Amplify expands on the set of AWS libraries available for native mobile development by also providing a command line tool that assists in configuring the appropriate AWS resources. The Amplify tool set is geared toward allowing mobile and web developers to focus on their development efforts and eliminate some of the manual steps needed to setup back end resources on AWS. The Amplify libraries provide access to things like AWS APIs, Storage, Analytics, Push Notifications, and PubSub. PubSub is the terminology that AWS uses to describe connecting to the AWS IoT platform from a mobile or web application via MQTT.
We only need access to AWS IoT, so the the AWSIoT pod was the only part of Amplify that was needed. I incorporated the interactions with AWS IoT API into a MessageManager class. That class is initialized when the app starts and used for communication on the PubSub topic "heartrate". Topics are user defined in MQTT and generally use a hierarchical format, but to keep it simple for this app - publish and subscribe on the same topic. The data will use a JSON format and have a unique user GUID that can be used to identify data coming from each app install.
The MessageManager class reads a configured endpoint for the unique AWS IoT endpoint for your AWS account. The settings screen in the app provides a way to set the endpoint for your account.
A certificate/key pair is also needed to securely connect to AWS IoT and will show on the Settings screen of the app as well. For this proof of concept app, I've implemented opening a .p12 file with the app from the Files app via iCloud or an email attachment on the iPhone. If a .p12 file is opened within the app, it will be copied to the Documents location of the app and be used when connecting to AWS IoT. In a more production type environment, this key file could be created for an account and sent to the iOS app client from the back end. The certificate/key pair uniquely identifies the app instance in the AWS IoT Thing registry. You can reference the Readme for more information on how to set up AWS IoT and get the .p12 certificate file.
The AWS IoT library provides a mechanism to load the certificate/key pair and connect to the MQTT endpoint. Once the connection is established, it's as simple as calling publish to post information to the MQTT broker. We post the data in a JSON format that will be common when publishing and subscribing to messages. Take a look at the MessageManager class for more details.
Now that heart rate data is being published to the topic, you can use the AWS IoT Test console to subscribe to the topic and inspect messages being sent over MQTT. You can also publish test messages to the topic that will be received by subscribers.
The AWS IoT library provides a subscribe call to subscribe to a specific topic that takes a callback method that is called every time messages are received on the topic. I implemented a subscribe method that updates a dictionary of heart rate data that is unique per user id. As new heart rate data is sent in, the data is updated in the dictionary and it signals to the UI that new data is available.
The Dashboard screen in the app uses a UICollectionView to show any number of unique heart rates for users as the messages are received on the MQTT topic. The collection view updates in real time as data is sent in. It's fun to watch the values change as the heart rates monitored by Apple Watch move up and down.
As this example shows, MQTT and IoT can be used for broader use cases than traditional IoT devices for the smart home or smart industrial facility.
What types of applications could you build to aggregate data from sensors in the real world that would provide insight into your organization?
Looking for help with an IoT or mobile development project? We'd love to help you build and innovate your products.