feat: 重写 SDK 支持 iOS 12.2,移除 async/await 和 Combine
- 所有公开 API 改为 completion handler (Result<T, Error>) - 状态通知改为 DuooomiBleSDKDelegate 协议 - 移除 Sendable、@MainActor、AsyncStream、CheckedContinuation - 网络请求改为 URLSession.dataTask 回调 - BLE 通信改为 delegate + 闭包模式 - deployment target 降至 iOS 12.2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
130
README.md
130
README.md
@@ -28,70 +28,119 @@ let sdk = DuooomiBleSDK(config: .init(
|
||||
apiKey: "your-api-key" // 必填
|
||||
// apiHost: URL(...)!, // 默认 https://api.duooomi.com
|
||||
// cdnHost: "https://cdn.bowong.cc/", // 默认
|
||||
// firmwareIdentifier: "duomi", // 默认
|
||||
// firmwareStatus: "DRAFT" // 默认
|
||||
// aniWidth: 360, // ANI 转换宽度,默认 360
|
||||
// aniHeight: 360, // ANI 转换高度,默认 360
|
||||
// aniFps: "24", // ANI 转换帧率,默认 24
|
||||
// firmwareIdentifier: "duomi", // 默认
|
||||
// firmwareStatus: "DRAFT" // 默认
|
||||
))
|
||||
|
||||
// 设置代理接收状态变化
|
||||
sdk.delegate = self
|
||||
```
|
||||
|
||||
## 代理(Delegate)
|
||||
|
||||
通过 `DuooomiBleSDKDelegate` 接收状态变化,所有方法在主线程调用,均有默认空实现:
|
||||
|
||||
```swift
|
||||
extension ViewController: DuooomiBleSDKDelegate {
|
||||
func sdk(_ sdk: DuooomiBleSDK, didChangeState state: ConnectionState) { }
|
||||
func sdk(_ sdk: DuooomiBleSDK, didUpdateDevices devices: [DiscoveredDevice]) { }
|
||||
func sdk(_ sdk: DuooomiBleSDK, didConnectDevice device: DiscoveredDevice?) { }
|
||||
func sdk(_ sdk: DuooomiBleSDK, didUpdateDeviceInfo info: DeviceInfo?) { }
|
||||
func sdk(_ sdk: DuooomiBleSDK, didUpdateVersion version: String) { }
|
||||
func sdk(_ sdk: DuooomiBleSDK, didChangeActivation isActivated: Bool) { }
|
||||
func sdk(_ sdk: DuooomiBleSDK, didUpdateProgress progress: Int) { }
|
||||
func sdk(_ sdk: DuooomiBleSDK, didEncounterError error: String?) { }
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
所有异步方法使用 `completion` 回调,返回 `Result<T, Error>`。
|
||||
|
||||
### 扫描
|
||||
|
||||
| 方法 | 返回 | 说明 |
|
||||
|------|------|------|
|
||||
| `scan()` | `Void` | 开始扫描,结果通过 `discoveredDevices` 观察 |
|
||||
| `stopScan()` | `Void` | 停止扫描 |
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| `scan()` | 开始扫描,结果通过 delegate `didUpdateDevices` 回调 |
|
||||
| `stopScan()` | 停止扫描 |
|
||||
|
||||
### 连接
|
||||
|
||||
| 方法 | 返回 | 说明 |
|
||||
|------|------|------|
|
||||
| `connect(deviceId: String)` | `DiscoveredDevice` | 连接设备 |
|
||||
| `disconnect()` | `Void` | 断开连接 |
|
||||
| `getConnectedDevices()` | `[DiscoveredDevice]` | 获取系统已连接设备 |
|
||||
```swift
|
||||
sdk.connect(deviceId: deviceId) { result in
|
||||
switch result {
|
||||
case .success(let device): print("Connected: \(device.name ?? device.id)")
|
||||
case .failure(let error): print("Failed: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
sdk.disconnect { result in
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 设备命令
|
||||
|
||||
| 方法 | 返回 | 说明 |
|
||||
|------|------|------|
|
||||
| `getDeviceInfo()` | `DeviceInfo` | 品牌、容量、电量、型号 |
|
||||
| `getVersion()` | `VersionInfo` | 固件版本 |
|
||||
| `bind(userId: String)` | `BindingResponse` | 绑定设备,返回 sn + 文件列表。**绑定后才能查看设备文件** |
|
||||
| `unbind(userId: String)` | `UnbindResponse` | 解绑设备。**解绑后该账号的设备文件将被删除** |
|
||||
| `deleteFile(key: String)` | `DeleteFileResponse` | 删除设备上的单个文件 |
|
||||
```swift
|
||||
sdk.getDeviceInfo { result in
|
||||
if case .success(let info) = result {
|
||||
print("Brand: \(info.brand), Power: \(info.powerlevel)%")
|
||||
}
|
||||
}
|
||||
|
||||
sdk.getVersion { result in
|
||||
if case .success(let info) = result {
|
||||
print("Version: \(info.version)")
|
||||
}
|
||||
}
|
||||
|
||||
sdk.bind(userId: "user-id") { result in
|
||||
if case .success(let resp) = result {
|
||||
print("SN: \(resp.sn), Files: \(resp.contents.count)")
|
||||
}
|
||||
}
|
||||
|
||||
sdk.unbind(userId: "user-id") { result in /* ... */ }
|
||||
sdk.deleteFile(key: "file-key") { result in /* ... */ }
|
||||
```
|
||||
|
||||
### 文件传输
|
||||
|
||||
| 方法 | 返回 | 说明 |
|
||||
|------|------|------|
|
||||
| `transferMedia(fileUrl: String)` | `Void` | 输入文件 URL(mp4/jpg/png),内部自动完成 ANI 转换 → prepare → 传输。进度通过 `transferProgress` 观察 |
|
||||
```swift
|
||||
// 一步完成:自动 ANI 转换 → prepare → transfer
|
||||
sdk.transferMedia(fileUrl: "https://example.com/video.mp4") { result in
|
||||
switch result {
|
||||
case .success: print("Transfer complete")
|
||||
case .failure(let error): print("Transfer failed: \(error)")
|
||||
}
|
||||
}
|
||||
// 进度通过 delegate didUpdateProgress 回调
|
||||
```
|
||||
|
||||
### 固件升级
|
||||
|
||||
| 方法 | 返回 | 说明 |
|
||||
|------|------|------|
|
||||
| `fetchLatestFirmware(identifier:status:)` | `FirmwareInfo?` | 查询最新固件,nil 表示无可用版本 |
|
||||
| `hasNewerFirmware(deviceVersion:serverVersion:)` | `Bool` | 对比版本号末尾10位时间戳,判断是否有新版本。参数无效返回 false |
|
||||
| `upgradeFirmware(fileUrl: String)` | `Void` | OTA 传输固件包到设备 |
|
||||
|
||||
```swift
|
||||
// 1. 查询最新固件
|
||||
let info = try await sdk.fetchLatestFirmware()
|
||||
sdk.fetchLatestFirmware { result in
|
||||
guard case .success(let info?) = result else { return }
|
||||
|
||||
// 2. 检查是否有新版本
|
||||
let needUpdate = sdk.hasNewerFirmware(
|
||||
deviceVersion: sdk.version, // 当前设备版本
|
||||
serverVersion: info?.version // 服务端最新版本
|
||||
)
|
||||
// 2. 检查是否有新版本
|
||||
let needUpdate = sdk.hasNewerFirmware(
|
||||
deviceVersion: sdk.version,
|
||||
serverVersion: info.version
|
||||
)
|
||||
|
||||
// 3. OTA 升级
|
||||
try await sdk.upgradeFirmware(fileUrl: info.fileUrl)
|
||||
// 3. OTA 升级
|
||||
if needUpdate {
|
||||
sdk.upgradeFirmware(fileUrl: info.fileUrl) { result in /* ... */ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 可观察状态
|
||||
### 可读取状态
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
@@ -124,8 +173,8 @@ public struct DeviceInfo {
|
||||
let brand: String // 品牌
|
||||
let size: String // 屏幕尺寸
|
||||
let powerlevel: Int // 电量百分比
|
||||
let allspace: Int // 总存储(字节)
|
||||
let freespace: Int // 可用存储(字节)
|
||||
let allspace: UInt64 // 总存储(字节)
|
||||
let freespace: UInt64 // 可用存储(字节)
|
||||
}
|
||||
|
||||
// BindingResponse — bind 返回
|
||||
@@ -145,5 +194,6 @@ public struct BindingResponse {
|
||||
|
||||
## 技术规格
|
||||
|
||||
- iOS 16.0+ / Swift 5.9+ / 零依赖
|
||||
- 公开 API @MainActor,BLE 操作专用串行队列
|
||||
- iOS 12.2+ / Swift 5.0+ / 零依赖
|
||||
- Delegate 回调模式,所有状态变化在主线程通知
|
||||
- BLE 操作专用串行队列
|
||||
|
||||
Reference in New Issue
Block a user