| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- --[[
- @module ble_client_main
- @summary ble client 主应用功能模块
- @version 1.0
- @date 2025.08.20
- @author 王世豪
- @usage
- 本文件为ble client 主应用功能模块,核心业务逻辑为:
- 1. 初始化BLE功能
- 2. 扫描目标BLE设备(默认名称为"LuatOS")
- 3. 建立与目标设备的连接
- 4. 处理各类BLE事件(连接、断开连接、扫描报告、GATT操作完成等)
- 5. 接收并处理来自其他模块的请求(如READ_REQ读取请求)
- 6. 异常处理与自动重连机制
- 7. 依赖模块
- - ble_client_receiver: 用于处理接收到的BLE数据
- - ble_client_sender: 用于发送BLE数据
- 8. 事件处理
- 通过ble_event_cb函数处理以下BLE事件:
- - EVENT_CONN: 连接成功
- - EVENT_DISCONN: 断开连接
- - EVENT_SCAN_REPORT: 扫描报告
- - EVENT_GATT_DONE: GATT操作完成
- - EVENT_READ_VALUE: 读取特征值完成
- 本文件没有对外接口,直接在main.lua中require "ble_client_main"就可以加载运行;
- ]]
- local ble_client_receiver = require "ble_client_receiver"
- local ble_client_sender = require "ble_client_sender"
- -- ble_client_main的任务名
- local TASK_NAME = ble_client_sender.TASK_NAME_PREFIX.."main"
- -- 配置参数
- config = {
- target_device_name = "LuatOS", -- 目标设备名称
- target_service_uuid = "FA00", -- 目标服务UUID
- target_notify_char = "EA01", -- 目标通知特征值UUID
- target_write_char = "EA02", -- 目标写入特征值UUID
- target_read_char = "EA03", -- 目标读取特征值UUID
- scan_timeout = 10000, -- 等待SCAN_REPORT超时时间(ms)
- connect_timeout = 5000, -- 等待CONNECT超时时间(ms)
- }
- local bluetooth_device = nil
- local ble_device = nil
- local scan_create = false
- local scan_count = 0
- local last_operation = nil
- -- 设备过滤函数
- local function is_target_device(scan_param)
- log.info("scan_param", scan_param.data:toHex())
- -- 检查设备名称是否匹配
- if scan_param.data and scan_param.data:find(config.target_device_name) then
- log.info("BLE", "发现目标设备: " .. config.target_device_name)
- return true
- end
- return false
- end
- -- 事件回调函数
- local function ble_event_cb(ble_device, ble_event, ble_param)
- -- 仅表示连接成功,后续读/写/订阅 需等待GATT_DONE事件
- if ble_event == ble.EVENT_CONN then
- sys.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECT", ble_param)
- -- 连接断开
- elseif ble_event == ble.EVENT_DISCONN then
- sys.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", ble_param.reason)
- -- 扫描报告
- elseif ble_event == ble.EVENT_SCAN_REPORT then
- sys.sendMsg(TASK_NAME, "BLE_EVENT", "SCAN_REPORT", ble_param)
- -- GATT项处理
- elseif ble_event == ble.EVENT_GATT_ITEM then
- log.info("ble", "gatt item", ble_param)
- -- GATT操作完成,可进行读/写/订阅操作
- elseif ble_event == ble.EVENT_GATT_DONE then
- sys.sendMsg(TASK_NAME, "BLE_EVENT", "GATT_DONE", ble_param)
- -- 开启Notify监听,监听外围设备指定服务和特征值的通知,默认打开
- local notify_params = {
- uuid_service = string.fromHex(config.target_service_uuid),
- uuid_characteristic = string.fromHex(config.target_notify_char)
- }
- ble_device:notify_enable(notify_params, true)
- -- 读取特征值完成
- elseif ble_event == ble.EVENT_READ_VALUE then
- -- 通知receiver处理数据
- ble_client_receiver.proc(ble_param.uuid_service:toHex(), ble_param.uuid_characteristic:toHex(), ble_param.data)
- end
- end
- -- 初始化BLE
- local function ble_init()
- -- 初始化蓝牙核心
- bluetooth_device = bluetooth_device or bluetooth.init()
- if not bluetooth_device then
- log.error("BLE", "蓝牙初始化失败")
- return false
- end
- -- 初始化BLE功能
- ble_device = ble_device or bluetooth_device:ble(ble_event_cb)
- if not ble_device then
- log.error("BLE", "当前固件不支持完整的BLE")
- return false
- end
- -- 创建BLE扫描
- scan_create = scan_create or ble_device:scan_create({})
- if not scan_create then -- 默认参数:addr_mode=ble.PUBLIC, scan_interval=100, scan_window=100
- log.error("BLE", "BLE创建扫描失败")
- return false
- end
- -- 启动BLE扫描
- if not ble_device:scan_start() then
- log.error("BLE", "BLE扫描启动失败")
- return false
- end
- last_operation = "scan"
- return true
- end
- -- 主任务处理函数
- local function ble_client_main_task_func()
- local result,msg
- while true do
- result = ble_init()
- if not result then
- log.error("ble_client_main_task_func", "ble_init error")
- goto EXCEPTION_PROC
- end
- -- 扫描上报、连接、断开连接、异常等各种事件的处理调度逻辑
- while true do
- -- 根据最后操作设置超时时间
- if last_operation == "scan" then
- timeout = config.scan_timeout
- elseif last_operation == "connect" then
- timeout = config.connect_timeout
- else
- timeout = nil
- end
- msg = sys.waitMsg(TASK_NAME, "BLE_EVENT", timeout)
- if not msg then
- log.error("ble_client_main_task_func", "waitMsg timeout")
- goto EXCEPTION_PROC
- end
-
- if msg[2] == "CONNECT" then
- -- 仅表示连接成功,后续读/写/订阅 需等待GATT_DONE事件
- local conn_param = msg[3]
- log.info("BLE", "设备连接成功: " .. conn_param.addr:toHex())
- last_operation = nil
- elseif msg[2] == "GATT_DONE" then
- -- 连接成功且服务发现完成,后续可执行业务操作(读/写/订阅)
- -- 通知sender模块连接成功
- log.info("BLE", "GATT服务发现完成")
- sys.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "CONNECT_OK", ble_device)
- last_operation = nil
- elseif msg[2] == "DISCONNECTED" then
- log.info("BLE", "设备断开连接,原因: " .. msg[3])
- break
- elseif msg[2] == "SCAN_REPORT" then
- local ble_param = msg[3]
- log.info("BLE", string.format("扫描报告 | Type: %d | MAC: %s | RSSI: %d | Data: %s ",
- ble_param.addr_type, -- 类型(整数)
- ble_param.adv_addr:toHex(), -- MAC地址(字符串)
- ble_param.rssi, -- 信号强度(整数)
- ble_param.data:toHex() -- 广播数据(字符串)
- ))
- -- 检查是否为目标设备
- if is_target_device(ble_param) 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)
- last_operation = "connect"
- end
- scan_count = scan_count + 1
- if scan_count > 100 then
- log.info("ble", "扫描次数超过100次, 停止扫描, 10秒后重新开始")
- scan_count = 0
- ble_device:scan_stop()
- sys.sendMsg(TASK_NAME, "BLE_EVENT", "RESTART_SCAN")
- end
- elseif msg[2] == "RESTART_SCAN" then
- -- 5s后重新开始扫描
- sys.wait(5000)
- log.info("ble", "重新开始扫描")
- ble_device:scan_start()
- last_operation = "scan"
- elseif msg[2] == "READ_REQ" then
- -- 从消息中获取传入的UUID参数,若没有则使用默认配置
- local service_uuid = msg[3] or config.target_service_uuid
- local char_uuid = msg[4] or config.target_read_char
- local read_params = {
- uuid_service = string.fromHex(service_uuid),
- uuid_characteristic = string.fromHex(char_uuid)
- }
- ble_device:read_value(read_params)
- end
- end
- -- 出现异常
- ::EXCEPTION_PROC::
- log.error("ble_client_main_task_func", "异常退出, 5秒后重新扫描连接")
- -- 清空此task绑定的消息队列中的未处理的消息
- sys.cleanMsg(TASK_NAME)
- -- 通知ble sender数据发送应用模块的task,ble连接已经断开
- sys.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
- -- 5秒后跳转到循环体开始位置,自动发起重连
- sys.wait(5000)
- end
- end
- -- 启动主任务
- sys.taskInitEx(ble_client_main_task_func, TASK_NAME)
|