224 lines
7.1 KiB
Markdown
224 lines
7.1 KiB
Markdown
# Duooomi BLE SDK (Native iOS)
|
||
|
||
纯原生 Swift 蓝牙 SDK,使用 CoreBluetooth 直接操作,零第三方依赖。
|
||
|
||
## 架构设计
|
||
|
||
```
|
||
调用方 (宿主 App)
|
||
│
|
||
└── DuooomiBleSDK (ObservableObject) ← 公开 API + 状态观察
|
||
│
|
||
├── BleClient ← CoreBluetooth 封装
|
||
│ CBCentralManager / CBPeripheral
|
||
│
|
||
├── BleProtocolService ← 协议帧收发 + 分包重组
|
||
│ ProtocolManager (编码/解码/校验)
|
||
│
|
||
├── DeviceInfoService ← 设备命令 (JSON 请求/响应)
|
||
│
|
||
└── FileTransferService ← 文件下载 + 二进制传输
|
||
```
|
||
|
||
### 目录结构
|
||
|
||
```
|
||
Sources/DuooomiBleSDK/
|
||
├── DuooomiBleSDK.swift # 公开 API facade (ObservableObject)
|
||
├── Core/
|
||
│ ├── BleClient.swift # CoreBluetooth 封装 (scan/connect/write/notify)
|
||
│ └── BleTypes.swift # ConnectionState, DiscoveredDevice, DuooomiBleError
|
||
├── Protocol/
|
||
│ ├── ProtocolConstants.swift # BLE UUID, 帧常量, CommandType 枚举
|
||
│ ├── ProtocolFrame.swift # 协议帧结构体
|
||
│ └── ProtocolManager.swift # 帧编解码、校验和、分片/重组
|
||
├── Services/
|
||
│ ├── BleProtocolService.swift # 监听通知、解析帧、分包重组、帧发送
|
||
│ ├── DeviceInfoService.swift # 设备命令发送 (JSON payload)
|
||
│ └── FileTransferService.swift # 文件下载 + 二进制传输
|
||
└── Models/
|
||
├── DeviceInfo.swift # 设备信息 (allspace/freespace/brand/...)
|
||
├── VersionInfo.swift # 固件版本
|
||
├── BindingResponse.swift # 绑定响应 (sn/success/contents)
|
||
├── UnbindResponse.swift # 解绑响应
|
||
├── DeleteFileResponse.swift # 删除文件响应
|
||
└── PrepareTransferResponse.swift # 预传输响应
|
||
```
|
||
|
||
### 协议帧格式
|
||
|
||
```
|
||
[head:1][type:1][subpageTotal:2][curPage:2][dataLen:2][data:N][checksum:1]
|
||
```
|
||
|
||
| 字段 | 大小 | 说明 |
|
||
|------|------|------|
|
||
| head | 1 byte | 方向标识: APP→Device=0xC7, Device→APP=0xB0 |
|
||
| type | 1 byte | 命令类型 (CommandType 枚举) |
|
||
| subpageTotal | 2 bytes | 总分包数 (0=单帧) |
|
||
| curPage | 2 bytes | 当前包序号 (从 total-1 倒数到 0) |
|
||
| dataLen | 2 bytes | 数据段长度 |
|
||
| data | N bytes | 数据内容 (JSON 或二进制) |
|
||
| checksum | 1 byte | 校验: (~字节和 + 1) & 0xFF |
|
||
|
||
### 请求-响应模式
|
||
|
||
```swift
|
||
// 发送命令 → 注册 CheckedContinuation → 等待设备回包 → 自动解码
|
||
let info = try await sdk.getDeviceInfo() // 10s 超时
|
||
```
|
||
|
||
内部流程:
|
||
1. 注册 continuation (keyed by commandType)
|
||
2. 编码 JSON → 创建协议帧 → 写入 write characteristic
|
||
3. 设备回包 → notify → 解析帧 → 分包重组 → 匹配 continuation → resume
|
||
|
||
---
|
||
|
||
## 功能清单
|
||
|
||
### 扫描
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `scan()` | 开始扫描,结果通过 `discoveredDevices` 属性观察 (500ms 批量刷新) |
|
||
| `stopScan()` | 停止扫描 |
|
||
|
||
### 连接
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `connect(deviceId:) async throws -> DiscoveredDevice` | 连接设备 (含服务发现 + 特征发现 + notify 启用) |
|
||
| `disconnect() async throws` | 断开连接,清理所有状态 |
|
||
|
||
### 设备命令 (请求-响应,10s 超时)
|
||
|
||
| 方法 | 发送 payload | 响应类型 |
|
||
|------|-------------|---------|
|
||
| `getDeviceInfo()` | `{"type":13}` | `DeviceInfo` |
|
||
| `getVersion()` | `{"type":7}` | `VersionInfo` |
|
||
| `bind(userId:)` | `{"type":15,"userId":"..."}` | `BindingResponse` |
|
||
| `unbind(userId:)` | `{"type":18,"userId":"..."}` | `UnbindResponse` |
|
||
| `deleteFile(key:)` | `{"type":19,"key":"..."}` | `DeleteFileResponse` |
|
||
| `prepareTransfer(key:size:)` | `{"type":20,"key":"...","size":N}` | `PrepareTransferResponse` |
|
||
|
||
### 文件传输
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `transferFile(fileUri:commandType:) async throws` | 下载文件 + 分帧传输,进度通过 `transferProgress` 观察 |
|
||
|
||
### 可观察状态
|
||
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `btState` | `ConnectionState` | idle/scanning/connecting/connected/disconnecting/disconnected |
|
||
| `discoveredDevices` | `[DiscoveredDevice]` | 扫描发现的设备列表 |
|
||
| `connectedDevice` | `DiscoveredDevice?` | 当前连接的设备 |
|
||
| `deviceInfo` | `DeviceInfo?` | 设备信息 (空间/品牌/电量等) |
|
||
| `version` | `String` | 固件版本 |
|
||
| `isActivated` | `Bool` | 是否已绑定 |
|
||
| `transferProgress` | `Int` | 传输进度 0-100 |
|
||
| `error` | `String?` | 最近的错误信息 |
|
||
|
||
### CommandType 枚举
|
||
|
||
| Case | 值 | 用途 |
|
||
|------|-----|------|
|
||
| `.otaPackage` | 0x02 | OTA 升级包 |
|
||
| `.transferBootAnimation` | 0x03 | 开机动画 |
|
||
| `.transferAniVideo` | 0x05 | ANI 视频 (默认) |
|
||
| `.transferJpegImage` | 0x06 | JPEG 图片 |
|
||
| `.getDeviceVersion` | 0x07 | 获取固件版本 |
|
||
| `.getDeviceInfo` | 0x0D | 获取设备信息 |
|
||
| `.bindDevice` | 0x0F | 绑定设备 |
|
||
| `.unbindDevice` | 0x12 | 解绑设备 |
|
||
| `.deleteFile` | 0x13 | 删除文件 |
|
||
| `.prepareTransfer` | 0x14 | 预传输检查 |
|
||
|
||
---
|
||
|
||
## 集成方式
|
||
|
||
### Swift Package Manager (推荐)
|
||
|
||
```swift
|
||
// Package.swift
|
||
dependencies: [
|
||
.package(path: "../duooomi-ios-sdk")
|
||
]
|
||
|
||
// 或远程
|
||
dependencies: [
|
||
.package(url: "https://github.com/xxx/duooomi-ios-sdk.git", from: "1.0.0")
|
||
]
|
||
```
|
||
|
||
### 使用示例
|
||
|
||
```swift
|
||
import DuooomiBleSDK
|
||
|
||
@main
|
||
struct MyApp: App {
|
||
@StateObject private var sdk = DuooomiBleSDK()
|
||
|
||
var body: some Scene {
|
||
WindowGroup {
|
||
ContentView()
|
||
.environmentObject(sdk)
|
||
}
|
||
}
|
||
}
|
||
|
||
struct ContentView: View {
|
||
@EnvironmentObject var sdk: DuooomiBleSDK
|
||
|
||
var body: some View {
|
||
VStack {
|
||
Text("State: \(sdk.btState.rawValue)")
|
||
|
||
Button("Scan") { sdk.scan() }
|
||
|
||
ForEach(sdk.discoveredDevices) { device in
|
||
Button(device.name ?? device.id) {
|
||
Task {
|
||
try await sdk.connect(deviceId: device.id)
|
||
let info = try await sdk.getDeviceInfo()
|
||
print("Device: \(info.brand)")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Info.plist 权限
|
||
|
||
```xml
|
||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||
<string>This app needs Bluetooth to communicate with your device</string>
|
||
```
|
||
|
||
---
|
||
|
||
## 技术规格
|
||
|
||
- **平台**: iOS 16.0+
|
||
- **语言**: Swift 5.9+
|
||
- **依赖**: 零 (仅 CoreBluetooth 系统框架)
|
||
- **分发**: SPM / XCFramework
|
||
- **线程模型**: 公开 API 为 @MainActor,BLE 操作在专用串行队列
|
||
|
||
## 与旧 Brownfield SDK 对比
|
||
|
||
| 维度 | Brownfield | 原生 SDK |
|
||
|------|-----------|---------|
|
||
| 体积 | ~75MB (含 Hermes + RN) | ~几百KB |
|
||
| 构建 | 7 个 patch + prebuild + pod | `swift build` |
|
||
| 类型安全 | `[String: Any]` 字典 | 强类型 struct/enum |
|
||
| API | 回调 + 消息传递 | `async throws` |
|
||
| 调试 | JS + Native 两层 | 纯 Xcode 断点 |
|
||
| 依赖 | React Native, Hermes, Expo | CoreBluetooth (系统框架) |
|