> ## Documentation Index
> Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Synheart Wear - Swift/iOS SDK

> Native iOS SDK with HealthKit integration

## Overview

The Synheart Wear Swift SDK provides native iOS support for streaming biometric data from Apple Watch via HealthKit, vendor cloud APIs (WHOOP, Garmin, Fitbit, Oura), direct BLE heart-rate sensors, and offline Apple Health `export.xml` backfill.

## Installation

### Swift Package Manager

Add to your `Package.swift`:

```swift theme={null}
dependencies: [
    .package(url: "https://github.com/synheart-ai/synheart-wear-swift.git", from: "0.4.0")
]
```

Or in Xcode:

1. File → Add Packages...
2. Enter: `https://github.com/synheart-ai/synheart-wear-swift.git`

### Requirements

* iOS 13.0+
* Swift 5.9+
* Xcode 15.0+

## Quick Start

### Configure HealthKit

Add to `Info.plist`:

```xml theme={null}
<key>NSHealthShareUsageDescription</key>
<string>We need access to your health data</string>
```

Enable HealthKit capability in Xcode:

* Target → Signing & Capabilities → + Capability → HealthKit

### Initialize SDK

```swift theme={null}
import SynheartWear

let config = SynheartWearConfig(
    enabledAdapters: [.platformHealth],
    enableLocalCaching: true
)

let synheartWear = SynheartWear(config: config)
```

### Request Permissions & Read Data

```swift theme={null}
Task {
    let permissions: Set<PermissionType> = [
        .heartRate,
        .steps,
        .calories
    ]

    let result = try await synheartWear.requestPermissions(permissions: permissions)

    if result[.heartRate] == true {
        try await synheartWear.initialize()
        let metrics = try await synheartWear.readMetrics()
        print("Heart Rate: \(metrics.getMetric(.hr) ?? 0) bpm")
    }
}
```

### Real-Time Streaming

`streamHR(interval:)` returns a Combine `AnyPublisher<WearMetrics, Error>`. Use `streamHRAsync(interval:)` if you prefer `AsyncStream`.

```swift theme={null}
import Combine

var cancellables = Set<AnyCancellable>()

synheartWear.streamHR(interval: 5.0)
    .sink(
        receiveCompletion: { _ in },
        receiveValue: { metrics in
            if let hr = metrics.getMetric(.hr) {
                print("Current HR: \(hr) bpm")
            }
        }
    )
    .store(in: &cancellables)

// Async/await alternative:
Task {
    for await metrics in synheartWear.streamHRAsync(interval: 5.0) {
        if let hr = metrics.getMetric(.hr) {
            print("Current HR: \(hr) bpm")
        }
    }
}
```

## BLE Heart Rate Monitor

Connect directly to any standard Bluetooth LE heart rate monitor for real-time HR streaming.

### Setup

Add to `Info.plist`:

```xml theme={null}
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to connect to heart rate monitors.</string>
```

### Usage

```swift theme={null}
import SynheartWear

let config = SynheartWearConfig(enabledAdapters: [.bleHrm])
let synheartWear = SynheartWear(config: config)

// Access the BLE HRM provider
guard let bleHrm = synheartWear.bleHrm else { return }

// Scan for nearby HR monitors
let devices = try await bleHrm.scan(timeoutMs: 10000, namePrefix: "WHOOP")

// Connect to a device
try await bleHrm.connect(deviceId: devices.first.deviceId, sessionId: "my-session")

// Stream heart rate samples
for await sample in bleHrm.onHeartRate {
    print("BPM: \(sample.bpm)")
    if let rr = sample.rrIntervalsMs {
        print("RR: \(rr)")
    }
}

// Disconnect
try await bleHrm.disconnect()
```

### Supported Devices

Works with any BLE device implementing the standard Heart Rate Profile (0x180D):

* WHOOP (Broadcast HR mode)
* Polar H10, OH1
* Wahoo TICKR
* Garmin HRM-Pro / HRM-Dual

## Cloud providers (WHOOP / Garmin / Fitbit / Oura)

Each cloud vendor is exposed via a typed accessor on `SynheartWear` plus the generic `getProvider()` lookup:

```swift theme={null}
let whoop:  WhoopProvider?  = synheartWear.whoop
let garmin: GarminProvider? = synheartWear.garmin
let fitbit: FitbitProvider? = synheartWear.fitbit
let oura:   OuraProvider?   = synheartWear.oura
```

OAuth is mediated by the Synheart Wear API; the device never sees vendor access tokens. Call `provider.connect()` to launch the system browser at the authorize URL, then `provider.connectWithCode(code:state:redirectUri:)` from your deep-link handler. For Fitbit and Oura, the cloud delivers a `vendor_user_id` directly via deep link — pass that as the `code` argument.

## Apple Health XML Backfill

The `AppleXmlImport` module ingests an Apple Health `export.xml` (the file produced by the Health app's "Export All Health Data" feature) and converts it into a stream of `AppleHealthSample` records. The streaming SAX parser stays under a 200 MB working-set budget regardless of file size, so multi-hundred-MB exports are safe.

```swift theme={null}
import SynheartWear

let xmlURL: URL = ...   // path to unzipped export.xml

let importer = AppleHealthXmlImport()
let result = try await importer.import(
    fileURL: xmlURL,
    sink: MyIngestSink()  // conforms to AppleXmlIngestSink
)
print("imported \(result.totalSamples) samples")
```

Each sample's stable identity is computed by `IdempotencyKey` (SHA-256 over a canonical subset of fields), so re-running the import on the same file produces the same keys and downstream sinks can dedupe safely.

## Garmin Health SDK (Native RTS)

The `GarminHealth` facade provides native Garmin device integration for scanning, pairing, and real-time streaming using generic SDK-owned types.

> **Important:** The Garmin Health SDK Real-Time Streaming (RTS) capability requires a separate license from Garmin. This facade is available on demand for licensed integrations. The underlying Garmin Health SDK code is proprietary to Garmin and is not distributed as open source.

```swift theme={null}
import SynheartWear

let garmin = GarminHealth(licenseKey: "your-garmin-sdk-key")
try await garmin.initialize()

// Scan for devices
for await devices in garmin.scannedDevicesStream() {
    print("Found \(devices.count) devices")
}

// Pair and read metrics
let paired = try await garmin.pairDevice(scannedDevice)
let metrics = try await garmin.readMetrics()
```

For cloud-based Garmin data (OAuth + webhooks), use `GarminProvider` instead.

## Resources

* **Repository**: [synheart-wear-swift](https://github.com/synheart-ai/synheart-wear-swift)
* **Full README**: [View on GitHub](https://github.com/synheart-ai/synheart-wear-swift#readme)
* **Issues**: [GitHub Issues](https://github.com/synheart-ai/synheart-wear-swift/issues)

For comprehensive documentation, see the [full README on GitHub](https://github.com/synheart-ai/synheart-wear-swift#readme).
