Salt la continutul principal

iOS SDK Usage

Initialization

The SDK is consumed as a KMP framework on iOS. Use the builder pattern to create an instance. The build() function is async and performs DPoP key pair generation (Secure Enclave), token activation, and entitlement verification.

import VitaleraSdkCore

let sdk = try await VitaleraSdk.companion.builder()
.clientId(clientId: "your-org-license-key")
.addProvider(providerName: "omron")
.addProvider(providerName: "polar")
.addProvider(providerName: "standard-ble")
.connectedMode(enabled: true)
.build()

Handle authentication errors:

do {
let sdk = try await VitaleraSdk.companion.builder()
.clientId(clientId: "your-org-license-key")
.build()
} catch let error as SdkAuthException {
switch error.errorCode {
case "activation_failed":
showInvalidLicenseError()
case "entitlements_expired":
showConnectToInternetPrompt()
case "no_cache":
showFirstLaunchOfflineError()
default:
showGenericError(error.message)
}
}

Permissions

Add the required permissions to your Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to connect with medical devices.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses Bluetooth to communicate with devices.</string>

For HealthKit:

<key>NSHealthShareUsageDescription</key>
<string>This app reads health data for monitoring.</string>

Device Discovery

Discovery uses Swift AsyncSequence. Each discovered device is returned as a DeviceDescriptor.

let filter = DiscoveryFilter(
providers: nil,
capabilities: [DeviceCapability.bloodPressure],
namePrefix: nil
)

for try await descriptor in sdk.devices.discover(filter: filter, timeoutMs: 15_000) {
print("Found: \(descriptor.name) (\(descriptor.provider))")
}

Filter Options

// Only Polar devices
let polarFilter = DiscoveryFilter(
providers: ["polar"],
capabilities: nil,
namePrefix: nil
)

// Only heart rate monitors
let hrFilter = DiscoveryFilter(
providers: nil,
capabilities: [DeviceCapability.heartRate],
namePrefix: nil
)

Device Connection

Create a device from a descriptor and connect. The connect() function is async with a configurable timeout.

let device = sdk.devices.createDevice(descriptor: descriptor)

// Connect (async, with timeout)
try await device.connect(timeoutMs: 10_000)

Data Collection

The collect() method returns an AsyncSequence of typed observation classes.

for try await observation in device.collect() {
if let bp = observation as? BloodPressureObservation {
print("BP: \(bp.systolic)/\(bp.diastolic) mmHg")
if let pulse = bp.pulseRate {
print("Pulse: \(pulse) bpm")
}
} else if let hr = observation as? HeartRateObservation {
print("HR: \(hr.heartRate) bpm")
} else if let temp = observation as? TemperatureObservation {
print("Temp: \(temp.temperature) C")
} else if let weight = observation as? WeightObservation {
print("Weight: \(weight.weight) kg")
} else if let spo2 = observation as? OxygenSaturationObservation {
print("SpO2: \(spo2.spo2)%")
}
}

// Disconnect when done
try await device.disconnect()

Connected Mode

When connected mode is enabled, resolve patients and post observations:

let patient = try await sdk.connected().resolveMonitored(externalId: "patient-ext-id")

try await sdk.connected().postObservation(
monitoredId: patient.id,
observation: BaseObservation(
observationType: "blood-pressure",
issued: ISO8601DateFormatter().string(from: Date()),
components: [
ObservationComponent(name: "systolic", value: "120", valueUnit: "mmHg"),
ObservationComponent(name: "diastolic", value: "80", valueUnit: "mmHg"),
]
)
)

Error Handling

do {
try await device.connect(timeoutMs: 10_000)
for try await obs in device.collect() {
// process observation
}
} catch let error as SdkError {
switch error {
case is SdkError.ConnectionTimeout:
showError("Connection timed out. Move closer to the device.")
case is SdkError.BluetoothDisabled:
showError("Please enable Bluetooth.")
case is SdkError.BluetoothPermissionDenied:
showError("Bluetooth permissions required.")
default:
showError("Device error: \(error.localizedDescription)")
}
}

HealthKit

Read from Apple HealthKit (no BLE scanning required):

let descriptor = try await sdk.devices.discover(
filter: DiscoveryFilter(providers: ["apple-healthkit"], capabilities: nil, namePrefix: nil),
timeoutMs: 5_000
).first { _ in true }!

let store = sdk.devices.createDevice(descriptor: descriptor)
try await store.connect()
for try await observation in store.collect() {
// Process HealthKit observations
}
try await store.disconnect()

Resource Cleanup

Always call close() when the SDK is no longer needed:

sdk.close()