From 6ed3c555df849d12b45790416c66975ebeec3720 Mon Sep 17 00:00:00 2001 From: km2023 Date: Wed, 20 May 2026 16:02:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(sdk):=20=E6=97=A5=E5=BF=97=E7=AD=89?= =?UTF-8?q?=E7=BA=A7=20logLevel=20=E9=85=8D=E7=BD=AE=E5=8C=96=EF=BC=88?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=20.off=EF=BC=8C=E5=AF=B9=E5=A4=96=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E5=AE=8C=E5=85=A8=E9=9D=99=E9=BB=98=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BleLog 之前所有调用都无条件 print(Debug 包),集成方没法关。新增 public enum BleLogLevel(off/error/warn/info/debug),通过 DuooomiBleConfig.logLevel 传入,DuooomiBleSDK.init 第一行写入 BleLog.level。默认 .off 保证对外集成默认静默,排查时显式开 .debug。 保留 #if DEBUG 兜底,Release 任何 level 都不输出。 frameIntervalMs 越界 warn 从 DuooomiBleConfig.init 挪到 DuooomiBleSDK.init 内、level 设置之后,避免在 level 写入前丢日志。 Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 17 +++++++++++++++++ Sources/DuooomiBleSDK/DuooomiBleConfig.swift | 10 ++++++---- Sources/DuooomiBleSDK/DuooomiBleSDK.swift | 6 +++++- Sources/DuooomiBleSDK/Utils/BleLogger.swift | 17 ++++++++++++++++- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 24a809b..5f53310 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,28 @@ let sdk = DuooomiBleSDK(config: .init( // cdnHost: "https://cdn.bowong.cc/", // 默认 // aniWidth: 360, aniHeight: 360, aniFps: "24", // ANI 转换默认参数 // frameIntervalMs: 35, // 协议帧间隔(ms),合法 [0,500],越界 warn 后 clamp + // logLevel: .off, // 日志等级,默认 .off(完全静默),排查时改 .debug )) sdk.delegate = self ``` +### 日志(BleLogLevel) + +SDK 内部所有日志统一走 `BleLog` → `print`,分级 `off / error / warn / info / debug`。集成方通过 `config.logLevel` 控制输出: + +```swift +// 对外发布:什么都不传,默认完全静默 +DuooomiBleSDK(config: .init(apiKey: ..., brand: ..., scanNamePrefix: ...)) + +// 本地排查:开 debug 看到所有 BLE 帧、RPC opId、传输进度等 +DuooomiBleSDK(config: .init(apiKey: ..., brand: ..., scanNamePrefix: ..., logLevel: .debug)) +``` + +- 等级单调:`.warn` 会输出 warn + error;`.info` 输出 info + warn + error;以此类推。 +- **Release 构建因 `#if DEBUG` 条件编译,任何 `logLevel` 都不会输出**(双保险)。 +- 日志按 category 分桶:`SDK / Scan / Connect / BLE / RPC / Command / Transfer / Firmware / Protocol / Decode / Config`,Xcode console 可按 `[DuooomiBleSDK][]` 过滤。 + ## SDK 能力范围 - **内置**:BLE 协议(扫描/连接/绑定/解绑/播放模式/文件传输/OTA 烧录)+ 固件版本检查 diff --git a/Sources/DuooomiBleSDK/DuooomiBleConfig.swift b/Sources/DuooomiBleSDK/DuooomiBleConfig.swift index cb4a87e..06e13ef 100644 --- a/Sources/DuooomiBleSDK/DuooomiBleConfig.swift +++ b/Sources/DuooomiBleSDK/DuooomiBleConfig.swift @@ -21,6 +21,9 @@ public struct DuooomiBleConfig { /// 协议帧之间的发送间隔(毫秒)。合法区间 `[0, 500]`,越界仅 warn,使用点会 clamp。 /// 集成方一般无需调整;调高用于排查接收端丢帧/拥塞。默认 35。 public let frameIntervalMs: Int + /// SDK 日志等级。默认 `.off`,对外发布完全静默;排查时改 `.warn` 或 `.debug`。 + /// Release 构建因 `#if DEBUG` 条件编译,任何 level 都不会输出。 + public let logLevel: BleLogLevel public init( apiHost: URL = URL(string: "https://api.duooomi.com")!, @@ -31,7 +34,8 @@ public struct DuooomiBleConfig { aniHeight: Int = 360, aniFps: String = "24", scanNamePrefix: String, - frameIntervalMs: Int = 35 + frameIntervalMs: Int = 35, + logLevel: BleLogLevel = .off ) { self.apiHost = apiHost self.apiKey = apiKey @@ -41,9 +45,7 @@ public struct DuooomiBleConfig { self.aniHeight = aniHeight self.aniFps = aniFps self.scanNamePrefix = scanNamePrefix - if frameIntervalMs < 0 || frameIntervalMs > 500 { - BleLog.w("frameIntervalMs=\(frameIntervalMs) out of [0,500], will clamp at use site", "Config") - } self.frameIntervalMs = frameIntervalMs + self.logLevel = logLevel } } diff --git a/Sources/DuooomiBleSDK/DuooomiBleSDK.swift b/Sources/DuooomiBleSDK/DuooomiBleSDK.swift index e33a9ea..3075a90 100644 --- a/Sources/DuooomiBleSDK/DuooomiBleSDK.swift +++ b/Sources/DuooomiBleSDK/DuooomiBleSDK.swift @@ -108,6 +108,7 @@ public final class DuooomiBleSDK: NSObject { // MARK: - Init public init(config: DuooomiBleConfig) { + BleLog.level = config.logLevel self.config = config bleClient = BleClient() protocolService = BleProtocolService(client: bleClient, frameIntervalMs: config.frameIntervalMs) @@ -122,7 +123,10 @@ public final class DuooomiBleSDK: NSObject { super.init() protocolService.delegate = self - BleLog.i("SDK initialized (apiHost=\(config.apiHost), brand=\(config.brand))", "SDK") + BleLog.i("SDK initialized (apiHost=\(config.apiHost), brand=\(config.brand), logLevel=\(config.logLevel))", "SDK") + if config.frameIntervalMs < 0 || config.frameIntervalMs > 500 { + BleLog.w("frameIntervalMs=\(config.frameIntervalMs) out of [0,500], will clamp at use site", "Config") + } setupDisconnectHandler() // UpgradeRecord 变化(含对账上报结果)→ delegate 通知 diff --git a/Sources/DuooomiBleSDK/Utils/BleLogger.swift b/Sources/DuooomiBleSDK/Utils/BleLogger.swift index 037c12c..98dabf2 100644 --- a/Sources/DuooomiBleSDK/Utils/BleLogger.swift +++ b/Sources/DuooomiBleSDK/Utils/BleLogger.swift @@ -1,28 +1,43 @@ import Foundation +/// SDK 日志等级。集成方通过 `DuooomiBleConfig.logLevel` 设定;Release 构建无论如何都静默。 +public enum BleLogLevel: Int { + case off = 0 + case error + case warn + case info + case debug +} + enum BleLog { + /// 由 `DuooomiBleSDK.init(config:)` 写入;默认 `.off`,对外发布完全静默。 + static var level: BleLogLevel = .off + static func d(_ message: @autoclosure () -> String, _ category: String = "General") { #if DEBUG + guard level.rawValue >= BleLogLevel.debug.rawValue else { return } print("[DuooomiBleSDK][\(category)] \(message())") #endif } static func i(_ message: @autoclosure () -> String, _ category: String = "General") { #if DEBUG + guard level.rawValue >= BleLogLevel.info.rawValue else { return } print("ℹ️ [DuooomiBleSDK][\(category)] \(message())") #endif } static func w(_ message: @autoclosure () -> String, _ category: String = "General") { #if DEBUG + guard level.rawValue >= BleLogLevel.warn.rawValue else { return } print("⚠️ [DuooomiBleSDK][\(category)] \(message())") #endif } static func e(_ message: @autoclosure () -> String, _ category: String = "General") { #if DEBUG + guard level.rawValue >= BleLogLevel.error.rawValue else { return } print("❌ [DuooomiBleSDK][\(category)] \(message())") #endif } } -