iOS
🚀 准备工作
硬件连接指引
有关头环设备的开关机操作、状态指示灯含义及各端 SDK 的设备配对说明,请在开发前优先查阅:设备使用说明与常见问题 (FAQ)。
编译环境要求
- 开发工具:Xcode 14.0 及以上版本。
- 系统层门槛:应用部署目标(Deployment Target)必须设置为 iOS 12.0 或更高。
- 开发语言:Swift 5.0 及以上版本。
安装和集成
导入 SDK (CocoaPods)
推荐使用 CocoaPods 集成 OxyZen iOS SDK。在您的 Podfile 中添加以下依赖:
ruby
source 'https://github.com/BrainCoTech/cocoapods-specs.git'
source 'https://cdn.cocoapods.org/'
platform :ios, '12.0'
use_frameworks!
target 'YourAppTarget' do
pod 'ZenLiteSDK', '=1.5.2'
end执行安装配置:
bash
pod install所需权限
在项目的 Info.plist 中,必须声明蓝牙权限及后台运行策略(若需要):
xml
<!-- 蓝牙权限说明 -->
<key>NSBluetoothAlwaysUsageDescription</key>
<string>此应用需要蓝牙权限来连接和管理 OxyZen 设备</string>
<!-- 后台运行配置(可选) -->
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
</array>API 核心组件参考
💡 SDK 架构说明
OxyZen iOS SDK 在架构上划分为以下两个模块(代码中的 ZenLite 前缀为产品曾用名,类名保持向后兼容):
ZenLiteSDK(通过 CocoaPods 引入):闭源的核心引擎,负责蓝牙原始数据解析、信号滤波及各类算法指标(如专注度、冥想指数、睡眠分期等)的计算与输出。- BLE 通信层:负责设备扫描、连接管理与指令交互。该模块的完整源码已在 示例工程 中公开,开发者可根据自身需求对扫描策略、连接保活等逻辑进行自定义修改,也可以将其整体替换为自己的 BLE 通信实现。
BLEDeviceManager (Class)
负责 BLE 设备的全局扫描与管理:
swift
// 开启设备扫描
BLEDeviceManager.shared.startScan()
// 设置扫描回调代理
BLEDeviceManager.scannerDelegate = self
// 停止设备扫描
BLEDeviceManager.shared.stopScan()ZenLiteDevice (Class)
设备控制和数据通信的核心设备对象:
swift
@objc public class ZenLiteDevice: NSObject {
// 基础属性
public weak var delegate: ZenLiteDelegate?
public private(set) var id: String
public private(set) var name: String
public private(set) var inPairngMode: Bool
public private(set) var batteryLevel: Int
public private(set) var rssi: Int
public private(set) var deviceInfo: DeviceInfo
public private(set) var connectivity: Connectivity
public var contactState: DeviceContactState
// 连接
func connect()
func disconnect()
// 配对
// 在配对模式下(inPairngMode)或者重连时需要调用
func pair(onResponse: @escaping ZenLiteRespCallback)
// 综合数据流控制
func startDataStream()
func stopDataStream()
// EEG 数据流控制
func startEEG()
func stopEEG()
func configAfe(_ sampleRate: AfeDataSampleRate)
// IMU 数据流控制
func startImu()
func stopImu()
func configImu(_ sampleRate: ImuDataSampleRate, _ mode: ImuMode)
// PPG 数据流控制
func startPpg()
func stopPpg()
func configPpg(_ sampleRate: PpgDataSampleRate, _ mode: PpgMode)
// 设备设置
func setDeviceName(_ name: String, onResponse: @escaping ZenLiteRespCallback)
}ZenLiteDelegate (Protocol)
用于接收设备事件与生理指标的数据回调监听器:
swift
@objc public protocol ZenLiteDelegate {
// 错误处理
@objc optional func onError(_ error: ZenLiteError)
// 设备与系统信息
@objc optional func onDeviceInfoReady(_ deviceInfo: DeviceInfo)
@objc optional func onSystemInfo(_ systemInfo: SystemInfo)
// 连接与硬件状态
@objc optional func onConnectivityChange(_ connectivity: Connectivity)
@objc optional func onBatteryLevelChange(_ batteryLevel: Int)
@objc optional func onContactStateChange(_ contactState: DeviceContactState)
@objc optional func onOrientationChange(_ orientation: Orientation)
// 传感器数据 - 脑电
@objc optional func onEEGData(_ eeg: OxyZenEEG)
@objc optional func onRawEEGData(_ eeg: OxyZenEEG)
@objc optional func onBrainWave(_ wave: BrainWave)
// 传感器数据 - 运动学与光学
@objc optional func onIMUData(_ imu: OxyZenIMU)
@objc optional func onPPGData(_ ppg: PPG)
@objc optional func onSignalQualityWarning(quality: Int)
// 算法指标
@objc optional func onAttention(attention: Float)
@objc optional func onMeditation(meditation: Float, calmness: Float, awareness: Float)
@objc optional func onSleep(stage: SleepStageType, conf: Float, drowsiness: Int)
}数据模型
DeviceInfo 设备信息
swift
struct DeviceInfo {
var manufacturerName: String // 制造商名称
var modelNumber: String // 型号
var serialNumber: String // 序列号
var hardwareRevision: String // 硬件版本
var firmwareRevision: String // 固件版本
}OxyZenEEG 脑电波数据
swift
@objc public class OxyZenEEG: NSObject {
@objc public let sequenceNumber: Int // 序列号
@objc public let sampleRate: Float // 采样率
@objc public let eegData: [Float] // EEG 数据,每组 30 个
}BrainWave 脑波频段指标
swift
@objc public class BrainWave: NSObject {
@objc public let delta: Double // Delta 波 (0.5-4 Hz)
@objc public let theta: Double // Theta 波 (4-8 Hz)
@objc public let alpha: Double // Alpha 波 (8-13 Hz)
@objc public let lowBeta: Double // Low Beta 波 (13-17 Hz)
@objc public let highBeta: Double // High Beta 波 (17-30 Hz)
@objc public let gamma: Double // Gamma 波 (30-50 Hz)
}OxyZenIMU 惯性测量单元数据
swift
@objc public class OxyZenIMU: NSObject {
@objc public var accData: ACC? // 加速度计数据
@objc public var gyroData: Gyro? // 陀螺仪数据
@objc public var eulerAngleData: EulerAngle? // 欧拉角数据
@objc public var sampleRate: Float // 采样率
@objc public var head: Int // 头部方向
@objc public var body: Int // 身体方向
}
// 加速度计数据
@objc public class ACC: NSObject {
@objc public let sequenceNumber: Int
@objc public var x: [Float] // X 轴加速度
@objc public var y: [Float] // Y 轴加速度
@objc public var z: [Float] // Z 轴加速度
}
// 陀螺仪数据
@objc public class Gyro: NSObject {
@objc public let sequenceNumber: Int
@objc public var x: [Float] // X 轴角速度
@objc public var y: [Float] // Y 轴角速度
@objc public var z: [Float] // Z 轴角速度
}
// 欧拉角数据
@objc public class EulerAngle: NSObject {
@objc public var yaw: [Float] // 偏航角 (-180 ~ 180)
@objc public var pitch: [Float] // 俯仰角 (-180 ~ 180)
@objc public var roll: [Float] // 翻滚角 (-180 ~ 180)
}PPG 光电容积脉搏波数据
swift
@objc public class PPG: NSObject {
@objc public var sequenceNumber: Int // 序列号
@objc public var reportRate: Float // 上报频率
@objc public var rawData: [PPGRaw]? // 原始数据
@objc public var algoData: [PPGAlgo]? // 算法指标
@objc public var respiratoryRate: Float // 呼吸频率
@objc public var respiratoryCurve: [Float]? // 呼吸曲线
@objc public var respiratoryState: Int // 呼吸状态
}
// PPG 算法指标
@objc public class PPGAlgo: NSObject {
@objc public let hr: Float // 心率
@objc public let hr_conf: Int // 心率置信度
@objc public let rr: Float // 呼吸率
@objc public let rr_conf: Int // 呼吸率置信度
@objc public let activity: Int // 活动状态
@objc public let spo2: Float // 血氧饱和度
@objc public let spo2_r: Float // 血氧 R 值
@objc public let spo2_conf: Int // 血氧置信度
@objc public let spo2_progress: Int // 血氧测量进度
@objc public let hrv: Float // 心率变异性
@objc public let hrv_stress: Float // HRV 压力指数
@objc public let stress: Float // 压力指数
@objc public let spo2_state: Int // 血氧状态
@objc public let contact_state: Int // 接触状态
}
// PPG 原始数据
@objc public class PPGRaw: NSObject {
@objc public let green1: Int // 绿光 1 计数
@objc public let green2: Int // 绿光 2 计数
@objc public let ir: Int // 红外光计数
@objc public let red: Int // 红光计数
}枚举常量类
连接状态
swift
@objc public enum Connectivity: Int, CaseIterable {
case connecting = 0 // 连接中
case connected = 1 // 已连接
case disconnecting = 2 // 断开中
case disconnected = 3 // 已断开
}接触状态
swift
@objc public enum DeviceContactState: Int, CaseIterable {
case unknown = 0 // 未知
case off = 1 // 未正确佩戴
case eeg = 2 // EEG 接触良好
case all = 3 // EEG & PPG 接触良好
}方向
swift
@objc public enum Orientation: Int, CaseIterable {
case unknown = 0 // 未知
case upward = 1 // 设备佩戴正确
case downward = 2 // 设备戴反了
}睡眠分期
swift
@objc public enum SleepStageType: Int, CaseIterable {
case unknown = -1 // 未知
case awake = 0 // 清醒
case rem = 1 // 快速眼动
case light = 2 // 浅睡眠
case deep = 3 // 深睡眠
}EEG 采样率
swift
@objc public enum AfeDataSampleRate: Int, CaseIterable {
case none = 0 // 无
case off = 1 // 关闭
case sr128 = 2 // 128 Hz
case sr256 = 3 // 256 Hz
}IMU 采样率
swift
@objc public enum ImuDataSampleRate: Int, CaseIterable {
case none = 0 // 无
case off = 1 // 关闭
case sr25 = 2 // 25 Hz
case sr50 = 3 // 50 Hz
case sr100 = 4 // 100 Hz
case sr200 = 5 // 200 Hz
case sr400 = 6 // 400 Hz
case sr800 = 7 // 800 Hz
}IMU 模式
swift
@objc public enum ImuMode: Int, CaseIterable {
case none = 0 // 无
case acc = 1 // 仅加速度计
case gyro = 2 // 仅陀螺仪
case acc_gyro = 3 // 加速度计 + 陀螺仪
case euler = 4 // 欧拉角
}PPG 采样率
swift
@objc public enum PpgDataSampleRate: Int, CaseIterable {
case none = 0 // 无
case off = 1 // 关闭
case sr1 = 2 // 1 Hz
case sr5 = 3 // 5 Hz
case sr25 = 4 // 25 Hz
case sr50 = 5 // 50 Hz(HRV 等需要更高频率)
case sr100 = 6 // 100 Hz
}PPG 模式
swift
@objc public enum PpgMode: Int, CaseIterable {
case none = 0 // 无
case raw_data = 1 // 原始数据
case algo = 2 // 算法指标
case spo2 = 3 // 仅血氧
case hr = 4 // 仅心率
case hrv = 5 // 心率变异性
}故障排查与注意事项
常见连接与配对问题
若出现“无法扫描到设备”、“连接失败”或“配对失败”等通用蓝牙排障场景,请优先参考全局指南中的时序说明和问题排查指引:
CocoaPods 依赖获取失败
若在执行 pod install 时阻塞或报错:
- 检查网络环境及代理配置,并更新 CocoaPods 至最新版本(
sudo gem install cocoapods)。 - 请尝试清理本地缓存并重新执行:bash
pod cache clean --all pod deintegrate pod install
iOS 平台开发注意事项
- UI 线程更新:SDK 中所有数据回调(如
onEEGData等)均由底层蓝牙代理分发。若需更新界面元素,开发者必须确保将其调度至主线程(DispatchQueue.main.async或 Swift 6MainActor),以防触发不可预知的线程安全问题及崩溃。 - 内存安全与避免循环引用:蓝牙设备的监听具有异步时序特点,当使用 Closures 控制请求回调或声明 Delegate 时,请注意使用
[weak self]以避免造成视图控制器的循环引用(Retain Cycle)。 - 资源清理策略:由于硬件数据吞吐量较大(特别是 256Hz EEG),建议在视图消失(
viewWillDisappear)或 App 切入后台(若未申请后台运行权限)时,主动请求关闭对应的数据通道(如调用device.stopDataStream()),节省设备耗电;在真正不需要连接时执行device.disconnect()释放句柄。
📖 完整集成示例
以上 API 参考涵盖了 SDK 核心组件的功能定义。为了协助开发者更直观地将各个模块组合应用至实际的 iOS 工程体系中,我们提供了一套开源参考实现。
该工程利用原生的 UIKit 与 Storyboard 构建,重点演示了:
- 结合系统
CoreBluetooth和 SDK 内置能力的扫描和鉴权全流程。 - iOS 权限安全体系下的时序调用策略。
- 采用 DGCharts 之类的图形库在主线程展示实时生理参数的时延优化。
查阅具体代码与完整应用层实现:
