import SwiftUI import DuooomiBleSDK /// Demo 入口:初始化 SDK 并注入到视图树。 @main struct DemoApp: App { @StateObject private var viewModel = DemoViewModel() var body: some Scene { WindowGroup { NavigationView { WrapperTestView(viewModel: viewModel) } } } } /// ViewModel 包装 SDK callback API,通过 DuooomiBleSDKDelegate 驱动 UI 更新。 final class DemoViewModel: NSObject, ObservableObject, DuooomiBleSDKDelegate { // MARK: - SDK Config(demo 内可改,持久化到 UserDefaults) @Published var configBrand: String { didSet { defaults.set(configBrand, forKey: Self.keyBrand) } } @Published var configApiKey: String { didSet { defaults.set(configApiKey, forKey: Self.keyApiKey) } } @Published var configScanPrefix: String { didSet { defaults.set(configScanPrefix, forKey: Self.keyScanPrefix) } } @Published var configFrameIntervalMs: String { didSet { defaults.set(configFrameIntervalMs, forKey: Self.keyFrameIntervalMs) } } // MARK: - SDK State (driven by delegate) @Published var btState: ConnectionState = .idle @Published var connectedDevice: DiscoveredDevice? = nil @Published var discoveredDevices: [DiscoveredDevice] = [] @Published var deviceInfo: DeviceInfo? = nil @Published var version: String = "" @Published var isActivated: Bool = false @Published var transferProgress: Int = 0 @Published var error: String? = nil @Published var upgradeRecords: [UpgradeRecord] = [] @Published private(set) var sdk: DuooomiBleSDK // MARK: - Internals private let defaults = UserDefaults.standard private static let keyBrand = "demo.config.brand" private static let keyApiKey = "demo.config.apiKey" private static let keyScanPrefix = "demo.config.scanPrefix" private static let keyFrameIntervalMs = "demo.config.frameIntervalMs" /// demo 调试默认值(仅当 UserDefaults 没存过时使用)。秘钥从 DemoSecrets 读,避免泄露到仓库。 private static let defaultBrand = DemoSecrets.brand private static let defaultApiKey = DemoSecrets.apiKey private static let defaultScanPrefix = DemoSecrets.scanNamePrefix private static let defaultFrameIntervalMs = "35" override init() { let d = UserDefaults.standard let brand = d.string(forKey: Self.keyBrand) ?? Self.defaultBrand let apiKey = d.string(forKey: Self.keyApiKey) ?? Self.defaultApiKey let scanPrefix = d.string(forKey: Self.keyScanPrefix) ?? Self.defaultScanPrefix let frameIntervalMs = d.string(forKey: Self.keyFrameIntervalMs) ?? Self.defaultFrameIntervalMs self.configBrand = brand self.configApiKey = apiKey self.configScanPrefix = scanPrefix self.configFrameIntervalMs = frameIntervalMs self.sdk = DuooomiBleSDK(config: .init( apiKey: apiKey, brand: brand, scanNamePrefix: scanPrefix, frameIntervalMs: Int(frameIntervalMs) ?? 35 )) super.init() sdk.delegate = self // 初次加载 SDK 持久化的 records(之前历史升级 / 待对账) upgradeRecords = sdk.upgradeRecords } /// demo 内修改配置后调用:重新创建 SDK 实例并迁移 delegate。 func reloadSDK() { let new = DuooomiBleSDK(config: .init( apiKey: configApiKey, brand: configBrand, scanNamePrefix: configScanPrefix, frameIntervalMs: Int(configFrameIntervalMs) ?? 35 )) new.delegate = self self.sdk = new // 重置展示状态 btState = .idle connectedDevice = nil discoveredDevices = [] deviceInfo = nil version = "" isActivated = false transferProgress = 0 error = nil upgradeRecords = new.upgradeRecords } // MARK: - DuooomiBleSDKDelegate func sdk(_ sdk: DuooomiBleSDK, didChangeState state: ConnectionState) { btState = state } func sdk(_ sdk: DuooomiBleSDK, didUpdateDevices devices: [DiscoveredDevice]) { discoveredDevices = devices } func sdk(_ sdk: DuooomiBleSDK, didConnectDevice device: DiscoveredDevice?) { connectedDevice = device } func sdk(_ sdk: DuooomiBleSDK, didUpdateDeviceInfo info: DeviceInfo?) { deviceInfo = info } func sdk(_ sdk: DuooomiBleSDK, didUpdateVersion version: String) { self.version = version } func sdk(_ sdk: DuooomiBleSDK, didChangeActivation isActivated: Bool) { self.isActivated = isActivated } func sdk(_ sdk: DuooomiBleSDK, didUpdateProgress progress: Int) { transferProgress = progress } func sdk(_ sdk: DuooomiBleSDK, didUpdateUpgradeRecords records: [UpgradeRecord]) { upgradeRecords = records } func sdk(_ sdk: DuooomiBleSDK, didEncounterError error: String?) { self.error = error } }