Răsfoiți Sursa

add: 添加nimble.advParams函数,设置ble广播参数

Wendal Chen 2 ani în urmă
părinte
comite
01511a54a8

+ 67 - 0
components/nimble/src/luat_lib_nimble.c

@@ -21,6 +21,7 @@
 #include "host/ble_hs_id.h"
 #include "host/util/util.h"
 #include "host/ble_hs_adv.h"
+#include "host/ble_gap.h"
 
 #define LUAT_LOG_TAG "nimble"
 #include "luat_log.h"
@@ -40,6 +41,15 @@ ble_uuid_any_t ble_peripheral_write_uuid;
 #define WM_GATT_WRITE_UUID    0xFFF2
 // #define WM_GATT_NOTIFY_UUID    0xFFF3
 
+
+uint8_t luat_ble_dev_name[32];
+size_t  luat_ble_dev_name_len;
+
+uint8_t adv_buff[128];
+int adv_buff_len = 0;
+struct ble_hs_adv_fields adv_fields;
+struct ble_gap_adv_params adv_params = {0};
+
 /*
 初始化BLE上下文,开始对外广播/扫描
 @api nimble.init(name)
@@ -55,6 +65,10 @@ static int l_nimble_init(lua_State* L) {
     const char* name = NULL;
     if(lua_isstring(L, 1)) {
         name = luaL_checklstring(L, 1, &len);
+        if (len > 0) {
+            memcpy(luat_ble_dev_name, name, len);
+            luat_ble_dev_name_len = len;
+        }
     }
     LLOGD("init name %s mode %d", name == NULL ? "-" : name, nimble_mode);
     rc = luat_nimble_init(0xFF, name, nimble_mode);
@@ -148,6 +162,7 @@ static int l_nimble_send_msg(lua_State *L) {
 @usage
 -- 参考 demo/nimble
 -- 本函数对central/主机模式适用
+-- 本函数会直接返回, 然后通过异步回调返回结果
 */
 static int l_nimble_scan(lua_State *L) {
     int ret = luat_nimble_blecent_scan();
@@ -334,6 +349,55 @@ static int l_nimble_set_adv_data(lua_State *L) {
     return 1;
 }
 
+
+/*
+设置广播参数
+@api nimble.advParams(conn_mode, disc_mode, itvl_min, itvl_max, channel_map, filter_policy, high_duty_cycle)
+@int 广播模式, 0 - 不可连接, 1 - 定向连接, 2 - 未定向连接, 默认0
+@int 发现模式, 0 - 不可发现, 1 - 限制发现, 3 - 通用发现, 默认0
+@int 最小广播间隔, 0 - 使用默认值, 范围 1 - 65535, 单位0.625ms, 默认0
+@int 最大广播间隔, 0 - 使用默认值, 范围 1 - 65535, 单位0.625ms, 默认0
+@int 广播通道, 默认0, 一般不需要设置
+@int 过滤规则, 默认0, 一般不需要设置
+@int 当广播模式为"定向连接"时,是否使用高占空比模式, 默认0, 可选1
+@return nil 无返回值
+@usage
+-- 当前仅ibeacon模式/peripheral/从机可使用
+-- 例如设置 不可连接 + 限制发现
+-- 需要在nimble.init之前设置好
+nimble.advParams(0, 1)
+-- 注意peripheral模式下自动配置 conn_mode 和 disc_mode
+*/
+static int l_nimble_set_adv_params(lua_State *L) {
+    /** Advertising mode. Can be one of following constants:
+     *  - BLE_GAP_CONN_MODE_NON (non-connectable; 3.C.9.3.2).
+     *  - BLE_GAP_CONN_MODE_DIR (directed-connectable; 3.C.9.3.3).
+     *  - BLE_GAP_CONN_MODE_UND (undirected-connectable; 3.C.9.3.4).
+     */
+    adv_params.conn_mode = luaL_optinteger(L, 1, 0);
+    /** Discoverable mode. Can be one of following constants:
+     *  - BLE_GAP_DISC_MODE_NON  (non-discoverable; 3.C.9.2.2).
+     *  - BLE_GAP_DISC_MODE_LTD (limited-discoverable; 3.C.9.2.3).
+     *  - BLE_GAP_DISC_MODE_GEN (general-discoverable; 3.C.9.2.4).
+     */
+    adv_params.disc_mode = luaL_optinteger(L, 2, 0);
+
+    /** Minimum advertising interval, if 0 stack use sane defaults */
+    adv_params.itvl_min = luaL_optinteger(L, 3, 0);
+    /** Maximum advertising interval, if 0 stack use sane defaults */
+    adv_params.itvl_max = luaL_optinteger(L, 4, 0);
+    /** Advertising channel map , if 0 stack use sane defaults */
+    adv_params.channel_map = luaL_optinteger(L, 5, 0);
+
+    /** Advertising  Filter policy */
+    adv_params.filter_policy = luaL_optinteger(L, 6, 0);
+
+    /** If do High Duty cycle for Directed Advertising */
+    adv_params.high_duty_cycle = luaL_optinteger(L, 7, 0);
+
+    return 0;
+}
+
 #include "rotable2.h"
 static const rotable_Reg_t reg_nimble[] =
 {
@@ -356,7 +420,10 @@ static const rotable_Reg_t reg_nimble[] =
 
     // ibeacon广播模式
     { "ibeacon",        ROREG_FUNC(l_nimble_ibeacon)},
+
+    // 广播数据
     { "advData",        ROREG_FUNC(l_nimble_set_adv_data)},
+    { "advParams",        ROREG_FUNC(l_nimble_set_adv_params)},
 
     // 放一些常量
     { "STATE_OFF",           ROREG_INT(BT_STATE_OFF)},

+ 13 - 1
components/nimble/src/luat_nimble_mode_central.c

@@ -33,8 +33,10 @@ typedef struct luat_nimble_scan_result
     uint16_t uuids_16[16];
     uint32_t uuids_32[16];
     uint8_t uuids_128[16][16];
+    uint8_t mfg_data[128];
     char name[64];
     char addr[7]; // 地址类型 + MAC地址
+    uint8_t mfg_data_len;
 }luat_nimble_scan_result_t;
 
 void rand_bytes(uint8_t *data, int len);
@@ -212,8 +214,14 @@ int luat_nimble_scan_cb(lua_State*L, void*ptr) {
     //     }
     //     lua_setfield(L, -2, "uuids128");
     // }
+    if (res->mfg_data_len) {
+        lua_pushlstring(L, (const char*)res->mfg_data, res->mfg_data_len);
+    }
+    else {
+        lua_pushnil(L);
+    }
     luat_heap_free(res);
-    lua_call(L, 4, 0);
+    lua_call(L, 5, 0);
     return 0;
 }
 
@@ -279,6 +287,10 @@ static int blecent_gap_event(struct ble_gap_event *event, void *arg)
         }
         memcpy(res->addr, &event->disc.addr, 7);
         memcpy(res->name, fields.name, fields.name_len);
+        if (fields.mfg_data_len) {
+            memcpy(res->mfg_data, fields.mfg_data, fields.mfg_data_len);
+            res->mfg_data_len = fields.mfg_data_len;
+        }
         LLOGD("addr %02X%02X%02X%02X%02X%02X", event->disc.addr.val[0], event->disc.addr.val[1], event->disc.addr.val[2], 
                                                event->disc.addr.val[3], event->disc.addr.val[4], event->disc.addr.val[5]);
         // for (i = 0; i < fields.num_uuids128 && i < 16; i++) {

+ 26 - 9
components/nimble/src/luat_nimble_mode_ibeacon.c

@@ -37,9 +37,14 @@ static uint8_t own_addr_type;
 static uint8_t ble_ready;
 void ble_store_config_init(void);
 
-static uint8_t adv_buff[128];
-static int adv_buff_len = 0;
-static struct ble_hs_adv_fields adv_fields;
+
+extern uint8_t luat_ble_dev_name[];
+extern size_t  luat_ble_dev_name_len;
+
+extern uint8_t adv_buff[];
+extern int adv_buff_len;
+extern struct ble_hs_adv_fields adv_fields;
+extern struct ble_gap_adv_params adv_params;
 
 static void ble_app_advertise(void);
 
@@ -82,6 +87,18 @@ int luat_nimble_set_adv_data(char* buff, size_t len, int flags) {
     adv_fields.mfg_data_len = adv_buff_len;
     adv_fields.flags = flags;
 
+    if (luat_ble_dev_name_len == 0) {
+        const char * name = ble_svc_gap_device_name();
+        adv_fields.name = (uint8_t *)name;
+        adv_fields.name_len = strlen(name);
+        adv_fields.name_is_complete = 1;
+    }
+    else {
+        adv_fields.name = (uint8_t *)luat_ble_dev_name;
+        adv_fields.name_len = luat_ble_dev_name_len;
+        adv_fields.name_is_complete = 1;
+    }
+
     if (ble_ready) {
         rc = ble_gap_adv_set_fields(&adv_fields);
         LLOGD("ble_gap_adv_set_fields rc %d", rc);
@@ -105,7 +122,6 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
 static void
 ble_app_advertise(void)
 {
-    struct ble_gap_adv_params adv_params = {0};
     // uint8_t uuid128[16];
     int rc;
 
@@ -131,11 +147,12 @@ bleprph_on_sync(void)
     rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);
 
     LLOGI("Device Address: " ADDR_FMT, ADDR_T(addr_val));
-    if (ble_use_custom_name == 0) {
-        char buff[32];
-        sprintf_(buff, "LOS-" ADDR_FMT, ADDR_T(addr_val));
-        LLOGD("BLE name: %s", buff);
-        rc = ble_svc_gap_device_name_set((const char*)buff);
+    if (luat_ble_dev_name_len == 0) {
+        sprintf_((char*)luat_ble_dev_name, "LOS-" ADDR_FMT, ADDR_T(addr_val));
+        LLOGD("BLE name: %s", luat_ble_dev_name);
+        luat_ble_dev_name_len = strlen((const char*)luat_ble_dev_name);
+        rc = ble_svc_gap_device_name_set((const char*)luat_ble_dev_name);
+        
     }
 
     /* Advertise indefinitely. */

+ 11 - 12
components/nimble/src/luat_nimble_mode_peripheral.c

@@ -43,8 +43,9 @@ extern ble_uuid_any_t ble_peripheral_write_uuid;
 #define LUAT_LOG_TAG "nimble"
 #include "luat_log.h"
 
-static uint8_t ble_use_custom_name;
-// extern uint16_t g_ble_conn_handle;
+extern uint8_t luat_ble_dev_name[];
+extern size_t  luat_ble_dev_name_len;
+extern struct ble_gap_adv_params adv_params;
 
 typedef struct ble_write_msg {
     // uint16_t conn_handle,
@@ -316,7 +317,7 @@ ext_bleprph_advertise(void)
 static void
 bleprph_advertise(void)
 {
-    struct ble_gap_adv_params adv_params;
+    // struct ble_gap_adv_params adv_params;
     struct ble_hs_adv_fields fields;
     const char *name;
     int rc;
@@ -364,7 +365,7 @@ bleprph_advertise(void)
     }
 
     /* Begin advertising. */
-    memset(&adv_params, 0, sizeof adv_params);
+    // memset(&adv_params, 0, sizeof adv_params);
     adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
     adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
     rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
@@ -593,15 +594,14 @@ bleprph_on_sync(void)
     rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);
 
     LLOGI("Device Address: " ADDR_FMT, ADDR_T(addr_val));
-    if (ble_use_custom_name == 0) {
-        char buff[32];
-        sprintf_(buff, "LOS-" ADDR_FMT, ADDR_T(addr_val));
-        LLOGD("BLE name: %s", buff);
-        rc = ble_svc_gap_device_name_set((const char*)buff);
+    if (luat_ble_dev_name_len == 0) {
+        sprintf_((char*)luat_ble_dev_name, "LOS-" ADDR_FMT, ADDR_T(addr_val));
+        LLOGD("BLE name: %s", luat_ble_dev_name);
+        luat_ble_dev_name_len = strlen((const char*)luat_ble_dev_name);
+        rc = ble_svc_gap_device_name_set((const char*)luat_ble_dev_name);
     }
     ble_gatts_start();
-    //print_addr(addr_val);
-    // LLOGI("");
+
     /* Begin advertising. */
 #if CONFIG_EXAMPLE_EXTENDED_ADV
     ext_bleprph_advertise();
@@ -622,7 +622,6 @@ int luat_nimble_init_peripheral(uint8_t uart_idx, char* name, int mode) {
     /* Set the default device name. */
     if (name != NULL && strlen(name)) {
         rc = ble_svc_gap_device_name_set((const char*)name);
-        ble_use_custom_name = 1;
     }
 
     /* Initialize the NimBLE host configuration. */

+ 57 - 0
demo/nimble/adv_free/main.lua

@@ -0,0 +1,57 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "advdemo"
+VERSION = "1.0.0"
+
+--[[
+BLE 自由广播示例
+支持的模块:
+1. Air101/Air103, 开发板的BLE天线未引出, 需要靠近使用, 且功耗高
+2. ESP32系列, 包括ESP32C3/ESP32S3
+
+-- 使用蓝牙小程序, BeaconController, 可搜索到,且能看到数据变化
+]]
+
+log.info("main", PROJECT, VERSION)
+
+-- 一定要添加sys.lua !!!!
+sys = require("sys")
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+sys.taskInit(function()
+    sys.wait(2000)
+
+    -- 设置自由广播的数据
+    local data = string.fromHex("4C000215AABBCCDDAABBCCDDAABBCCDDAABBCCDD00")
+    -- local data = crypto.trng(25)
+    -- local data = string.char(0x11, 0x13, 0xA3, 0x5A, 0x11, 0x13, 0xA3, 0x5A, 0x11, 0x13, 0xA3, 0x5A, 0x11, 0x13, 0xA3, 0x5A)
+    nimble.advData(data)
+    -- 带flags配置
+    -- nimble.advData(data, 0x05)
+    -- 设置广播参数, 可选
+    -- nimble.advParams(0x00, 0x01)
+    log.info("adv_free", "data", data:toHex())
+    
+    -- BLE模式, BEACON模式, 兼容自由广播
+    nimble.mode(nimble.MODE_BLE_BEACON)
+    -- 启动之
+    nimble.init()
+
+    -- 运行时改变数据也是可以的
+    while 1 do
+        sys.wait(60000) -- 每隔1分钟变一次
+        --data = crypto.trng(25)
+        --log.info("adv_free", "data", data:toHex())
+        --nimble.advData(data)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 17 - 3
demo/nimble/central/main.lua

@@ -4,7 +4,14 @@ PROJECT = "bledemo"
 VERSION = "1.0.0"
 
 --[[
-BLE centraldemo, 扫码并连接其他设备 ** 未完成 **
+BLE 中心/从机模式
+状态: 
+1. 扫描, 可用
+2. 接收扫描结果, 可用
+3. 连接到指定设备, 可用
+4. 获取已连接设备的描述符, 暂不可用
+5. 发送数据, 暂不可用
+
 支持的模块:
 1. Air101/Air103, 开发板的BLE天线未引出, 需要靠近使用, 且功耗高
 2. ESP32系列, 包括ESP32C3/ESP32S3
@@ -33,8 +40,14 @@ sys.subscribe("BLE_GATT_WRITE_CHR", function(info, data)
 end)
 
 -- 接收扫描结果
-sys.subscribe("BLE_SCAN_RESULT", function(addr, name, uuids)
-    log.info("ble scan", (addr:toHex()), name, json.encode(uuids))
+sys.subscribe("BLE_SCAN_RESULT", function(addr, name, uuids, mfg_data)
+    -- addr 蓝牙设备的地址, 7字节
+    --      首字节是地址类型, 0 代表 随机地址, 1 代表真实地址
+    --      后6字节是蓝牙地址
+    -- name 设备名称, 不一定有
+    -- uuids 服务id
+    -- mfg_data 工厂默认信息, 主要是iBeacon或者自由广播的数据, 2023-03-19添加
+    log.info("ble scan", (addr:toHex()), name, json.encode(uuids), mfg_data and mfg_data:toHex() or "")
     if name == "LOS-065614A23900" then
         nimble.connect(addr)
     end
@@ -59,6 +72,7 @@ sys.taskInit(function()
     -- 发送数据
     while 1 do
         nimble.scan()
+        -- TODO 扫描到指定设备后, 应跳出循环
         sys.wait(120000)
     end
 end)