Terra Docs
Dashboard
  • Docs
  • API Reference
  • Changelog
  • Get started ⚡️ Choose your integration
  • Health & Fitness API
    • Overview
    • Set up your Integrations
    • Connect a User
    • Receive data updates
    • Request Historical data
    • Write data
    • Debugging FAQ
    • Mobile-Only Sources: Apple, Samsung, Google Fit
      • iOS (Swift)
      • Android (Kotlin)
      • React Native
      • Flutter
  • Streaming API
    • Getting Started
    • Wearable -> Your app
      • iOS (Swift)
      • Android
    • Your app -> Terra
      • iOS (Swift)
      • Android
    • Terra -> Your Backend
  • Teams API
  • Biomarkers API - Upcoming
Powered by GitBook
On this page

Was this helpful?

  1. Streaming API
  2. Wearable -> Your app

iOS (Swift)

PreviousWearable -> Your appNextAndroid

Last updated 6 months ago

Was this helpful?

SDK Installation

RealTime streaming on iOS is only available to those registered on the

Summary:

  1. In your info.plist, add:

    1. Privacy - Bluetooth Always Usage Description: Justification for BLE usage (shown to the user when requesting permission)

    2. Privacy - Motion Usage Description: Justification for phone motion sensor usage (shown to the user when requesting permission - only add if using phone sensors for streaming)

When the app is launched for the first time, these permissions will be requested from the user.


Connection setup/management

The SDK revolves around the TerraRT class, which manages Bluetooth connections and real-time data streaming.

SDK Initialization

Always initialize the TerraRT class to begin using the SDK.

Do so every time the app is opened or brought into the foreground.

To do this, run the TerraRT manager initialization function as below:

import TerraRT

let developerId = "yourDeveloperId"       // Replace with your actual developer ID
let referenceId: String? = "yourReferenceId"  // This is optional; can be nil

// Initialize TerraRT
let terraRT = TerraRT(devId: developerId, referenceId: referenceId) { success in
    if success {
        print("TerraRT initialization successful!")
        // Perform further actions if needed
    } else {
        print("TerraRT initialization failed.")
        // Handle failure case
    }
}

Initializing a Connection

Register the phone by calling initConnection.

This connects the phone to Terra, allows you to use other SDK functions, and allows it to be a producer once a wearable is connected later on.

let token = "yourAuthToken"  // Replace with your actual token

// Call the initConnection function with the token
terraRT.initConnection(token: token) { success in
    if success {
        print("Connection initialized successfully!")
        // Perform further actions after a successful connection
    } else {
        print("Failed to initialize connection.")
        // Handle failure case
    }
}

To generate the token, make the below call from your backend

Connecting a device

You may use an example as below to call the startBluetoothScan function, which pulls up a modal allowing the user to select a wearable to connect

import SwiftUI
import TerraRTSDK  // Assuming the SDK is imported as TerraRTSDK

struct BluetoothScanView: View {
    @State private var showScanWidget = false
    @State private var scanSuccess = false

    var body: some View {
        VStack {
            if showScanWidget {
                // Show the TerraBLEWidget which is returned by the scan function
                terraRT.startBluetoothScan(type: .BLE) { success in
                    scanSuccess = success
                    if success {
                        print("Bluetooth scan and connection successful!")
                    } else {
                        print("Bluetooth scan failed.")
                    }
                }
                // Optionally, handle success/failure states within the UI
            } else {
                Button(action: {
                    startScan()
                }) {
                    Text("Start Bluetooth Scan")
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(8)
                }
            }

            if scanSuccess {
                Text("Scan successful! Device connected.")
                    .foregroundColor(.green)
            } else if showScanWidget && !scanSuccess {
                Text("Scanning for devices...")
            }
        }
        .padding()
    }

    // Function to start the scan and show the TerraBLEWidget
    func startScan() {
        showScanWidget = true
    }
}

// Example of how to use the BluetoothScanView
struct ContentView: View {
    var body: some View {
        BluetoothScanView()
    }
}

Streaming Real-Time Data

Start Streaming

You can start receiving data from the connected wearable's stream by calling startRealtime with the following signature

func startRealtime(type: TerraRTiOS.Connections, dataType: Swift.Set<TerraRTiOS.DataTypes>, callback: @escaping (TerraRTiOS.Update) -> Swift.Void)

you can also stop the stream and disconnect the wearable once done

import TerraRT

// Example function to start real-time data streaming, stop it, and disconnect
func manageRealtimeData() {
    let connectionType: TerraRTiOS.Connections = .BLE  // Replace with your connection type (e.g., BLE)
    let dataTypes: Set<TerraRTiOS.DataTypes> = [.heartRate, .steps]  // Replace with desired data types to stream

    // Start real-time data streaming
    terraRT.startRealtime(type: connectionType, dataType: dataTypes) { update in
        handleUpdate(update: update)
    }
    
    // Stop the real-time streaming after some action or condition
    // Example: stopping after a delay (5 seconds here, for demonstration)
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        terraRT.stopRealtime(type: connectionType)
        print("Real-time streaming stopped.")
    }

    // Optionally, disconnect after stopping the real-time data stream
    DispatchQueue.main.asyncAfter(deadline: .now() + 7) {
        terraRT.disconnect(type: connectionType)
        print("Disconnected from connection.")
    }
}

// Function to handle updates from the real-time data stream
func handleUpdate(update: TerraRTiOS.Update) {
    // Process the real-time data update here
    print("Received update at timestamp: \(update.ts)")
    print("Update type: \(update.type)")
    if let value = update.val {
        print("Value: \(value)")
    }
    if let dataArray = update.d {
        print("Array of data values: \(dataArray)")
    }
}

// Call the function to start the real-time data management process
manageRealtimeData()

WatchOS Integration

To receive a data stream from an Apple Watch, the watch must be instructed to initiate a data stream to the iOS phone it is paired with.

For that, you'll need to have a WatchOS companion app running on the watch, which runs startStream or startExercise

Setup

  1. Create a WatchOS target within your iOS project:

    File -> New -> Target -> Watch App for iOS App.

  2. Enable HealthKit and Background Modes for the WatchOS app, and add the following privacy keys to your Info.plist:

    1. Privacy - Health Share Usage Description

    2. Privacy - Health Update Usage Description

    3. Privacy - Health Records Usage Description

Start Streaming from WatchOS

To begin streaming data from Apple Watch, call the startStream() function from within the Watch app. This will initiate data streaming from the Watch sensors to the paired iOS app.

On the iOS app, you'll equivalently need to listen for updates from the WatchOS app:

import WatchKit
import TerraRTiOS

class InterfaceController: WKInterfaceController {
    var terraRT: Terra?

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        // Initialize Terra SDK on watchOS
        do {
            terraRT = try Terra()
            terraRT?.connect()
            print("Terra SDK initialized on watchOS")
            startStreamingData()
        } catch {
            print("Failed to initialize Terra SDK: \(error)")
        }
    }

    // Start streaming real-time data (e.g., heart rate and steps)
    @IBAction func startStreamingData() {
        let dataTypes: Set<TerraRTiOS.ReadTypes> = [.HEART_RATE, .STEPS]
        terraRT?.startStream(forDataTypes: dataTypes) { success, error in
            if success {
                print("Streaming started")
            } else {
                print("Failed to start streaming: \(error?.localizedDescription ?? "Unknown error")")
            }
        }
    }

    // Stop streaming real-time data
    @IBAction func stopStreamingTapped() {
        terraRT?.stopStream()
        print("Streaming stopped")
    }
}
import TerraRTiOS
import UIKit

class ViewController: UIViewController {
    var terraRT: TerraRT?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Initialize the Terra SDK
        terraRT = TerraRT(devId: "your-dev-id", referenceId: "your-reference-id") { success in
            if success {
                print("Terra SDK initialized successfully")
                self.setupWatchOSConnection()
            } else {
                print("Failed to initialize Terra SDK")
            }
        }
    }

    // Setting up a watchOS connection
    func setupWatchOSConnection() {
        terraRT?.connectWithWatchOS()
        self.listenForDataFromWatch()
    }

    // Listening to real-time data from watchOS
    func listenForDataFromWatch() {
        let dataTypes: Set<DataTypes> = [.HEART_RATE, .STEPS]
        terraRT?.startRealtime(type: .WATCH_OS, dataTypes: dataTypes) { update in
            print("Received update from watchOS: \(update)")
        }
    }

    // Stop real-time data collection from watchOS
    func stopRealtimeData() {
        terraRT?.stopRealtime(connections: [.WATCH_OS])
    }

    // Disconnect the watchOS
    func disconnectWatchOS() {
        terraRT?.disconnect(connections: [.WATCH_OS])
    }
}

Streaming Workouts from WatchOS

The Apple Watch app can also manage a workout session, during which recording frequency is enhanced.

To manage a workout session, you can use the following convenience functions:

From the Watch:

  • startExercise

  • stopExercise

  • resumeExercise

  • pauseExercise

From the iOS app:

  • pauseWatchOSWorkout

  • resumeWatchOSWorkout

  • stopWatchOSWorkout

Here is an example template of the watchOS app using the functions outlined above

import WatchKit
import TerraRTiOS

class InterfaceController: WKInterfaceController {
    var terraRT: Terra?

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        // Initialize Terra SDK on watchOS
        do {
            terraRT = try Terra()
            terraRT?.connect()
            print("Terra SDK initialized on watchOS")
        } catch {
            print("Failed to initialize Terra SDK: \(error)")
        }
    }

    // Start an exercise session (e.g., Running) using TerraRT
    @IBAction func startExerciseTapped() {
        terraRT?.startExercise(forType: .RUNNING) { success, error in
            if success {
                print("Running exercise started on watchOS")
            } else {
                print("Failed to start exercise: \(error?.localizedDescription ?? "Unknown error")")
            }
        }
    }

    // Pause the exercise session using TerraRT
    @IBAction func pauseExerciseTapped() {
        terraRT?.pauseExercise()
        print("Exercise paused")
    }

    // Resume the exercise session using TerraRT
    @IBAction func resumeExerciseTapped() {
        terraRT?.resumeExercise()
        print("Exercise resumed")
    }

    // Stop the exercise session using TerraRT
    @IBAction func stopExerciseTapped() {
        terraRT?.stopExercise { success, error in
            if success {
                print("Exercise stopped on watchOS")
            } else {
                print("Failed to stop exercise: \(error?.localizedDescription ?? "Unknown error")")
            }
        }
    }

    // Start streaming real-time data (e.g., heart rate and steps)
    @IBAction func startStreamingTapped() {
        let dataTypes: Set<TerraRTiOS.ReadTypes> = [.HEART_RATE, .STEPS]
        terraRT?.startStream(forDataTypes: dataTypes) { success, error in
            if success {
                print("Streaming started")
            } else {
                print("Failed to start streaming: \(error?.localizedDescription ?? "Unknown error")")
            }
        }
    }

    // Stop streaming real-time data
    @IBAction func stopStreamingTapped() {
        terraRT?.stopStream()
        print("Streaming stopped")
    }
}

Add as a package dependency

Use the and call initConnection as below:

iOS devices only support connection via BLE or Apple Watch's custom bluetooth protocol. For the Apple Watch connection, refer to

Once the and you've , you can stream data from the wearable to your mobile app.

Outside of a workout session, data recording frequency may be reduced. In order to capture data at the highest possible frequency, you'll want to

Reading a data stream on iOS will only be possible if you have previously

https://github.com/tryterra/TerraRTiOS
terraRT instance created above
the guide below
phone is registered
connected a wearable
start a workout session
created a connection
Apple Developer Program

Generates an authentication token for the Terra mobile SDKs

post

Creates a token to be used with initConnection() functions in the Terra mobile SDKs in order to create a user record for Apple Health or Samsung Health (or equivalent)

Header parameters
dev-idstringRequired

your developer ID

Example: testingTerra
x-api-keystringRequired

your API key

Example: OtHJok60oQmT8zhnUWc4SWBJI7ztPTs88C0gOsJJ
Responses
200
200
application/json
404
404
application/json
post
POST /v2/auth/generateAuthToken HTTP/1.1
Host: api.tryterra.co
dev-id: text
x-api-key: text
Accept: */*
{
    "status": "success",
    "token": "250c68b9c21b78e40e7a3285a2d538d3bc24aabd3b4c76a782fb0a571ca4501d",
    "expires_in": 180
}
  • SDK Installation
  • Connection setup/management
  • SDK Initialization
  • Initializing a Connection
  • POSTGenerates an authentication token for the Terra mobile SDKs
  • Connecting a device
  • Streaming Real-Time Data
  • WatchOS Integration
  • Start Streaming from WatchOS
  • Streaming Workouts from WatchOS