Files
duooomi-ios-sdk/Sources/DuooomiBleSDK/Services/FirmwareService.swift
km2023 1a7bbdc625 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>
2026-04-16 16:59:39 +08:00

86 lines
2.8 KiB
Swift

import Foundation
///
public struct FirmwareInfo: Codable, Equatable {
public let version: String
public let fileUrl: String
public let description: String?
public let fileSize: String?
public let fileMd5: String?
public let identifier: String?
public let status: String?
}
struct FirmwareResponse: Codable {
let success: Bool
let data: FirmwareInfo?
}
///
final class FirmwareService {
private let config: DuooomiBleConfig
private let latestPath = "api/auth/loomart/firmware/latest-published"
init(config: DuooomiBleConfig) {
self.config = config
}
func fetchLatest(
identifier: String? = nil,
status: String? = nil,
completion: @escaping (Result<FirmwareInfo?, Error>) -> Void
) {
let id = (identifier ?? config.firmwareIdentifier).trimmingCharacters(in: .whitespacesAndNewlines)
let st = status ?? config.firmwareStatus
guard !id.isEmpty else {
completion(.failure(DuooomiBleError.transferFailed("Invalid firmware identifier")))
return
}
let urlString = "\(config.apiHost)/\(latestPath)"
guard var comps = URLComponents(string: urlString) else {
completion(.failure(DuooomiBleError.transferFailed("Invalid firmware URL")))
return
}
comps.queryItems = [
URLQueryItem(name: "identifier", value: id),
URLQueryItem(name: "status", value: st)
]
guard let url = comps.url else {
completion(.failure(DuooomiBleError.transferFailed("Invalid firmware URL")))
return
}
var req = URLRequest(url: url)
req.httpMethod = "GET"
req.setValue(config.apiKey, forHTTPHeaderField: "x-api-key")
req.setValue("application/json", forHTTPHeaderField: "accept")
URLSession.shared.dataTask(with: req) { data, resp, error in
if let error = error {
completion(.failure(error))
return
}
guard let http = resp as? HTTPURLResponse else {
completion(.failure(DuooomiBleError.transferFailed("Invalid response")))
return
}
guard (200...299).contains(http.statusCode) else {
completion(.failure(DuooomiBleError.transferFailed("HTTP \(http.statusCode)")))
return
}
guard let data = data else {
completion(.failure(DuooomiBleError.transferFailed("Empty response")))
return
}
do {
let decoded = try JSONDecoder().decode(FirmwareResponse.self, from: data)
completion(.success(decoded.data))
} catch {
completion(.failure(error))
}
}.resume()
}
}