跳转至

01 BLE 中心设备模式(central)

一、BLE 概述

BLE(Bluetooth Low Energy),也称为 Bluetooth Smart,是蓝牙 4.0 及更高版本引入的低功耗无线通信技术,专为低带宽、间歇性数据传输的物联网(IoT)和穿戴设备设计。

Air8101 支持最新的 BLE 5.4 版本,BLE 5.4 在上一代基础上继续优化了功耗和性能,为用户提供了更高效、更稳定的蓝牙连接体验。具体的 BLE 版本区别若有兴趣请自行上网查询,本处不再赘述。

BLE 支持的四种模式

Air8101 的 BLE 支持 4 种模式,分别是中心设备模式(central),外围设备模式(peripheral),广播者模式(ibeacon),以及观察者模式(scan)。

1、中心设备模式(central):

中心设备模式是能够搜索别人并主动建立连接的一方,从扫描状态转化而来的。其可以和一个或多个从设备进行连接通信,它会定期的扫描周围的广播状态设备发送的广播信息,可以对周围设备进行搜索并选择所需要连接的从设备进行配对连接,建立通信链路成功后,主从双方就可以发送接收数据。

2、外围设备模式(peripheral):

外围设备模式是从广播者模式转化而来的,未被连接的外围设备首先进入广播状态,等待被中心设备搜索,当中心设备扫描到外围设备建立连接后,就可以和中心设备进行数据的收发,其不能主动的建立连接,只能等别人来连接自己。和广播模式有区别的地方在于,外围设备模式的设备是可以被连接的,定期的和中心设备进行连接和数据传输,在数据传输过程中作外围设备。

3、广播者模式(ibeacon)

处于广播模式的设备,会周期性的广播 beacon 信息, 可以被扫描, 但一般不会被连接,典型应用 ibeacon。

4、观察者模式(scan)

观察者模式,该模式下模块为非连接,相对广播者模式的一对多发送广播,观察者可以一对多接收数据。在该模式中,设备可以仅监听和读取空中的广播数据。和中心设备唯一的区别是不能发起连接,只能持续扫描外围设备。

蓝牙中的重要概念

1、GATT(通用属性配置文件)

定义 BLE 设备如何组织和传输数据,以 “服务(Service)” 和 “特征(Characteristic)” 为单位。

示例:心率监测设备的 GATT 服务包含 “心率特征”,手机通过读取该特征获取心率数据。

2、服务和特征

服务是特征的容器,通过逻辑分组简化复杂功能的管理;

特征是数据交互的最小单元,通过属性定义实现灵活的读写与推送机制;

两者结合构成 GATT 协议的核心框架,支撑蓝牙设备间的标准化数据交互(如智能穿戴、医疗设备、物联网传感器)。

3、特征的关键属性(Properties)

特征通过 “属性” 定义数据的操作方式,常见属性包括:

  1)可读(Read):允许客户端读取特征值(如读取电池电量)。

  2)可写(Write):允许客户端写入特征值(如设置设备参数)。

  3)通知(Notification):服务端主动发送特征值更新(如心率变化时推送给手机)。

4、UUID

UUID 是蓝牙 GATT 协议的 “数字身份证”,通过标准化的唯一标识机制,实现了跨厂商设备的功能互认(标准 UUID)与厂商个性化功能的扩展(自定义 UUID)

Air8101 的所有操作,都通过 UUID 来索引和管理

二、演示功能概述

本示例使用两个 Air8101 核心板来演示 BLE 中心设备模式:一个核心板做中心设备(烧录 central demo),另一个核心板做外围设备(烧录 peripheral demo)。

演示功能概述如下:

1、ble 中心设备扫描并连接外围设备;

2、ble 中心设备连接成功后,开始定时读取外围设备特征值 UUID 数据, 同时也定时发送数据给外围设备;

3、ble 中心设备收到外围设备特征值 UUID 的 notify 数据后,通过 uart 发送到 pc 端串口工具;

4、pc 端串口工具收到数据后,打印到串口工具窗口。

三、准备硬件环境

3.1 Air8101 核心板

使用 Air8101 核心板,如下图所示:

淘宝购买链接:Air8101 核心板淘宝购买链接

此核心板的详细使用说明参考:硬件手册和证书 中的 Air8101 核心板使用说明

3.2 PC 电脑

WIN10 以及以上版本的 WINDOWS 系统。

3.3 数据通信线

USB 数据线(其一端为 Type-C 接口,用于连接 Air8101 开发板)。

四、准备软件环境

4.1 软件环境

1、烧录工具:Luatools 下载调试工具

2、内核固件:Air8101 V1005 版本固件(理论上,2025 年 7 月 26 日之后发布的固件都可以)

3、脚本文件:

中心设备:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8101/demo/ble/central

外围设备:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8101/demo/ble/peripheral

4、PC 端串口工具:例如 SSCOM、LLCOM 等都可以

5、LuatOS 运行所需要的 lib 文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件。

准备好软件环境之后,接下来查看如何烧录项目文件到 Air8101 核心板中,将本篇文章中演示使用的项目文件烧录到 Air8101 核心板中。

4.2 API 介绍

ble 库:https://docs.openluat.com/osapi/core/ble/

五、程序结构

ble/
├── central/
   ├── main.lua
   ├── ble_client_main.lua
   ├── ble_client_receiver.lua
   |── ble_client_sender.lua
   ├── ble_timer_app.lua
   |── readme.md

5.1 文件说明

  1. main.lua:主程序入口文件。

  2. ble_client_main.lua:BLE 中心设备主程序,进行 BLE 初始化,处理各类 BLE 事件(连接、断开连接、扫描报告、GATT 操作完成等)。

  3. ble_client_receiver.lua:BLE 中心设备接收数据处理。

  4. ble_client_sender.lua:BLE 中心设备发送数据处理。

  5. ble_timer_app.lua:BLE 中心设备定时器处理逻辑,启动两个循环定时器,一个用于定时读取外围设备特征值 UUID 数据,一个用于定时向外围设备特征值 UUID 发送数据。

  6. ble_uart_app.lua:BLE 中心设备接 uart 处理逻辑,将收到的 notify 数据,通过 uart 发送到 pc 端串口工具。

六、核心模块详解

6.1 主程序 (main.lua)

主程序文件 main.lua 是整个项目的入口点。它负责初始化系统环境。

6.1.1 初始化流程

1、项目和版本定义

定义 PROJECTVERSION 变量。

2、日志记录

使用 log.info("main", PROJECT, VERSION) 在日志中打印项目名和版本号。

3、看门狗初始化(如果支持):

配置并启动硬件看门狗,防止程序死循环卡死。

4、加载功能模块

加载 BLE Central(中心设备)主控制模块(ble_client_main)。

加载串口应用功能模块(ble_uart_app)。

加载定时器应用功能模块(ble_timer_app)。

5、启动任务调度器

调用 sys.run() 启动 LuatOS 的任务调度器,开始执行各个任务。

6.2 ble_client_main

本文件为 ble client 主应用功能模块,整个应用通过 sysplus.taskInitEx 启动主任务,实现了完整的 BLE 中心设备功能,包括设备发现、连接管理、数据收发和异常恢复机制。核心业务逻辑为:

6.2.1 初始化与配置

  1. 加载依赖模块( ble_client_receiver 用于数据接收处理, ble_client_sender 用于数据发送处理)。

  2. 定义配置参数(目标设备名称、服务 UUID、特征值 UUID、超时时间等)。

  3. 调用 ble_init(),初始化蓝牙功能。

6.2.2 设备扫描与连接

  1. 创建并启动 BLE 扫描(默认参数:公共地址模式、扫描间隔 100ms、扫描窗口 100ms)。

  2. 通过 is_target_device 函数过滤扫描到的设备(匹配设备名称)。

  3. 发现目标设备后停止扫描并发起连接。

  4. 连接超时处理和重连机制。

6.2.3 事件处理

通过 ble_event_cb 回调函数处理各类 BLE 事件:

  1. 连接成功(EVENT_CONN)

  2. 断开连接(EVENT_DISCONN)

  3. 扫描报告(EVENT_SCAN_REPORT)

  4. GATT 操作完成(EVENT_GATT_DONE)

  5. 读取特征值完成(EVENT_READ_VALUE)

6.2.4 业务功能

  1. GATT 服务发现完成后,自动启用目标特征值的通知监听。

  2. 接收并处理来自其他模块的读取请求( READ_REQ )。

  3. 通过消息队列与其他模块通信。

6.2.5 异常处理

  1. 扫描超时或连接失败时触发异常处理。

  2. 断开连接后自动清理消息队列并尝试重连。

  3. 异常情况下 5 秒后重新开始扫描连接。

6.2 ble_client_receiver

6.2.1 主要功能

  1. 数据分类处理 :接收两类数据(外围设备通知数据和主动读取到的数据)。

  2. 数据分发 :根据数据类型(通过特征值 UUID 区分)发布到不同的消息队列,供其他模块处理。

6.2.2 核心实现

  1. 提供 proc(service_uuid, char_uuid, data) 接口函数,接收服务 UUID、特征值 UUID 和数据。

  2. 通过判断特征值 UUID 是否匹配配置中的 target_notify_chartarget_read_char 来区分数据类型。

  3. 对于外围设备的通知数据,通过 sys.publish("RECV_BLE_NOTIFY_DATA", ...) 发布。

  4. 对于主动读取到的数据,通过 sys.publish("RECV_BLE_READ_DATA", ...) 发布。

6.2.3 数据流转

  1. ble_client_main 模块接收到 EVENT_READ_VALUE 事件时,会调用此模块的 proc 函数。

  2. 本模块将数据分类后发布到对应的消息主题。

  3. 其他订阅了这些消息主题的模块可以接收并处理数据。

6.3 ble_client_sender

其他模块只需发布 "SEND_DATA_REQ" 消息即可请求中心设备向外围设备发送数据。

6.3.1 主要功能

  1. 消息订阅:订阅 "SEND_DATA_REQ" 消息,接收其他模块的发送请求。

  2. 队列管理:维护发送队列 send_queue,存储待发送的数据项(包含服务 UUID、特征值 UUID、数据、回调信息)。

  3. 任务调度:通过任务处理函数 ble_client_sender_task_func 处理各类 BLE 事件。

  4. 数据发送:按顺序发送队列中的数据,并通过回调通知发送结果。

6.3.2 核心实现

  1. 其他模块通过 sys.publish("SEND_DATA_REQ", ...) 发布 发送请求。

  2. send_data_req_proc_func 函数将请求数据加入发送队列,并通知任务。

  3. 任务处理函数根据 BLE 事件状态(连接成功、断开连接等)处理队列数据。

  4. send_item_func 函数负责实际发送数据。

  5. send_item_cbfunc 函数处理发送结果,调用用户回调。

6.3.3 事件处理

  1. CONNECT_OK :BLE 连接成功,开始发送队列数据。

  2. SEND_REQ :有新数据需要发送,继续处理队列。

  3. DISCONNECTED :连接断开,清空队列并通知所有发送请求失败。

6.4 ble_uart_app

6.4.1 主要功能

  1. UART 初始化:打开 UART1 接口,配置波特率 115200、数据位 8、停止位 1、无奇偶校验。

  2. 数据接收:订阅 "RECV_BLE_NOTIFY_DATA" 消息,接收来自 BLE 外围设备的通知数据。

  3. 数据转发:将接收到的 BLE 数据(包含服务 UUID、特征值 UUID 和实际数据)格式化后通过 UART1 发送到 PC 端。

6.5 ble_timer_app

6.5.1 主要功能

  1. 创建两个独立的 5 秒循环定时器

  2. 一个用于定时 发送 数据到外围设备特定特征值 UUID。

  3. 一个用于定时 读取 外围设备特定特征值 UUID 的数据。

6.5.2 核心实现

  1. 定义了目标服务 UUID( FA00 )和特征值 UUID(写: EA02 ,读: EA03 )。

  2. 实现数据发送结果回调函数 send_data_cbfunc ,用于处理发送成功/失败的通知。

  3. 实现两个定时器回调函数:

  4. send_data_req_timer_cbfunc :发布 SEND_DATA_REQ 消息到 ble_client_sender 模块。

  5. read_data_req_timer_cbfunc :发送 READ_REQ 请求到 ble_client_main 模块。

  6. 启动两个 5 秒循环定时器,分别绑定上述两个回调函数。

6.5.3 数据流转

  1. 发送流程:定时器触发 → 发布 SEND_DATA_REQ 消息 → ble_client_sender 处理 → 回调通知结果。

  2. 读取流程:定时器触发 → 发送 READ_REQ 请求 → ble_client_main 处理 → 结果通过事件返回。

七、结果展示

7.1 中心设备订阅外围设备特征通知(Notify)

1、中心设备端实现

在 ble_client_main.lua 文件中,在 ble.EVENT_GATT_DONE 事件触发后,开启 notify 监听,监听外围设备指定服务和特征值的通知,中心设备收到 notify 数据后,将数据通过 uart1 发送到 PC 端。开启监听的主要 demo 如下:

local notify_params = {
    uuid_service = string.fromHex(config.target_service_uuid),
    uuid_characteristic = string.fromHex(config.target_notify_char)
}
ble_device:notify_enable(notify_params, true)

2、外围设备端要求

服务 UUID 和特征 UUID 需要和上面中心设备端实现的一致,同时特征 UUID 的属性需包含 NOTIFY,才能正常通信。

服务 UUID:FA00,特征 UUID:EA01。

local wt = {
    uuid_service = string.fromHex("FA00"),
    uuid_characteristic = string.fromHex("EA01"), 
}
local result = ble_device:write_notify(wt, "123456" .. os.date())
log.info("ble", "发送数据", result)

3、结果展示

7.2 中心设备写入特征值(Write)

1、中心设备端实现

ble_timer_app.lua 中,启动 5 秒的循环定时器,发布 SEND_DATA_REQ 消息到 ble_client_sender 模块,ble_client_sender 模块订阅到消息后,开始调用 write_value 向外围设备特征值写入数据,关键发送部分 demo 如下所示:

-- 发送数据
local write_params = {
    uuid_service = string.fromHex(item.service_uuid),
    uuid_characteristic = string.fromHex(item.char_uuid)
}
local data = item.data
local result = ble_device:write_value(write_params, data)

2、外围设备端要求

服务 UUID 和特征 UUID 需要和上面中心设备端实现的一致,同时特征 UUID 的属性需包含 WRITE。

服务 UUID:FA00,特征 UUID:EA02。

触发 ble.EVENT_WRITE 事件,接收到写请求并通过 luatools 打印出来。

3、结果展示

7.3 中心设备读取特征值(Read)

1、中心设备端实现

ble_timer_app.lua 中,启动 5 秒的循环定时器,发送 READ_REQ 请求,ble_client_main 模块收到请求后通过 read_value 开始读取外围设备特征值数据,读取成功后将数据转给 ble_client_receiver 模块处理,关键 demo 如下所示:

-- 从消息中获取传入的UUID参数,若没有则使用默认配置
local service_uuid = msg[3] or config.target_service_uuid
local char_uuid = msg[4] or config.target_read_char

local read_params = {
    uuid_service = string.fromHex(service_uuid),
    uuid_characteristic = string.fromHex(char_uuid)
}
ble_device:read_value(read_params)

2、外围设备端要求

服务 UUID 和特征 UUID 需要和上面中心设备端实现的一致,同时特征 UUID 的属性需包含 READ。

服务 UUID:FA00,特征 UUID:EA03。

local wt = {
    uuid_service = string.fromHex("FA00"),
    uuid_characteristic = string.fromHex("EA03"), 
}
ble_device:write_value(wt, "8888 123454")

3、结果展示

八、总结

本篇文档介绍了 Air8101 的 BLE central 模式,通过两个 Air8101 核心板:一个作中心设备,一个作外围设备,演示了 BLE 中心设备三大核心操作:

1)订阅通知(Notify):自动获取外围设备推送的数据,

2)写入特征值(Write):用于发送控制指令,要求外围设备特征支持 WRITE 属性;

3)读取特征值(Read):主动获取外围设备状态,需外围设备开放 READ 权限。

三种操作均需中心设备和外围设备的服务/特征 UUID 严格匹配。