ble_client_main.lua 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. --[[
  2. @module ble_client_main
  3. @summary ble client 主应用功能模块
  4. @version 1.0
  5. @date 2025.08.20
  6. @author 王世豪
  7. @usage
  8. 本文件为ble client 主应用功能模块,核心业务逻辑为:
  9. 1. 初始化BLE功能
  10. 2. 扫描目标BLE设备(默认名称为"LuatOS")
  11. 3. 建立与目标设备的连接
  12. 4. 处理各类BLE事件(连接、断开连接、扫描报告、GATT操作完成等)
  13. 5. 接收并处理来自其他模块的请求(如READ_REQ读取请求)
  14. 6. 异常处理与自动重连机制
  15. 7. 依赖模块
  16. - ble_client_receiver: 用于处理接收到的BLE数据
  17. - ble_client_sender: 用于发送BLE数据
  18. 8. 事件处理
  19. 通过ble_event_cb函数处理以下BLE事件:
  20. - EVENT_CONN: 连接成功
  21. - EVENT_DISCONN: 断开连接
  22. - EVENT_SCAN_REPORT: 扫描报告
  23. - EVENT_GATT_DONE: GATT操作完成
  24. - EVENT_READ_VALUE: 读取特征值完成
  25. 本文件没有对外接口,直接在main.lua中require "ble_client_main"就可以加载运行;
  26. ]]
  27. local ble_client_receiver = require "ble_client_receiver"
  28. local ble_client_sender = require "ble_client_sender"
  29. -- ble_client_main的任务名
  30. local TASK_NAME = ble_client_sender.TASK_NAME_PREFIX.."main"
  31. -- 配置参数
  32. config = {
  33. target_device_name = "LuatOS", -- 目标设备名称
  34. target_service_uuid = "FA00", -- 目标服务UUID
  35. target_notify_char = "EA01", -- 目标通知特征值UUID
  36. target_write_char = "EA02", -- 目标写入特征值UUID
  37. target_read_char = "EA03", -- 目标读取特征值UUID
  38. scan_timeout = 10000, -- 等待SCAN_REPORT超时时间(ms)
  39. connect_timeout = 5000, -- 等待CONNECT超时时间(ms)
  40. }
  41. local bluetooth_device = nil
  42. local ble_device = nil
  43. local scan_create = false
  44. local scan_count = 0
  45. local last_operation = nil
  46. -- 设备过滤函数
  47. local function is_target_device(scan_param)
  48. log.info("scan_param", scan_param.data:toHex())
  49. -- 检查设备名称是否匹配
  50. if scan_param.data and scan_param.data:find(config.target_device_name) then
  51. log.info("BLE", "发现目标设备: " .. config.target_device_name)
  52. return true
  53. end
  54. return false
  55. end
  56. -- 事件回调函数
  57. local function ble_event_cb(ble_device, ble_event, ble_param)
  58. -- 仅表示连接成功,后续读/写/订阅 需等待GATT_DONE事件
  59. if ble_event == ble.EVENT_CONN then
  60. sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECT", ble_param)
  61. -- 连接断开
  62. elseif ble_event == ble.EVENT_DISCONN then
  63. sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", ble_param.reason)
  64. -- 扫描报告
  65. elseif ble_event == ble.EVENT_SCAN_REPORT then
  66. sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "SCAN_REPORT", ble_param)
  67. -- GATT项处理
  68. elseif ble_event == ble.EVENT_GATT_ITEM then
  69. log.info("ble", "gatt item", ble_param)
  70. -- GATT操作完成,可进行读/写/订阅操作
  71. elseif ble_event == ble.EVENT_GATT_DONE then
  72. sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "GATT_DONE", ble_param)
  73. -- 开启Notify监听,监听外围设备指定服务和特征值的通知,默认打开
  74. local notify_params = {
  75. uuid_service = string.fromHex(config.target_service_uuid),
  76. uuid_characteristic = string.fromHex(config.target_notify_char)
  77. }
  78. ble_device:notify_enable(notify_params, true)
  79. -- 读取特征值完成
  80. elseif ble_event == ble.EVENT_READ_VALUE then
  81. -- 通知receiver处理数据
  82. ble_client_receiver.proc(ble_param.uuid_service:toHex(), ble_param.uuid_characteristic:toHex(), ble_param.data)
  83. end
  84. end
  85. -- 初始化BLE
  86. local function ble_init()
  87. -- 初始化蓝牙核心
  88. bluetooth_device = bluetooth_device or bluetooth.init()
  89. if not bluetooth_device then
  90. log.error("BLE", "蓝牙初始化失败")
  91. return false
  92. end
  93. -- 初始化BLE功能
  94. ble_device = ble_device or bluetooth_device:ble(ble_event_cb)
  95. if not ble_device then
  96. log.error("BLE", "当前固件不支持完整的BLE")
  97. return false
  98. end
  99. -- 创建BLE扫描
  100. scan_create = scan_create or ble_device:scan_create({})
  101. if not scan_create then -- 默认参数:addr_mode=ble.PUBLIC, scan_interval=100, scan_window=100
  102. log.error("BLE", "BLE创建扫描失败")
  103. return false
  104. end
  105. -- 启动BLE扫描
  106. if not ble_device:scan_start() then
  107. log.error("BLE", "BLE扫描启动失败")
  108. return false
  109. end
  110. last_operation = "scan"
  111. return true
  112. end
  113. -- 主任务处理函数
  114. local function ble_client_main_task_func()
  115. local result,msg
  116. while true do
  117. result = ble_init()
  118. if not result then
  119. log.error("ble_client_main_task_func", "ble_init error")
  120. goto EXCEPTION_PROC
  121. end
  122. -- 扫描上报、连接、断开连接、异常等各种事件的处理调度逻辑
  123. while true do
  124. -- 根据最后操作设置超时时间
  125. if last_operation == "scan" then
  126. timeout = config.scan_timeout
  127. elseif last_operation == "connect" then
  128. timeout = config.connect_timeout
  129. else
  130. timeout = nil
  131. end
  132. msg = sysplus.waitMsg(TASK_NAME, "BLE_EVENT", timeout)
  133. if not msg then
  134. log.error("ble_client_main_task_func", "waitMsg timeout")
  135. goto EXCEPTION_PROC
  136. end
  137. if msg[2] == "CONNECT" then
  138. -- 仅表示连接成功,后续读/写/订阅 需等待GATT_DONE事件
  139. local conn_param = msg[3]
  140. log.info("BLE", "设备连接成功: " .. conn_param.addr:toHex())
  141. last_operation = nil
  142. elseif msg[2] == "GATT_DONE" then
  143. -- 连接成功且服务发现完成,后续可执行业务操作(读/写/订阅)
  144. -- 通知sender模块连接成功
  145. log.info("BLE", "GATT服务发现完成")
  146. sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "CONNECT_OK", ble_device)
  147. last_operation = nil
  148. elseif msg[2] == "DISCONNECTED" then
  149. log.info("BLE", "设备断开连接,原因: " .. msg[3])
  150. break
  151. elseif msg[2] == "SCAN_REPORT" then
  152. local ble_param = msg[3]
  153. log.info("BLE", string.format("扫描报告 | Type: %d | MAC: %s | RSSI: %d | Data: %s ",
  154. ble_param.addr_type, -- 类型(整数)
  155. ble_param.adv_addr:toHex(), -- MAC地址(字符串)
  156. ble_param.rssi, -- 信号强度(整数)
  157. ble_param.data:toHex() -- 广播数据(字符串)
  158. ))
  159. -- 检查是否为目标设备
  160. if is_target_device(ble_param) then
  161. log.info("ble", "停止扫描, 连接设备", ble_param.adv_addr:toHex(), ble_param.addr_type)
  162. ble_device:scan_stop()
  163. scan_count = 0
  164. ble_device:connect(ble_param.adv_addr, ble_param.addr_type)
  165. last_operation = "connect"
  166. end
  167. scan_count = scan_count + 1
  168. if scan_count > 100 then
  169. log.info("ble", "扫描次数超过100次, 停止扫描, 10秒后重新开始")
  170. scan_count = 0
  171. ble_device:scan_stop()
  172. sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "RESTART_SCAN")
  173. end
  174. elseif msg[2] == "RESTART_SCAN" then
  175. -- 5s后重新开始扫描
  176. sys.wait(5000)
  177. log.info("ble", "重新开始扫描")
  178. ble_device:scan_start()
  179. last_operation = "scan"
  180. elseif msg[2] == "READ_REQ" then
  181. -- 从消息中获取传入的UUID参数,若没有则使用默认配置
  182. local service_uuid = msg[3] or config.target_service_uuid
  183. local char_uuid = msg[4] or config.target_read_char
  184. local read_params = {
  185. uuid_service = string.fromHex(service_uuid),
  186. uuid_characteristic = string.fromHex(char_uuid)
  187. }
  188. ble_device:read_value(read_params)
  189. end
  190. end
  191. -- 出现异常
  192. ::EXCEPTION_PROC::
  193. log.error("ble_client_main_task_func", "异常退出, 5秒后重新扫描连接")
  194. -- 清空此task绑定的消息队列中的未处理的消息
  195. sysplus.cleanMsg(TASK_NAME)
  196. -- 通知ble sender数据发送应用模块的task,ble连接已经断开
  197. sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
  198. -- 5秒后跳转到循环体开始位置,自动发起重连
  199. sys.wait(5000)
  200. end
  201. end
  202. -- 启动主任务
  203. sysplus.taskInitEx(ble_client_main_task_func, TASK_NAME)