slave

# 简介 从设备模式:工作在从机模式下的蓝牙模块只能被主机搜索,不能主动搜索。从设备跟主机连接以后,也可以和主机设备进行发送和接收数据。 # API说明 以下API是模块BLE从模式用到的接口,其余接口及具体接口参数说明和用法请到API说明章节和demo内查看并学习 | API接口 | 描述 | | ------------------------- | -------------------------------------- | | btcore.open() | 打开蓝牙 | | btcore.close() | 关闭蓝牙 | | btcore.state() | 查询蓝牙状态(开启或者关闭) | | btcore.disconnect() | 蓝牙主动断开连接 | | btcore.setname() | 设置蓝牙名称 | | btcore.setadvdata() | 设置广播包数据 | | btcore.setscanrspdata() | 设置扫描响应包数据 | | btcore.addservice() | 蓝牙添加服务 | | btcore.addcharacteristic() | 蓝牙添加服务内的特征 | | btcore.adddescriptor() | 蓝牙添加特征的描述 | | btcore.setadvparam() | 设置广播参数 | | btcore.advertising() | 蓝牙广播开关 | | btcore.send() | 写数据 | | btcore.recv() | 读数据 | | btcore.getaddr() | 获取本机蓝牙MAC地址 | | btcore.addwhitelist() | 将蓝牙地址添加到白名单 | | btcore.removewhitelist() | 将蓝牙地址从白名单内移除 | | btvore.clearwhitelist() | 清空白名单 | BLE从设备模式用到的蓝牙消息 | API接口 | 描述 | | ------------------------- | -------------------------------------- | | MSG_OPEN_CNF | 蓝牙打开成功 | | MSG_CLOSE_CNF | 蓝牙关闭成功 | | MSG_BLE_CONNECT_IND | 蓝牙从模式连接 | | MSG_BLE_DISCONNECT_IND | 蓝牙从模式断开连接 | | MSG_BLE_DATA_IND | 数据接收 | > 详细的API介绍见[btcore API章节](https://doc.openluat.com/wiki/21?wiki_page_id=2244) # 实现流程 - 注册蓝牙消息回调函数 通过rtos.on() 注册蓝牙消息回调函数 - 打开蓝牙 使用btcore.open(0)打开蓝牙从设备模式 - 设置蓝牙名称 使用btcore.setname()设置蓝牙名称 - 设置广播数据 使用btcore.setadvdata()设置广播包 使用btcore.setscanrspdata()设置扫描响应包 需要根据蓝牙广播/响应包的格式来设置 - 添加BLE服务、特征、描述 使用btcore.addservice()添加服务 使用btcore.addcharacteristic()添加特征 使用btcore.adddescriptor()添加描述 需要遵从一定的格式来设置,具体使用方式请看bluetooth/slave的demo - 设置广播参数 使用btcore.setadvparam()来设置广播参数,如果没有设置,则使用默认的广播参数 - 开启蓝牙广播 使用btcore.advertising()来打开广播 - 开启广播后等待其他蓝牙设备的连接 - 连接成功后就可以进行数据的收发 - 收数据 btcore.recv()来读取数据 - 发数据 btcore.send()来发送数据 # 白名单 将一组蓝牙地址添加到一个列表,这个列表就是白名单 通过白名单,可以只允许特定的蓝牙设备(白名单中列出的)扫描(Scan)、连接(connect)我们,也可以只扫描、连接特定的蓝牙设备(白名单中列出的)。 通过以下接口来实现白名单广播与全局广播 ```lua --参数释义: --其余接口、参数释义请到蓝牙API章节介绍去查询,这里介绍白名单与全局广播用到的接口与参数 --addr:蓝牙mac地址 --addr_type:蓝牙mac地址类型 --advfiter:广播过滤策略 --以下是广播过滤策略的取值,是白名单是否启用的关键 --0: Process scan and connection requests from all devices. --禁用白名单机制,允许任何设备连接和扫描 --1: Process connection requests from all devices and only scan requests from devices that are in the White List. --允许任何设备连接,但只允许白名单中的设备扫描。 --2: Process scan requests from all devices and only connection requests from devices that are in the White List. --允许任何设备扫描,但只允许白名单中的设备连接。 --3: Process scan and connection requests only from devices in the White List --只允许白名单中的设备扫描和连接。 --btcore.addwhitelist(addr, addr_type)将蓝牙地址添加到白名单 --btcore.removewhitelist(addr, addr_type)将蓝牙地址从白名单内移除 --btvore.clearwhitelist()清空白名单 --btcore.setadvparam(advmin, advmax, advtype, ownaddtype, advchannmap, advfilter[, directaddrtype, directaddr])设置广播参数 ``` **白名单广播示例** 将mac地址添加到白名单中,配合广播参数的广播过滤策略的设置,即可开启白名单广播或全局广播功能 **全局广播** ```lua --禁用白名单机制,允许任何设备连接和扫描 btcore.setadvparam(0x80, 0xa0, 0, 0, 0x07, 0) btcore.advertising(1) ``` **白名单广播** ```lua --举个例子,设两个蓝牙设备mac地址分别为A、B,地址类型为Public Device Address(取值为0) --A的地址为:"11:22:33:44:55:66" --B的地址为:"aa:bb:cc:dd:ee:ff" --将A的地址添加进广播设备的白名单,通过以下广播过滤策略即可达到不同的效果 btcore.addwhitelist("11:22:33:44:55:66", 0) --允许任何设备连接,但只允许白名单中的设备扫描。 --此广播状态下,A、B设备都可以连接此从机设备,但只有A设备可以扫描到它 btcore.setadvparam(0x80, 0xa0, 0, 0, 0x07, 1) btcore.advertising(1) --允许任何设备扫描,但只允许白名单中的设备连接。 --此广播状态下,A、B设备都可以扫描到此从机设备,但只有A设备可以连接它 btcore.setadvparam(0x80, 0xa0, 0, 0, 0x07, 2) btcore.advertising(1) --只允许白名单中的设备扫描和连接。 --此广播状态下,只有A设备可以扫描并连接此从机设备,B设备无法扫描、连接此从机设备 btcore.setadvparam(0x80, 0xa0, 0, 0, 0x07, 3) btcore.advertising(1) ``` # 示例 相关实例程序在脚本库的demo\bluetooth文件夹下,包含主机、从机、becaon和经典蓝牙。可以根据实际需要选择demo进行研究。 本示例是对demo的程序删改而来 **初始化注册蓝牙消息回调函数** 以\script_LuaTask_V2.3.9\demo\bluetooth\slave.lua作为基础进行修改。首先使用rtos.on()注册蓝牙消息的回调处理函数。 ```lua local function init() log.info("bt", "init") rtos.on(rtos.MSG_BLUETOOTH, function(msg) if msg.event == btcore.MSG_OPEN_CNF then --蓝牙打开成功 --此处根据自己需要的业务逻辑来处理 --例如:在这里sys.publish一条消息,表示蓝牙打开成功了 sys.publish("BLE_OPEN") elseif msg.event == btcore.MSG_CLOSE_CNF then --蓝牙关闭成功 --此处根据自己需要的业务逻辑来处理 elseif msg.event == btcore.MSG_BLE_CONNECT_IND then --蓝牙连接结果 --此处根据自己需要的业务逻辑来处理 --msg.result表示连接结果,0为连接成功 --msg.handle为连接句柄 --例如:在这里sys.publish一条消息,消息携带的参数含有蓝牙连接结果 sys.publish("BT_CONNECT_IND", {["handle"] = msg.handle, ["result"] = msg.result}) elseif msg.event == btcore.MSG_BLE_DISCONNECT_IND then--蓝牙断开连接 --此处根据自己需要的业务逻辑来处理 elseif msg.event == btcore.MSG_BLE_DATA_IND then --蓝牙收到消息 --此处根据自己需要的业务逻辑来处理,当收到蓝牙消息时,使用btcore.recv()读取即可 --例如:在这里sys.publish一条消息,表示蓝牙收到数据了 sys.publish("BT_DATA_IND", {["result"] = msg.result}) end end) end ``` **打开蓝牙** ```lua local function poweron() log.info("bt", "poweron") btcore.open(0) --打开蓝牙从模式 --蓝牙打开后,在上面的消息回调内会有蓝牙打开成功的消息上报 --在这里阻塞住,当收到蓝牙打开成功消息时退出阻塞 sys.waitUntil("BLE_OPEN") end ``` ***注意:接口返回成功不一定是打开成功,需要等待蓝牙打开成功的消息*** **设置蓝牙名称,广播参数,服务、特征、描述,广播包、响应包、打开广播** <br> **这里我们添加一个服务和两个特征作为演示** **服务uuid为0xfee0,特征uuid分别为0xfee1和0xfee2** <br> 0xfee1具有write的属性,这表示主机与从机建立链接后可向0xfee1发送数据 0xfee2具有notify、write、write without response <br> <br> ```lua local function service(uuid,struct) btcore.addservice(uuid) --添加服务 for i = 1, #struct do btcore.addcharacteristic(struct[i][1],struct[i][2],struct[i][3]) --添加特征 if(type(struct[i][4]) == "table") then for j = 1,#struct[i][4] do btcore.adddescriptor(struct[i][4][j][1],struct[i][4][j][2]) --添加描述 end end end end local function advertising() btcore.setname("TESTBLE")-- 设置广播名称 btcore.setadvdata(string.fromHex("02010604ff000203"))-- 设置广播数据 根据蓝牙广播包协议格式 --btcore.setscanrspdata(string.fromHex("04ff000203"))-- 设置扫描响应包 根据蓝牙广播包协议格式 local struct1 = {{0xfee1, 0x08, 0x0002}, {0xfee2, 0x1c,0x0003, {{0x2902,0x0003},{0x2901,"123456"}}}}--{特征uuid,特征属性,特征权限,{特征描述uuid,描述属性}} service(0xfee0, struct1)--添加服务16bit uuid 自定义服务 --btcore.setadvparam(0x80,0xa0,0,0,0x07,2,0,"11:22:33:44:55:66") --广播参数设置 (最小广播间隔,最大广播间隔,广播类型,广播本地地址类型,广播channel map,广播过滤策略,定向地址类型,定向地址) btcore.advertising(1)-- 打开广播 end ``` **打开广播等待连接成功后,之后可以进行数据收发,例如** ```lua local function data_trans() _, bt_connect = sys.waitUntil("BT_CONNECT_IND") if bt_connect.result ~= 0 then --连接失败 return false end while true do _, bt_recv = sys.waitUntil("BT_DATA_IND") --等待接收到数据 local data = "" local len = 0 local uuid = "" while true do --读取数据,数据来源uuid,数据,数据长度 local recvuuid, recvdata, recvlen = btcore.recv(3) if recvlen == 0 then break end uuid = recvuuid len = len + recvlen data = data .. recvdata end --打印出收到的数据 if len ~= 0 then log.info("bt.recv_data", data) log.info("bt.recv_data len", len) log.info("bt.recv_uuid", string.toHex(uuid)) btcore.send(data, 0xfee2, bt_connect.handle)--发送数据(数据 对应特征uuid 连接句柄) end end ``` **最后将以上几个功能模块结合起来,就实现了一个简易的蓝牙连接收发数据功能** ```lua sys.taskInit( function() init() poweron() advertising() data_trans() end ) ``` # 注意事项 使用手机、电脑与模块低功耗蓝牙进行测试时,需要使用专门的低功耗蓝牙调试软件 手机低功耗蓝牙调试软件这里推荐使用nRF Connect [nRF Connect下载及使用教程](https://hmi.wiki.luatos.com/doc/65042949/e6zPC3k9/sivVjmZk)