feat(sdk): 绑定时上报设备 log 到 update-metadata 并内聚双层绑定

- bind(userId:) 内聚为硬绑 + getVersion + 软绑 + updateMetadata 一次原子调用,
  软绑失败自动硬解绑回滚 + 清状态;集成方无需感知双层绑定
- fetchLatestFirmware 简化为对账上报 + checkUpgrade 两步,不再重复软绑
- VersionInfo 增加 log: [String: Any]?,走 JSONSerialization 解析(放弃 Codable);
  SDK 暴露只读 versionLog,断连/解绑/软绑回滚时清空
- ShipmentSnDeviceService 新增 updateMetadata(sn:data:),抽出 performPOST
  共享 HTTP 编排,新增 postAnyJSON 支持 [String: Any] body
- 老固件不返回 log → versionLog == nil → 自动跳过 updateMetadata,前向兼容

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
km2023
2026-05-18 16:25:55 +08:00
parent cdcf36a75b
commit 4bc8fdb64d
6 changed files with 163 additions and 67 deletions

View File

@@ -41,8 +41,10 @@ extension DuooomiBleSDK {
/// `bind()`
///
/// - Parameter completion: `Result<VersionInfo, Error>`
/// - `VersionInfo` `version` / `type`
/// - `VersionInfo` `version` / `type` / `log?`
/// - `.notConnected` / `.timeout(.getDeviceVersion)` / JSON
/// - Note: `log` JSON SDK `sdk.versionLog`
/// `fetchLatestFirmware` shipment-sn `update-metadata`
public func getVersion(completion: @escaping (Result<VersionInfo, Error>) -> Void) {
guard ensureConnected(completion: completion) else { return }
BleLog.d("Sending getDeviceVersion", "Command")
@@ -54,11 +56,14 @@ extension DuooomiBleSDK {
completion(.failure(error))
case .success(let data):
do {
let info = try self.decodeResponse(VersionInfo.self, from: data)
let info = try VersionInfo.parse(from: data)
self.version = info.version
BleLog.i("Version received: \(info.version) (type=\(info.type))", "Command")
self.versionLog = info.log
BleLog.i("Version received: \(info.version) (type=\(info.type), log=\(info.log != nil ? "present" : "nil"))", "Command")
completion(.success(info))
} catch {
let raw = String(data: data.filter { $0 != 0 }, encoding: .utf8) ?? "<non-utf8, \(data.count) bytes>"
BleLog.e("VersionInfo parse failed: \(error.localizedDescription)\nRaw: \(raw)", "Decode")
completion(.failure(error))
}
}