鸿蒙 BLE 蓝牙智能设备固件升级之DFU升级方式(Nordic芯片)

发布于:2025-09-07 ⋅ 阅读:(21) ⋅ 点赞:(0)
前言:近期接入 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}%`)
      break
    case 'completed':
      this.isSuccessOta = true
   
   
      console.log(`升级完成!设备地址:${event.address}`)
      break
    case 'aborted':
      console.warn(`升级被中止,设备:${event.address}`)
      break
    case 'error':
  
      console.error(`升级失败: ${event.message} (设备: ${event.address})`)
      break
    case 'dfu_starting':
      console.log(`状态:${event.type} 设备:${event.address}`)
      break
  }
})

2.开始升级

DfuController.getInstance().startDFU(this.connectedDeviceInfo._currentDevice.mDeviceName, this.mac, filePath)

下面是我上传的全部升级库源码


网站公告

今日签到

点亮在社区的每一天
去签到