更新记录

0.2.1(2026-10-08)

0.2.1

0.2.0(2026-10-08)

初版


平台兼容性

uni-app(3.8.5)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ × × √ √ √ √ ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

Zql Nordic DFU 蓝牙固件升级

面向 uni-app 的 UTS API 插件,封装 Nordic 官方原生 DFU 库,提供 ZIP 固件升级、原生进度、完成通知和取消接口。本插件并非 Nordic 官方出品或认证产品。

购买前确认

  • 适用于匹配 Nordic nRF5 SDK Secure/Legacy Bootloader 的设备,不支持 nRF Connect SDK / MCUmgr 固件。底层库支持范围不等于本插件已验证所有设备,请先用目标设备试用。
  • Android 依赖 no.nordicsemi.android:dfu:2.11.0,iOS 依赖 NordicDFU 4.17.0。
  • 当前示例为传统 uni-app + Vue 3;uni-app x、Vue 2 未纳入当前实测承诺。Web、小程序、鸿蒙没有实现。
  • 原生配置下限为 Android API 21、iOS 12.0,实际要求还受宿主、依赖和 HBuilderX 限制。package.json 声明的 HBuilderX 4.27 下限尚需补充实测,不表示全版本兼容保证。
  • 不提供固件制作、签名密钥或固件托管。ZIP 必须匹配目标硬件、Bootloader 和签名配置。

安装与运行

  1. 导入插件到 uni_modules/zql-nordic-dfu,保持目录名不变。
  2. 为宿主配置蓝牙能力及权限。插件不接管扫描界面或自定义授权弹窗。
  3. 插件含 Maven / CocoaPods 原生依赖,按 HBuilderX 提示配置 UTS 原生运行环境或云打包自定义基座,安装到真机。普通标准基座不能代替此步骤。
  4. 修改原生依赖、权限或服务声明后,重新打包并安装基座 / APK。仅同步代码不会更新已安装包的 Manifest。
  5. 宿主扫描选定设备后停止扫描,避免自己的 BLE 连接与 DFU 争用设备。厂商自定义的进入 Bootloader 指令需由宿主处理。

Android 的蓝牙、附近设备、定位授权要求取决于系统和宿主 targetSdk。插件 Manifest 声明了蓝牙、定位、FOREGROUND_SERVICE 和 FOREGROUND_SERVICE_CONNECTED_DEVICE,声明不等于已获用户授权。iOS 宿主应配置蓝牙用途说明(如 NSBluetoothAlwaysUsageDescription,兼容旧系统时配置对应说明),并在真机授权。

接入示例

以下代码放在传统 uni-app 页面脚本中,设备和路径由宿主选择后传入;不包含自动扫描、下载或权限申请。

// #ifdef APP-PLUS
import { startDfu, cancelDfu, isDfuRunning } from '@/uni_modules/zql-nordic-dfu'
// #endif

export default {
  data() {
    return { upgrading: false, percent: 0, status: '待机' }
  },
  methods: {
    upgrade(deviceId, firmwarePath) {
      // #ifdef APP-PLUS
      if (this.upgrading || isDfuRunning()) return
      this.upgrading = true
      this.percent = 0
      this.status = '准备升级'
      try {
        startDfu({
          deviceId,
          firmwarePath,
          progress: (event) => {
            this.percent = event.percent
            this.status = event.percent >= 100 ? '等待设备确认' : '正在传输'
          },
          log: (entry) => console.log('[DFU]', entry.level, entry.message),
          success: () => {
            this.upgrading = false
            this.percent = 100
            this.status = '升级完成'
          },
          fail: (error) => {
            this.upgrading = false
            this.status = error.errCode === 9011003 ? '已取消' : '升级失败'
            console.error('[DFU]', error.errCode, error.errMsg)
          }
        })
      } catch (error) {
        this.upgrading = false
        this.status = '插件启动失败'
        console.error(error)
      }
      // #endif
    },
    cancelUpgrade() {
      // #ifdef APP-PLUS
      cancelDfu()
      // iOS 当前主动取消不保证发送 fail,宿主自行更新取消界面。
      this.upgrading = isDfuRunning()
      this.status = this.upgrading ? '正在取消' : '已请求取消'
      // #endif
    }
  }
}

升级期间保持页面和回调所有者存活,页面退出不等于取消。iOS 取消后不要立即重启会话,先确认设备退出前次连接;也不要在 success 回调内部立即启动下一次 iOS 升级。

设备和文件

  • Android deviceId:扫描返回的 BLE MAC 地址,例如 AA:BB:CC:DD:EE:FF。
  • iOS deviceId:扫描返回的 UUID,不能传 MAC 地址。
  • firmwarePath:App 可读取的本地路径,不是单独的 ZIP 名称或 HTTP 地址。网络固件须先下载。
  • 打包资源路径示例:_www/static/firmware/device.zip,需自行提供合法固件并确认已打入当前安装包。
  • 必须为 Nordic DFU 格式 ZIP,不能随意压缩 BIN 或修改扩展名。当前不提供 Android content:// 文档 URI 接入。

API

方法 行为
startDfu(options) 启动真实原生 DFU,请串行调用
cancelDfu() 请求取消原生或模拟任务,空闲时不执行操作
isDfuRunning() 插件记录的会话状态,不代表设备重启后的业务状态
onDfuProgress(callback) 设置一个全局进度监听,新监听覆盖旧监听
offDfuProgress() 清除全局监听,不会停止升级或清除 options.progress
startDfuDemo(options) 仅模拟,不连接设备或读取文件,不得作为真机升级验证

startDfu 必填 deviceId: string、firmwarePath: string,回调均可选。避免同时用全局监听与 progress 回调重复更新同一份状态。

回调 返回字段
progress percent、currentBytes、totalBytes、state、simulated
log deviceId、数字 level、message;当前仅 Android
success deviceId、simulated、message
fail errSubject、数字 errCode、errMsg

真实进度来自 Nordic SDK,simulated 为 false。真实升级的 currentBytes、totalBytes 目前固定为 0,不能用于计算速度或文件大小。Android 合并多部分百分比;iOS 当前为单部分百分比,切换部分时可能回落。

100% 仅代表传输进度,只有 success 表示原生 DFU 流程完成。 宿主需要确认新固件正常运行时,应等待重启、重新连接并读取设备版本。

模拟模式约 3 秒完成,通过 onDfuProgress 发送进度,不使用 options.progress;不要与真实升级并行。Android 取消完成后 fail 返回 9011003;iOS 当前主动取消会清理回调,不保证发送该事件。

错误排查

错误码 / 现象 排查
9011001 参数为空,或 iOS ID 不是 UUID
9011002 已有会话,结束后再试
9011003 任务取消,不代表固件损坏
9011004 共享模拟引擎不提供原生升级,不是正常 App 原生入口
9011005 Android 文件不存在或 iOS ZIP 无法解析
9011006 原生启动失败,保留完整错误信息
9011007 已安装 Android 包缺少前台服务权限,重新打包并安装,热更新无效
其他数字码 可能为 Nordic SDK 原生错误,结合 errMsg 和平台判断
找不到 no / DfuBaseService 检查原生编译环境、Maven 依赖、自定义基座
扫描权限拒绝 检查宿主授权与系统蓝牙 / 定位状态;扫描不是本插件 API
pod install 下载失败 检查网络和 CocoaPods 完整日志

隐私和支持

插件处理设备标识、本地 ZIP 及诊断信息,不包含自建服务上传、广告、账户或统计代码。Android 日志写入控制台,可能含设备地址和协议数据,请勿直接公开。

开发示例将每台设备最近 200 条日志保存于宿主本地存储,可在升级页清空;插件核心不执行此持久化。宿主应单独披露实际权限、日志保留及其他 SDK 行为,此说明不是整个 App 的隐私政策。

第三方依赖见 THIRD_PARTY_NOTICES.md。售价、是否出售源码、售后联系方式以最终商品页为准;购买前核对 DCloud 授权与打包规则、AppID、包名及所用打包方式。

反馈请附插件与 HBuilderX 版本、手机系统、基座生成时间、Bootloader 类型及脱敏日志,不要发送私钥、证书或未授权固件。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

使用蓝牙连接和扫描相关权限;Android 扫描可能需要定位权限,并使用 connectedDevice 前台服务;iOS 宿主需配置蓝牙用途说明。运行时授权由宿主负责。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

处理设备标识、本地固件路径、进度及诊断日志,无自建服务器上传代码。示例在本地保存每台设备最近 200 条日志,可清空;宿主及其他 SDK 的数据处理须另行声明。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

插件自身不包含广告。

暂无用户评论。