03 BLE 扫描
一、BLE 概述
BLE(Bluetooth Low Energy),也称为 Bluetooth Smart,是蓝牙 4.0 及更高版本引入的低功耗无线通信技术,专为低带宽、间歇性数据传输的物联网(IoT)和穿戴设备设计。
Air8000 支持最新的 BLE 5.4 版本,BLE 5.4 在上一代基础上继续优化了功耗和性能,为用户提供了更高效、更稳定的蓝牙连接体验。具体的 BLE 版本区别若有兴趣请自行上网查询,本处不再赘述。
Air8000 的 BLE 支持 4 种模式,分别是主机模式(central),从机模式(peripheral),广播者模式(ibeacon),以及观察者模式(scan)。
1.主机模式(central):
主机模式是能够搜索别人并主动建立连接的一方,从扫描状态转化而来的。其可以和一个或多个从设备进行连接通信,它会定期的扫描周围的广播状态设备发送的广播信息,可以对周围设备进行搜索并选择所需要连接的从设备进行配对连接,建立通信链路成功后,主从双方就可以发送接收数据。
2.从机模式(peripheral):
从机模式是从广播者模式转化而来的,未被连接的从机首先进入广播状态,等待被主机搜索,当主机扫描到从设备建立连接后,就可以和主机设备进行数据的收发,其不能主动的建立连接,只能等别人来连接自己。和广播模式有区别的地方在于,从机模式的设备是可以被连接的,定期的和主机进行连接和数据传输,在数据传输过程中作从机。
3.广播者模式(ibeacon)
处于广播模式的设备,会周期性的广播 beacon 信息, 但不会被扫描到, 也不会连接其他设备。
4.观察者模式(scan)
观察者模式,该模式下模块为非连接,相对广播者模式的一对多发送广播,观察者可以一对多接收数据。在该模式中,设备可以仅监听和读取空中的广播数据。和主机唯一的区别是不能发起连接,只能持续扫描从机。
蓝牙中的重要概念
1. GATT(通用属性配置文件)
定义 BLE 设备如何组织和传输数据,以 “服务(Service)” 和 “特征(Characteristic)” 为单位。
示例:心率监测设备的 GATT 服务包含 “心率特征”,手机通过读取该特征获取心率数据。
2. 服务和特征
服务是特征的容器,通过逻辑分组简化复杂功能的管理;
特征是数据交互的最小单元,通过属性定义实现灵活的读写与推送机制;
两者结合构成 GATT 协议的核心框架,支撑蓝牙设备间的标准化数据交互(如智能穿戴、医疗设备、物联网传感器)。
3. 特征的关键属性(Properties)
特征通过 “属性” 定义数据的操作方式,常见属性包括:
a. 可读(Read):允许客户端读取特征值(如读取电池电量)。
b. 可写(Write):允许客户端写入特征值(如设置设备参数)。
c. 通知(Notification):服务端主动发送特征值更新(如心率变化时推送给手机)。
d. 指示(Indication):比通知更可靠的推送(需客户端确认接收)
4. UUID
UUID 是蓝牙 GATT 协议的 “数字身份证”,通过标准化的唯一标识机制,实现了跨厂商设备的功能互认(标准 UUID)与厂商个性化功能的扩展(自定义 UUID)
Air8000 的所有操作,都通过 UUID 来索引和管理
二、演示功能概述
本示例将演示如何使用 Air8000 在观察者模式下工作。
观察者模式(scan)的基本流程(概要描述)
1. 初始化蓝牙框架
2. 创建 BLE 对象
local ble_device = bluetooth_device:ble(ble_event_cb)
3.设置扫描模式
ble_device:scan_create() -- 使用默认参数, addr_mode=0, scan_interval=100, scan_window=100
4. 开始扫描
ble_device:scan_start()
5. 在回调函数中处理扫描事件, 如接收设备信息等
6. 按需停止扫描
ble_device:scan_stop()
三、准备硬件环境
3.1 Air8000 核心板
使用 Air8000 开发套件,如下图所示:
淘宝购买链接:Air8000 开发套件淘宝购买链接 ;
此开发套件的详细使用说明参考:硬件手册和证书 - product@air8000 - 合宙模组资料中心中的 Core_Air8000 核心板使用说明 V1.3.pdf。
3.2 PC 电脑
WINDOWS 系统,其他暂无特别要求;
3.3 数据通信线
USB 数据线(其一端为 Type-C 接口,用于连接 Air8000 开发板)。
四、准备软件环境
4.1 下载调试工具
使用说明参考:如何使用 LuaTools 烧录软件 - luatos@air8000 - 合宙模组资料中心
4.2 蓝牙调试工具
本示例使用的蓝牙调试软件是 nrf connect ,Android 版,下载下面的压缩包;IOS 版请在APP Store搜索 nrf connect下载。
五、软硬件资料
5.1 源码及固件
-
Air8000 模组使用固件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/core。
-
源码链接:https://gitee.com/openLuat/LuatOS/blob/master/module/Air8000/demo/ble/scan。
5.2 demo 使用 api 介绍
本教程使用 api 接口为:
https://wiki.luatos.com/api/ble.html?highlight=ble#(后续搬运到 docs 上后,再修改到新的引用链接)
https://wiki.luatos.com/api/bluetooth.html(后续搬运到 docs 上后,再修改到新的引用链接)
六、代码解析
6.1 初始化蓝牙框架
-- 开始初始化蓝牙核心
bluetooth_device = bluetooth.init()
6.2 创建 BLE 对象
ble_callback 是自定义函数,用于处理 BLE 事件,详见 6.5
-- 创建BLE对象, 需要先调用bluetooth.init()
ble_device = bluetooth_device:ble(ble_callback)
6.3 创建 BLE 扫描
扫描窗口(scan_window):是指 BLE 设备在扫描过程中,打开接收器去监听广播设备的时间段。这个时间段是设备实际进行扫描操作的时间,也称为扫描事件的持续时间。扫描窗口的单位通常是 0.625ms,并且它的值必须小于或等于扫描间隔。
扫描间隔(scan_interval):表示两次扫描事件之间的间隔时间。扫描间隔的单位与扫描窗口相同,单位也是 0.625ms。
注:如果扫描窗口与扫描间隔一样长,表明主机一直在扫描。
ble_device:scan_create(addr_mode, scan_interval, scan_window)
-- scan_interval:扫描间隔,单位为0.625ms,最小值为20,最大值为10240
-- scan_window:扫描窗口,单位为0.625ms,最小值为20,最大值为10240
示例如下:
-- 默认参数
ble_device:scan_create() -- 默认参数, addr_mode=0, scan_interval=100, scan_window=100
-- 自定义参数,比如自定义扫描间隔625ms,扫描窗口62.5ms,设置如下
ble_device:scan_create(0, 1000, 100) -- 625ms/0.625ms = 1000; 62.5ms/0.625ms = 100
6.4 开始扫描
ble_device:scan_start()
6.5 在回调函数中处理扫描事件, 如接收设备信息等
-- ble_callback 是自定义函数, 用于处理BLE事件
-- BLE事件回调函数, 回调时的参数如下:
-- dev 是BLE设备对象, 可以通过dev:adv_create()等方法进行操作
-- evt 是BLE事件类型, 可以是以下几种:
-- ble.EVENT_CONN: 连接成功
-- param 是事件参数, 包含以下字段:
-- param.addr: 对端设备的地址, 6字节的二进制数据, 代表BLE设备的MAC地址
-- ble.EVENT_DISCONN: 断开连接
-- param 是事件参数, 包含以下字段:
-- param.reason: 断开连接的原因
-- ble.EVENT_WRITE: 收到写请求
-- param 是事件参数, 包含以下字段:
-- param.uuid_service: 服务的UUID
-- param.uuid_characteristic: 特征的UUID
-- param.uuid_descriptor: 描述符的UUID, 可选, 不一定存在
-- param.data: 写入的数据
-- ble.EVENT_SCAN_REPORT: 扫描到设备
-- param 是事件参数, 包含以下字段:
-- param.rssi: 信号强度
-- param.adv_addr: 广播地址, 6字节的二进制数据
-- param.data: 广播数据, 二进制数据
local function ble_callback(ble_device, ble_event, ble_param)
if ble_event == ble.EVENT_SCAN_INIT then
log.info("ble", "scan init")
elseif ble_event == ble.EVENT_SCAN_REPORT then
log.info("ble", "scan report", ble_param.rssi, ble_param.adv_addr:toHex(), ble_param.data:toHex())
elseif ble_event == ble.EVENT_SCAN_STOP then
log.info("ble", "scan stop")
end
end
6.6 按需停止扫描
ble_device:scan_stop()
七、运行结果展示
7.1 完整代码
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "ble"
VERSION = "1.0.0"
-- 引入必要的库文件(lua编写), 内部库不需要require
sys = require("sys")
log.info("main", "project name is ", PROJECT, "version is ", VERSION)
-- 通过boot按键方便刷Air8000S
function PWR8000S(val)
gpio.set(23, val)
end
gpio.debounce(0, 1000)
gpio.setup(0, function()
sys.taskInit(function()
log.info("复位Air8000S")
PWR8000S(0)
sys.wait(20)
PWR8000S(1)
end)
end, gpio.PULLDOWN)
local function ble_callback(ble_device, ble_event, ble_param)
if ble_event == ble.EVENT_SCAN_INIT then
log.info("ble", "scan init")
elseif ble_event == ble.EVENT_SCAN_REPORT then
log.info("ble", "scan report", ble_param.rssi, ble_param.adv_addr:toHex(), ble_param.data:toHex())
elseif ble_event == ble.EVENT_SCAN_STOP then
log.info("ble", "scan stop")
end
end
local bt_scan = false -- 是否扫描蓝牙
sys.taskInit(function()
sys.wait(500)
log.info("开始初始化蓝牙核心")
bluetooth_device = bluetooth.init()
sys.wait(100)
log.info("初始化BLE功能")
ble_device = bluetooth_device:ble(ble_callback)
if ble_device == nil then
log.error("当前固件不支持完整的BLE")
return
end
sys.wait(100)
-- 扫描模式
sys.wait(1000)
ble_device:scan_create() -- 使用默认参数, addr_mode=0, scan_interval=100, scan_window=100
-- ble_device:scan_create(0, 10, 10) -- 使用自定义参数
sys.wait(100)
log.info("开始扫描")
ble_device:scan_start()
sys.wait(15000)
log.info("停止扫描")
ble_device:scan_stop()
end)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
7.2 结果演示
八、总结
本文介绍了 Air8000 的 BLE 的观察者模式(SCAN),通过示例演示了如何开启蓝牙设备的观察者模式(SCAN),扫描附近的蓝牙设备信息并通过 luatools 日志打印出来。