Просмотр исходного кода

add: Air8000/Air8101的ble peripheral demo

wangshihao 6 месяцев назад
Родитель
Сommit
4c438ca800

+ 10 - 10
module/Air8000/demo/ble/central/ble_client_main.lua

@@ -63,19 +63,19 @@ end
 local function ble_event_cb(ble_device, ble_event, ble_param)
     -- 仅表示连接成功,后续读/写/订阅 需等待GATT_DONE事件
     if ble_event == ble.EVENT_CONN then
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECT", ble_param)
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECT", ble_param)
     -- 连接断开
     elseif ble_event == ble.EVENT_DISCONN then
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", ble_param.reason)
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", ble_param.reason)
     -- 扫描报告
     elseif ble_event == ble.EVENT_SCAN_REPORT then
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "SCAN_REPORT", ble_param)
+        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
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "GATT_DONE", ble_param)
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "GATT_DONE", ble_param)
 
         -- 开启Notify监听,监听外围设备指定服务和特征值的通知,默认打开
         local notify_params = {
@@ -145,7 +145,7 @@ local function ble_client_main_task_func()
                 timeout = nil
             end
 
-            msg = sysplus.waitMsg(TASK_NAME, "BLE_EVENT", timeout)
+            msg = sys.waitMsg(TASK_NAME, "BLE_EVENT", timeout)
 
             if not msg then
                 log.error("ble_client_main_task_func", "waitMsg timeout")
@@ -161,7 +161,7 @@ local function ble_client_main_task_func()
                 -- 连接成功且服务发现完成,后续可执行业务操作(读/写/订阅)
                 -- 通知sender模块连接成功
                 log.info("BLE", "GATT服务发现完成")
-                sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "CONNECT_OK", ble_device)
+                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])
@@ -188,7 +188,7 @@ local function ble_client_main_task_func()
                     log.info("ble", "扫描次数超过100次, 停止扫描, 10秒后重新开始")
                     scan_count = 0
                     ble_device:scan_stop()
-                    sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "RESTART_SCAN")
+                    sys.sendMsg(TASK_NAME, "BLE_EVENT", "RESTART_SCAN")
                 end
             elseif msg[2] == "RESTART_SCAN" then
                 -- 5s后重新开始扫描
@@ -214,10 +214,10 @@ local function ble_client_main_task_func()
         log.error("ble_client_main_task_func", "异常退出, 5秒后重新扫描连接")
 
         -- 清空此task绑定的消息队列中的未处理的消息
-        sysplus.cleanMsg(TASK_NAME)
+        sys.cleanMsg(TASK_NAME)
 
         -- 通知ble sender数据发送应用模块的task,ble连接已经断开
-        sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
+        sys.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
 
         -- 5秒后跳转到循环体开始位置,自动发起重连
         sys.wait(5000)
@@ -225,4 +225,4 @@ local function ble_client_main_task_func()
 end
 
 -- 启动主任务
-sysplus.taskInitEx(ble_client_main_task_func, TASK_NAME)
+sys.taskInitEx(ble_client_main_task_func, TASK_NAME)

+ 3 - 3
module/Air8000/demo/ble/central/ble_client_sender.lua

@@ -45,7 +45,7 @@ local function send_data_req_proc_func(tag, service_uuid, char_uuid, data, cb)
     -- 将数据插入到发送队列send_queue中
     table.insert(send_queue, {service_uuid=service_uuid, char_uuid=char_uuid, data="send from " .. tag .. ": " .. data, cb=cb})
     -- 发送消息通知 BLE sender task,有新数据等待发送
-    sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "SEND_REQ")
+    sys.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "SEND_REQ")
 end
 
 -- 按照顺序发送send_queue中的数据
@@ -99,7 +99,7 @@ local function ble_client_sender_task_func()
 
     while true do
         -- 等待"BLE_EVENT"消息
-        msg = sysplus.waitMsg(ble_client_sender.TASK_NAME, "BLE_EVENT")
+        msg = sys.waitMsg(ble_client_sender.TASK_NAME, "BLE_EVENT")
 
         -- BLE连接成功
         -- msg[3]表示ble_device对象
@@ -150,7 +150,7 @@ sys.subscribe("SEND_DATA_REQ", send_data_req_proc_func)
 
 --创建并且启动一个task
 --运行这个task的处理函数ble_client_sender_task_func
-sysplus.taskInitEx(ble_client_sender_task_func, ble_client_sender.TASK_NAME)
+sys.taskInitEx(ble_client_sender_task_func, ble_client_sender.TASK_NAME)
 
 return ble_client_sender
 

+ 2 - 2
module/Air8000/demo/ble/central/ble_timer_app.lua

@@ -19,7 +19,7 @@
     --   cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
     --   cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
 
-2、sysplus.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid), 发送读取外围设备特征值UUID数据请求,在ble_client_main文件中处理,携带的参数为:
+2、sys.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid), 发送读取外围设备特征值UUID数据请求,在ble_client_main文件中处理,携带的参数为:
     -- msg[2]: "READ_REQ" --消息类型
     -- msg[3]: server_uuid --服务UUID
     -- msg[4]: read_char_uuid --特征值UUID
@@ -55,7 +55,7 @@ local function read_data_req_timer_cbfunc()
     -- msg[2]: "READ_REQ" --消息类型
     -- msg[3]: server_uuid --服务UUID
     -- msg[4]: read_char_uuid --特征值UUID
-    sysplus.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid)
+    sys.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid)
 end
 
 -- 启动5秒的循环定时器用于发送数据

+ 0 - 124
module/Air8000/demo/ble/peripheral/ble_peripheral.lua

@@ -1,124 +0,0 @@
---[[
-@module  ble_ibeacon
-@summary Air8000演示peripheral功能模块
-@version 1.0
-@date    2025.07.01
-@author  wangshihao
-@usage
-本文件为Air8000核心板演示peripheral功能的代码示例,核心业务逻辑为:
-从机模式(peripheral)的基本流程(概要描述)
-1. 初始化蓝牙框架
-2. 创建BLE对象
-    local ble_device = bluetooth_device:ble(ble_event_cb)
-3. 创建GATT描述
-    local att_db = {xxx}
-4. 创建广播信息
-    ble_device:adv_create(adv_data)
-5. 开始广播
-    ble_device:adv_start()
-6. 等待连接
-7. 在回调函数中处理连接事件, 如接收数据, 发送数据等
-]]
-
-local att_db = { -- Service
-    string.fromHex("FA00"), -- Service UUID
-    -- Characteristic
-    { -- Characteristic 1
-        string.fromHex("EA01"), -- Characteristic UUID Value
-        ble.NOTIFY | ble.READ | ble.WRITE -- Properties
-    }, { -- Characteristic 2
-        string.fromHex("EA02"), ble.WRITE
-    }, { -- Characteristic 3
-        string.fromHex("EA03"), ble.READ
-    }, { -- Characteristic 4
-        string.fromHex("EA04"), ble.IND | ble.READ
-    }
-}
-
-ble_stat = false
-
-local function ble_callback(dev, evt, param)
-    if evt == ble.EVENT_CONN then
-        log.info("ble", "connect 成功", param, param and param.addr and param.addr:toHex() or "unknow")
-        ble_stat = true
-    elseif evt == ble.EVENT_DISCONN then
-        log.info("ble", "disconnect")
-        ble_stat = false
-        -- 1秒后重新开始广播
-        sys.timerStart(function() dev:adv_start() end, 1000)
-    elseif evt == ble.EVENT_WRITE then
-        -- 收到写请求
-        log.info("ble", "接收到写请求", param.uuid_service:toHex(), param.uuid_characteristic:toHex(), param.data:toHex())
-    end
-end
-
-local bt_scan = false -- 是否扫描蓝牙
-
-function ble_peripheral()
-    local ret = 0
-    sys.wait(500)
-    log.info("开始初始化蓝牙核心")
-    bluetooth_device = bluetooth.init()
-    sys.wait(100)
-    log.info("初始化BLE功能")
-    ble_device = bluetooth_device:ble(ble_callback)
-    if ble_device == nil then
-        log.error("当前固件不支持完整的BLE")
-        return
-    end
-    sys.wait(100)
-
-    log.info('开始创建GATT')
-    ret = ble_device:gatt_create(att_db)
-    log.info("创建的GATT", ret)
-
-    sys.wait(100)
-    log.info("开始设置广播内容")
-    ble_device:adv_create({
-        addr_mode = ble.PUBLIC,
-        channel_map = ble.CHNLS_ALL,
-        intv_min = 120,
-        intv_max = 120,
-        adv_data = {
-            {ble.FLAGS, string.char(0x06)},
-            {ble.COMPLETE_LOCAL_NAME, "LuatOS"},
-            {ble.SERVICE_DATA, string.fromHex("FE01")},
-            {ble.MANUFACTURER_SPECIFIC_DATA, string.fromHex("05F0")}
-        }
-    })
-
-    sys.wait(100)
-    log.info("开始广播")
-    ble_device:adv_start()
-
-        
-    -- 放入预设值, 注意是有READ属性的特性才能读取
-    -- 手机APP设置MTU到256
-    local wt = {
-        uuid_service = string.fromHex("FA00"),
-        uuid_characteristic = string.fromHex("EA01"), 
-    }
-    ble_device:write_value(wt, "12345678901234567890")
-
-    while 1 do
-        sys.wait(3000)
-        if ble_stat then
-            local wt = {
-                uuid_service = string.fromHex("FA00"),
-                uuid_characteristic = string.fromHex("EA01"), 
-            }
-            local result = ble_device:write_notify(wt, "123456" .. os.date())
-            log.info("ble", "发送数据", result)
-        else
-            -- log.info("等待连接成功之后发送数据")
-        end
-        
-        local wt = {
-            uuid_service = string.fromHex("FA00"),
-            uuid_characteristic = string.fromHex("EA03"), 
-        }
-        ble_device:write_value(wt, "8888 123454")
-    end
-end
-
-sys.taskInit(ble_peripheral)

+ 168 - 0
module/Air8000/demo/ble/peripheral/ble_server_main.lua

@@ -0,0 +1,168 @@
+
+--[[
+@module  ble_server_main
+@summary ble server 主应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为ble server 主应用功能模块,核心业务逻辑为:
+1. 初始化BLE功能
+2. 创建GATT数据库
+3. 设置广播内容并开始广播
+4. 处理各类BLE事件(连接、断开连接、写入请求等)
+5. 接收并处理来自其他模块的请求
+6. 依赖模块
+    - ble_server_receiver: 用于处理接收到的BLE数据
+    - ble_server_sender: 用于发送BLE数据
+]]
+local ble_server_receiver = require "ble_server_receiver"
+local ble_server_sender = require "ble_server_sender"
+
+-- ble_server_main的任务名
+local TASK_NAME = ble_server_sender.TASK_NAME_PREFIX.."main"
+
+-- 配置参数
+config = {
+    device_name = "LuatOS",          -- 设备名称
+    service_uuid = "FA00",           -- 服务UUID
+    char_uuid1 = "EA01",             -- Characteristic 1
+    char_uuid2 = "EA02",             -- Characteristic 2
+    char_uuid3 = "EA03",             -- Characteristic 3
+}
+
+local bluetooth_device = nil
+local ble_device = nil
+local adv_create = nil
+local gatt_create = nil
+
+-- GATT数据库定义
+local att_db = { 
+    string.fromHex(config.service_uuid), -- Service UUID
+    -- Characteristic
+    { -- Characteristic 1 (Notify + Read + Write)
+        string.fromHex(config.char_uuid1),
+        ble.NOTIFY | ble.READ | ble.WRITE
+    }, { -- Characteristic 2 (Write)
+        string.fromHex(config.char_uuid2),
+        ble.WRITE
+    }, { -- Characteristic 3 (Read)
+        string.fromHex(config.char_uuid3),
+        ble.READ
+    }
+}
+
+-- 事件回调函数
+local function ble_event_cb(ble_device, ble_event, ble_param)
+    -- 连接中心设备成功
+    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_WRITE then
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "WRITE_REQ", ble_param)
+    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
+
+    -- 创建GATT
+    gatt_create = gatt_create or ble_device:gatt_create(att_db)
+    if not gatt_create then
+        log.error("BLE", "BLE创建GATT失败")
+        return false
+    end
+
+    -- 设置广播内容
+    adv_create = adv_create or ble_device:adv_create({
+        addr_mode = ble.PUBLIC, -- 广播地址模式, 可选值: ble.PUBLIC, ble.RANDOM, ble.RPA, ble.NRPA
+        channel_map = ble.CHNLS_ALL, -- 广播的通道, 可选值: ble.CHNLS_37, ble.CHNLS_38, ble.CHNLS_39, ble.CHNLS_ALL
+        intv_min = 120, -- 广播间隔最小值, 单位为0.625ms, 最小值为20, 最大值为10240
+        intv_max = 120, -- 广播间隔最大值, 单位为0.625ms, 最小值为20, 最大值为10240
+        adv_data = {    -- 支持表格形式, 也支持字符串形式(255字节以内)
+            {ble.FLAGS, string.char(0x06)}, -- 广播标志位, 0x06: 支持LE Limited Discoverable Mode, 0x04: 支持LE General Discoverable Mode
+            {ble.COMPLETE_LOCAL_NAME, config.device_name}, -- 广播本地名称
+        }
+    })
+    if not adv_create then
+        log.error("BLE", "BLE创建广播失败")
+        return false
+    end
+
+    -- 开始广播
+    ble_device:adv_start()
+
+    return true
+end
+
+-- 主任务处理函数
+local function ble_server_main_task_func()
+    local result,msg
+
+    while true do
+        result = ble_init()
+        if not result then
+            log.error("ble_main_task_func", "ble_init error")
+            goto EXCEPTION_PROC
+        end
+
+        while true do
+            msg = sys.waitMsg(TASK_NAME, "BLE_EVENT")
+
+            if not msg then
+                log.error("ble_client_main_task_func", "waitMsg timeout")
+                goto EXCEPTION_PROC
+            end
+    
+            if msg[2] == "CONNECT" then
+                local conn_param = msg[3]
+                log.info("BLE", "设备连接成功: " .. conn_param.addr:toHex())
+                sys.sendMsg(ble_server_sender.TASK_NAME, "BLE_EVENT", "CONNECT_OK", ble_device)
+            elseif msg[2] == "DISCONNECTED" then
+                log.info("BLE", "设备断开连接,原因: " .. msg[3])
+                break
+            -- 收到中心设备的写请求,将写的数据发给ble_server_receiver模块处理
+            elseif msg[2] == "WRITE_REQ" then
+                local ble_param = msg[3]
+                log.info("BLE", "收到写请求: " .. ble_param.uuid_service:toHex() .. " " .. ble_param.uuid_characteristic:toHex() .. " " .. ble_param.data:toHex())
+                ble_server_receiver.proc(ble_param.uuid_service:toHex(), ble_param.uuid_characteristic:toHex(), ble_param.data)
+            end
+        end
+
+        ::EXCEPTION_PROC::
+        log.error("ble_server_main_task_func", "异常退出, 5秒后重新开启广播")
+        
+        -- 停止广播
+        ble_device:adv_stop()
+
+        -- 清空此task绑定的消息队列中的未处理的消息
+        sys.cleanMsg(TASK_NAME)
+
+        -- 通知ble sender数据发送应用模块的task,ble连接已经断开
+        sys.sendMsg(ble_server_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
+
+        -- 5秒后跳转到循环体开始位置,自动发起重连
+        sys.wait(5000)
+    end
+end
+
+-- 启动主任务
+sys.taskInitEx(ble_server_main_task_func, TASK_NAME)

+ 24 - 0
module/Air8000/demo/ble/peripheral/ble_server_receiver.lua

@@ -0,0 +1,24 @@
+--[[
+@module  ble_server_receiver
+@summary BLE server 数据接收应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为BLE server 数据接收应用功能模块,核心业务逻辑为:
+1. 处理接收到的BLE写入请求数据。
+
+本文件的对外接口有1个:
+1. ble_server_receiver.proc(service_uuid, char_uuid, data): 处理接收到的BLE写入请求数据
+]]
+
+local ble_server_receiver = {}
+
+-- 处理接收到的BLE写入请求数据
+function ble_server_receiver.proc(service_uuid, char_uuid, data)
+    log.info("ble_server_receiver", "收到写入数据", service_uuid:toHex(), char_uuid:toHex(), data:toHex())
+
+    sys.publish("RECV_BLE_WRITE_DATA", service_uuid, char_uuid, data)
+end
+
+return ble_server_receiver

+ 160 - 0
module/Air8000/demo/ble/peripheral/ble_server_sender.lua

@@ -0,0 +1,160 @@
+--[[
+@module  ble_server_sender
+@summary BLE server 数据发送应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为BLE server 数据发送应用功能模块,核心业务逻辑为:
+1、订阅"SEND_DATA_REQ"消息,将其他应用模块需要发送的数据存储到队列send_queue中;
+2、BLE_server_sender task接收"CONNECT_OK"、"SEND_REQ"、两种类型的"BLE_EVENT"消息,处理队列中的数据;
+3、接收"DISCONNECTED"类型的"BLE_EVENT"消息,清空发送队列;
+4、数据发送完成后通过回调函数通知发送方。
+
+本文件的对外接口有1个:
+1. sys.subscribe("SEND_DATA_REQ", send_data_req_proc_func); 订阅"SEND_DATA_REQ"消息;
+    其他应用模块如果需要发送数据,直接sys.publish这个消息即可,将需要发送的服务UUID、特征值UUID、数据、回调函数和回调参数一起publish出去;
+    本demo项目中ble_timer_app.lua中publish了这个消息;
+]]
+
+local ble_server_sender = {}
+
+--[[
+数据发送队列,数据结构为:
+{
+    [1] = {service_uuid="service1", char_uuid="char1", data="data1", cb={func=callback_function1, para=callback_para1}},
+    [2] = {service_uuid="service2", char_uuid="char2", data="data2", cb={func=callback_function2, para=callback_para2}},
+}
+service_uuid: BLE服务UUID,string类型,必须存在;
+char_uuid: BLE特征值UUID,string类型,必须存在;
+data: 要发送的数据,string类型,必须存在;
+send_type: 发送类型,string类型,可选,默认值为"write",可选值为"notify";
+cb.func: 数据发送结果的用户回调函数,可以不存在;
+cb.para: 数据发送结果的用户回调函数参数,可以不存在;
+]]
+
+local send_queue = {}
+
+-- BLE server的任务名前缀
+ble_server_sender.TASK_NAME_PREFIX = "ble_server_"
+
+-- ble_client_sender的任务名
+ble_server_sender.TASK_NAME = ble_server_sender.TASK_NAME_PREFIX.."sender"
+
+-- "SEND_DATA_REQ"消息的处理函数
+local function send_data_req_proc_func(tag, service_uuid, char_uuid, data, send_type, cb)
+    -- 将数据插入到发送队列send_queue中
+    table.insert(send_queue, {
+        service_uuid = service_uuid, 
+        char_uuid = char_uuid, 
+        data = data, 
+        send_type = send_type or "write",
+        cb = cb,
+    })
+    -- 发送消息通知 BLE sender task,有新数据等待发送
+    sys.sendMsg(ble_server_sender.TASK_NAME, "BLE_EVENT", "SEND_REQ")
+end
+
+-- 按照顺序发送send_queue中的数据
+-- 如果发送成功,则返回当前正在发送的数据项
+-- 如果发送失败,通知回调函数发送失败后,继续发送下一条数据
+local function send_item_func(ble_device)
+    local item
+    -- 如果发送队列中有数据等待发送
+    while #send_queue>0 do
+        -- 取出来第一条数据赋值给item
+        -- 同时从队列send_queue中删除这一条数据
+        item = table.remove(send_queue, 1)
+
+        -- 发送数据
+        local params = {
+            uuid_service = string.fromHex(item.service_uuid),
+            uuid_characteristic = string.fromHex(item.char_uuid)
+        }
+        local data = item.data
+        local result = false
+        local send_type = string.lower(item.send_type or "write")
+
+        -- notify方式:主动向中心设备推送数据(需中心设备先开启notify订阅)
+        if send_type == "notify" then
+            result = ble_device:write_notify(params, data)
+            log.info("ble_server_sender", "使用notify方式发送数据")
+        else -- 默认使用write方式,更新特征值数据,中心设备需要主动读取特征值获取最新数据
+            result = ble_device:write_value(params, data)
+            log.info("ble_server_sender", "使用write方式发送数据")
+        end
+
+        -- 发送接口调用成功
+        if result then
+            -- 保存当前发送项,等待写入完成通知
+            return item
+        -- 发送接口调用失败
+        else
+            -- 如果当前发送的数据有用户回调函数,则执行用户回调函数
+            if item.cb and item.cb.func then
+                item.cb.func(false, item.cb.para)
+            end
+        end
+    end
+end
+
+-- 处理发送结果的回调函数
+local function send_item_cbfunc(item, result)
+    if item then
+        -- 如果当前发送的数据有用户回调函数,则执行用户回调函数
+        if item.cb and item.cb.func then
+            item.cb.func(result, item.cb.para)
+        end
+    end
+end
+
+-- BLE server sender的任务处理函数
+local function ble_server_sender_task_func()
+    local ble_device
+    local send_item
+    local result, msg
+
+    while true do
+        msg = sys.waitMsg(ble_server_sender.TASK_NAME, "BLE_EVENT")
+
+        -- BLE连接成功
+        -- msg[3]表示ble_device对象
+        if msg[2] == "CONNECT_OK" then
+            ble_device = msg[3]
+            -- 发送send_queue中的数据
+            send_item = send_item_func(ble_device)
+        -- BLE发送数据请求
+        elseif msg[2] == "SEND_REQ" then
+            -- 如果ble_device对象存在,发送send_queue中的数据
+            if ble_device then
+                send_item_cbfunc(send_item, true)
+                send_item = send_item_func(ble_device)
+            end
+        elseif msg[2] == "DISCONNECTED" then
+            -- 清空ble_device对象
+            ble_device = nil
+            -- 如果存在正在等待发送结果的发送项,执行回调函数通知发送方失败
+            send_item_cbfunc(send_item, false)
+            -- 如果发送队列中有数据等待发送
+            while #send_queue>0 do
+                -- 取出来第一条数据赋值给send_item
+                -- 同时从队列send_queue中删除这一条数据
+                send_item = table.remove(send_queue,1)
+                -- 执行回调函数通知发送方失败
+                send_item_cbfunc(send_item, false)
+            end
+            -- 当前没有正在等待发送结果的发送项
+            send_item = nil
+        end
+    end
+end
+
+-- 订阅"SEND_DATA_REQ"消息;
+-- 其他应用模块如果需要发送数据,直接sys.publish这个消息即可
+-- 参数: tag(标签), service_uuid(服务UUID), char_uuid(特征值UUID), data(数据), cb(回调函数和参数)
+sys.subscribe("SEND_DATA_REQ", send_data_req_proc_func)
+
+-- 启动任务
+sys.taskInitEx(ble_server_sender_task_func, ble_server_sender.TASK_NAME)
+
+return ble_server_sender

+ 66 - 0
module/Air8000/demo/ble/peripheral/ble_timer_app.lua

@@ -0,0 +1,66 @@
+--[[
+@module  ble_timer_app
+@summary 定时器应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为定时器应用功能模块,核心业务逻辑为:
+创建两个独立的循环定时器,用于定时向中心设备发送数据;
+
+本文件的对外接口有1个:
+1、sys.publish("SEND_DATA_REQ", "timer", server_uuid, write_char_uuid, data, send_type, {func = send_data_cbfunc, para="timer"..data}),发布SEND_DATA_REQ消息,在ble_client_sender文件中处理,携带的参数为:
+    -- 发布消息"SEND_DATA_REQ"
+    -- 携带的第一个参数"timer"表示是定时器应用模块发布的消息
+    -- 携带的第二个参数server_uuid表示要发送的服务UUID
+    -- 携带的第三个参数write_char_uuid表示要发送的特征值UUID
+    -- 携带的第四个参数data表示要发送的数据
+    -- 携带的第五个参数send_type表示发送类型,notify表示通知,write表示写入
+    -- 携带的第六个参数cb为发送结果回调(可以为空,如果为空,表示不关心ble client 发送数据成功还是失败),其中:
+    --   cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
+    --   cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
+]]
+
+-- 数据发送结果回调函数
+-- result:发送结果,true为发送成功,false为发送失败
+-- para:回调参数,sys.publish("SEND_DATA_REQ", "timer", "FA00", "EA02", data, {func=send_data_cbfunc, para="timer"..data})中携带的para
+local function send_data_cbfunc(result, para)
+    log.info("send_data_cbfunc", result, para)
+end
+
+-- 定时器回调函数
+function send_notify_data_timer_cbfunc()
+    local notify_data = "1 " .. os.date()
+    -- 发布消息"SEND_DATA_REQ"
+    -- 携带的第一个参数"timer"表示是定时器应用模块发布的消息
+    -- 携带的第二个参数server_uuid表示要发送的服务UUID
+    -- 携带的第三个参数char_uuid表示要发送的特征值UUID
+    -- 携带的第四个参数data表示要发送的数据
+    -- 携带的第五个参数cb为发送结果回调(可以为空,如果为空,表示不关心ble client 发送数据成功还是失败),其中:
+    --       cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
+    --       cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
+    sys.publish("SEND_DATA_REQ", "timer", config.service_uuid, config.char_uuid1, notify_data, "notify", {func = send_data_cbfunc, para="timer "..notify_data})
+end
+
+-- 定时器回调函数
+function send_write_data_timer_cbfunc()
+    local write_data = "2 " .. os.date()
+    -- 发布消息"SEND_DATA_REQ"
+    -- 携带的第一个参数"timer"表示是定时器应用模块发布的消息
+    -- 携带的第二个参数server_uuid表示要发送的服务UUID
+    -- 携带的第三个参数char_uuid表示要发送的特征值UUID
+    -- 携带的第四个参数data表示要发送的数据
+    -- 携带的第五个参数cb为发送结果回调(可以为空,如果为空,表示不关心ble client 发送数据成功还是失败),其中:
+    --       cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
+    --       cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
+    sys.publish("SEND_DATA_REQ", "timer", config.service_uuid, config.char_uuid3, write_data, "write", {func = send_data_cbfunc, para="timer "..write_data})
+end
+
+-- 启动5秒的循环定时器用于通过notify方式发送数据
+sys.timerLoopStart(send_notify_data_timer_cbfunc, 5000)
+log.info("ble_timer_app", "已启动notify发送定时器, 间隔: 5000ms")
+
+-- 启动6秒的循环定时器用于通过write方式发送数据
+sys.timerLoopStart(send_write_data_timer_cbfunc, 6000)
+log.info("ble_timer_app", "已启动write发送定时器, 间隔: 6000ms")
+

+ 28 - 0
module/Air8000/demo/ble/peripheral/ble_uart_app.lua

@@ -0,0 +1,28 @@
+--[[
+@module  ble_uart_app
+@summary 串口应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为串口应用功能模块,核心业务逻辑为:
+1、打开uart1,波特率115200,数据位8,停止位1,无奇偶校验位;
+2、uart1和pc端的串口工具相连;
+3、收到中心设备的写请求数据后,将数据通过uart1发送到pc端串口工具;
+
+本文件的对外接口有1个:
+1. sys.subscribe("RECV_BLE_WRITE_DATA", recv_ble_write_data_proc),订阅RECV_BLE_WRITE_DATA消息,处理消息携带的数据;
+]]
+
+local UART_ID = 1
+-- 初始化UART1,波特率115200,数据位8,停止位1
+uart.setup(UART_ID, 115200, 8, 1)
+
+-- 将service_uuid,char_uuid和data数据拼接
+-- 然后末尾增加回车换行两个字符,通过uart1发送出去,方便在PC端换行显示查看
+local function recv_ble_write_data_proc(service_uuid, char_uuid, data)
+    uart.write(UART_ID, service_uuid..","..char_uuid..","..data.."\r\n")
+end
+
+-- 订阅"RECV_BLE_WRITE_DATA"消息的处理函数recv_ble_write_data_proc
+sys.subscribe("RECV_BLE_WRITE_DATA", recv_ble_write_data_proc)

+ 19 - 5
module/Air8000/demo/ble/peripheral/check_wifi.lua

@@ -1,12 +1,26 @@
+--[[
+@module  check_wifi
+@summary 远程升级wifi固件模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+检查WiFi版本并自动升级
+功能:检查当前Air8000模组的WiFi固件是否为最新版本,若不是则自动启动升级(需插入可联网的SIM卡)。
+说明:Air8000的蓝牙功能依赖WiFi协处理器,需确保WiFi固件为最新版本。
+
+本文件没有对外接口,直接在main.lua中require ""check_wifi"就可以加载运行。
+]]
+
 -- 用于检查当前模组中WiFi是否是最新版本,如果不是最新版本则启动升级。
-local exfotawifi = require("exfotawifi")
+local fota_wifi = require("fota_wifi")
 
 local function wifi_fota_task_func()
-    local result = exfotawifi.request()
+    local result = fota_wifi.request()
     if result then
-        log.info("exfotawifi", "升级任务执行成功")
+        log.info("fota_wifi", "升级任务执行成功")
     else
-        log.info("exfotawifi", "升级任务执行失败")
+        log.info("fota_wifi", "升级任务执行失败")
     end
 end
 
@@ -14,7 +28,7 @@ end
 local function wait_ip_ready()
     local result, ip, adapter = sys.waitUntil("IP_READY", 30000)
     if result then
-        log.info("exfotawifi", "开始执行升级任务")
+        log.info("fota_wifi", "开始执行升级任务")
         sys.taskInit(wifi_fota_task_func)
     else
         log.error("当前正在升级WIFI&蓝牙固件,请插入可以上网的SIM卡")

+ 18 - 7
module/Air8000/demo/ble/peripheral/main.lua

@@ -2,11 +2,15 @@
 @module  main
 @summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
 @version 1.0
-@date    2025.07.01
-@author  wangshihao
+@date    2025.08.29
+@author  王世豪
 @usage
 本demo演示的核心功能为:
-Air8000的BLE从机模式,通过示例演示了如何发送通知,以及如何通过手机对从机设备进行读写操作。
+演示了Air8000核心板作为BLE peripheral(外围设备)的功能:
+1. Air8000作为外围设备开启广播,被动等待中心设备发起连接;
+2. 建立连接成功后,外围设备定期向中心设备发送数据;
+3. 外围设备收到中心设备的写入数据后,通过uart发送到pc端串口工具;
+4. pc端串口工具收到数据后,打印到串口工具窗口。
 
 更多说明参考本目录下的readme.md文件
 ]]
@@ -57,11 +61,18 @@ end
 --     log.info("mem.sys", rtos.meminfo("sys"))
 -- end, 3000)
 
--- 如果需要升级WIFI固件,请打开下面注释
-require "check_wifi"
 
--- 加载 peripheral 蓝牙功能模块
-require "ble_peripheral"
+-- Air8000蓝牙依赖WiFi协处理器,需更新WiFi固件(默认自动更新,需插入联网SIM卡)
+require "check_wifi" ---- 自动检查并更新WiFi固件
+
+-- 加载BLE peripheral(外围设备)主控制模块
+require "ble_server_main"
+
+-- 加载串口应用功能模块
+require "ble_uart_app"
+
+-- 加载定时器应用功能模块
+require "ble_timer_app"
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句

+ 64 - 8
module/Air8000/demo/ble/peripheral/readme.md

@@ -1,7 +1,36 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口;
+
+2、ble_server_main.lua:ble外围设备主程序,进行ble初始化,设置广播内容,处理各类ble事件(连接、断开连接、写入请求等);
+
+3、ble_server_receiver.lua:ble外围设备接收数据处理逻辑;
+
+4、ble_server_sender.lua:ble外围设备发送数据处理逻辑;
+
+5、ble_timer_app.lua:ble外围设备定时器处理逻辑,启动两个循环定时器,分别以notify,write的形式定时向中心设备发送数据;
+
+6、ble_uart_app.lua:ble外围设备接uart处理逻辑,将收到的中心设备的写入数据,通过uart发送到pc端串口工具;
+
+7、check_wifi.lua:检查当前Air8000模组的WiFi固件是否为最新版本,若不是则自动启动升级(需插入可联网的SIM卡)。
+
+## 用户消息介绍
+
+1、"RECV_BLE_WRITE_DATA":ble外围设备收到中心设备的写入数据后,会发布此消息,通知其他应用模块(如ble_uart_app)处理数据;
+
+3、"SEND_DATA_REQ":其他应用模块(ble_timer_app)发布此消息,通知ble 外围设备发送publish数据给中心设备;
 
 ## 演示功能概述
 
-将使用Air8000核心板,演示Air8000蓝牙从机模式下发送通知到主机,以及如何通过手机向Air8000进行读写操作。
+使用Air8000核心板演示 ble的peripheral(外围设备) 功能。
+
+1、Air8000作为外围设备开启广播,被动等待中心设备发起连接;
+
+2、连接成功后,定期向中心设备发送数据;
+
+3、外围设备收到中心设备的写入数据后,通过uart1发送到pc端串口工具;
+   
+4、pc端串口工具收到数据后,打印到串口工具窗口。
 
 ## 演示硬件环境
 
@@ -17,18 +46,45 @@
 
 ## 演示软件环境
 
-1、Luatools下载调试工具
+1、[Luatools下载调试工具](https://docs.openluat.com/air8000/luatos/common/download/)
+
+2、[Air8000 V2012版本固件](https://docs.openluat.com/air8000/luatos/firmware/)(理论上,2025年7月26日之后发布的固件都可以)
 
-[如何使用 LuaTools 烧录软件 - luatos@air8000 - 合宙模组资料中心](https://docs.openluat.com/air8000/luatos/common/download/)
+3、PC端的串口工具,例如SSCOM、LLCOM等都可以
 
-2、[Air8000 V2008版本固件(2025.06.27及之后发布)](https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/core)(测试通过的固件是LuatOS-SoC_V2008_Air8000_LVGL_0627.soc)
+4、nrf connect 蓝牙调试软件
 
 ## 演示核心步骤
 
-1、搭建好演示硬件环境
+1、搭建好硬件环境
+
+2、Luatools烧录内核固件和修改后的demo脚本代码
+
+3、烧录成功后,自动开机运行,如果设备出现以下日志,表示有中心设备主动发起连接,并连接成功
+
+```lua
+ I/user.BLE 设备连接成功: 5933D9B08C4B
+```
+4、如果出现以下日志,则表示Air8000在向中心设备指定的特征值UUID发送数据
+
+```lua
+-- 以下日志表示Air8000在向中心设备指定的特征值UUID发送数据,分别以notify,write的方式发送
+I/user.ble_server_sender 使用write方式发送数据
+I/user.send_data_cbfunc true timer 2 Fri Aug 29 17:17:21 2025
+I/user.ble_server_sender 使用notify方式发送数据
+I/user.send_data_cbfunc true timer 1 Fri Aug 29 17:17:19 2025
+```
+5、打开PC端的串口工具,选择uart1对应的端口,配置波特率115200,数据位8,停止位1,无奇偶校验位;
 
-2、通过Luatools将demo与固件烧录到核心板中
+6、在PC端的串口工具窗口中,会打印出中心设备写入外围设备的数据;
 
-3、烧录成功后,自动开机运行
+```lua
+-- 以下便是uart1接收到的写入数据,数据格式为:服务UUID,特征值UUID,特征值数据
+FA00,EA02,123456
+```
+7、在luatools日志中同样可以看到中心设备写入外围设备的数据。
 
-4、接下来通过蓝牙APP 连接作为蓝牙从机设备的Air8000进行操作
+```lua
+I/user.BLE 收到写请求: FA00 EA02 123456
+I/user.ble_server_receiver 收到写入数据 46413030 45413032 123456 6
+```

+ 10 - 10
module/Air8101/demo/ble/central/ble_client_main.lua

@@ -63,19 +63,19 @@ end
 local function ble_event_cb(ble_device, ble_event, ble_param)
     -- 仅表示连接成功,后续读/写/订阅 需等待GATT_DONE事件
     if ble_event == ble.EVENT_CONN then
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECT", ble_param)
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "CONNECT", ble_param)
     -- 连接断开
     elseif ble_event == ble.EVENT_DISCONN then
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", ble_param.reason)
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "DISCONNECTED", ble_param.reason)
     -- 扫描报告
     elseif ble_event == ble.EVENT_SCAN_REPORT then
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "SCAN_REPORT", ble_param)
+        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
-        sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "GATT_DONE", ble_param)
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "GATT_DONE", ble_param)
 
         -- 开启Notify监听,监听外围设备指定服务和特征值的通知,默认打开
         local notify_params = {
@@ -145,7 +145,7 @@ local function ble_client_main_task_func()
                 timeout = nil
             end
 
-            msg = sysplus.waitMsg(TASK_NAME, "BLE_EVENT", timeout)
+            msg = sys.waitMsg(TASK_NAME, "BLE_EVENT", timeout)
 
             if not msg then
                 log.error("ble_client_main_task_func", "waitMsg timeout")
@@ -161,7 +161,7 @@ local function ble_client_main_task_func()
                 -- 连接成功且服务发现完成,后续可执行业务操作(读/写/订阅)
                 -- 通知sender模块连接成功
                 log.info("BLE", "GATT服务发现完成")
-                sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "CONNECT_OK", ble_device)
+                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])
@@ -188,7 +188,7 @@ local function ble_client_main_task_func()
                     log.info("ble", "扫描次数超过100次, 停止扫描, 10秒后重新开始")
                     scan_count = 0
                     ble_device:scan_stop()
-                    sysplus.sendMsg(TASK_NAME, "BLE_EVENT", "RESTART_SCAN")
+                    sys.sendMsg(TASK_NAME, "BLE_EVENT", "RESTART_SCAN")
                 end
             elseif msg[2] == "RESTART_SCAN" then
                 -- 5s后重新开始扫描
@@ -214,10 +214,10 @@ local function ble_client_main_task_func()
         log.error("ble_client_main_task_func", "异常退出, 5秒后重新扫描连接")
 
         -- 清空此task绑定的消息队列中的未处理的消息
-        sysplus.cleanMsg(TASK_NAME)
+        sys.cleanMsg(TASK_NAME)
 
         -- 通知ble sender数据发送应用模块的task,ble连接已经断开
-        sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
+        sys.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
 
         -- 5秒后跳转到循环体开始位置,自动发起重连
         sys.wait(5000)
@@ -225,4 +225,4 @@ local function ble_client_main_task_func()
 end
 
 -- 启动主任务
-sysplus.taskInitEx(ble_client_main_task_func, TASK_NAME)
+sys.taskInitEx(ble_client_main_task_func, TASK_NAME)

+ 3 - 3
module/Air8101/demo/ble/central/ble_client_sender.lua

@@ -45,7 +45,7 @@ local function send_data_req_proc_func(tag, service_uuid, char_uuid, data, cb)
     -- 将数据插入到发送队列send_queue中
     table.insert(send_queue, {service_uuid=service_uuid, char_uuid=char_uuid, data="send from " .. tag .. ": " .. data, cb=cb})
     -- 发送消息通知 BLE sender task,有新数据等待发送
-    sysplus.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "SEND_REQ")
+    sys.sendMsg(ble_client_sender.TASK_NAME, "BLE_EVENT", "SEND_REQ")
 end
 
 -- 按照顺序发送send_queue中的数据
@@ -99,7 +99,7 @@ local function ble_client_sender_task_func()
 
     while true do
         -- 等待"BLE_EVENT"消息
-        msg = sysplus.waitMsg(ble_client_sender.TASK_NAME, "BLE_EVENT")
+        msg = sys.waitMsg(ble_client_sender.TASK_NAME, "BLE_EVENT")
 
         -- BLE连接成功
         -- msg[3]表示ble_device对象
@@ -150,7 +150,7 @@ sys.subscribe("SEND_DATA_REQ", send_data_req_proc_func)
 
 --创建并且启动一个task
 --运行这个task的处理函数ble_client_sender_task_func
-sysplus.taskInitEx(ble_client_sender_task_func, ble_client_sender.TASK_NAME)
+sys.taskInitEx(ble_client_sender_task_func, ble_client_sender.TASK_NAME)
 
 return ble_client_sender
 

+ 2 - 2
module/Air8101/demo/ble/central/ble_timer_app.lua

@@ -19,7 +19,7 @@
     --   cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
     --   cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
 
-2、sysplus.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid), 发送读取外围设备特征值UUID数据请求,在ble_client_main文件中处理,携带的参数为:
+2、sys.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid), 发送读取外围设备特征值UUID数据请求,在ble_client_main文件中处理,携带的参数为:
     -- msg[2]: "READ_REQ" --消息类型
     -- msg[3]: server_uuid --服务UUID
     -- msg[4]: read_char_uuid --特征值UUID
@@ -55,7 +55,7 @@ local function read_data_req_timer_cbfunc()
     -- msg[2]: "READ_REQ" --消息类型
     -- msg[3]: server_uuid --服务UUID
     -- msg[4]: read_char_uuid --特征值UUID
-    sysplus.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid)
+    sys.sendMsg(BLE_TASK_NAME,"BLE_EVENT","READ_REQ",server_uuid,read_char_uuid)
 end
 
 -- 启动5秒的循环定时器用于发送数据

+ 168 - 0
module/Air8101/demo/ble/peripheral/ble_server_main.lua

@@ -0,0 +1,168 @@
+
+--[[
+@module  ble_server_main
+@summary ble server 主应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为ble server 主应用功能模块,核心业务逻辑为:
+1. 初始化BLE功能
+2. 创建GATT数据库
+3. 设置广播内容并开始广播
+4. 处理各类BLE事件(连接、断开连接、写入请求等)
+5. 接收并处理来自其他模块的请求
+6. 依赖模块
+    - ble_server_receiver: 用于处理接收到的BLE数据
+    - ble_server_sender: 用于发送BLE数据
+]]
+local ble_server_receiver = require "ble_server_receiver"
+local ble_server_sender = require "ble_server_sender"
+
+-- ble_server_main的任务名
+local TASK_NAME = ble_server_sender.TASK_NAME_PREFIX.."main"
+
+-- 配置参数
+config = {
+    device_name = "LuatOS",          -- 设备名称
+    service_uuid = "FA00",           -- 服务UUID
+    char_uuid1 = "EA01",             -- Characteristic 1
+    char_uuid2 = "EA02",             -- Characteristic 2
+    char_uuid3 = "EA03",             -- Characteristic 3
+}
+
+local bluetooth_device = nil
+local ble_device = nil
+local adv_create = nil
+local gatt_create = nil
+
+-- GATT数据库定义
+local att_db = { 
+    string.fromHex(config.service_uuid), -- Service UUID
+    -- Characteristic
+    { -- Characteristic 1 (Notify + Read + Write)
+        string.fromHex(config.char_uuid1),
+        ble.NOTIFY | ble.READ | ble.WRITE
+    }, { -- Characteristic 2 (Write)
+        string.fromHex(config.char_uuid2),
+        ble.WRITE
+    }, { -- Characteristic 3 (Read)
+        string.fromHex(config.char_uuid3),
+        ble.READ
+    }
+}
+
+-- 事件回调函数
+local function ble_event_cb(ble_device, ble_event, ble_param)
+    -- 连接中心设备成功
+    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_WRITE then
+        sys.sendMsg(TASK_NAME, "BLE_EVENT", "WRITE_REQ", ble_param)
+    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
+
+    -- 创建GATT
+    gatt_create = gatt_create or ble_device:gatt_create(att_db)
+    if not gatt_create then
+        log.error("BLE", "BLE创建GATT失败")
+        return false
+    end
+
+    -- 设置广播内容
+    adv_create = adv_create or ble_device:adv_create({
+        addr_mode = ble.PUBLIC, -- 广播地址模式, 可选值: ble.PUBLIC, ble.RANDOM, ble.RPA, ble.NRPA
+        channel_map = ble.CHNLS_ALL, -- 广播的通道, 可选值: ble.CHNLS_37, ble.CHNLS_38, ble.CHNLS_39, ble.CHNLS_ALL
+        intv_min = 120, -- 广播间隔最小值, 单位为0.625ms, 最小值为20, 最大值为10240
+        intv_max = 120, -- 广播间隔最大值, 单位为0.625ms, 最小值为20, 最大值为10240
+        adv_data = {    -- 支持表格形式, 也支持字符串形式(255字节以内)
+            {ble.FLAGS, string.char(0x06)}, -- 广播标志位, 0x06: 支持LE Limited Discoverable Mode, 0x04: 支持LE General Discoverable Mode
+            {ble.COMPLETE_LOCAL_NAME, config.device_name}, -- 广播本地名称
+        }
+    })
+    if not adv_create then
+        log.error("BLE", "BLE创建广播失败")
+        return false
+    end
+
+    -- 开始广播
+    ble_device:adv_start()
+
+    return true
+end
+
+-- 主任务处理函数
+local function ble_server_main_task_func()
+    local result,msg
+
+    while true do
+        result = ble_init()
+        if not result then
+            log.error("ble_main_task_func", "ble_init error")
+            goto EXCEPTION_PROC
+        end
+
+        while true do
+            msg = sys.waitMsg(TASK_NAME, "BLE_EVENT")
+
+            if not msg then
+                log.error("ble_client_main_task_func", "waitMsg timeout")
+                goto EXCEPTION_PROC
+            end
+    
+            if msg[2] == "CONNECT" then
+                local conn_param = msg[3]
+                log.info("BLE", "设备连接成功: " .. conn_param.addr:toHex())
+                sys.sendMsg(ble_server_sender.TASK_NAME, "BLE_EVENT", "CONNECT_OK", ble_device)
+            elseif msg[2] == "DISCONNECTED" then
+                log.info("BLE", "设备断开连接,原因: " .. msg[3])
+                break
+            -- 收到中心设备的写请求,将写的数据发给ble_server_receiver模块处理
+            elseif msg[2] == "WRITE_REQ" then
+                local ble_param = msg[3]
+                log.info("BLE", "收到写请求: " .. ble_param.uuid_service:toHex() .. " " .. ble_param.uuid_characteristic:toHex() .. " " .. ble_param.data:toHex())
+                ble_server_receiver.proc(ble_param.uuid_service:toHex(), ble_param.uuid_characteristic:toHex(), ble_param.data)
+            end
+        end
+
+        ::EXCEPTION_PROC::
+        log.error("ble_server_main_task_func", "异常退出, 5秒后重新开启广播")
+
+        -- 停止广播
+        ble_device:adv_stop()
+
+        -- 清空此task绑定的消息队列中的未处理的消息
+        sys.cleanMsg(TASK_NAME)
+
+        -- 通知ble sender数据发送应用模块的task,ble连接已经断开
+        sys.sendMsg(ble_server_sender.TASK_NAME, "BLE_EVENT", "DISCONNECTED")
+
+        -- 5秒后跳转到循环体开始位置,自动发起重连
+        sys.wait(5000)
+    end
+end
+
+-- 启动主任务
+sys.taskInitEx(ble_server_main_task_func, TASK_NAME)

+ 24 - 0
module/Air8101/demo/ble/peripheral/ble_server_receiver.lua

@@ -0,0 +1,24 @@
+--[[
+@module  ble_server_receiver
+@summary BLE server 数据接收应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为BLE server 数据接收应用功能模块,核心业务逻辑为:
+1. 处理接收到的BLE写入请求数据。
+
+本文件的对外接口有1个:
+1. ble_server_receiver.proc(service_uuid, char_uuid, data): 处理接收到的BLE写入请求数据
+]]
+
+local ble_server_receiver = {}
+
+-- 处理接收到的BLE写入请求数据
+function ble_server_receiver.proc(service_uuid, char_uuid, data)
+    log.info("ble_server_receiver", "收到写入数据", service_uuid:toHex(), char_uuid:toHex(), data:toHex())
+
+    sys.publish("RECV_BLE_WRITE_DATA", service_uuid, char_uuid, data)
+end
+
+return ble_server_receiver

+ 160 - 0
module/Air8101/demo/ble/peripheral/ble_server_sender.lua

@@ -0,0 +1,160 @@
+--[[
+@module  ble_server_sender
+@summary BLE server 数据发送应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为BLE server 数据发送应用功能模块,核心业务逻辑为:
+1、订阅"SEND_DATA_REQ"消息,将其他应用模块需要发送的数据存储到队列send_queue中;
+2、BLE_server_sender task接收"CONNECT_OK"、"SEND_REQ"、两种类型的"BLE_EVENT"消息,处理队列中的数据;
+3、接收"DISCONNECTED"类型的"BLE_EVENT"消息,清空发送队列;
+4、数据发送完成后通过回调函数通知发送方。
+
+本文件的对外接口有1个:
+1. sys.subscribe("SEND_DATA_REQ", send_data_req_proc_func); 订阅"SEND_DATA_REQ"消息;
+    其他应用模块如果需要发送数据,直接sys.publish这个消息即可,将需要发送的服务UUID、特征值UUID、数据、回调函数和回调参数一起publish出去;
+    本demo项目中ble_timer_app.lua中publish了这个消息;
+]]
+
+local ble_server_sender = {}
+
+--[[
+数据发送队列,数据结构为:
+{
+    [1] = {service_uuid="service1", char_uuid="char1", data="data1", cb={func=callback_function1, para=callback_para1}},
+    [2] = {service_uuid="service2", char_uuid="char2", data="data2", cb={func=callback_function2, para=callback_para2}},
+}
+service_uuid: BLE服务UUID,string类型,必须存在;
+char_uuid: BLE特征值UUID,string类型,必须存在;
+data: 要发送的数据,string类型,必须存在;
+send_type: 发送类型,string类型,可选,默认值为"write",可选值为"notify";
+cb.func: 数据发送结果的用户回调函数,可以不存在;
+cb.para: 数据发送结果的用户回调函数参数,可以不存在;
+]]
+
+local send_queue = {}
+
+-- BLE server的任务名前缀
+ble_server_sender.TASK_NAME_PREFIX = "ble_server_"
+
+-- ble_client_sender的任务名
+ble_server_sender.TASK_NAME = ble_server_sender.TASK_NAME_PREFIX.."sender"
+
+-- "SEND_DATA_REQ"消息的处理函数
+local function send_data_req_proc_func(tag, service_uuid, char_uuid, data, send_type, cb)
+    -- 将数据插入到发送队列send_queue中
+    table.insert(send_queue, {
+        service_uuid = service_uuid, 
+        char_uuid = char_uuid, 
+        data = data, 
+        send_type = send_type or "write",
+        cb = cb,
+    })
+    -- 发送消息通知 BLE sender task,有新数据等待发送
+    sys.sendMsg(ble_server_sender.TASK_NAME, "BLE_EVENT", "SEND_REQ")
+end
+
+-- 按照顺序发送send_queue中的数据
+-- 如果发送成功,则返回当前正在发送的数据项
+-- 如果发送失败,通知回调函数发送失败后,继续发送下一条数据
+local function send_item_func(ble_device)
+    local item
+    -- 如果发送队列中有数据等待发送
+    while #send_queue>0 do
+        -- 取出来第一条数据赋值给item
+        -- 同时从队列send_queue中删除这一条数据
+        item = table.remove(send_queue, 1)
+
+        -- 发送数据
+        local params = {
+            uuid_service = string.fromHex(item.service_uuid),
+            uuid_characteristic = string.fromHex(item.char_uuid)
+        }
+        local data = item.data
+        local result = false
+        local send_type = string.lower(item.send_type or "write")
+
+        -- notify方式:主动向中心设备推送数据(需中心设备先开启notify订阅)
+        if send_type == "notify" then
+            result = ble_device:write_notify(params, data)
+            log.info("ble_server_sender", "使用notify方式发送数据")
+        else -- 默认使用write方式,更新特征值数据,中心设备需要主动读取特征值获取最新数据
+            result = ble_device:write_value(params, data)
+            log.info("ble_server_sender", "使用write方式发送数据")
+        end
+
+        -- 发送接口调用成功
+        if result then
+            -- 保存当前发送项,等待写入完成通知
+            return item
+        -- 发送接口调用失败
+        else
+            -- 如果当前发送的数据有用户回调函数,则执行用户回调函数
+            if item.cb and item.cb.func then
+                item.cb.func(false, item.cb.para)
+            end
+        end
+    end
+end
+
+-- 处理发送结果的回调函数
+local function send_item_cbfunc(item, result)
+    if item then
+        -- 如果当前发送的数据有用户回调函数,则执行用户回调函数
+        if item.cb and item.cb.func then
+            item.cb.func(result, item.cb.para)
+        end
+    end
+end
+
+-- BLE server sender的任务处理函数
+local function ble_server_sender_task_func()
+    local ble_device
+    local send_item
+    local result, msg
+
+    while true do
+        msg = sys.waitMsg(ble_server_sender.TASK_NAME, "BLE_EVENT")
+
+        -- BLE连接成功
+        -- msg[3]表示ble_device对象
+        if msg[2] == "CONNECT_OK" then
+            ble_device = msg[3]
+            -- 发送send_queue中的数据
+            send_item = send_item_func(ble_device)
+        -- BLE发送数据请求
+        elseif msg[2] == "SEND_REQ" then
+            -- 如果ble_device对象存在,发送send_queue中的数据
+            if ble_device then
+                send_item_cbfunc(send_item, true)
+                send_item = send_item_func(ble_device)
+            end
+        elseif msg[2] == "DISCONNECTED" then
+            -- 清空ble_device对象
+            ble_device = nil
+            -- 如果存在正在等待发送结果的发送项,执行回调函数通知发送方失败
+            send_item_cbfunc(send_item, false)
+            -- 如果发送队列中有数据等待发送
+            while #send_queue>0 do
+                -- 取出来第一条数据赋值给send_item
+                -- 同时从队列send_queue中删除这一条数据
+                send_item = table.remove(send_queue,1)
+                -- 执行回调函数通知发送方失败
+                send_item_cbfunc(send_item, false)
+            end
+            -- 当前没有正在等待发送结果的发送项
+            send_item = nil
+        end
+    end
+end
+
+-- 订阅"SEND_DATA_REQ"消息;
+-- 其他应用模块如果需要发送数据,直接sys.publish这个消息即可
+-- 参数: tag(标签), service_uuid(服务UUID), char_uuid(特征值UUID), data(数据), cb(回调函数和参数)
+sys.subscribe("SEND_DATA_REQ", send_data_req_proc_func)
+
+-- 启动任务
+sys.taskInitEx(ble_server_sender_task_func, ble_server_sender.TASK_NAME)
+
+return ble_server_sender

+ 66 - 0
module/Air8101/demo/ble/peripheral/ble_timer_app.lua

@@ -0,0 +1,66 @@
+--[[
+@module  ble_timer_app
+@summary 定时器应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为定时器应用功能模块,核心业务逻辑为:
+创建两个独立的循环定时器,用于定时向中心设备发送数据;
+
+本文件的对外接口有1个:
+1、sys.publish("SEND_DATA_REQ", "timer", server_uuid, write_char_uuid, data, send_type, {func = send_data_cbfunc, para="timer"..data}),发布SEND_DATA_REQ消息,在ble_client_sender文件中处理,携带的参数为:
+    -- 发布消息"SEND_DATA_REQ"
+    -- 携带的第一个参数"timer"表示是定时器应用模块发布的消息
+    -- 携带的第二个参数server_uuid表示要发送的服务UUID
+    -- 携带的第三个参数write_char_uuid表示要发送的特征值UUID
+    -- 携带的第四个参数data表示要发送的数据
+    -- 携带的第五个参数send_type表示发送类型,notify表示通知,write表示写入
+    -- 携带的第六个参数cb为发送结果回调(可以为空,如果为空,表示不关心ble client 发送数据成功还是失败),其中:
+    --   cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
+    --   cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
+]]
+
+-- 数据发送结果回调函数
+-- result:发送结果,true为发送成功,false为发送失败
+-- para:回调参数,sys.publish("SEND_DATA_REQ", "timer", "FA00", "EA02", data, {func=send_data_cbfunc, para="timer"..data})中携带的para
+local function send_data_cbfunc(result, para)
+    log.info("send_data_cbfunc", result, para)
+end
+
+-- 定时器回调函数
+function send_notify_data_timer_cbfunc()
+    local notify_data = "1 " .. os.date()
+    -- 发布消息"SEND_DATA_REQ"
+    -- 携带的第一个参数"timer"表示是定时器应用模块发布的消息
+    -- 携带的第二个参数server_uuid表示要发送的服务UUID
+    -- 携带的第三个参数char_uuid表示要发送的特征值UUID
+    -- 携带的第四个参数data表示要发送的数据
+    -- 携带的第五个参数cb为发送结果回调(可以为空,如果为空,表示不关心ble client 发送数据成功还是失败),其中:
+    --       cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
+    --       cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
+    sys.publish("SEND_DATA_REQ", "timer", config.service_uuid, config.char_uuid1, notify_data, "notify", {func = send_data_cbfunc, para="timer "..notify_data})
+end
+
+-- 定时器回调函数
+function send_write_data_timer_cbfunc()
+    local write_data = "2 " .. os.date()
+    -- 发布消息"SEND_DATA_REQ"
+    -- 携带的第一个参数"timer"表示是定时器应用模块发布的消息
+    -- 携带的第二个参数server_uuid表示要发送的服务UUID
+    -- 携带的第三个参数char_uuid表示要发送的特征值UUID
+    -- 携带的第四个参数data表示要发送的数据
+    -- 携带的第五个参数cb为发送结果回调(可以为空,如果为空,表示不关心ble client 发送数据成功还是失败),其中:
+    --       cb.func为回调函数(可以为空,如果为空,表示不关心ble client发送数据成功还是失败)
+    --       cb.para为回调函数的第二个参数(可以为空),回调函数的第一个参数为发送结果(true表示成功,false表示失败)
+    sys.publish("SEND_DATA_REQ", "timer", config.service_uuid, config.char_uuid3, write_data, "write", {func = send_data_cbfunc, para="timer "..write_data})
+end
+
+-- 启动5秒的循环定时器用于通过notify方式发送数据
+sys.timerLoopStart(send_notify_data_timer_cbfunc, 5000)
+log.info("ble_timer_app", "已启动notify发送定时器, 间隔: 5000ms")
+
+-- 启动6秒的循环定时器用于通过write方式发送数据
+sys.timerLoopStart(send_write_data_timer_cbfunc, 6000)
+log.info("ble_timer_app", "已启动write发送定时器, 间隔: 6000ms")
+

+ 28 - 0
module/Air8101/demo/ble/peripheral/ble_uart_app.lua

@@ -0,0 +1,28 @@
+--[[
+@module  ble_uart_app
+@summary 串口应用功能模块
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本文件为串口应用功能模块,核心业务逻辑为:
+1、打开uart1,波特率115200,数据位8,停止位1,无奇偶校验位;
+2、uart1和pc端的串口工具相连;
+3、收到中心设备的写请求数据后,将数据通过uart1发送到pc端串口工具;
+
+本文件的对外接口有1个:
+1. sys.subscribe("RECV_BLE_WRITE_DATA", recv_ble_write_data_proc),订阅RECV_BLE_WRITE_DATA消息,处理消息携带的数据;
+]]
+
+local UART_ID = 1
+-- 初始化UART1,波特率115200,数据位8,停止位1
+uart.setup(UART_ID, 115200, 8, 1)
+
+-- 将service_uuid,char_uuid和data数据拼接
+-- 然后末尾增加回车换行两个字符,通过uart1发送出去,方便在PC端换行显示查看
+local function recv_ble_write_data_proc(service_uuid, char_uuid, data)
+    uart.write(UART_ID, service_uuid..","..char_uuid..","..data.."\r\n")
+end
+
+-- 订阅"RECV_BLE_WRITE_DATA"消息的处理函数recv_ble_write_data_proc
+sys.subscribe("RECV_BLE_WRITE_DATA", recv_ble_write_data_proc)

+ 76 - 0
module/Air8101/demo/ble/peripheral/main.lua

@@ -0,0 +1,76 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.08.29
+@author  王世豪
+@usage
+本demo演示的核心功能为:
+演示了Air8101核心板作为BLE peripheral(外围设备)的功能:
+1. Air8101作为外围设备开启广播,被动等待中心设备发起连接;
+2. 建立连接成功后,外围设备定期向中心设备发送数据;
+3. 外围设备收到中心设备的写入数据后,通过uart发送到pc端串口工具;
+4. pc端串口工具收到数据后,打印到串口工具窗口。
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "ble_peripheral"
+VERSION = "001.000.000"
+
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载BLE peripheral(外围设备)主控制模块
+require "ble_server_main"
+
+-- 加载串口应用功能模块
+require "ble_uart_app"
+
+-- 加载定时器应用功能模块
+require "ble_timer_app"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 94 - 0
module/Air8101/demo/ble/peripheral/readme.md

@@ -0,0 +1,94 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口;
+
+2、ble_server_main.lua:ble外围设备主程序,进行ble初始化,设置广播内容,处理各类ble事件(连接、断开连接、写入请求等);
+
+3、ble_server_receiver.lua:ble外围设备接收数据处理逻辑;
+
+4、ble_server_sender.lua:ble外围设备发送数据处理逻辑;
+
+5、ble_timer_app.lua:ble外围设备定时器处理逻辑,启动两个循环定时器,分别以notify,write的形式定时向中心设备发送数据;
+
+6、ble_uart_app.lua:ble外围设备接uart处理逻辑,将收到的中心设备的写入数据,通过uart发送到pc端串口工具;
+
+## 用户消息介绍
+
+1、"RECV_BLE_WRITE_DATA":ble外围设备收到中心设备的写入数据后,会发布此消息,通知其他应用模块(如ble_uart_app)处理数据;
+
+3、"SEND_DATA_REQ":其他应用模块(ble_timer_app)发布此消息,通知ble 外围设备发送publish数据给中心设备;
+
+## 演示功能概述
+
+使用Air8101核心板演示 ble的peripheral(外围设备) 功能。
+
+1、Air8101作为外围设备开启广播,被动等待中心设备发起连接;
+
+2、连接成功后,定期向中心设备发送数据;
+
+3、外围设备收到中心设备的写入数据后,通过uart1发送到pc端串口工具;
+   
+4、pc端串口工具收到数据后,打印到串口工具窗口。
+
+## 演示硬件环境
+
+1、Air8101核心板一块
+
+2、TYPE-C USB数据线一根
+
+3、USB转串口数据线一根
+
+4、Air8101核心板和数据线的硬件接线方式为
+
+- Air8101核心板通过TYPE-C USB口供电;(核心板背面的功耗测试开关拨到OFF一端)
+
+- 如果测试发现软件频繁重启,重启原因值为:poweron reason 0,可能是供电不足,此时再通过直流稳压电源对核心板的vbat管脚进行4V供电,或者VIN管脚进行5V供电;
+
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+- USB转串口数据线,一般来说,白线连接核心板的12/U1TX,绿线连接核心板的11/U1RX,黑线连接核心板的gnd,另外一端连接电脑USB口;
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air8101 V1005版本固件](https://docs.openluat.com/air8101/luatos/firmware/)(理论上,2025年7月26日之后发布的固件都可以)
+
+3、PC端的串口工具,例如SSCOM、LLCOM等都可以
+
+4、nrf connect 蓝牙调试软件
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、Luatools烧录内核固件和修改后的demo脚本代码
+
+3、烧录成功后,自动开机运行,如果设备出现以下日志,表示有中心设备主动发起连接,并连接成功
+
+```lua
+ I/user.BLE 设备连接成功: 5933D9B08C4B
+```
+4、如果出现以下日志,则表示Air8101在向中心设备指定的特征值UUID发送数据
+
+```lua
+-- 以下日志表示Air8101在向中心设备指定的特征值UUID发送数据,分别以notify,write的方式发送
+I/user.ble_server_sender 使用write方式发送数据
+I/user.send_data_cbfunc true timer 2 Fri Aug 29 17:17:21 2025
+I/user.ble_server_sender 使用notify方式发送数据
+I/user.send_data_cbfunc true timer 1 Fri Aug 29 17:17:19 2025
+```
+5、打开PC端的串口工具,选择uart1对应的端口,配置波特率115200,数据位8,停止位1,无奇偶校验位;
+
+6、在PC端的串口工具窗口中,会打印出中心设备写入外围设备的数据;
+
+```lua
+-- 以下便是uart1接收到的写入数据,数据格式为:服务UUID,特征值UUID,特征值数据
+FA00,EA02,123456
+```
+7、在luatools日志中同样可以看到中心设备写入外围设备的数据。
+
+```lua
+I/user.BLE 收到写请求: FA00 EA02 123456
+I/user.ble_server_receiver 收到写入数据 46413030 45413032 123456 6
+```