現(xiàn)在公司用的藍牙芯片是 NRF51 系列,DFU 升級(OTA 升級)可直接使用官方提供的 iOSDFULibrary鹏浅。
準備
使用 cocoapods 安裝
target 'YourAppTargetName' do
use_frameworks!
pod 'iOSDFULibrary'
end
安裝后除了iOSDFULibrary 還有一個 ZIPFoundation。是iOSDFULibrary的一個依賴庫桶至,解壓zip 包用的晾匠,我們不會直接使用。
使用前確認硬件同事發(fā)過來的空升包能正常使用准颓,在 APP Store 下載 nRF Connect 操作哈蝇,能升級成功,再看代碼不遲瞬场。
空升步驟
- 確認手柄與系統(tǒng)已連接
- 向藍牙設備發(fā)“開啟升級模式”消息买鸽。此時手柄會主動斷連。
- APP 收到藍牙斷開回調(diào)贯被,APP 發(fā)起藍牙連接請求眼五,(此時連接的設備名變?yōu)闀淖儯韬陀布麓_認)
- APP 收到藍牙連接成功回調(diào)彤灶,讀本地空升包看幼,調(diào)用 iOSDFULibrary與 dfuService 通信
空升代碼
開始空升(空升步驟第3步),我這里建了一個單獨的類 DFUHelper幌陕,遵守協(xié)議 DFUServiceDelegate, DFUProgressDelegate, LoggerDelegate诵姜。
func startDFU() {
guard let filePath = Bundle.main.path(forResource: "你的空升包名字", ofType: "zip") else {
return
}
guard let selectedFirmware = DFUFirmware(urlToZipFile: URL(fileURLWithPath: filePath)) else { return }
let initiator = DFUServiceInitiator(centralManager: BlueToothHelper.centralManager, target: BlueToothHelper.peripheral)
initiator.forceDfu = UserDefaults.standard.bool(forKey: "dfu_force_dfu")
initiator.packetReceiptNotificationParameter = UInt16(UserDefaults.standard.integer(forKey: "dfu_number_of_packets"))
initiator.logger = self
initiator.delegate = self
initiator.progressDelegate = self
initiator.enableUnsafeExperimentalButtonlessServiceInSecureDfu = true
dfuController = initiator.with(firmware: selectedFirmware).start()
}
協(xié)議回調(diào)
// 升級狀態(tài)回調(diào)
func dfuStateDidChange(to state: DFUState) {
switch state {
case .completed:
print("升級成功")
default:
break
}
}
// 升級進度回調(diào),范圍 1-100
func dfuProgressDidChange(for part: Int, outOf totalParts: Int, to progress: Int, currentSpeedBytesPerSecond: Double, avgSpeedBytesPerSecond: Double) {
DispatchQueue.main.async {
// 回主線程更新 UI
}
}
func dfuError(_ error: DFUError, didOccurWithMessage message: String) {
print("?? dfuError: \(error), didOccurWithMessage: \(message)")
}
func logWith(_ level: LogLevel, message: String) {
print("?? logWith \(level), message: \(message)")
}