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:
@@ -7,17 +7,17 @@ import Foundation
|
||||
|
||||
extension DuooomiBleSDK {
|
||||
|
||||
/// 拉取服务端最新固件信息。**内部串三步业务编排**(顺序固定):
|
||||
/// 拉取服务端最新固件信息。**内部串两步业务编排**(顺序固定):
|
||||
///
|
||||
/// 1. **对账上报**:把本地 pending `UpgradeRecord` 逐条报给服务端(容错失败,不阻断)
|
||||
/// 2. **软绑**:POST `/api/auth/loomart/shipment-sn/device/bind`,登记云端绑定关系
|
||||
/// - 软绑失败 → 自动硬解绑(BLE 0x12)回滚 + 重置 `isActivated`/`sn`,整个 fetch 失败
|
||||
/// 3. **拉服务端最新固件**:写入 `self.firmwareUpgrade`,通过 completion 回传
|
||||
/// 2. **拉服务端最新固件**:写入 `self.firmwareUpgrade`,通过 completion 回传
|
||||
///
|
||||
/// 软绑 / metadata 上报 / 硬绑失败回滚 → 已全部内聚到 `bind(userId:)`,本方法不再处理。
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - sn: 设备序列号(bind 成功后从 `sdk.sn` 取)
|
||||
/// - currentVersion: 设备当前固件版本(从 `sdk.version` 取)
|
||||
/// - userId: 当前用户 ID
|
||||
/// - userId: 当前用户 ID(写入对账上报的 failureReason)
|
||||
public func fetchLatestFirmware(
|
||||
sn: String,
|
||||
currentVersion: String,
|
||||
@@ -34,41 +34,18 @@ extension DuooomiBleSDK {
|
||||
// Step 1: 对账上报历史 OTA 记录(容错失败,sn 级 in-flight 互斥)
|
||||
self.tryReportPendingUpgrade(sn: sn, currentVersion: currentVersion, userId: userId)
|
||||
|
||||
// Step 2: 软绑(shipment-sn HTTP)
|
||||
// 失败 → 自动硬解绑(BLE 0x12)回滚 + 重置 isActivated/sn,保持云端 ↔ 本地状态一致;
|
||||
// 整个 fetchLatestFirmware 失败回传,调用方收到错误后可重新走 bind 流程。
|
||||
BleLog.d("Soft bind start: sn=\(sn)", "Firmware")
|
||||
shipmentService.bind(sn: sn, bindUserId: userId) { [weak self] result in
|
||||
// Step 2: 服务端 checkUpgrade
|
||||
self.firmwareUpgradeService.checkUpgrade(sn: sn, currentVersion: currentVersion) { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
if case .failure(let err) = result {
|
||||
BleLog.e("Soft bind failed during fetchLatestFirmware: \(err.localizedDescription); rolling back hard unbind", "Firmware")
|
||||
// 硬解绑回滚(fire-and-forget;BLE ack 不影响这次 fetch 错误回传)
|
||||
self.deviceInfoService.unbindDevice(userId: userId) { rollbackResult in
|
||||
if case .failure(let rbErr) = rollbackResult {
|
||||
BleLog.w("Hard unbind rollback failed (ignored): \(rbErr.localizedDescription)", "Firmware")
|
||||
} else {
|
||||
BleLog.i("Hard unbind rollback sent", "Firmware")
|
||||
}
|
||||
switch result {
|
||||
case .success(let r):
|
||||
DispatchQueue.main.async {
|
||||
self.firmwareUpgrade = r
|
||||
completion(.success(r))
|
||||
}
|
||||
self.isActivated = false
|
||||
self.sn = ""
|
||||
case .failure(let err):
|
||||
BleLog.w("checkUpgrade failed: \(err.localizedDescription)", "Firmware")
|
||||
DispatchQueue.main.async { completion(.failure(err)) }
|
||||
return
|
||||
}
|
||||
BleLog.i("Soft bind success: sn=\(sn)", "Firmware")
|
||||
|
||||
// Step 3: 服务端 checkUpgrade
|
||||
self.firmwareUpgradeService.checkUpgrade(sn: sn, currentVersion: currentVersion) { result in
|
||||
switch result {
|
||||
case .success(let r):
|
||||
DispatchQueue.main.async {
|
||||
self.firmwareUpgrade = r
|
||||
completion(.success(r))
|
||||
}
|
||||
case .failure(let err):
|
||||
BleLog.w("checkUpgrade failed: \(err.localizedDescription)", "Firmware")
|
||||
DispatchQueue.main.async { completion(.failure(err)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user