
大家好啊,我是夢程~合宙Cat.1模塊1.3主線固件支持雙模藍牙,今天就簡單說一下藍牙應該如何使用。
本教程以Air820開發板為例,講解BLE的廣播和從機功能。
我們將從經典藍牙、Beacon、Broadcast、Slave四種模式進行具體講解,在大多數的使用環境下,基本離不開這四種模式。
經典藍牙示例
1.1 藍牙功能系統信息
首先了解一下藍牙功能里面的一些系統消息服務,我們要使用這些服務進行邏輯編排。

1.2 經典藍牙函數


1.3 經典藍牙示例代碼
--- 模塊功能:經典藍牙示例
-- @author Darren Cheng
-- @module bluetooth.bt
-- @license MIT
-- @copyright openLuat-
- @release 2021.08.24
-- @注意 需要使用core(Luat_VXXXX_RDA8910_BT_FLOAT)版本
module(..., package.seeall)
require "audio"
local vol = 50
local musicstatus = 1
local keyMap = {{},{},{},{},{},{},{},{},{},{}}
keyMap[0] = {}
keyMap[255] = {}
keyMap[2][0] = "ENTER"
keyMap[2][1] = "DOWN"
keyMap[1][0] = "UP"
keyMap[1][1] = "ESC"
keyMap[255][255] = "PWK"
local function keyMsg(msg)
if keyMap[msg.key_matrix_row][msg.key_matrix_col] == "PWK" and msg.pressed then
btcore.setavrcpsongs(musicstatus)
if musicstatus == 0 then
musicstatus = 1
elseif musicstatus == 1 then
musicstatus = 0
end
log.info("bt", "musicstatus",musicstatus) end
if msg.pressed then
if keyMap[msg.key_matrix_row][msg.key_matrix_col] == "ENTER" then
btcore.setavrcpsongs(3)
log.info("bt","下一曲")
elseif keyMap[msg.key_matrix_row][msg.key_matrix_col] == "ESC" then
btcore.setavrcpsongs(2)
log.info("bt","上一曲")
elseif keyMap[msg.key_matrix_row][msg.key_matrix_col] == "UP" then
vol = vol + 10
if vol > 127 then
vol = 127
end
btcore.setavrcpvol(vol)
log.info("bt","加音量", vol)
elseif keyMap[msg.key_matrix_row][msg.key_matrix_col] == "DOWN" then
vol = vol - 10
if vol < 0 then
vol = 0
end
btcore.setavrcpvol(vol)
log.info("bt","減音量", vol)
end
end
end
rtos.on(rtos.MSG_KEYPAD,keyMsg)
rtos.init_module(rtos.MOD_KEYPAD,0,0x7F,0x7F)
local function init()
log.info("bt", "init")
rtos.on(rtos.MSG_BLUETOOTH, function(msg)
if msg.event == btcore.MSG_OPEN_CNF then
sys.publish("BT_OPEN", msg.result) --藍牙打開成功
elseif msg.event == btcore.MSG_BT_HFP_CONNECT_IND then
sys.publish("BT_HFP_CONNECT_IND", msg.result) --hfp連接成功
elseif msg.event == btcore.MSG_BT_HFP_DISCONNECT_IND then
log.info("bt", "bt hfp disconnect") --hfp斷開連接
elseif msg.event == btcore.MSG_BT_HFP_CALLSETUP_OUTGOING then
log.info("bt", "bt call outgoing") --建立呼出電話
elseif msg.event == btcore.MSG_BT_HFP_CALLSETUP_INCOMING then
log.info("bt", "bt call incoming") --呼叫傳入
sys.publish("BT_CALLSETUP_INCOMING", msg.result)
elseif msg.event == btcore.MSG_BT_HFP_RING_INDICATION then
log.info("bt", "bt ring indication") --呼叫傳入鈴聲
elseif msg.event == btcore.MSG_BT_AVRCP_CONNECT_IND then sys.publish("BT_AVRCP_CONNECT_IND", msg.result) --avrcp連接成功
elseif msg.event == btcore.MSG_BT_AVRCP_DISCONNECT_IND then
log.info("bt", "bt avrcp disconnect") --avrcp斷開連接
end
end)
end
sys.taskInit(function()
sys.wait(5000) -- audio.setChannel(1) -- 可調用此api切換播放通道,默認spk
init() -- 初始化
log.info("bt", "poweron")
btcore.open(2) --打開經典藍牙
sys.waitUntil("BT_OPEN", 5000) --等待藍牙打開成功
log.info("bt", "設置藍牙參數")
btcore.setname("Cat1BT")-- 設置廣播名稱
btcore.setvisibility(0x11)-- 設置藍牙可見性
log.info("bt", "藍牙可見性",btcore.getvisibility())
local _, result = sys.waitUntil("BT_AVRCP_CONNECT_IND") --等待連接成功
if result ~= 0 then
return
end
log.info("bt", "連接成功")
while true do
vol = btcore.getavrcpvol() if vol == -1 then
log.info("bt", "獲取音量失敗", vol) elseif vol == -2 then
log.info("bt", "設備不支持獲取音量", vol)
else
log.info("bt", "設備音量", vol)
end
sys.wait(1000)
end
end)
代碼效果解釋:
-
模塊成功開機后會初始化藍牙並廣播名稱為“Cat1BT”的藍牙設備
-
使用手機連接名為“Cat1BT”的設備
-
按POWER鍵控制音樂播放與暫停
-
按DOWN鍵減小音量,單位為10
-
按UPWARD鍵增大音量,單位為10
-
按ENTER鍵切換下一首音樂
-
按ESC鍵切換上一首音樂
-
部分手機可能不支持音量調節和獲取
源碼下載鏈接:
https://gitee.com/openLuat/X-MagicBox-820/blob/master/demo/bt-learn/bt.lua
BLE-Beacon示例
Beacon:一種特殊的廣播,多用於藍牙定位環境。
系統信息及函數說明詳見:
https://doc.openluat.com/article/3495#BLEBeacon_393
2.1 BLE-Beacon示例代碼
--- 模塊功能:藍牙功能測試
-- @author openLuat
-- @module bluetooth.beacon
-- @license MIT
-- @copyright openLuat
-- @release 2020.09.27
-- @注意 需要使用core(Luat_VXXXX_RDA8910_BT_FLOAT)版本module(..., package.seeall)
local function init()
log.info("bt", "init")
rtos.on(rtos.MSG_BLUETOOTH, function(msg)
if msg.event == btcore.MSG_OPEN_CNF then sys.publish("BT_OPEN", msg.result) --藍牙打開成功
end
end)
end
sys.taskInit(function()
sys.wait(5000)
init() -- 初始化
log.info("bt", "poweron")
btcore.open(0) --打開藍牙從模式
sys.waitUntil("BT_OPEN", 5000) --等待藍牙打開成功
log.info("bt", "設置藍牙參數")
btcore.setadvparam(0x80,0xa0,0,0,0x01,0)
--廣播參數設置 (最小廣播間隔,最大廣播間隔,廣播類型,廣播本地地址類型,廣播channel map,廣播過濾策略,定向地址類型,定向地址)
btcore.setbeacondata("AB8190D5D11E4941ACC442F30510B4AB",10107,50179) --beacon設置 (uuid,major,minor)
btcore.advertising(1)-- 打開廣播
end)
源碼下載鏈接:
https://gitee.com/openLuat/X-MagicBox-820/blob/master/demo/bt-learn/beacon.lua
2.2 抓包分析
這是通過抓包獲取的Beacon數據包:
-----------------------------------------------+-------------------- - - -
| Packet sniffer frame header |
+-------+-------------+-------------------------+-------+----------------- - - -
|channel| Packet nbr. | Time stamp | Length| Packet data
+-------+-------------+-------------------------+-------+----------------- - - -
| 0x25 | 03 00 00 00 | 9D B0 E3 07 00 00 00 00 | 26 00 | 00 24 A2 65 44 C6 C2 C8 02 01 1A 1A FF 4C 00 02 15 AB 81 90 D5 D1 1E 49 41 AC C4 42 F3 05 10 B4 AB 27 7B C4 03 C5
+-------+-------------+-------------------------+-------+----------------- - - -

這里我們可以獲取的信息有:Channel就是為0x25,轉換成十進制就是37通道AdvA就是模塊的MAC地址AdvData為抓取的信息,這是封裝用戶數據生成的,在代碼中則為UUID的數據,即:AB 81 90 D5 D1 1E 49 41 AC C4 42 F3 05 10 B4 AB
這里沒有分析儀也可以使用手機app查看,推薦軟件為nRF Connect。


BLE-Broadcast示例
系統信息及函數說明詳見:
https://doc.openluat.com/article/3495#BLEBroadcast_582
3.1 BLE廣播示例代碼
-- 模塊功能:BLE廣播示例
-- @author Darren Cheng
-- @module bluetooth.slave
-- @license MIT
-- @copyright openLuat
-- @release 2021.08.24
-- @注意 需要使用core(Luat_VXXXX_RDA8910_BT_FLOAT)版本
module(..., package.seeall)
local function init()
log.info("bt", "init")
rtos.on(rtos.MSG_BLUETOOTH, function(msg)
if msg.event == btcore.MSG_OPEN_CNF then
sys.publish("BT_OPEN", msg.result) --藍牙打開成功
end
end)
end
sys.taskInit(function()
sys.wait(5000)
init() --初始化
log.info("bt", "開藍牙")
btcore.open(0) --打開藍牙從模式
sys.waitUntil("BT_OPEN", 5000) --等待藍牙打開成功
log.info("bt", "設置藍牙參數")
btcore.setname("Cat1BT") -- 設置廣播名稱
------------ 設置藍牙廣播數據(LTV格式) --------------
advData = "64617272656e"
advType = "08"
advLenth = string.format("%02x",(advData:len()/2)+1)
btcore.setadvdata(string.fromHex(advLenth .. advType .. advData)) ------------ 設置藍牙響應包數據(LTV格式) --------------
rspData = "6368656e67"
rspType = "08"
rspLenth = string.format("%02x",(rspData:len()/2)+1)
btcore.setscanrspdata(string.fromHex(rspLenth .. rspType .. rspData))
btcore.setadvparam(0x80,0xa0,0,0,0x07,0) --廣播參數設置 (最小廣播間隔,最大廣播間隔,廣播類型,廣播本地地址類型,廣播channel map,廣播過濾策略,定向地址類型,定向地址)
btcore.advertising(1) -- 打開廣播
end)
源碼下載鏈接:
https://gitee.com/openLuat/X-MagicBox-820/blob/master/demo/bt-learn/broadcast.lua
3.2 現象展示及分析

通過抓取數據包得知:
設備會廣播設置好的數據64617272656e
當主機端發出scan請求時,設備端會回復響應包內容6368656e67
注意:
藍牙廣播數據和響應包數據務必要符合LTV格式
完成所有設置之后,再去調用打開廣播的API
BLE-Slave示例
系統信息及函數說明詳見:
https://doc.openluat.com/article/3495#BLESlave_810
4.1 BLE-Slave示例代碼
-- @module bluetooth.slave
-- @license MIT
-- @copyright openLuat
-- @release 2021.08.24
-- @注意 需要使用core(Luat_VXXXX_RDA8910_BT_FLOAT)版本
module(..., package.seeall)
local useUserService = true -- 用戶自定義服務,true啟用,false禁用
local function init()
log.info("bt", "init")
rtos.on(rtos.MSG_BLUETOOTH, function(msg)
if msg.event == btcore.MSG_OPEN_CNF then
sys.publish("BT_OPEN", msg.result) --藍牙打開成功
elseif msg.event == btcore.MSG_BLE_CONNECT_IND then
sys.publish("BT_CONNECT_IND", {["handle"] = msg.handle, ["result"] = msg.result}) --藍牙連接成功
elseif msg.event == btcore.MSG_BLE_DISCONNECT_IND then
log.info("bt", "ble disconnect") --藍牙斷開連接
elseif msg.event == btcore.MSG_BLE_DATA_IND then
sys.publish("BT_DATA_IND", {["result"] = msg.result})--接收到的數據內容
end
end)
end
sys.taskInit(function()
sys.wait(5000)
init() --初始化
log.info("bt", "poweron")
btcore.open(0) --打開藍牙從模式
sys.waitUntil("BT_OPEN", 5000) --等待藍牙打開成功
log.info("bt", "設置藍牙參數")
btcore.setname("Cat1BT")-- 設置廣播名稱
btcore.setadvparam(0x80,0xa0,0,0,0x07,0) --廣播參數設置 (最小廣播間隔,最大廣播間隔,廣播類型,廣播本地地址類型,廣播channel map,廣播過濾策略,定向地址類型,定向地址)
if useUserService then
log.info("bt", "useUserService")
btcore.addservice(0xff88) -- 添加服務uuid
btcore.addcharacteristic(0xffe1,0x08,0x002) --添加特征 可寫
-- btcore.addcharacteristic(0xffe1,0x08+0x04,0x002) --添加特征 可寫 特征屬性可以寫多個,用+連接
btcore.addcharacteristic(0xffe2,0x10,0x001) --添加特征 通知
btcore.adddescriptor(0x2902,0x0001) --添加描述
btcore.addcharacteristic(0xffe3,0x02,0x001) --添加特征 可讀
end
btcore.advertising(1)-- 打開廣播
_, bt_connect = sys.waitUntil("BT_CONNECT_IND") if bt_connect.result ~= 0 then
return false
end
--鏈接成功
log.info("bt","connect_handle",bt_connect.handle) -- 連接句柄
while true do
_, bt_recv = sys.waitUntil("BT_DATA_IND") -- 等待接收到數據
local data = ""
local len = 0
local uuid = ""
while true do
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)) if data == "close" then
btcore.disconnect()--主動斷開連接
end
if useUserService then
btcore.send(data, 0xffe2, bt_connect.handle) -- 發送數據(數據 對應特征uuid 連接句柄)
end
btcore.send(data, 0xfee2, bt_connect.handle) -- 發送數據(數據 對應特征uuid 連接句柄)
end
end
end)
源碼下載鏈接:
https://gitee.com/openLuat/X-MagicBox-820/blob/master/demo/bt-learn/slave2.lua
4.2 代碼效果展示:
用戶需根據需求設置useUserService,true為啟用用戶添加服務,false為禁用用戶添加服務,使用默認服務。
1)用戶不添加服務的情況下,會提供幾個默認服務,若用戶自行添加服務,則默認服務會被刪除。


2)用戶添加自定義服務


用戶可使用0xFFE1的UUID向模塊發送數據,發送的數據會回顯到0xFFE2,用戶可通過訂閱0xFFE2獲取數據。
注意:
-
添加服務時不要與已有服務的UUID重復
-
添加特征時,特征屬性和特征權限要按照規定的格式
-
特征屬性和權限可使用多個,使用+連接
-
用戶完成所有添加操作之后,再去調用打開廣播API
今天的內容就分享到這里了,建議大家閱讀本文的API相關知識,已經根據官方文檔做了部分翻譯和注釋,也提到了一些注意點。根據我編寫的一些小demo去學習和實踐,甚至可以說,改一改demo就是你自己的作品,期待大家可以使用藍牙去做一些更有意思的項目。
- 相關開發資料鏈接 -
Air820UG開發板資料
https://gitee.com/openLuat/X-MagicBox-820/
LuatOS-Air開發資料
https://gitee.com/openLuat/Luat_Lua_Air724U
LuatOS-SoC倉庫
https://gitee.com/openLuat/LuatOS
LuatOS開發指南/入門教程
