Skip to main content

Overview

The Synheart Session Swift SDK provides SynheartSession, 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 your Package.swift:
Or in Xcode:
  1. File > Add Packages…
  2. Enter: https://github.com/synheart-ai/synheart-session-swift.git
The package has four library products:

Requirements

  • iOS 13.0+ / macOS 13.0+ / watchOS 8.0+
  • Swift 5.9+ (swift-tools-version 5.9)

Quick Start

The stream buffers events emitted before you start iterating, so .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

Set includeRawSamples: true to emit .biosignalFrame events alongside session frames:
You can also create a SessionConfig from a dictionary, for example a start_session command received over WatchConnectivity:
It throws 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 every emitIntervalSec 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 every rawEmitIntervalSec 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 from startStreaming (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

Initialize the 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

The latest dictionary replaces the previous one and is used for every following frame and the summary. Values must be 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 run SynheartSession 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 the start_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)

The 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