基于 Air5101 的 Air780EPM/EHM OTA 远程升级方案
作者:王世豪 | 最后修改:2026-04-08
一、概述
本演示项目展示了 Air780EPM/EHM 核心板通过 Air5101 蓝牙模块实现固件远程升级(FOTA)的完整解决方案。项目采用蓝牙低功耗(BLE)通信方式,支持两种升级模式:文件写入方式和分段写入方式,为不同应用场景提供灵活的升级方案。
通过本演示,开发者可以学习如何:
- 使用 Air5101 蓝牙模块进行 BLE 通信
- 实现基于蓝牙的固件升级功能
- 处理升级过程中的数据传输和状态管理
- 选择适合自己项目的升级方式
二、演示功能概述
本 demo 演示的核心功能为:
Air780EPM/EHM 模块通过 Air5101 蓝牙模块进行固件远程升级(FOTA)的完整实现方案,支持两种升级方式:
1、文件写入方式:将接收到的升级包数据先保存到本地临时文件,完成数据接收后再执行升级
- 优点:适合完整固件升级,逻辑清晰,易于调试
- 缺点:需要额外的文件系统分区存储空间保存完整固件
- 适用场景:存储空间充足的设备
2、分段写入方式:直接将接收到的升级包数据通过 fota.run()函数处理,无需保存到本地文件
- 优点:节省存储空间,适合差分升级
- 缺点:对内存要求较高,需要足够的内存缓冲区实时处理数据
- 适用场景:存储空间有限的设备
适用场景:
- 智能硬件、可穿戴设备等蓝牙连接设备的固件升级
- 需要自定义升级流程的应用场景
- 无网络环境下的设备固件更新
- 使用 Air5101 蓝牙模块的嵌入式设备
三、准备硬件环境
3.1 Air780EPM/EHM 核心板
使用 Air780EPM/EHM 核心板,如下图所示:

此核心板的详细使用说明参考:硬件手册和证书 中的 Air780EPM/EHM 核心板使用说明。
3.2 Air5101S 开发板

3.3 PC 电脑
WINDOWS 系统,其他暂无特别要求;
3.4 数据通信线
USB 数据线(其一端为 Type-C 接口,用于连接 Air780EPM/EHM 核心板)。
Air780EPM/EHM 核心板和数据线的硬件接线方式为:
- Air780EPM/EHM 核心板通过 TYPE-C USB 口供电,核心板正面的 ON/OFF 拨动开关 拨到 ON 一端;
- TYPE-C USB 数据线直接插到核心板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;
3.5 接线说明
| Air780EPM/EHM | Air5101S |
| UART1_TX | RXD |
| UART1_RX | TXD |
| GND | GND |
| 3.3V | VBAT |
四、准备软件环境
4.1 软件环境
- 烧录工具:Luatools 下载调试工具
- 本demo开发测试时使用的固件为Air780EPM V2028 版本固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件Air780EPM固件,Air780EHM固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试
- 脚本文件: https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EPM/demo/fota/ble_5101_fota
- LuatOS 运行所需要的 lib 文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件。
准备好软件环境之后,接下来查看如何烧录项目文件到 Air780EPM/EHM 核心板中,将本篇文章中演示使用的项目文件烧录到 Air780EPM/EHM 核心板中。
五、API 接口说明
详细 API 文档请参考:
exril_5101 扩展库:https://docs.openluat.com/osapi/ext/exril_5101/
fota:https://docs.openluat.com/osapi/core/fota/
六、蓝牙 GATT 服务设计
6.1 服务与特征值定义
| 类型 | UUID | 属性 | 功能描述 |
| Service | 0000ff00-f7e3-55b4-6c4c-9fd140100a16 | - | FOTA服务主UUID,用于标识升级服务 |
| Characteristic | 0000ff02-f7e3-55b4-6c4c-9fd140100a16 | Write, Write Without Response | 写入特征值,用于发送升级命令和数据 |
报文格式
由于 Air5101 只有一个可写入的特征值(0000ff02),所以协议采用分层设计,第一字节为数据类型,用于区分命令数据和固件数据:
- 0x01: 命令数据
- 0x02: 固件数据
6.1.1 命令报文格式
开始升级命令
命令码:0x01
格式:[数据类型(1字节)] + [命令码(1字节)] + [文件大小(4字节)]
示例:01 01 75 15 00 00 表示开始升级,固件大小为 5493 字节
说明:
- 数据类型固定为 0x01,表示命令数据
- 命令码固定为 0x01,表示开始升级
- 文件大小为 4 字节小端序
- 设备收到此命令后,初始化 FOTA 子系统并准备接收数据
结束升级命令
命令码:0x02
格式:[数据类型(1字节)] + [命令码(1字节)]
示例:01 02
说明:
- 数据类型固定为 0x01,表示命令数据
- 命令码固定为 0x02,表示结束升级
- 设备收到此命令后,验证固件完整性并执行升级
6.1.2 数据报文格式
数据类型: 0x02
格式:[数据类型(1字节)] + [固件数据(n字节)]
默认长度:500 字节(可通过 ble_5101_fota_tool.py 配置调整,最大 MTU-3 字节,MTU 最大是 512)
说明:
- 数据类型固定为 0x02,表示固件数据
- 固件数据为二进制格式
- 每包数据大小不超过 BLE 数据包最大长度:Air5101 模块硬件支持最大 509 字节
-
设备收到数据后,根据所选的 FOTA 方式进行处理:
-
(1)文件方式:将数据写入临时文件
- (2)分段方式:直接通过 fota.run()处理数据
6.2 升级流程说明
用法
1、先把脚本和固件烧录到 Air780EPM/EHM 模块中,并确认设备正常启动
2、模块启动后会自动初始化 Air5101 并开启 BLE 广播,广播名称为"Air5101_FOTA"
3、电脑端操作:运行 ble_5101_fota_tool.py 脚本连接设备并发送升级固件(注意:确保升级文件名为正确格式,并且与 ble_5101_fota_tool.py 在同一目录下)
4、观察日志输出确认升级进度
5、模块接收并验证固件成功后,会自动重启并应用新固件
BLE 通讯过程说明
蓝牙 FOTA 升级通过 Air5101 的 GATT 特征值进行命令控制、数据传输和状态通知:
协议流程:
- 上位机通过 BLE 扫描并连接名为"Air5101_FOTA"的设备
- 上位机向写入特征值(0000ff02)发送开始升级命令(0x01)和固件大小
- 设备初始化 FOTA 功能并准备接收数据
- 上位机向写入特征值(0000ff02)分包发送固件数据
- 设备接收并保存数据到临时文件或直接处理
- 上位机向写入特征值(0000ff02)发送结束升级命令(0x02)
- 设备验证固件完整性并执行 FOTA 升级流程
- 升级成功后设备自动重启
6.3 蓝牙 FOTA 升级工具使用流程
本项目提供两种上位机升级工具,可根据实际需求选择使用:
6.3.1 Python 脚本工具 (ble_5101_fota_tool.py)
功能特点:
- 通过命令行操作,适合自动化脚本集成
- 支持自定义设备名称和固件文件路径
- 实时显示升级进度和传输速度
使用方法:
- 确保 Air5101 模块处于蓝牙广播状态(设备名称为"Air5101_FOTA")
- 在命令行中运行脚本,指定升级包文件名
python ble_5101_fota_tool.py -f 升级包文件名
参数说明:
-
-d或--device- 指定目标设备名称(默认值为"Air5101_FOTA") -
-f或--firmware- 指定固件文件路径(必需参数)
工作流程:
-
加载指定的固件文件
-
扫描并发现蓝牙设备
-
连接到目标设备
-
发送开始升级命令(包含固件大小)
-
分包发送固件数据
-
发送结束升级命令
-
等待设备处理升级
-
断开连接并完成升级过程
界面说明:

6.3.2 Web网页工具 (ble_fota_web.html)
功能特点:
-
基于Web Bluetooth API,无需安装Python环境
-
可视化界面操作,支持拖拽选择固件文件
-
实时显示升级进度和日志输出
浏览器要求:
-
必须使用支持Web Bluetooth API的浏览器:Chrome、Edge或Opera
-
不支持Safari和Firefox浏览器
-
需要电脑具备蓝牙功能
使用方法:
-
使用Chrome或Edge浏览器打开ble_fota_web.html文件
-
确保Air5101模块处于蓝牙广播状态,设备名称为"Air5101_FOTA"
-
点击"扫描并连接设备"按钮,选择"Air5101_FOTA"设备进行连接
-
点击固件选择区域,选择要升级的升级包文件
-
根据需要调整数据包大小和发送间隔(默认500字节/50毫秒)
-
点击"开始升级"按钮,等待升级完成
界面说明:

七、代码示例介绍
7.1 主要代码分析
7.1.1 ble服务主功能模块(ble_5101_main.lua)
本文件为 Air5101 蓝牙服务主功能模块,整个应用通过 sys.taskInitEx 启动主任务,实现了完整的 Air5101 蓝牙模块控制功能,核心业务逻辑为:
1、初始化与配置
(1) 加载依赖模块
exril_5101 用于 Air5101 蓝牙模块的 AT 指令封装, ble_5101_file_fota 或 ble_5101_packet_fota 用于 FOTA 业务逻辑处理。
(2) 定义 FOTA 升级模式选择机制,支持两种升级方式:
-- 选择FOTA升级方式:"file" 或 "packet"
-- 1. file方式:将升级包数据先写入本地文件,然后调用fota.file()进行升级
-- 2. packet方式:直接使用fota.packet()处理分段数据,不写入文件,适合差分升级
local fota_mode = "packet" -- 默认使用packet方式
-- 根据选择动态加载对应的FOTA模块
if fota_mode == "file" then
current_fota_handler = require "ble_5101_file_fota"
else
current_fota_handler = require "ble_5101_packet_fota"
end
(3) 定义配置参数:
local config = {
device_name = "Air5101_FOTA", -- 设备广播名称
}
(4) 调用 exril_5101.mode() 进行模块模式切换,完成 Air5101 蓝牙模块的初始化配置流程:
- 获取当前工作模式
- 切换到 AT 指令模式进行参数配置
- 设置设备名称等参数
- 切换到透传模式(UA 模式)用于数据接收
2、事件处理
通过 ble_event_cb 回调函数处理各类 Air5101 蓝牙事件:
(1) 连接成功("connected") - 蓝牙设备连接建立
(2) 连接断开("disconnected") - 蓝牙连接断开
(3) 数据接收("data") - 收到中心设备发送的数据
(4) 错误事件("error") - 处理 AE 或 UE 错误码
(5) 系统事件("system") - 检测设备重启等系统级事件
3、业务功能
FOTA 升级流程控制 :
(1) 连接建立时通知 FOTA 模块: current_fota_handler.proc_connect()
(2) 连接断开时通知 FOTA 模块: current_fota_handler.proc_disconnect()
(3) 数据接收时转发给 FOTA 模块: current_fota_handler.proc(payload.data)
4、异常处理
(1) 初始化失败 :配置初始化失败后,5 秒后自动重试初始化流程。
(2) 设备重启检测 :通过系统事件检测到设备重启后,自动触发重新初始化。
(3) 消息队列清理 :异常发生时清理任务绑定的未处理消息,避免消息堆积。
(4) 连接异常恢复 :连接断开后自动等待重连,保持服务可用性。
7.1.2 文件系统方式 FOTA 升级业务逻辑模块(ble_5101_file_fota.lua)
本文件为 Air5101 蓝牙 FOTA 升级功能模块(文件写入方式),实现了通过 Air5101 接收升级包数据并写入文件进行固件升级的完整业务逻辑,核心业务逻辑为:
1、初始化与状态管理
(1) 定义升级状态管理结构,用于跟踪升级进度和文件操作:
local upgrade_state = {
is_upgrading = false, -- 是否正在升级
total_size = 0, -- 总文件大小(字节)
received_size = 0, -- 已接收大小(字节)
upgrade_file = "/ble_fota.bin" -- 临时升级文件路径
}
(2) 提供对外接口函数,供主模块调用:
-- 主要接口函数
ble_5101_file_fota.proc(data) -- 处理接收到的BLE数据
ble_5101_file_fota.proc_connect() -- 处理连接成功事件
ble_5101_file_fota.proc_disconnect() -- 处理连接断开事件
2、协议解析与命令处理
数据协议格式:
- 命令数据:
0x01 + [命令码(1字节)] + [文件大小(4字节)] - 固件数据:
0x02 + [固件数据块]
支持的命令码:
- 0x01:开始升级命令,包含文件大小信息
- 0x02:结束升级命令,触发 FOTA 升级执行
命令处理流程:
-- 开始升级命令处理
1. 解析文件大小
2. 初始化FOTA子系统
3. 等待FOTA底层准备就绪
4. 设置升级状态,准备接收数据
-- 结束升级命令处理
1. 验证文件完整性
2. 执行fota.file()升级
3. 清理临时文件
4. 重启设备完成升级
3、文件操作与数据管理
文件写入机制:
- 使用追加模式("ab")写入接收到的数据块
- 实时更新接收进度和文件完整性检查
- 支持断点续传,连接断开后自动清理临时文件
进度跟踪:
-- 实时计算并显示升级进度
local progress = math.floor((received_size / total_size) * 100)
log.info("FOTA_DATA", "接收进度:", progress, "%")
4、异常处理与容错机制
连接异常处理:
- 连接断开时自动终止升级流程
- 清理临时文件,释放系统资源
- 重置升级状态,准备重新开始
文件操作异常:
- 文件打开失败时终止升级
- 文件写入失败时记录错误日志
- 确保 FOTA 流程正确结束
数据完整性验证:
- 结束升级时验证接收文件大小与预期一致
- 文件不完整时拒绝执行升级操作
5、FOTA 升级执行流程
升级执行步骤:
(1) 文件完整性检查:验证接收数据与预期大小匹配
(2) FOTA 升级执行:调用 fota.file(upgrade_file) 进行升级
(3) 结果验证:检查升级结果,确认是否成功
(4) 设备重启:延迟 2 秒后自动重启设备
升级结果处理:
if result and isDone then
log.info("FOTA_CMD", "FOTA升级成功!")
-- 延迟重启,给用户反应时间
sys.timerStart(ble_reboot, 2000)
else
log.error("FOTA_CMD", "FOTA升级失败")
end
7.1.3 分段写入方式 FOTA 升级业务逻辑模块(ble_5101_packet_fota.lua)
本文件为 Air5101 蓝牙 FOTA 升级功能模块(分段写入方式),实现了通过 Air5101 接收升级包数据并直接处理分段数据进行固件升级的完整业务逻辑,核心业务逻辑为:
1、初始化与状态管理
(1) 定义升级状态管理结构,用于跟踪升级进度和分段数据处理:
local upgrade_state = {
is_upgrading = false, -- 是否正在升级
total_size = 0, -- 总文件大小(字节)
received_size = 0, -- 已接收大小(字节)
upgrade_packet = 0 -- 升级包计数器
}
(2) 提供对外接口函数,供主模块调用:
-- 主要接口函数
ble_5101_packet_fota.proc(data) -- 处理接收到的BLE数据
ble_5101_packet_fota.proc_connect() -- 处理连接成功事件
ble_5101_packet_fota.proc_disconnect() -- 处理连接断开事件
2、协议解析与命令处理
数据协议格式:
- 命令数据:
0x01 + [命令码(1字节)] + [文件大小(4字节)] - 固件数据:
0x02 + [固件数据块]
支持的命令码:
- 0x01:开始升级命令,包含文件大小信息
- 0x02:结束升级命令,触发 FOTA 升级完成检查
命令处理流程:
-- 开始升级命令处理
1. 解析文件大小
2. 初始化FOTA子系统
3. 等待FOTA底层准备就绪
4. 设置升级状态,准备接收分段数据
-- 结束升级命令处理
1. 验证数据完整性
2. 等待底层校验完成
3. 检查升级结果
4. 重启设备完成升级
3、分段数据处理机制
分段写入机制:
- 使用
fota.run(data)直接处理接收到的数据块 - 无需写入临时文件,节省存储空间
进度跟踪:
-- 实时计算并显示升级进度
local progress = math.floor((received_size / total_size) * 100)
log.info("FOTA_DATA", "接收进度:", progress, "%")
数据包计数:
- 记录已处理的升级包数量
- 便于调试和数据完整性验证
4、异常处理与容错机制
连接异常处理:
- 连接断开时自动终止升级流程
- 清理升级状态,释放系统资源
- 重置升级状态,准备重新开始
分段写入异常:
fota.run()失败时终止升级- 记录错误日志,便于问题排查
- 确保 FOTA 流程正确结束
数据完整性验证:
- 结束升级时验证接收数据大小与预期一致
- 数据不完整时拒绝完成升级操作
5、FOTA 升级执行流程
升级执行步骤:
(1) 数据完整性检查:验证接收数据与预期大小匹配
(2) 等待底层校验:等待 FOTA 底层完成数据校验
(3) 结果验证:检查升级结果,确认是否成功
(4) 设备重启:延迟 2 秒后自动重启设备
升级结果处理:
-- 等待底层校验完成
for i = 1, 30 do -- 最多等待3秒
sys.wait(100)
local succ, fotaDone = fota.isDone()
if fotaDone then
log.info("FOTA_CMD", "FOTA升级成功!")
-- 延迟重启,给用户反应时间
sys.timerStart(ble_reboot, 2000)
break
end
end
7.2 升级包制作
升级包制作是 FOTA 功能的关键步骤,确保按照升级包制作流程操作。
7.3 功能验证
7.3.1 文件系统方式
代码中修改 fota_mode 参数为"file"方式:
-- 选择FOTA升级方式:"file" 或 "packet"
-- 1. file方式:将升级包数据先写入本地文件,然后调用fota.file()进行升级
-- 2. packet方式:直接使用fota.packet()处理分段数据,不写入文件,适合差分升级
local fota_mode = "file" -- 默认使用file方式
模组 luatools 日志如下:




日志解读:
(1) 设备启动,蓝牙服务初始化成功
(2) 收到开始升级命令,初始化 FOTA 分区和缓冲区
(3) 开始分段接收升级数据保存到文件中
(4) 所有数据接收完成,验证固件完整性
(5) 运行升级流程,升级完成,设备重启
(6) 重启后新版本正常运行,确认升级成功
Web 网页工具:
代码文件夹中有个 html 文件,放到 Chrome 或者 Edge 浏览器打开:


然后等待升级完成即可。
Python 脚本工具:
进入到 ble_fota 目录下运行 cmd 命令进入命令行程序,然后等待设备运行并初始化蓝牙后运行下面命令:
python ble_fota_tool.py -f ble_fota.bin

7.3.2 分段写入方式
代码中修改 fota_mode 参数为"packet"方式:
-- 选择FOTA升级方式:"file" 或 "packet"
-- 1. file方式:将升级包数据先写入本地文件,然后调用fota.file()进行升级
-- 2. packet方式:直接使用fota.packet()处理分段数据,不写入文件,适合差分升级
local fota_mode = "packet" -- 默认使用packet方式
模组 luatools 日志如下:




日志解读:
(1) 设备启动,蓝牙服务初始化成功
(2) 收到开始升级命令,初始化 FOTA 分区和缓冲区
(3) 开始分段接收升级数据并通过 fota.run 接口写入 fota 分区
(4) 所有数据接收完成,验证固件完整性
(5) 运行升级流程,升级完成,设备重启
(6) 重启后新版本正常运行,确认升级成功
Web 网页工具:
代码文件夹中有个 html 文件,放到 Chrome 或者 Edge 浏览器打开:


然后等待升级完成即可。
Python 脚本工具:
进入到 ble_fota 目录下运行 cmd 命令进入命令行程序,然后等待设备运行并初始化蓝牙后运行下面命令:
python ble_fota_tool.py -f ble_fota.bin

八、常见问题与解决方案
8.1 蓝牙连接失败
- 问题:Python 脚本无法找到或连接设备
- 解决方案:
- 确认设备已上电并正常启动
- 检查设备名称是否为"Air5101_FOTA"
- 确认电脑蓝牙功能已开启
8.2 数据传输中断
- 问题:升级过程中数据传输中断
- 解决方案:
- 确保设备与电脑之间没有障碍物
- 避免其他蓝牙设备的干扰
- 检查设备电量是否充足
- 重新运行升级工具
8.3 升级后版本未更新
- 问题:升级完成后版本号未变化
- 解决方案:
- 检查升级包制作是否正确
- 确认 VERSION 变量已修改
- 查看设备日志确认升级是否成功
- 尝试完全断电后重新上电
8.4 Python 环境问题
- 问题:Python 脚本无法运行
- 解决方案:
- 确认已安装 Python 3.x
- 安装必要的库:
pip install bleak - 检查脚本文件路径是否正确
- 确保有足够的权限运行脚本
九、总结
至此,本教程详细介绍了如何使用 Air5101 的蓝牙功能,来实现 Air780EPM/EHM 的无线固件升级。蓝牙 FOTA 提供了一种便捷、低功耗的固件更新方案,特别适合需要远程维护的物联网设备。