Skip to main content

Events

BioSDK uses a single Combine publisher to emit all SDK events. Subscribe to sdk.events to receive real-time updates about device lifecycle, biosignal data, connection state changes, and session activity.

import Combine

var cancellables = Set<AnyCancellable>()

sdk.events
.sink { event in
// Handle all event types
}
.store(in: &cancellables)

Event Types

BioEvent

The top-level event enum:

public enum BioEvent {
case lifecycle(BioLifecycleEvent)
case sample(deviceId: String, BioSample)
case deviceState(device: BioDevice, connection: BioConnectionState, stream: BioStreamState)
case session(BioSessionEvent)
case notification(BioNotificationEvent)
}

Lifecycle Events

Emitted when devices are discovered, connected, or disconnected.

public enum BioLifecycleEvent {
case discovered(BioDevice)
case connected(BioDevice)
case disconnected(BioDevice, errorMessage: String?, errorCode: Int?, errorDomain: String?)
}

Sample Events

Emitted for each biosignal data point received from a device. See the Streaming guide for details on signal types.

Device State Events

Emitted whenever a device's connection or streaming state changes. Each device has independent (BioConnectionState, BioStreamState) tracking.

Session Events

Emitted for session lifecycle changes on the AnyBio platform.

public enum BioSessionEvent {
case started(id: String, devices: [SessionDevice])
case resumed(id: String, devices: [SessionDevice])
case conflict(activeId: String, startedAt: Date?)
case ended(id: String, ok: Bool)
case endFailed(id: String, status: Int?)
case recoveryAvailable(OrphanedSessionInfo)
case forbidden
case serverError(status: Int)
case error(message: String)
}

Notification Events

Emitted for push notification activity (if notifications are configured).

public enum BioNotificationEvent {
case received(BioNotification)
case acknowledged(notificationId: String)
case dismissed(notificationId: String)
case connectionStateChanged(NotificationConnectionState)
}

Filtering Events

Use Combine operators to subscribe to specific event types:

// Only heart rate samples
sdk.events
.compactMap { event -> Double? in
guard case .sample(_, let sample) = event,
sample.isHeartRate,
let bpm = sample.scalarValue else { return nil }
return bpm
}
.sink { bpm in
print("HR: \(bpm) BPM")
}
.store(in: &cancellables)

// Only connection state changes
sdk.events
.compactMap { event -> (BioDevice, BioConnectionState)? in
guard case .deviceState(let device, let connection, _) = event else { return nil }
return (device, connection)
}
.sink { device, state in
print("\(device.name): \(state)")
}
.store(in: &cancellables)
tip

Keep your event sink subscription alive for the lifetime of the SDK client. Store cancellables in a property that outlives any individual view — for example, on your app delegate or a long-lived coordinator.