Overview
The Synheart Session Swift SDK providesSynheartSession, a timer-driven session engine that buffers heart-rate samples from a BiosignalProvider, emits typed SessionEvents on an AsyncStream, and delivers a .sessionSummary when the session ends. An optional BehaviorProvider adds behavioral signals to each frame. It runs on iOS, macOS, and watchOS.
The SDK computes mean HR locally from sampled biosignals. HRV (
rmssd_ms, hr_sdnn_ms, pnn50) is produced upstream (typically by the Synheart runtime) and supplied with ingestHsiMetrics(sessionId:hsiMetrics:). Without that call, HRV fields are 0.0.Installation
Swift Package Manager
Add to yourPackage.swift:
- File > Add Packages…
- Enter:
https://github.com/synheart-ai/synheart-session-swift.git
Requirements
- iOS 13.0+ / macOS 13.0+ / watchOS 8.0+
- Swift 5.9+ (swift-tools-version 5.9)
Quick Start
.sessionStarted is not lost. The engine schedules its timers on RunLoop.main, and MockBiosignalProvider schedules its timer on the current run loop, so start sessions from the main thread.
Types
SessionConfig
includeRawSamples: true to emit .biosignalFrame events alongside session frames:
SessionConfig from a dictionary, for example a start_session command received over WatchConnectivity:
SessionError.invalidState if session_id, mode, or duration_sec is missing or the mode is unknown.
SessionMode
ComputeProfile
SessionError
SessionError is the error type thrown by the API. Each case carries a String message; code returns the matching SessionErrorCode.
Session Events
SessionEvent is an enum. Every case exposes sessionId, and toDictionary() returns the snake_case wire dictionary shared with the other SDKs.
session_frame
Emitted everyemitIntervalSec while the window holds at least one sample (frames are skipped while it is empty). Wire form:
hr_mean_bpm is rounded to one decimal. behavior is added when a BehaviorProvider is configured, reports isAvailable, and returns a snapshot.
biosignal_frame
Emitted everyrawEmitIntervalSec when includeRawSamples is true and the window is not empty. Its seq is a separate counter from the session frame seq. Each sample has timestamp_ms, bpm, source, and, when the provider supplies them, rr_intervals_ms and device_id:
session_summary
session_error
Emitted instead of a summary when the provider throws fromstartStreaming (for example WearBiosignalProvider with no connected HRM); the code is .sensorUnavailable and the stream finishes. On the wire the code is under error_code:
Providers
BLE Heart Rate Monitor
HealthKit
SynheartWear instance before passing it in. The provider subscribes to streamHR(interval: 1.0); when a reading has no RR intervals, it derives one from BPM (60000 / bpm).
HRV Metrics
Double. The call is a no-op after dispose() or when sessionId does not match the running session.
WatchOS Integration
The Swift SDK runs on Apple Watch. A watch app can receive commands from the phone over WatchConnectivity and runSynheartSession locally. The relay below is an example you write in your watch app, not part of the SDK:
Watch-Side Relay
Phone Side
The Swift SDK does not include a phone-side relay. A native iOS app that drives a watch session sends thestart_session / stop_session commands itself and decodes the returned event dictionaries; the message format is described in Watch Protocol. The Flutter SDK’s iOS plugin carries its own relay.
XcodeGen Configuration
If you use XcodeGen for your watchOS project, add the SDK as a local package and link WatchConnectivity:Behavioral Signals
SynheartSession accepts an optional BehaviorProvider. The engine pulls a snapshot at each frame and once more for the summary.
Mock Behavior (Development)
Production (via synheart-behavior)
behavior value is only present in frames when a BehaviorProvider is configured and returns data. See Flutter SDK — Behavioral Fields for the keys; they are the same in every SDK.
API Reference
SynheartSession
Resources
- Repository: synheart-session-swift
- Issues: GitHub Issues