跳转至

6 ble-低功耗蓝牙

作者:王世豪

一、概述

1.1 模式解释 -> BLE 不同模式的解读

合宙BLE设备,可以工作在几种不同的模式: 外围设备模式,中心设备模式,广播者模式,观察者模式。

外围设备模式(peripheral), 设备会被扫描到, 并且可以被连接;

中心设备模式(central), 设备会扫描其他设备, 并且可以连接其他设备;

广播者模式(ibeacon), 设备会周期性的广播 beacon 信息, 可以被扫描到, 但一般不会被连接;

观察者模式(scan), 设备会扫描其他设备, 但不会连接其他设备。

注: 目前Air8000,Air8101 只能支持同时连接一个从设备。

1.2 蓝牙中的重要概念

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

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

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

2、服务和特征

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

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

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

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

特征通过"属性"定义数据的操作方式。从 GATT 通信角色看:

服务端(通常为外围设备):存储特征值的数据提供方

客户端(通常为中心设备):操作特征值的数据消费方

常见属性包括:

1)可读(Read):允许客户端读取服务端的特征值(如手机读取手环的电量)。

2)可写(Write):允许客户端向服务端写入特征值(如手机设置设备的参数)。

3)通知(Notify):服务端主动向客户端推送特征值更新(如手环向手机推送心率数据)。

4、UUID

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

注:

一个蓝牙设备可以包含多个服务(Service),每个服务通过一个 UUID(服务UUID) 进行标识。

每个服务下包含多个特征(Characteristic),每个特征都拥有一个独立的UUID(特征UUID)作为其唯一标识。

特征是最小的数据单元,我们通过读写特征来与设备交互。

1.3 四种模式的基本流程

1.3.1 外围设备模式(peripheral)的基本流程(概要描述)

1、初始化蓝牙框架

bluetooth_device = bluetooth.init()

2、创建 BLE 对象

local ble_device = bluetooth_device:ble(ble_callback)

3、创建 GATT 描述

local att_db = {xxx}

ble_device:gatt_create(att_db)

4、创建广播信息

ble_device:adv_create(adv_data)

5、开始广播

ble_device:adv_start()

6、等待连接

7、在回调函数中处理连接事件, 如接收数据, 发送数据等

1.3.2 中心设备模式(central)的基本流程(概要描述)

1、初始化蓝牙框架

bluetooth_device = bluetooth.init()

2、创建 BLE 对象

local ble_device = bluetooth_device:ble(ble_callback)

3、扫描目标 BLE 设备

ble_device:scan_start()

4、建立与目标设备的连接

ble_device:connect(mac, add_type)

5、处理各类 BLE 事件(连接、断开连接、扫描报告、GATT 操作完成等)

1.3.3 广播者模式(ibeacon)的基本流程(概要描述)

1、初始化蓝牙底层框架

bluetooth_device = bluetooth.init()

2、创建 BLE 对象

local ble_device = bluetooth_device:ble(ble_callback)

3、配置 ibeacon 广播数据包

包含厂商特定数据格式,ibeacon 类型标识符,设置UUID、Major、Minor等关键参数

4、启动 BLE 广播功能

ble_device:adv_start()

1.3.4 观察者模式(scan)的基本流程(概要描述)

1、初始化蓝牙框架

bluetooth_device = bluetooth.init()

2、创建 BLE 对象

local ble_device = bluetooth_device:ble(ble_callback)

3、开始扫描

ble_device:scan_start()

4、在回调函数中处理扫描事件, 如接收设备信息等

5、按需停止扫描

ble_device:scan_stop()

1.4 应用场景

1.4.1 外围设备 + 中心设备(连接模式)

设计框图:

1.4.2 广播者 + 观察者(无连接模式)

设计框图:

1.5 注意事项

1、Air8000,Air8101 只能支持同时连接一个从设备。

2、Air8000,Air8101 蓝牙发射功率固定为 6dBm,不可调节;最大通讯距离约为10米。

3、Air8000,Air8101 的MTU(最大传输单元)为 256 字节,不可调整,超过256字节的数据需要分包处理。

4、Air8000、Air8101 的蓝牙接收数据时不进行缓冲,收到数据后立即触发通知事件。

5、Air8000,Air8101 蓝牙接收灵敏度的指标为-97 dBm。

二、核心示例

  1. 核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;

  2. 核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

  3. 更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/ble;

2.1 中心设备模式(central)的核心示例

-- 重启BLE扫描的函数
local function restart_ble_scan(device)
    device:scan_start()
end

-- 蓝牙事件回调函数
local function ble_callback(ble_device, ble_event, ble_param)
    if ble_event == ble.EVENT_CONN then
        log.info("ble", "connect 成功")
    elseif ble_event == ble.EVENT_DISCONN then
        log.info("ble", "disconnect", ble_param.reason)
        sys.timerStart(restart_ble_scan, 1000, ble_device)
    elseif ble_event == ble.EVENT_WRITE then
        log.info("ble", "write", ble_param.handle,ble_param.uuid_service:toHex(),ble_param.uuid_characteristic:toHex())
        log.info("ble", "data", ble_param.data:toHex())
    elseif ble_event == ble.EVENT_READ_VALUE then
        log.info("ble", "read", ble_param.handle,ble_param.uuid_service:toHex(),ble_param.uuid_characteristic:toHex(),ble_param.data:toHex())
    elseif ble_event == ble.EVENT_SCAN_REPORT then
        print("ble scan report",ble_param.addr_type,ble_param.rssi,ble_param.adv_addr:toHex(),ble_param.data:toHex())

        -- 注意, 这里是连接到另外一个设备, 设备名称带LuatOS字样
        if ble_param.addr_type == 0 and ble_param.data:find("LuatOS") then
            log.info("ble", "停止扫描, 连接设备", ble_param.adv_addr:toHex(), ble_param.addr_type)
            ble_device:scan_stop()
            scan_count = 0
            ble_device:connect(ble_param.adv_addr,ble_param.addr_type)
        end

        scan_count = scan_count + 1
        if scan_count > 100 then
            log.info("ble", "扫描次数超过100次, 停止扫描, 5秒后重新开始")
            scan_count = 0
            ble_device:scan_stop()
            sys.timerStart(function() ble_device:scan_start() end, 5000)
        end
    elseif ble_event == ble.EVENT_GATT_ITEM then
        -- 读取GATT完成, 打印出来
        log.info("ble", "gatt item", ble_param[1]:toHex(), #ble_param)
    elseif ble_event == ble.EVENT_GATT_DONE then
        log.info("ble", "gatt done", ble_param.service_num)

        local wt = {uuid_service = string.fromHex("FA00"), uuid_characteristic = string.fromHex("EA01")}
        ble_device:notify_enable(wt, true) -- 开启通知

        -- 主动写入数据, 但不带通知, 带通知是 write_notify
        local wt = {uuid_service = string.fromHex("FA00"), uuid_characteristic = string.fromHex("EA02")}
        ble_device:write_value(wt,string.fromHex("1234"))

        -- 主动读取数据
        local wt = {uuid_service = string.fromHex("FA00"), uuid_characteristic = string.fromHex("EA03")}
        ble_device:read_value(wt)
    elseif ble_event == ble.EVENT_SCAN_STOP then
        log.info("ble", "scan stop")
    end
end

local function ble_central_task_func()
    log.info("开始初始化蓝牙核心")
    bluetooth_device = bluetooth.init()
    log.info("初始化BLE功能")
    ble_device = bluetooth_device:ble(ble_callback)

    ble_device:scan_create({})
    ble_device:scan_start()
end

-- 启动蓝牙初始化任务
sys.taskInit(ble_central_task_func)

2.2 外围设备模式(peripheral)的核心示例

-- 重新开始广播
local function restart_ble_adv(device)
    device:adv_start()
end

local att_db = { -- Service
    string.fromHex("FA00"), -- Service UUID
    -- Characteristic
    { -- Characteristic 1
        string.fromHex("EA01"), -- Characteristic UUID Value
        ble.NOTIFY | ble.READ | ble.WRITE -- Properties
    }, { -- Characteristic 2
        string.fromHex("EA02"), ble.WRITE
    }, { -- Characteristic 3
        string.fromHex("EA03"), ble.READ
    }, { -- Characteristic 4
        string.fromHex("EA04"), ble.IND | ble.READ
    }
}

local function ble_callback(ble_device, ble_event, ble_param)
    if ble_event== ble.EVENT_CONN then
        ble_stat = true
    elseif ble_event== ble.EVENT_DISCONN then
        log.info("ble", "disconnect")
        ble_stat = false
        -- 1秒后重新开始广播
        sys.timerStart(restart_ble_adv, 1000, ble_device)
    elseif ble_event== ble.EVENT_WRITE then
        -- 收到写请求
        log.info("ble", "接收到写请求", ble_param.uuid_service:toHex(), ble_param.uuid_characteristic:toHex(), ble_param.data:toHex())
    end
end

local function ble_peripheral_task_func()
    log.info("开始初始化蓝牙核心")
    bluetooth_device = bluetooth.init()
    log.info("初始化BLE功能")
    ble_device = bluetooth_device:ble(ble_callback)
    log.info('开始创建GATT')
    ret = ble_device:gatt_create(att_db)
    log.info("创建的GATT", ret)

    log.info("开始设置广播内容")
    ble_device:adv_create({
        addr_mode = ble.PUBLIC,
        channel_map = ble.CHNLS_ALL,
        intv_min = 120,
        intv_max = 120,
        adv_data = {
            {ble.FLAGS, string.char(0x06)},
            {ble.COMPLETE_LOCAL_NAME, "LuatOS123"},
            {ble.SERVICE_DATA, string.fromHex("FE01")},
            {ble.MANUFACTURER_SPECIFIC_DATA, string.fromHex("05F0")}
        }
    })

    log.info("开始广播")
    ble_device:adv_start()

    -- 放入预设值, 注意是有READ属性的特性才能读取
    -- 手机APP设置MTU到256
    local wt = {
        uuid_service = string.fromHex("FA00"),
        uuid_characteristic = string.fromHex("EA01"),
    }
    ble_device:write_value(wt, "12345678901234567890")
end

-- 启动蓝牙初始化任务
sys.taskInit(ble_peripheral_task_func)

2.3 广播者模式(ibeacon)的核心示例

function ble_ibeacon_task_func()
    log.info("开始初始化蓝牙核心")
    bluetooth_device = bluetooth.init()
    log.info("初始化BLE功能")
    ble_device = bluetooth_device:ble(ble_callback)

    log.info("开始设置广播内容")
    local adv_data1 = string.char(0x4C, 0x00, -- Manufacturer ID(2字节)
                                0x02, 0x15, -- ibeacon数据类型(2字节)
                                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, -- UUID(16字节)
                                0x00, 0x01, -- Major(2字节)
                                0x00, 0x02, -- Minor(2字节)
                                0xC0) -- Signal Power(1字节)

    ble_device:adv_create({
        addr_mode = ble.PUBLIC, -- 广播地址模式, 目前仅支持ble.PUBLIC
        channel_map = ble.CHNLS_ALL, -- 广播的通道, 可选值: ble.CHNLS_37, ble.CHNLS_38, ble.CHNLS_39, ble.CHNLS_ALL
        intv_min = 120, -- 广播间隔最小值, 单位为0.625ms, 最小值为20, 最大值为10240
        intv_max = 120, -- 广播间隔最大值, 单位为0.625ms, 最小值为20, 最大值为10240
        adv_data = { -- 支持表格形式, 也支持字符串形式(255字节以内)
            {ble.FLAGS, string.char(0x06)},
            {ble.COMPLETE_LOCAL_NAME, "1"},
            {ble.MANUFACTURER_SPECIFIC_DATA, adv_data1}
        }
    })

    log.info("开始广播")
    ble_device:adv_start()
end

sys.taskInit(ble_ibeacon_task_func)

2.4 观察者模式(scan)的核心示例

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())
        -- 解析广播数据, 日志很多, 按需使用
        -- local adv_data = ble_device:adv_decode(ble_param.data)
        -- if adv_data then
        --     for k, v in pairs(adv_data) do
        --         log.info("ble", "adv data", v.len, v.tp, v.data:toHex())
        --     end
        -- end
        -- if ble_param.data:byte(1) == 0x1A then
        --     log.info("ble", "ibeacon数据", ble_param.rssi, ble_param.adv_addr:toHex(), ble_param.data:toHex())
        -- end
    elseif ble_event == ble.EVENT_SCAN_STOP then
        log.info("ble", "scan stop")
    end
end

function ble_scan_task_func()
    log.info("开始初始化蓝牙核心")
    bluetooth_device = bluetooth.init()
    log.info("初始化BLE功能")
    ble_device = bluetooth_device:ble(ble_callback)

    -- 扫描模式
    ble_device:scan_create() -- 使用默认参数, addr_mode=0, scan_interval=100, scan_window=100
    -- ble_device:scan_create(0, 10, 10) -- 使用自定义参数
    log.info("开始扫描")
    ble_device:scan_start()
end

sys.taskInit(ble_scan_task_func)

三、常量详解

核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;

每个常量对应的常量取值仅做日志打印时查询使用,不要将这个常量取值用做具体的业务逻辑判断,因为LuatOS内核固件可能会变更每个常量对应的常量取值;

如果用做具体的业务逻辑判断,一旦常量取值发生改变,业务逻辑就会出错;

3.1 地址模式常量

3.1.1 ble.PUBLIC

常量含义:公共地址模式;
数据类型:number
注意事项:公共地址模式下,使用设备出厂时分配的MAC地址
示例代码:-- 设置广播地址模式为公共地址
         ble_device:adv_create({
             addr_mode = ble.PUBLIC
         })

3.2 特征属性常量

3.2.1 ble.READ

常量含义:特征可读属性;
数据类型:number
注意事项:表示该特征支持读取操作;
示例代码:-- 创建一个可读特征
         local att_db = { -- Service
             string.fromHex("FA00"), -- Service UUID, 服务的UUID, 可以是16位、32位或128位
             { 
                 string.fromHex("EA01"), -- Characteristic UUID, 特征UUID,可以是16位、32位或128位
                 ble.READ -- 特征可读属性
             }
         }
         ble_device:gatt_create(att_db)

3.2.2 ble.WRITE

常量含义:特征可写属性;
数据类型:number
注意事项:表示该特征支持写入操作;
示例代码:-- 创建一个可写特征
         local att_db = { -- Service
             string.fromHex("FA00"), -- Service UUID, 服务的UUID, 可以是16位、32位或128位
             { 
                 string.fromHex("EA01"), -- Characteristic UUID, 特征UUID,可以是16位、32位或128位
                 ble.WRITE -- 特征可写属性
             }
         }
         ble_device:gatt_create(att_db)

3.2.3 ble.NOTIFY

常量含义:特征通知属性;
数据类型:number
注意事项:表示该特征支持通知功能,无需接收方确认;
示例代码:-- 创建一个支持通知的特征
         local att_db = { -- Service
             string.fromHex("FA00"), -- Service UUID, 服务的UUID, 可以是16位、32位或128位
             { 
                 string.fromHex("EA01"), -- Characteristic UUID, 特征UUID,可以是16位、32位或128位
                 ble.NOTIFY -- 特征通知属性
             }
         }
         ble_device:gatt_create(att_db)

3.2.4 ble.IND

常量含义:特征指示属性;
数据类型:number
注意事项:表示该特征支持指示功能,需要接收方确认;
示例代码:-- 创建一个支持指示的特征
         local att_db = { -- Service
             string.fromHex("FA00"), -- Service UUID, 服务的UUID, 可以是16位、32位或128位
             { 
                 string.fromHex("EA01"), -- Characteristic UUID, 特征UUID,可以是16位、32位或128位
                 ble.IND -- 特征指示属性
             }
         }
         ble_device:gatt_create(att_db)

3.2.5 ble.WRITE_CMD

常量含义:特征写入无响应属性;
数据类型:number
注意事项:表示该特征支持无需响应的写入操作;
示例代码:-- 创建一个支持无响应写入的特征
         local att_db = { -- Service
             string.fromHex("FA00"), -- Service UUID
             {
                 string.fromHex("EA02"), -- Characteristic UUID, 特征UUID,可以是16位、32位或128位
                 ble.WRITE_CMD -- 特征写入无响应属性
             }
         }
         ble_device:gatt_create(att_db)

3.3 事件类型常量

3.3.1 ble.EVENT_CONN

常量含义:连接成功事件;
数据类型:number
注意事项:当BLE设备成功建立连接时触发
示例代码:-- 在回调函数中处理连接成功事件
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_event == ble.EVENT_CONN then
                 log.info("ble", "connect 成功", ble_param.addr:toHex())
             end
         end

3.3.2 ble.EVENT_DISCONN

常量含义:断开连接事件;
数据类型:number
注意事项:当BLE设备连接断开时触发
示例代码:-- 在回调函数中处理断开连接事件
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_event == ble.EVENT_DISCONN then
                 log.info("ble", "disconnect", ble_param.reason)
             end
         end

3.3.3 ble.EVENT_WRITE

常量含义:收到写请求事件;
数据类型:number
注意事项:当中心设备向外围设备的特征写入数据时(包括开启通知或指示功能),在外围设备端触发此事件;
示例代码:-- 在外围设备的回调函数中处理写请求_
         -- 示例场景:手机APP设置手环闹钟_
         -- 中心设备(手机)向外围设备(手环)的闹钟特征写入数据:"08:30"_
         -- 外围设备触发此事件,解析数据并设置闹钟_
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_event == ble.EVENT_WRITE then
                 log.info("ble", "接收到写请求", ble_param.data:toHex())
             end
         end

3.3.4 ble.EVENT_READ_VALUE

常量含义:读取操作完成事件;
数据类型:number
注意事项:当中心设备主动读取外围设备的特征值完成时,在中心设备端触发此事件;
示例代码:-- 在中心设备的回调函数中处理读取完成事件_
         -- 示例场景:读取手环电量_
         -- 中心设备(手机)读取外围设备(手环)的电量特征(0x2A19)_
         -- 读取完成后,手机触发此事件,获取电量百分比并显示_
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_event == ble.EVENT_READ_VALUE then
                 log.info("ble", "读取操作完成", ble_param.data:toHex())
             end
         end

3.3.5 ble.EVENT_SCAN_REPORT

常量含义:扫描报告事件;
数据类型:number
注意事项:当中心设备扫描到其他BLE设备的广播时触发
示例代码:-- 在中心设备的回调函数中处理扫描报告事件
         -- 示例场景:设备发现与连接_
         -- 中心设备(手机)扫描周围的外围设备_
         -- 每发现一个设备就触发此事件,可以显示设备列表供用户选择连接_
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_evt == ble.EVENT_SCAN_REPORT then
                 log.info("ble", "scan report", ble_param.rssi, ble_param.adv_addr:toHex())
             end
         end

3.3.6 ble.EVENT_GATT_ITEM

常量含义:收到GATT项事件
数据类型:number
注意事项:当中心设备发现外围设备的GATT服务或特征时触发
示例代码:-- 在中心设备的回调函数中处理GATT项事件,一般调试使用
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_event == ble.EVENT_GATT_ITEM then
                 log.info("ble", "gatt item", ble_param[1]:toHex(), #ble_param)
             end
         end

3.3.7 ble.EVENT_GATT_DONE

常量含义:GATT操作完成事件
数据类型:number
注意事项:当中心设备完成外围设备的GATT服务发现后触发
示例代码:-- 在中心设备的回调函数中处理GATT完成事件
         -- 示例场景:设备就绪通知_
         -- 中心设备(手机)完成对外围设备(手环)的GATT发现_
         -- 触发此事件表示可以开始正常的数据交互(读取、写入、订阅)_
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_event == ble.EVENT_GATT_DONE then
                 log.info("ble", "gatt done", ble_param.service_num)
             end
         end

3.3.8 ble.EVENT_SCAN_STOP

常量含义:扫描停止事件;
数据类型:number
注意事项:当中心设备停止扫描BLE外围设备时触发
示例代码:-- 在中心设备的回调函数中处理扫描停止事件
         function ble_callback(ble_device, ble_event, ble_param)
             if ble_event == ble.EVENT_SCAN_STOP then
                 log.info("ble", "scan stop")
             end
         end

3.4 广播相关常量

3.4.1 ble.COMPLETE_LOCAL_NAME

常量含义:完整本地名称;
数据类型:number
注意事项:用于在广播数据中设置设备的完整名称;
示例代码:-- 在广播数据中设置设备名称
         ble_device:adv_create({
             adv_data = {
                 {ble.COMPLETE_LOCAL_NAME, "LuatOS"}
             }
         })

3.4.2 ble.CHNLS_ALL

常量含义:使用所有广播通道;
数据类型:number
注意事项:表示使用蓝牙LE的所有三个广播通道(37, 38, 39)
示例代码:-- 设置使用所有广播通道
         ble_device:adv_create({
             channel_map = ble.CHNLS_ALL
         })

3.4.3 ble.CHNL_37

常量含义:使用广播通道37
数据类型:number
注意事项:表示仅使用蓝牙LE的广播通道37
示例代码:-- 设置仅使用广播通道37
         ble_device:adv_create({
             channel_map = ble.CHNL_37
         })

3.4.4 ble.CHNL_38

常量含义:使用广播通道38
数据类型:number
注意事项:表示仅使用蓝牙LE的广播通道38
示例代码:-- 设置仅使用广播通道38
         ble_device:adv_create({
             channel_map = ble.CHNL_38
         })

3.4.5 ble.CHNL_39

常量含义:使用广播通道39
数据类型:number
注意事项:表示仅使用蓝牙LE的广播通道39
示例代码:-- 设置仅使用广播通道39
         ble_device:adv_create({
             channel_map = ble.CHNL_39
         })

3.4.6 ble.FLAGS

常量含义:广播标志位;
数据类型:number
注意事项:用于在广播数据中设置设备的广播标志位;
示例代码:-- 在广播数据中设置广播标志位
         ble_device:adv_create({
             adv_data = {
                 {ble.FLAGS, string.char(0x06)}
             }
         })

3.4.7 ble.SERVICE_DATA

常量含义:服务数据;
数据类型:number
注意事项:用于在广播数据中设置设备的服务数据;
示例代码:-- 在广播数据中设置服务数据
         ble_device:adv_create({
             adv_data = {
                 {ble.SERVICE_DATA, string.fromHex("FE01")}
             }
         })

3.4.8 ble.MANUFACTURER_SPECIFIC_DATA

常量含义:制造商特定数据;
数据类型:number
注意事项:用于在广播数据中设置设备的制造商特定数据;
示例代码:-- 在广播数据中设置制造商特定数据
         ble_device:adv_create({
             adv_data = {
                 {ble.MANUFACTURER_SPECIFIC_DATA, string.fromHex("05F0")}
             }
         })

3.5 扫描相关常量

3.5.1 ble.SCAN_ACTIVE

常量含义:主动扫描;
数据类型:number
注意事项:用于设置设备的主动扫描;
        在收到广播包后,会向广播设备发送一个扫描请求(Scan Request);
        广播设备会回应一个 扫描响应包(Scan Response),其中可以包含更多设备信息(如完整的设备名称、额外服务等)。
示例代码:-- 设置主动扫描
        ble_device:scan_create(ble.PUBLIC, 1600, 100, ble.SCAN_ACTIVE)

3.5.2 ble.SCAN_PASSIVE

常量含义:被动扫描;
数据类型:number
注意事项:用于设置设备的被动扫描;
        只接收广播包,不向广播设备发送任何请求;
        只能获取设备在广播中主动发送的数据(如设备名称、服务UUID等)。
示例代码:-- 设置被动扫描
        ble_device:scan_create(ble.PUBLIC, 1600, 100, ble.SCAN_PASSIVE)

四、函数详解

4.1 bluetooth.init()

功能

初始化蓝牙框架

注意事项

1、必须在使用蓝牙功能之前调用;

2、仅需要调用一次, 不能重复初始化, 若创建失败, 会返回nil, 请检查内存是否足够。

参数

返回值

local bluetooth_device = bluetooth.init()

bluetooth_device

含义说明:蓝牙对象;
数据类型:userdata/nil
取值范围:创建成功返回userdata对象,失败返回nil
注意事项:有返回nil的情况,需做好对应逻辑处理;
返回示例:成功返回:BLUETOOTH*: 0C7FD730
         失败返回:nil
         local bluetooth_device = bluetooth.init()
         log.info("bluetooth_device", bluetooth_device)

示例

-- 初始化蓝牙
bluetooth_device = bluetooth.init()
if not bluetooth_device then
    log.error("bluetooth", "init failed")
    return
end

4.2 bluetooth_device:ble(ble_callback)

功能

创建一个BLE对象, 用于操作BLE设备

注意事项

1、必须在bluetooth.init()初始化成功后调用

2、初始化只能创建一次,不能重复初始化

参数

ble_callback

含义说明:BLE事件回调函数, 用于处理BLE设备的事件, 如连接、断开、接收数据等;
         详细说明请参考本api中的示例部分
数据类型:function
取值范围:无;
是否必选:是;
注意事项:不同事件类型的param参数结构不同,需根据evt值进行相应处理
参数示例:-- 创建回调函数处理BLE事件
         function ble_callback(ble_device, ble_event, ble_param)
             -- ble_device: BLE设备对象
             -- ble_event: 事件类型(如ble.EVENT_CONN、ble.EVENT_DISCONN等)
             -- ble_param: 事件相关参数,结构根据事件类型不同而变化
             -- 具体事件类型及参数说明详见后续示例代码
         end

返回值 local ble_device = bluetooth_device:ble(ble_callback)

ble_device

含义说明:BLE对象
数据类型:userdata/nil
取值范围:创建成功返回userdata对象,失败返回nil
注意事项:后续所有BLE操作都依赖此对象,注意对象的生命周期管理;
         有返回nil的情况,需做好对应逻辑处理。
返回示例:成功返回:BLE*: 0C7FCFA8
         失败返回:nil
         local ble_device = bluetooth_device:ble(ble_callback)
         log.info("ble_device", ble_device )

示例

-- ble_callback 是自定义函数, 用于处理BLE事件
-- BLE事件回调函数, 回调时的参数如下:
function ble_callback(ble_device, ble_event, ble_param)
    -- ble_device 是BLE设备对象, 可以通过dev:adv_create()等方法进行操作
    -- ble_event 是BLE事件类型, 可以是以下几种:
    -- ble.EVENT_CONN: 连接成功
        -- ble_param是事件参数(table)包含以下字段:
        -- ble_param.addr: 对端设备的地址(string), 6字节的二进制数据, 代表BLE设备的MAC地址

    -- ble.EVENT_DISCONN: 断开连接
        -- ble_param是事件参数(table), 包含以下字段:
        -- ble_param.reason: 断开连接的原因(number)

    -- ble.EVENT_WRITE: 收到写请求
        -- ble_param是事件参数(table), 包含以下字段:
        -- ble_param.uuid_service: 服务的UUID(string)
        -- ble_param.uuid_characteristic: 特征的UUID_(string)
        -- ble_param.uuid_descriptor: 描述符的UUID_(string), 可选, 不一定存在
        -- ble_param.data: 写入的数据

    -- ble.EVENT_READ_VALUE: 读取操作完成
        -- ble_param是事件参数_(table), 包含以下字段:
        -- ble_param.uuid_service: 服务的UUID(string)
        -- ble_param.uuid_characteristic: 特征的UUID(string)
        -- ble_param.uuid_descriptor: 描述符的UUID(string), 可选, 不一定存在
        -- ble_param.data: 读取到的数据

    -- ble.EVENT_SCAN_REPORT: 扫描到设备
        -- ble_param是事件参数(table), 包含以下字段:
        -- ble_param.rssi: 信号强度(number)
        -- ble_param.adv_addr: 广播地址(string), 6字节的二进制数据
        -- ble_param.data: 广播数据(string), 二进制数据

    -- ble.EVENT_GATT_ITEM: 收到GATT项
        -- ble_param是事件参数(table),为一个嵌套表结构,具体如下:
            -- ble_param[1]: 服务的UUID(string), 二进制数据
            -- ble_param[2...]: 特征值信息(table),每个都是一个子表
            --   ble_param[索引][1]: 特征值的UUID(string), 二进制数据
            --   ble_param[索引][2]: 特征值的属性(number), 表示读写权限等

    -- ble.EVENT_GATT_DONE: GATT操作完成
        -- ble_param是事件参数(table), 包含以下字段:
        -- ble_param.service_num: 服务数量(number)

    -- ble.EVENT_SCAN_STOP: 扫描停止
        -- ble_param为nil

    if ble_event == ble.EVENT_CONN then
        log.info("ble", "connect 成功", ble_param, ble_paramand, ble_param.addr and ble_param.addr:toHex() or "unknow")
        ble_stat = true
    elseif ble_event == ble.EVENT_DISCONN then
        log.info("ble", "disconnect")
        ble_stat = false
        -- 1秒后重新开始广播
        sys.timerStart(function() dev:adv_start() end, 1000)
    elseif ble_event == ble.EVENT_SCAN_REPORT then
        log.info("ble", "scan report", ble_param.rssi, param.adv_addr:toHex(), param.data:toHex())
    elseif ble_event == ble.EVENT_WRITE then
        log.info("ble", "接收到写请求", ble_param.uuid_service:toHex(), ble_param.uuid_characteristic:toHex(), ble_param.data:toHex())
    elseif ble_event == ble.EVENT_READ_VALUE then
        log.info("ble", "读取操作完成", ble_param.uuid_service:toHex(), ble_param.uuid_characteristic:toHex(), ble_param.data:toHex())
    elseif ble_event == ble.EVENT_SCAN_STOP then
        log.info("ble", "scan stop")
    elseif ble_event == ble.EVENT_GATT_ITEM then
        log.info("ble", "gatt item", ble_param[1]:toHex(), #ble_param)
    elseif ble_event == ble.EVENT_GATT_DONE then
        log.info("ble", "gatt done", ble_param.service_num)
    end
end

-- 初始化蓝牙并创建BLE对象
bluetooth_device = bluetooth.init()
ble_device = bluetooth_device:ble(ble_callback)

4.3 ble_device:scan_create(addr_mode,scan_interval,scan_window,scan_type)

功能

创建一个 BLE 扫描

注意事项

1、默认扫描模式为 ble.SCAN_PASSIVE,仅接收广播包,不向广播设备发送任何请求;

2、如果设备名称在扫描响应包中,则需要设置扫描模式为 ble.SCAN_ACTIVE ,此时会向广播设备发送扫描请求(Scan Request),并接收广播设备的扫描响应(Scan Response);

3、只能创建一次,不能重复创建

参数

addr_mode

含义说明:要扫描的广播地址模式
数据类型:number
取值范围:可选值: 当前仅支持ble.PUBLIC
是否必选:否;
注意事项:默认值为ble.PUBLIC
参数示例:ble.PUBLIC

scan_interval

含义说明:扫描间隔
         表示两次扫描事件之间的间隔时间;
数据类型:number
取值范围:单位为0.625ms, 最小值为20, 最大值为10240
是否必选:否;
注意事项:默认值为100
参数示例:100

scan_window

含义说明:扫描窗口
         是指 BLE 设备在扫描过程中,打开接收器去监听广播设备的时间段;
         这个时间段是设备实际进行扫描操作的时间,也称为扫描事件的持续时间;
数据类型:number
取值范围:单位为0.625ms, 最小值为20, 最大值为10240
是否必选:否;
注意事项:默认值为100,它的值必须小于或等于扫描间隔;
参数示例:100

scan_type

含义说明:扫描类型
数据类型:number
取值范围:可选值: ble.SCAN_ACTIVE, ble.SCAN_PASSIVE
是否必选:否;
注意事项:默认值为ble.SCAN_PASSIVE
参数示例:ble.SCAN_ACTIVE

返回值

local result = ble_device:scan_create(addr_mode,scan_interval,scan_window,scan_type)

result

含义说明:是否创建成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示创建成功false表示创建失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:scan_create(ble.PUBLIC, 100, 100, ble.SCAN_ACTIVE)
         log.info("result", result)

示例

-- 创建BLE 主动扫描
ble_device:scan_create(ble.PUBLIC, 100, 100, ble.SCAN_ACTIVE)

4.4 ble_device:scan_start()

功能

开始 BLE 扫描

注意事项

1、扫描会一直进行, 直到调用 ble.scan_stop()停止扫描;

2、扫描到结果会触发 ble.EVENT_SCAN_REPORT 事件,执行通过 bluetooth_device:ble(ble_callback)创建 BLE 对象时注册的回调函数;

3、扫描到同一个设备不会去重, 扫描到数据就会执行回调。

4、不要在扫描状态下,重复调用此接口开始扫描

参数

返回值

local result = ble_device:scan_start()

result

含义说明:是否开始扫描成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示开始扫描成功false表示开始扫描失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:scan_start()
         log.info("result", result)

示例

-- 开始BLE扫描
ble_device:scan_start()

4.5 ble_device:scan_stop()

功能

停止 BLE 扫描

注意事项

扫描会一直进行, 直到调用 ble.scan_stop()停止扫描。

参数

返回值

local result = ble_device:scan_stop()

result

含义说明:是否停止扫描成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示停止扫描成功false表示停止扫描失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:scan_stop()
         log.info("result", result)

示例

-- 停止BLE扫描
ble_device:scan_stop()

4.6 ble_device:connect(mac, addr_type)

功能

发起 BLE 连接请求

注意事项

参数

mac

含义说明:目标蓝牙设备的MAC地址
数据类型:string
取值范围:有效的12个十六进制字符组成的蓝牙MAC地址字符串(如"AABBCCDDEEFF"
是否必选:是;
注意事项:MAC地址需要先使用string.fromHex()函数将十六进制字符串转换为二进制格式;
参数示例:-- MAC地址转换示例
         local mac_hex = "AABBCCDDEEFF" -- 12位十六进制字符串
         -- 转换为二进制格式:
         local mac_bin = string.fromHex(mac_hex)

addr_type

含义说明:目标蓝牙设备的地址类型;
数据类型:number
取值范围:可选值: 当前仅支持ble.PUBLIC
是否必选:是;
注意事项:无;
参数示例:ble.PUBLIC

返回值

local result = ble_device:connect(mac, addr_type)

result

含义说明:是否成功发起连接请求;
         真正的连接结果通过异步事件ble.EVENT_CONN通知到bluetooth_device:ble(ble_callback)中设置的回调函数ble_callback:
数据类型:boolean
取值范围:true/false
注意事项:true表示连接请求已成功发起,不代表连接已建立;
         false表示发起连接请求失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:connect(mac, addr_type)
         log.info("result", result)

示例

-- BLE连接
ble_device:connect(string.fromHex("C8478C4E027D"),0)

4.7 ble_device:disconnect()

功能

发起 BLE 断开连接请求

注意事项

参数

返回值

local result = ble_device:disconnect()

result

含义说明:是否成功发起断开连接请求;
         真正的连接结果通过异步事件ble.EVENT_DISCONN通知到bluetooth_device:ble(ble_callback)中设置的回调函数ble_callback
数据类型:boolean
取值范围:true/false
注意事项:true表示断开连接请求已成功发起,不代表连接已被断开;
         false表示发起断开连接请求失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:disconnect()
         log.info("result", result)

示例

-- BLE断开连接
ble_device:disconnect()

4.8 ble_device:gatt_create(opts)

功能

创建一个 BLE GATT 服务

注意事项

1、确保 UUID 格式正确,且特征属性使用正确的权限常量;

2、特征属性必须是 ble.NOTIFY | ble.READ | ble.WRITE | ble.IND 的一种或多种组合;

3、只能创建一次,不能重复创建

4、只能创建一个 BLE GATT 服务, 当前不支持创建多个GATT服务

参数

opts

含义说明:GATT服务的描述信息,包含服务UUID和其下所有特征的定义
         表的第一个元素:服务的UUID(通过string.fromHex转换的16位32位或128UUID
         表的后续元素:特征定义表(每个特征为一个子表),子表结构为:
             第一个元素:特征的UUID(通过string.fromHex转换
             第二个元素:特征的属性(权限常量的组合,如ble.NOTIFY | ble.READ | ble.WRITE | ble.IND
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:确保UUID格式正确,且特征属性使用正确的权限常量;

返回值

local result = ble_device:gatt_create(opts)

result

含义说明:是否创建GATT服务成功
数据类型:boolean
取值范围:true/false
注意事项:true表示创建GATT服务成功false表示创建GATT服务失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:gatt_create(opts)
         log.info("result", result)

示例

local att_db = { -- Service
    string.fromHex("FA00"), -- Service UUID, 服务的UUID, 可以是16位、32位或128位
    -- Characteristic
    { -- Characteristic 1
        string.fromHex("EA01"), -- Characteristic UUID Value, 特征的UUID值, 可以是16位、32位或128位
        ble.NOTIFY | ble.READ | ble.WRITE -- Properties, 对应蓝牙特征的属性, 参考权限常量
    }, { -- Characteristic 2
        string.fromHex("EA02"), ble.WRITE
    }, { -- Characteristic 3
        string.fromHex("EA03"), ble.READ
    }, { -- Characteristic 4
        string.fromHex("EA04"), ble.IND | ble.READ
    }
}
ble_device:gatt_create(att_db)

4.9 ble_device:adv_create(opts)

功能

创建一个 BLE 广播

注意事项

只能创建一次,不能重复创建

参数

opts

含义说明:BLE广播配置参数表,包含广播的各种属性配置
         addr_mode: 广播地址模式(可选值:ble.PUBLIC
            -- addr_mode可选值说明:
            --   ble.PUBLIC   - 公共地址(设备出厂时分配的固定MAC地址)
         channel_map: 广播通道配置(可选值:ble.CHNL_37, ble.CHNL_38, ble.CHNL_39, ble.CHNLS_ALL
            -- channel_map可选值说明:
            --   ble.CHNL_37  - 广播通道37
            --   ble.CHNL_38  - 广播通道38
            --   ble.CHNL_39  - 广播通道39
            --   ble.CHNLS_ALL - 广播通道37、38、39
         intv_min: 广播间隔最小值(单位:0.625ms,取值范围:20-10240
         intv_max: 广播间隔最大值(单位:0.625ms,取值范围:20-10240
         adv_data: 广播数据内容(支持表格形式和字符串形式,字符串形式不超过255字节)
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:注意参数根据实际情况填写

返回值

local result = ble:adv_create(opts)

result

含义说明:是否创建广播成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示创建广播成功false表示创建广播失败
返回示例:成功返回:true
         失败返回:false
         local result = ble:adv_create(opts)
         log.info("result", result)

示例

-- 创建广播信息
ble_device:adv_create({
    addr_mode = ble.PUBLIC, -- 广播地址模式, 可选值: ble.PUBLIC
    channel_map = ble.CHNLS_ALL, -- 广播的通道, 可选值: ble.CHNL_37, ble.CHNL_38, ble.CHNL_39, ble.CHNLS_ALL
    intv_min = 120, -- 广播间隔最小值, 单位为0.625ms, 最小值为20, 最大值为10240
    intv_max = 120, -- 广播间隔最大值, 单位为0.625ms, 最小值为20, 最大值为10240
    adv_data = { -- 支持表格形式, 也支持字符串形式(255字节以内)
        {ble.FLAGS, string.char(0x06)},
        {ble.COMPLETE_LOCAL_NAME, "LuatOS123"}, -- 广播的设备名
        {ble.SERVICE_DATA, string.fromHex("FE01")}, -- 广播的服务数据
        {ble.MANUFACTURER_SPECIFIC_DATA, string.fromHex("05F0")}
    }
})

4.10 ble_device:adv_start()

功能

开始广播

注意事项

1、对于外围设备模式, 如果被断开了连接, 则需要重新开始广播, 才能被重新搜索到

2、不要在广播状态下,重复调用此接口开始广播

参数

返回值

local result = ble_device:adv_start()

result

含义说明:是否开始广播成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示开始广播成功false表示开始广播失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:adv_start()
         log.info("result", result)

示例

-- 开始广播
ble_device:adv_start()

4.11 ble_device:adv_stop()

功能

主动停止广播

注意事项

参数

返回值

local result = ble_device:adv_stop()

result

含义说明:是否停止广播成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示停止广播成功false表示停止广播失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:adv_stop()
         log.info("result", result)

示例

-- 停止广播
ble_device:adv_stop()

4.12 ble_device:write_notify(opts,value)

功能

写入带通知的特征值

注意事项

外围设备使用,主动向中心设备发送通知数据

参数

opts

含义说明:写入特征值的配置参数表,包含服务UUID和特征值的UUID
         uuid_service: 服务的UUID,用于标识要写入的特征值所属的服务
         uuid_characteristic: 特征的UUID值,用于标识要写入的特征值
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:注意参数根据实际情况填写

value

含义说明:写入的特征值内容
数据类型:string
取值范围:无特别限制
是否必选:是;
注意事项:注意参数根据实际情况填写

返回值

local result = ble_device:write_notify(opts,value)

result

含义说明:是否写入成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示写入成功false表示写入失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:write_notify(opts,value)
         log.info("result", result)

示例

-- 写入带通知的特征值
ble_device:write_notify({
    uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
    uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
}, "Hello BLE") -- 要写入的值

4.13 ble_device:write_indicate(opts,value)

功能

写入带指示的特征值

注意事项

外围设备使用,主动向中心设备发送指示数据

参数

opts

含义说明:写入特征值的配置参数表,包含服务UUID和特征值的UUID
         uuid_service: 服务的UUID,用于标识要写入的特征值所属的服务
         uuid_characteristic: 特征的UUID值,用于标识要写入的特征值
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:注意参数根据实际情况填写

value

含义说明:写入的特征值内容
数据类型:string
取值范围:无特别限制
是否必选:是;
注意事项:注意参数根据实际情况填写

返回值

local result = ble:write_indicate(opts,value)

result

含义说明:是否写入成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示写入成功false表示写入失败
返回示例:成功返回:true
         失败返回:false
         local result = ble:write_indicate(opts,value)
         log.info("result", result)

示例

-- 写入带指示的特征值
ble_device:write_indicate({
    uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
    uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
}, "Hello BLE") -- 要写入的值

4.14 ble_device:write_value(opts,value)

功能

写入特征值

注意事项

参数

opts

含义说明:写入特征值的配置参数表,包含服务UUID和特征值的UUID
         uuid_service: 服务的UUID,用于标识要写入的特征值所属的服务
         uuid_characteristic: 特征的UUID值,用于标识要写入的特征值
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:注意参数根据实际情况填写

value

含义说明:写入的特征值内容
数据类型:string
取值范围:无特别限制
是否必选:是;
注意事项:注意参数根据实际情况填写

返回值

local result = ble_device:write_value(opts,value)

result

含义说明:是否写入成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示写入成功false表示写入失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:write_value(opts,value)
         log.info("result", result)

示例

-- 写入特征值,填充预设值,被动读取
ble_device:write_value({
    uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
    uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
}, "Hello BLE") -- 要写入的值

4.15 ble_device:read_value(opts)

功能

读取特征值

注意事项

参数

opts

含义说明:读取特征值的配置参数表,包含服务UUID和特征值的UUID
         uuid_service: 服务的UUID,用于标识要读取的特征值所属的服务;
         uuid_characteristic: 特征的UUID值,用于标识要读取的特征值;
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:注意参数根据实际情况填写;

返回值

local result = ble_device:read_value(opts)

result

含义说明:是否读取成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示读取成功false表示读取失败
         通过回调中的 EVENT_READ_VALUE 事件返回读取的value值
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:read_value(opts)
         log.info("result", result)

示例

-- 读取特征值,通过回调中的 EVENT_READ_VALUE 事件返回读取的value值
ble_device:read_value({
    uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
    uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
})

4.16 ble_device:notify_enable(opts,enable)

功能

开关通知监听

注意事项

中心设备使用,配置是否接收外围设备发送的通知消息

参数

opts

含义说明:通知监听的配置参数表,包含服务UUID和特征值的UUID
         uuid_service: 服务的UUID,用于标识要通知监听的特征值所属的服务;
         uuid_characteristic: 特征的UUID值,用于标识要通知监听的特征值;
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:注意参数根据实际情况填写;

enable

含义说明:通知监听的状态;;
数据类型:boolean
取值范围:true/false
是否必选:是;
注意事项:true表示开启通知监听,false表示关闭通知监听

返回值

local result = ble_devie:notify_enable(opts,enable)

result

含义说明:是否开启通知监听成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示开启通知监听成功false表示开启通知监听失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_devie:notify_enable(opts,enable)
         log.info("result", result)

示例

ble_device:notify_enable({
    uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
    uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
}, true) -- 开/关

4.17 ble_device:indicate_enable(opts,enable)

功能

开关指示监听

注意事项

中心设备使用,配置是否接收外围设备发送的指示消息

参数

opts

含义说明:指示监听的配置参数表,包含服务UUID和特征值的UUID
         uuid_service: 服务的UUID,用于标识要指示监听的特征值所属的服务;
         uuid_characteristic: 特征的UUID值,用于标识要指示监听的特征值;
数据类型:table
取值范围:符合上述结构的table对象
是否必选:是;
注意事项:注意参数根据实际情况填写;

enable

含义说明:指示监听的状态;
数据类型:boolean
取值范围:true/false
是否必选:是;
注意事项:true表示开启指示监听,false表示关闭指示监听

返回值

local result = ble_device:indicate_enable(opts,enable)

result

含义说明:是否开启指示监听成功;
数据类型:boolean
取值范围:true/false
注意事项:true表示开启指示监听成功false表示开启指示监听失败
返回示例:成功返回:true
         失败返回:false
         local result = ble_device:indicate_enable(opts,enable)
         log.info("result", result)

示例

ble_device:indicate_enable({
    uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
    uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
}, true) -- 开/关

4.18 ble_device:adv_decode(data)

功能

解码广播数据

注意事项

广播数据通常来自于 ble.EVENT_SCAN_REPORT 事件的 ble_param.data

参数

data

含义说明:原始广播数据;
数据类型:string
取值范围:广播数据的字符串表示;
是否必选:是;
注意事项:注意参数根据实际情况填写;

返回值

local adv_data = ble_device:adv_decode(data)

adv_data

含义说明:广播数据的解码结果,为table类型,表结构如下:
         索引型表(索引从1开始);
         每个索引对应一个子表,代表一个广告数据单元(AD Structure)
         每个子表包含以下三个字段:
             len :整数类型,表示数据长度
             tp :整数类型,表示广播数据类型(AD Type)
             data :字符串类型(二进制数据),表示广播数据内容
数据类型:table/nil
取值范围:解码成功返回table对象,失败返回nil
注意事项:返回的数据需要自行解析提取
返回示例:成功返回:table: 0C7F6570
         失败返回:nil
         local result = ble_device:adv_decode(data)
         log.info("result", result)

示例

-- 解码广播数据
local adv_data = ble_device:adv_decode(ble_param.data)
-- 解析广播数据
if adv_data then
    for k, v in pairs(adv_data) do
        log.info("ble", "adv data", v.len, v.tp, v.data:toHex())
    end
end

4.19 ble.mac()

功能

获取蓝牙 MAC

注意事项

1、AP,STA,BLE三者的MAC地址关系:

AP = STA + 1 BLE = STA + 2

例如: STA = "C8C2C6906511" AP = "C8C2C6906512" BLE = "C8C2C6906513"

2、如何获取AP或者STA MAC地址?

使用wlan.getMac(mode, hexstr) 获取AP或者STA MAC地址,具体用法请参考:https://docs.openluat.com/osapi/core/wlan/#410-wlansetmacmode-mac

参数

返回值

local mac = ble.mac

mac

含义说明:蓝牙MAC地址
数据类型:string/nil
取值范围:成功返回string,失败返回nil
注意事项:成功返回6字节的二进制字符串,需要通过toHex()方法转换为可读的12个连续十六进制字符(如"AABBCCDDEEFF");
返回示例:成功返回:如果mac地址为"AABBCCDDEEFF",则返回6个字节长度的string数据
                  1个字节的ascii值为0xAA,后续5个字节的ascii值依次为0xBB, 0xCC, 0xDD, 0xEE, 0xFF
         失败返回:nil
         local mac = ble.mac()
         log.info("原始二进制字符串", mac)
         local mac_hex = mac:toHex()
         log.info("转换成十六进制字符", mac_hex) -- 输出如:"AABBCCDDEEFF"

示例

-- 本函数于2025.8.29新增
local mac = ble.mac()
log.info("ble mac", mac and mac:toHex())

五、产品支持说明

适用于 Air8000A / Air8000W / Air8000U / Air8000N / Air8000AB / Air8000DB,以及 Air8101 系列 此类支持蓝牙功能的产品。

六、常见问题

6.1 ibeacon 应用,为什么无法显示名称?

答:

一个完整的 BLE 广播数据包最长可以有 37 个字节,其中前 6 个字节固定用于设备 MAC 地址,剩下的 31 个字节才是我们可以自由配置的广播数据区域。这 31 个字节会被划分为若干个广播数据结构体(AD Structure)。

也就是 BLE 广播包 广播数据区域不超过 31 字节,那么 iBeacon 包含的数据和包含 flag 的 AD Structure 已经占了 30 个字节,如果要设置设备命名,会超出 31 字节。

可能有人会问,不是还有 1 个字节的空间吗,设备名称用一个字节不可以吗?

答:

  • 名称"1"(1 字符)。
  • AD Structure 长度:1(数据) + 1(类型) + 1(长度) = 3 字节。
  • 总长度:27(iBeacon) + 3(Flags) + 3(名称) = 33 字节 → 仍超出。

6.2 什么是 Flags?

ble.FLAGS 说明

在 BLE 中,标志(flags)通常出现在广播数据中,这些标志用于指示设备的能力和可发现性等。

根据蓝牙核心规范(Bluetooth Core Specification),广播数据中的 Flags 字段是一个 8 位的位图(bitmask),每个位代表特定的含义,以下是各个位的定义(从 LSB 到 MSB):

  • Bit 0: LE Limited Discoverable Mode(有限可发现模式)
  • Bit 1: LE General Discoverable Mode(通用可发现模式,设备持续可被发现)
  • Bit 2: BR/EDR Not Supported(不支持经典蓝牙)
  • Bit 3: Simultaneous LE and BR/EDR to Same Device Capable(同一设备同时支持 BLE 和经典蓝牙)
  • Bit 4: Simultaneous LE and BR/EDR to Different Devices Capable(支持同时连接不同设备的 BLE 和经典蓝牙)
  • Bit 5-7: 保留(Reserved)

注意:Bit 0 和 Bit 1 不能同时被设置。如果同时设置,则视为无效。

Bit1 和 Bit2 被设置时,Flags 字段的值为 0x06(二进制 0000 0110),

Bit2 被设置时,Flags 字段的值为 0x04(二进制 0000 0100)。

6.3 常见的 BLE 断开连接 reason


原因
0x08 (8)
Connection Timeout(数据传输过程中超时断开连接)
0x09 (9)
Maximum Number Of Connections(已达到最大连接数限制)
0x0C (12)
Command Disallowed(当前状态下不允许执行此命令)
0x13 (19)
Remote User Terminated Connection(远程用户终止连接,表示对方设备主动断开连接)
0x16 (22)
Connection Terminated By Local Host(本地主机终止连接,表示本设备主动断开连接)
0x18 (24)
Unacceptable Connection Parameters(不可接受的连接参数,如连接间隔、超时时间等参数不符合要求)
0x3E (62)
Connection Timeout("连接超时"或"未在规定时间内建立连接")

示例:

1、中心设备和外围设备在数据传输过程中,把外围设备断电

中心设备会提示 8 的错误码,即数据传输过程中超时断开连接。

2、中心设备和外围设备连接时,中心设备主动发起 disconnect

中心设备会提示 22 的错误码,即本地主机终止连接。

外围设备会提示 19 的错误码,即远程用户终止连接。

6.4 使用Air8000/Air8101 作为外围设备,向已经建立连接的手机蓝牙调试软件发送数据,发现手机调试软件接收到的数据不全。

原因:

MTU设置的问题,Air8000/Air8101支持的MTU默认是256字节,如果手机上的蓝牙调试软件的MTU较小,会以小的为准。

解决方案:

  1. 可以通过Air8000读到对端蓝牙设备的MTU大小,根据读到的MTU的大小做分包处理即可。(读取对端设备MTU的功能还在开发中)
  2. 调大对端蓝牙设备的MTU。

6.5 使用Air8000/Air8101 作为外围设备模式对外广播,如何广播完整的服务UUID?

鉴于固件空间考虑,只对常用的AD Type做了常量定义,比如特征属性常量,地址模式常量等。 具体参考上面第三章节的常量介绍。

其余未作常量定义的值,写原始number即可。

举例说明:

比如需要广播完整的16位服务UUID列表,需要看蓝牙协议中,对应的原始number值;通过查询可知,完整的16位服务UUID列表的原始number值为0x03,所以代码中设置广播内容部分,可参考下面的写法,其他的值同理。

如何查询AD Type对应的原始number值?

可以参考蓝牙协议规范,或者使用蓝牙调试软件(如nRF Connect)查看广播数据中的AD Structure,找到对应的AD Type,即可查询到对应的原始number值。

1、蓝牙官方文档:https://www.bluetooth.com/specifications/assigned-numbers/ 中的2.3 CommonDataTypes。

在蓝牙低功耗(BLE)的Advertising Data(AD)格式中,​AD Type字段用于标识后续数据的类型。以下是常见且重要的AD Type值:

  • 0x01: Flags(广播模式标志(LE有限发现/通用发现/BR/EDR支持等)
  • 0x02: Incomplete List of 16-bit Service Class UUIDs (不完整的16位服务UUID列表)
  • 0x03: Complete List of 16-bit Service Class UUIDs (完整的16位服务UUID列表)
  • 0x04: Incomplete List of 32-bit Service Class UUIDs (不完整的32位服务UUID列表)
  • 0x05: Complete List of 32-bit Service Class UUIDs (完整的32位服务UUID列表)
  • 0x06: Incomplete List of 128-bit Service Class UUIDs (不完整的128位服务UUID列表)
  • 0x07: Complete List of 128-bit Service Class UUIDs (完整的128位服务UUID列表)
  • 0x08: Shortened Local Name (缩短的本地名称)
  • 0x09: Complete Local Name (完整的本地名称)
  • 0x0A: Tx Power Level (广播发射功率等级)
  • 0x0D: Class of Device (设备类别)
  • 0x12: Peripheral Connection Interval Range (外设连接间隔范围)
  • 0x14: List of 16-bit Service Solicitation UUIDs (16位服务请求UUID列表)
  • 0x15: List of 128-bit Service Solicitation UUIDs (128位服务请求UUID列表)
  • 0x16: Service Data - 16-bit UUID (带16位UUID的服务数据)
  • 0x17: Public Target Address (公有目标地址)
  • 0x18: Random Target Address 随机目标地址
  • 0x19: Appearance 设备外观(图标类型)
  • 0x1A: Advertising Interval 广播间隔时间(ms)
  • 0x1B: LE Bluetooth Device Address (LE设备地址)
  • 0x1C: LE Role LE角色(主/从)
  • 0x1F: LE Secure Connections Confirmation (LE安全连接确认值)
  • 0x20: LE Secure Connections Random (LE安全连接随机数)
  • 0x24: URI (统一资源标识符)
  • 0xFF: Manufacturer Specific Data (制造商特定数据)

6.6 为什么使用扫描模式,无法扫描到从设备名称?

因为默认扫描模式为 ble.SCAN_PASSIVE,仅接收广播包,不向广播设备发送任何请求;

如果设备名称在扫描响应包中,则需要设置扫描模式为 ble.SCAN_ACTIVE ,此时会向广播设备发送扫描请求(Scan Request),并接收广播设备的扫描响应(Scan Response);

具体请查看本篇文档的4.3 小节。