iOS API 接口参考
SDK Version: 1.0.0
Platform: iOS
所有带 @MainActor 的类型、属性和方法都应在 MainActor 上使用。默认参数以下列签名为准。
XTalkBleClient
@MainActor public final class XTalkBleClient: NSObject, ObservableObject
public override init()
每个 client 管理一个 BLE 生命周期和一条串行 AT/RF 通道。teardown() 后不可复用。
公开状态
| 属性 | 类型 | 含义 |
|---|---|---|
connectionState | XTalkConnectionState | 当前扫描/连接状态;只读、可通过 $connectionState 观察 |
scanResults | [XTalkScanResult] | 当前扫描会话的设备列表 |
connectedName | String? | 已选/已连接设备名称 |
connectedAddress | String? | 地址(平台不提供时为空) |
connectedPeripheralId | UUID? | 当前 peripheral 标识 |
atReady | Bool | passthrough 写和通知是否已就绪 |
deviceControlReady | Bool | 设备控制查询是否已就绪 |
atEncoding | XTalkAtEncoding | 当前 AT 编码;默认 .xor |
events | AsyncStream<XTalkBleEvent> | 有界事件流;teardown() 时结束 |
onEvent | (@MainActor (XTalkBleEvent) -> Void)? | 可选单一事件回调 |
连接与生命周期方法
| 方法 | 前置条件 | 结果/注意事项 |
|---|---|---|
startScan() | client 未 teardown | 清空并持续更新扫描结果;失败发布 .failed |
stopScan() | 无 | 停止扫描;扫描态回到 .idle |
connect(id:) | 蓝牙可用,id 来自当前结果 | 停止扫描并异步连接;结果由状态/事件发布 |
disconnect() | 无 | 取消连接和待处理事务,可再次扫描连接 |
teardown() | 无 | 终止扫描、连接、事务和事件流;幂等、不可逆 |
AT 与 RF 方法
public func setAtEncoding(_ encoding: XTalkAtEncoding)
public func runAtCommand(
_ plain: String,
timeoutMs: Int = 3_000,
log: Bool = true,
responseMode: XTalkAtResponseMode = .automatic
) async throws -> [String]
public func sendAtCommandNoWait(_ plain: String) throws
public func withExclusiveAtSession<T>(
_ operation: @MainActor (XTalkBleClient) async throws -> T
) async throws -> T
public func sendRfPayload(_ rawPayload: Data, timeoutMs: Int = 5_000) async throws
public func sendRfPayloadNoWait(_ rawPayload: Data) throws
| 方法 | 输入 | 返回/错误 |
|---|---|---|
setAtEncoding | .plain 或 .xor | 清理当前文本解码缓冲;不要在事务中途切换 |
runAtCommand | 不含业务外 framing 的 AT 字符串、正超时、响应模式 | 返回响应行;可能抛连接、就绪、忙、超时、写入或取消错误 |
sendAtCommandNoWait | AT 字符串 | 只启动写入;响应走事件/observer,通道隔离期间可抛 .busy |
withExclusiveAtSession | 串行 async 闭包 | 返回闭包结果;保证一组 AT 操作不被其他调用插入 |
sendRfPayload | 原始业务 payload | 等待完整发送结束;超时或断链时抛错 |
sendRfPayloadNoWait | 原始业务 payload | 只启动发送;完成走事件,隔离期间可抛 .busy |
设备信息查询
public func fetchBatteryLevel(timeoutMs: Int = 2_000) async -> Int?
public func fetchBleFirmwareVersion(timeoutMs: Int = 2_000) async -> String?
public func fetchHardwareVersion(timeoutMs: Int = 2_000) async -> String?
这些便捷查询不抛错,失败返回 nil。调用前检查 deviceControlReady。电量是设备返回的整数;SDK 不承诺客户 UI 的范围或格式策略。版本字符串已去除首尾空白。
细粒度 observer
public func observeAtLines(_ handler: @escaping @MainActor (String) -> Void) -> UUID
public func removeAtLineObserver(_ id: UUID)
public func observeSendFinishLines(_ handler: @escaping @MainActor (String) -> Void) -> UUID
public func removeSendFinishLineObserver(_ id: UUID)
public func observePassthroughRaw(_ handler: @escaping @MainActor (Data) -> Void) -> UUID
public func removePassthroughRawObserver(_ id: UUID)
注册方法返回 token,移除方法只接受对应 token。observer 在 MainActor 回调;客户不要在回调中执行长时间阻塞工作。
扫描与连接模型
XTalkScanResult
public init(id: UUID, name: String, address: String?, rssi: Int)
public var displayName: String { get }
displayName 在地址存在时组合名称和地址,否则返回名称。id 用于 connect(id:)。
XTalkConnectionState
.idle、.scanning、.connecting、.connected、.disconnected、.failed(XTalkBleError)。
XTalkBleError
.bluetoothUnavailable、.permissionDenied、.scanFailed(String)、.deviceNotFound(UUID)、.deviceMismatch(String)、.connectionFailed(String)、.serviceMissing、.characteristicMissing、.notConnected、.notReady、.busy、.timeout、.writeFailed(String)、.cancelled、.malformedResponse(String)、.deviceControlFailed(String)。
处理建议见错误与常见问题。
AT、RF 与事件模型
XTalkAtEncoding:.plain、.xor。XTalkAtResponseMode:.automatic按命令策略结束;.collectUntilTimeout收集完整超时窗口。XTalkDiMeta:可选的diCnt、len、slot、snr、rssi、localSnr、localRssi、remoteSnr、remoteRssi、txp,初始化器所有参数默认nil。XTalkBleEvent.connectionStateChanged(XTalkConnectionState):状态变化。XTalkBleEvent.atLine(String):解析后的 AT 行。XTalkBleEvent.sendFinished:发送完成。XTalkBleEvent.diPayload(Data, XTalkDiMeta):业务 payload 与无线元数据。XTalkBleEvent.crcError(XTalkDiMeta, String):CRC 错误元数据和原始行。XTalkBleEvent.passthroughRaw(Data):未归类的原始透传数据。
DeviceAuthTransport
@MainActor public protocol DeviceAuthTransport: AnyObject {
var label: String { get }
var atEncoding: DeviceAuthAtEncoding { get }
func setAtEncoding(_ encoding: DeviceAuthAtEncoding)
func runAtCommand(
_ command: String,
timeoutMs: Int,
log: Bool,
responseMode: DeviceAuthResponseMode
) async throws -> [String]
}
DeviceAuthAtEncoding 有 .plain、.xor。DeviceAuthResponseMode 有 .automatic、.collectFullWindow、.recoverableEncodingProbe。后两种必须保留完整窗口语义;.recoverableEncodingProbe 在编码探测不确定时还要求下一个命令开始前通道已恢复干净。
完整 BLE adapter 见设备认证 SDK。
XTalkDeviceAuthenticator
@MainActor public final class XTalkDeviceAuthenticator: ObservableObject {
@Published public private(set) var state: XTalkDeviceAuthState
public init(transport: any DeviceAuthTransport)
public func authenticate(
configuration: XTalkDeviceAuthConfiguration = XTalkDeviceAuthConfiguration()
) async throws -> XTalkDeviceAuthResult
public func cancel()
}
authenticate 自动探测编码、按需要执行 Challenge、读取身份并返回结果。同一实例只允许一个活动会话;失败会更新 .failed(error) 并抛出同一公开错误。cancel() 请求取消当前会话,没有活动会话时无操作。
认证配置、结果与状态
XTalkDeviceAuthConfiguration
public init(
probeTimeoutMs: Int = 800,
strictProbeTimeoutMs: Int = 1_200,
challengeTimeoutMs: Int = 4_000,
identityTimeoutMs: Int = 4_000,
maxChallengeAttempts: Int = 3
)
所有值必须大于 0,否则认证抛 .invalidConfiguration。
XTalkDeviceAuthResult
identity: XTalkDeviceIdentity、encoding: DeviceAuthAtEncoding、didRequireChallenge: Bool;公开初始化器接受相同三个参数。
XTalkDeviceAuthState
.idle、.probing、.challenging(attempt:maxAttempts:)、.readingIdentity、.authenticated(XTalkDeviceIdentity)、.failed(XTalkDeviceAuthError)、.cancelled。
XTalkDeviceAuthError
.busy、.invalidConfiguration、.transportUnavailable、.commandTimedOut(String)、.secureRandomUnavailable、.invalidChallenge、.challengeMissing、.malformedChallengeReply、.invalidSignatureLength(Int)、.signatureVerificationFailed、.challengeRetryExhausted、.invalidDeviceIdentity、.cancelled。
设备身份与 DID 工具
XTalkDeviceIdentity
public init(
deviceID: UInt32,
did: String,
serial: String,
source: XTalkDeviceIdentitySource
)
source 为 .efuseSn 或 .sn。认证正常使用时直接消费返回的 identity,不要自行构造。
XTalkDeviceIDCodec
| 方法 | 作用 |
|---|---|
canonicalize(_ raw: UInt32) -> UInt32 | 规范化历史设备标识编码 |
fromSn(year: Int, week: Int, serial: UInt32) -> UInt32 | 按协议位宽从 SN 字段构建设备标识 |
parse(_ raw: String) -> UInt32? | 解析十进制或 0x 十六进制文本并规范化 |
format(_ raw: UInt32) -> String | 输出规范的 0x 加 8 位大写十六进制文本 |