鸿蒙 BLE 蓝牙智能设备固件升级之DFU升级方式(Nordic芯片)
前言:近期接入 DFU 的 OTA 升级,虽然 OpenHarmony 上面有第三方库,但是按照步骤导入三方库,并不能实现 OTA 升级,存在卡死问题,升级无响应等一系列问题,这个时候呢,我自己找到源码,进行了修改,下面是我修改后的工具类和遇到的问题点。
一:问题
(1)开始升级,crc 校验不通过
解码压缩包,发送 op code3 的时候,包校验不通过,直接卡死在 crc 校验不通过,这个是因为这个地方设置的有问题,在 writeInitData 里面的 writeInitPacket ,把写入方式修改为 await this.mGatt.writeCharacteristicValue(characteristic, ble.GattWriteType.WRITE_NO_RESPONSE);
(2)写入包的时候,由于写入过快,会导致丢包,固件接收到的包总数有问题,会导致升级失败
只需要在 BaseCustomDfuImpl 的 onCharacteristicWrite 里面添加发送包的延迟操作。
二:工具类
import { DfuProgressListener, DfuServiceInitiator, DfuServiceListenerHelper } from "ohos_dfu_library"
import { DfuEvent } from "./DfuEvent"
/**
* dfu 升级管理类
*/
export class DfuController{
private static instance : DfuController
private static eventListener: ((event: DfuEvent) => void) | null = null
public static getInstance() : DfuController{
if(!DfuController.instance){
DfuController.instance = new DfuController()
}
return DfuController.instance
}
public static setEventListener(listener: (event: DfuEvent) => void) {
DfuController.eventListener = listener
}
private static sendEvent(event: DfuEvent) {
console.log("DFU Event:", event)
if (DfuController.eventListener) {
DfuController.eventListener(event)
}
}
private listener: ProgressListener = new ProgressListener()
constructor() {
DfuServiceListenerHelper.registerProgressListener(this.listener)
}
static pageName : string = ""
public static SendMessage(msg:string){
if(!Boolean(DfuController.pageName)) return
console.log('sophie','---SendMessage---'+msg)
}
public startDFU(pageName:string, address:string, url: string){
DfuController.pageName = pageName
console.log('sophie','---startDFU---'+pageName+'===='+url)
new DfuServiceInitiator(address).setZipUri(url)
.setDeviceName(pageName)
.setKeepBond(true)
.setForceDfu(false)
.setPrepareDataObjectDelay(400)
.setForeground(false)
.start()
}
//给 ProgressListener
public static notify(event: DfuEvent) {
DfuController.sendEvent(event)
}
}
class ProgressListener implements DfuProgressListener {
progressInt: number = 0
dispose(): ESObject {
console.error("Dispose called")
return {}
}
onDeviceConnecting(address: string): ESObject {
DfuController.notify({ type: 'connecting', address })
return {}
}
onDeviceConnected(address: string): ESObject {
DfuController.notify({ type: 'connected', address })
return {}
}
onDfuProcessStarting(address: string): ESObject {
DfuController.notify({ type: 'dfu_starting', address })
return {}
}
onDfuProcessStarted(address: string): ESObject {
this.progressInt = 0
DfuController.notify({ type: 'dfu_started', address })
return {}
}
onEnablingDfuMode(address: string): ESObject {
DfuController.notify({ type: 'onEnablingDfuMode', address})
return {}
}
onProgressChanged(address: string, percent: number): ESObject {
const intPercent = Math.floor(percent)
if (intPercent > this.progressInt && intPercent < 100) {
this.progressInt = intPercent
DfuController.notify({ type: 'progress', value: this.progressInt })
} else if (intPercent >= 100) {
DfuController.notify({ type: 'completed', address })
}
return {}
}
onFirmwareValidating(address: string): ESObject {
DfuController.notify({ type: 'onFirmwareValidating', address })
return {}
}
onDeviceDisconnecting(address: string): ESObject {
DfuController.notify({ type: 'onDeviceDisconnecting',address })
return {}
}
onDeviceDisconnected(address: string): ESObject {
DfuController.notify({ type: 'onDeviceDisconnected', address })
return {}
}
onDfuCompleted(address: string): ESObject {
DfuController.notify({ type: 'completed', address })
return {}
}
onDfuAborted(address: string): ESObject {
DfuController.notify({ type: 'aborted', address })
return {}
}
onError(address: string, error: number, errorType: number, message: string): ESObject {
DfuController.notify({ type: 'error', address, message })
console.error("DFU Error:", message)
return {}
}
}
文件二:
interface GeneratedTypeLiteralInterface_1 {
type: 'connecting';
address: string;
}
interface GeneratedTypeLiteralInterface_2 {
type: 'connected';
address: string;
}
interface GeneratedTypeLiteralInterface_3 {
type: 'dfu_starting';
address: string;
}
interface GeneratedTypeLiteralInterface_4 {
type: 'dfu_started';
address: string;
}
interface GeneratedTypeLiteralInterface_5 {
type: 'progress';
value: number;
}
interface GeneratedTypeLiteralInterface_6 {
type: 'completed';
address: string;
}
interface GeneratedTypeLiteralInterface_7 {
type: 'aborted';
address: string;
}
interface GeneratedTypeLiteralInterface_8 {
type: 'error';
address: string;
message: string;
}
interface GeneratedTypeLiteralInterface_9 {
type: 'onEnablingDfuMode';
address: string;
}
interface GeneratedTypeLiteralInterface_10 {
type: 'onFirmwareValidating';
address: string;
}
interface GeneratedTypeLiteralInterface_11 {
type: 'onDeviceDisconnecting';
address: string;
}
interface GeneratedTypeLiteralInterface_12 {
type: 'onDeviceDisconnected';
address: string;
}
//外部调用
export type DfuEvent =
| GeneratedTypeLiteralInterface_1
| GeneratedTypeLiteralInterface_2
| GeneratedTypeLiteralInterface_3
| GeneratedTypeLiteralInterface_4
| GeneratedTypeLiteralInterface_5
| GeneratedTypeLiteralInterface_6
| GeneratedTypeLiteralInterface_7
| GeneratedTypeLiteralInterface_8
| GeneratedTypeLiteralInterface_9
| GeneratedTypeLiteralInterface_10
| GeneratedTypeLiteralInterface_11
| GeneratedTypeLiteralInterface_12
使用方法:
1.监听方法
DfuController.setEventListener((event: DfuEvent) => {switch (event.type) {case 'progress':console.log(`升级进度:${event.value}%`)breakcase 'completed':this.isSuccessOta = trueconsole.log(`升级完成!设备地址:${event.address}`)breakcase 'aborted':console.warn(`升级被中止,设备:${event.address}`)breakcase 'error':console.error(`升级失败: ${event.message} (设备: ${event.address})`)breakcase 'dfu_starting':console.log(`状态:${event.type} 设备:${event.address}`)break} })
2.开始升级
DfuController.getInstance().startDFU(this.connectedDeviceInfo._currentDevice.mDeviceName, this.mac, filePath)
下面是我上传的全部升级库源码