ble_main.lua 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. --[[
  2. @module ble_main
  3. @summary BLE服务主功能模块
  4. @version 1.0
  5. @date 2025.12.08
  6. @author 孟伟
  7. @usage
  8. -- BLE服务主功能模块
  9. -- 提供BLE服务的初始化、配置和事件处理
  10. -- 不包含FOTA业务逻辑,仅处理BLE相关功能
  11. 依赖模块:
  12. - ble_file_fota: 用于处理FOTA相关业务逻辑(文件写入方式)
  13. - ble_packet_fota: 用于处理FOTA相关业务逻辑(分段写入方式)
  14. ]]
  15. -- 选择FOTA升级方式:"file" 或 "packet"
  16. -- 1. file方式:将升级包数据先写入本地文件,然后调用fota.file()进行升级
  17. -- 2. packet方式:直接使用fota.packet()处理分段数据,不写入文件,适合差分升级
  18. local fota_mode = "packet" -- 默认使用file方式
  19. -- 根据选择加载对应的FOTA模块
  20. local ble_fota_main
  21. if fota_mode == "file" then
  22. ble_fota_main = require "ble_file_fota"
  23. else
  24. ble_fota_main = require "ble_packet_fota"
  25. end
  26. -- ble_main的任务名
  27. local TASK_NAME = "BLE_MAIN"
  28. -- 配置参数
  29. config = {
  30. device_name = "Air8000_FOTA", -- 设备广播名称
  31. service_uuid = "F000", -- FOTA服务UUID(短格式)
  32. char_uuid_cmd = "F001", -- 命令特征值UUID
  33. char_uuid_data = "F002", -- 数据特征值UUID
  34. max_packet_size = 20 -- BLE数据包最大长度(字节)
  35. }
  36. local bluetooth_device = nil
  37. local ble_device = nil
  38. local adv_create = nil
  39. local gatt_create = nil
  40. -- GATT服务数据库定义
  41. -- 这里定义了BLE设备提供的服务和特征值
  42. local att_db = {
  43. string.fromHex(config.service_uuid), -- Service UUID
  44. {
  45. string.fromHex(config.char_uuid_cmd),
  46. ble.WRITE | ble.WRITE_CMD
  47. },
  48. {
  49. string.fromHex(config.char_uuid_data),
  50. ble.WRITE | ble.WRITE_CMD
  51. }
  52. }
  53. -- BLE事件回调函数
  54. local function ble_event_cb(ble_dev, event, param)
  55. log.info("BLE_EVENT", "收到BLE事件:", event)
  56. -- 根据LuatOS BLE事件枚举处理不同事件
  57. if event == ble.EVENT_CONN then
  58. -- 连接成功事件
  59. log.info("BLE_EVENT", "设备已连接", "地址:", param.addr and param.addr:toHex() or "未知")
  60. sys.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECT", param)
  61. elseif event == ble.EVENT_DISCONN then
  62. -- 连接断开事件
  63. log.info("BLE_EVENT", "设备已断开连接", "原因:", param.reason or "未知")
  64. sys.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", param.reason)
  65. elseif event == ble.EVENT_WRITE then
  66. -- 写入事件 - 这是关键事件!
  67. log.info("BLE_EVENT", "处理写入事件")
  68. -- 检查参数是否完整
  69. if not param or not param.uuid_service or not param.uuid_characteristic or not param.data then
  70. log.error("BLE_EVENT", "写入事件参数不完整")
  71. return
  72. end
  73. -- 获取服务UUID和特征值UUID
  74. local service_uuid = param.uuid_service:toHex()
  75. local char_uuid = param.uuid_characteristic:toHex()
  76. local data = param.data
  77. log.info("BLE_EVENT", "服务UUID:", service_uuid)
  78. log.info("BLE_EVENT", "特征值UUID:", char_uuid)
  79. log.info("BLE_EVENT", "数据长度:", #data, "字节")
  80. sys.sendMsg(TASK_NAME, "BLE_EVENT", "WRITE_REQ", param)
  81. elseif event == ble.EVENT_READ then
  82. -- 读取事件 - 外围设备收到主设备读请求
  83. log.info("BLE_EVENT", "处理读取事件")
  84. elseif event == ble.EVENT_READ_VALUE then
  85. -- 读取操作完成事件 - 中心设备读取特征值完成
  86. log.info("BLE_EVENT", "读取操作完成", "数据:", param.data and param.data:toHex() or "无数据")
  87. elseif event == ble.EVENT_SCAN_REPORT then
  88. -- 扫描报告事件 - 中心设备扫描到其他BLE设备
  89. log.info("BLE_EVENT", "扫描报告", "RSSI:", param.rssi, "地址:", param.adv_addr and param.adv_addr:toHex() or "未知")
  90. elseif event == ble.EVENT_SCAN_STOP then
  91. -- 扫描停止事件
  92. log.info("BLE_EVENT", "扫描停止")
  93. else
  94. -- 其他事件
  95. log.info("BLE_EVENT", "其他事件类型:", event)
  96. if param then
  97. -- 尝试打印参数的基本信息,避免直接打印table导致错误
  98. if type(param) == "table" then
  99. log.info("BLE_EVENT", "事件参数为table,包含字段:", #param)
  100. for k, v in pairs(param) do
  101. if type(v) == "string" then
  102. log.info("BLE_EVENT", "参数字段:", k, "值:", v:toHex())
  103. else
  104. log.info("BLE_EVENT", "参数字段:", k, "类型:", type(v))
  105. end
  106. end
  107. else
  108. log.info("BLE_EVENT", "事件参数类型:", type(param))
  109. end
  110. end
  111. end
  112. end
  113. -- 初始化BLE功能
  114. local function ble_init()
  115. log.info("BLE_INIT", "开始初始化BLE...")
  116. -- 初始化蓝牙核心
  117. bluetooth_device = bluetooth.init()
  118. if not bluetooth_device then
  119. log.error("BLE_INIT", "蓝牙核心初始化失败")
  120. return false
  121. end
  122. log.info("BLE_INIT", "蓝牙核心初始化成功")
  123. -- 初始化BLE功能
  124. ble_device = bluetooth_device:ble(ble_event_cb)
  125. if not ble_device then
  126. log.error("BLE_INIT", "BLE功能初始化失败")
  127. return false
  128. end
  129. log.info("BLE_INIT", "BLE功能初始化成功")
  130. -- 创建GATT服务
  131. gatt_create = ble_device:gatt_create(att_db)
  132. if not gatt_create then
  133. log.error("BLE_INIT", "GATT服务创建失败")
  134. return false
  135. end
  136. log.info("BLE_INIT", "GATT服务创建成功")
  137. -- 配置广播数据
  138. log.info("BLE_INIT", "配置广播数据...")
  139. adv_create = ble_device:adv_create({
  140. addr_mode = ble.PUBLIC,
  141. channel_map = ble.CHNLS_ALL,
  142. intv_min = 120,
  143. intv_max = 120,
  144. adv_data = {
  145. { ble.FLAGS, string.char(0x06) }, -- BLE标志
  146. { ble.COMPLETE_LOCAL_NAME, config.device_name }, -- 设备名称
  147. }
  148. })
  149. if not adv_create then
  150. log.error("BLE_INIT", "广播配置失败")
  151. return false
  152. end
  153. log.info("BLE_INIT", "广播配置成功")
  154. -- 开始广播
  155. ble_device:adv_start()
  156. log.info("BLE_INIT", "BLE广播已启动,设备名称:", config.device_name)
  157. return true
  158. end
  159. -- 主任务处理函数
  160. local function ble_main_task_func()
  161. local result, msg
  162. while true do
  163. result = ble_init()
  164. if not result then
  165. log.error("ble_main_task_func", "ble_init error")
  166. goto EXCEPTION_PROC
  167. end
  168. while true do
  169. msg = sys.waitMsg(TASK_NAME, "BLE_EVENT")
  170. if not msg then
  171. log.error("ble_main_task_func", "waitMsg timeout")
  172. goto EXCEPTION_PROC
  173. end
  174. if msg[2] == "CONNECT" then
  175. local conn_param = msg[3]
  176. log.info("BLE", "设备连接成功: " .. conn_param.addr:toHex())
  177. elseif msg[2] == "DISCONNECTED" then
  178. log.info("BLE", "设备断开连接,原因: " .. msg[3])
  179. -- 通知FOTA模块连接断开
  180. ble_fota_main.proc_disconnect()
  181. break
  182. -- 收到中心设备的写请求,将写的数据发给ble_fota_main模块处理
  183. elseif msg[2] == "WRITE_REQ" then
  184. local ble_param = msg[3]
  185. local service_uuid = ble_param.uuid_service:toHex()
  186. local char_uuid = ble_param.uuid_characteristic:toHex()
  187. local data = ble_param.data
  188. log.info("BLE", "收到写请求: " .. service_uuid .. " " .. char_uuid .. " " .. data:toHex())
  189. ble_fota_main.proc(service_uuid, char_uuid, data)
  190. end
  191. end
  192. ::EXCEPTION_PROC::
  193. log.error("ble_main_task_func", "异常退出, 5秒后重新开启广播")
  194. -- 停止广播
  195. if ble_device then
  196. ble_device:adv_stop()
  197. end
  198. -- 清空此task绑定的消息队列中的未处理的消息
  199. sys.cleanMsg(TASK_NAME)
  200. -- 5秒后跳转到循环体开始位置,自动重试
  201. sys.wait(5000)
  202. end
  203. end
  204. -- 启动主任务
  205. sys.taskInitEx(ble_main_task_func, TASK_NAME)