当前位置: 首页 > news >正文

做网站的多钱寻找在山西运城专业做网站推广的

做网站的多钱,寻找在山西运城专业做网站推广的,wordpress 创建分类,中国建筑工程平台网前言 前面我们已经了解了 ESP32 的 BLE 整体架构#xff0c;现在我们开始实际学习一下Bluedroid 从机篇的广播和扫描。本文将会以 ble_ibeacon demo 为例子进行讲解#xff0c;需要注意的一点是。ibeacon 分为两个部分#xff0c;一个是作为广播者#xff0c;一个是作为观…前言 前面我们已经了解了 ESP32 的 BLE 整体架构现在我们开始实际学习一下Bluedroid 从机篇的广播和扫描。本文将会以 ble_ibeacon demo 为例子进行讲解需要注意的一点是。ibeacon 分为两个部分一个是作为广播者一个是作为观察者。IBEACON_RECEIVER 这个宏表示作为观察者IBEACON_SENDER 这个宏被置 1 表示为广播者。需要注意的一点是本文先仅介绍广播相关内容 ibeacon 介绍 ibeacon 是什么 作为一名初学者当听到 ibeacon 时候大概率是一脸懵逼的。即使网上搜索大量资料没有亲身体验也是一头雾水。为了方便各位理解就以我来上海实习周末逛的第一个景点 – 豫园 为例子进行分析。当我们进入景点肯定会有一个二维码建议我们扫描然后之后就会有电子讲解功能。例如我现在扫描了豫园的二维码打开了一个微信小程序此时微信小程序上就能够显示出我的位置在哪里。 3. 如果你移动到一个地方该小程序就会进行相关讲解当前景点的一些历史文化信息。此时各位有没有想过一个问题该小程序是如何精确的知道我们当前是在哪个景点呢 4. 此时就是利用的 ibeacon 技术进行的。如果你有兴趣的话可以在走到某个景点发现微信小程序播报讲解时刻停下来然后在这个附近十米内的范围转转会惊奇的发现一些地方藏有这种小方块。 5. 这个小方块就是本文要进行讲解的ESP32 作为广播者的功能。而你手机就是充当的观察者。 ibeacon 有什么用 现在我们明白了 ibeacon 技术大概是什么东西了。那么这个有什么作用呢从上面的例子我们就可以很好的知道室内定位广播信息。当前室内定位技术一直是一项值得探索的技术ibeacon 可以说提供了一个不错的选择不过个人感觉目前 BLE 室内定位更多的是聚焦于 AOA。同样在商场我们只需要打开微信小程序走到哪家店铺就可以直接查看那家店铺的商品信息这样一定程度上可以方便用户挑选商品。 ibeacon 工程介绍 工程源码 我们先拷贝 ble_ibeacon demo 例程出来打开ibeacon_demo.c 文件将其替换为如下内容。 /** SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD** SPDX-License-Identifier: Unlicense OR CC0-1.0*//**************************************************************************** * * This file is for iBeacon demo. It supports both iBeacon sender and receiver * which is distinguished by macros IBEACON_SENDER and IBEACON_RECEIVER, * * iBeacon is a trademark of Apple Inc. Before building devices which use iBeacon technology, * visit https://developer.apple.com/ibeacon/ to obtain a license. * ****************************************************************************/#include stdint.h #include string.h #include stdbool.h #include stdio.h #include nvs_flash.h#include esp_bt.h #include esp_gap_ble_api.h #include esp_gattc_api.h #include esp_gatt_defs.h #include esp_bt_main.h #include esp_bt_defs.h #include esp_ibeacon_api.h #include esp_log.h #include freertos/FreeRTOS.hstatic const char* DEMO_TAG IBEACON_DEMO; extern esp_ble_ibeacon_vendor_t vendor_config;#if (IBEACON_MODE IBEACON_RECEIVER) // 在停止扫描请求发送后蓝牙堆栈可能还会处理一些尚未完成的扫描结果。因此需要通过这个标志位来设置是否需要继续处理扫描完成事件 static bool is_scanning false; #endif///Declare static functions static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);#if (IBEACON_MODE IBEACON_RECEIVER) static esp_ble_scan_params_t ble_scan_params {.scan_type BLE_SCAN_TYPE_ACTIVE, // 主动扫描.own_addr_type BLE_ADDR_TYPE_PUBLIC, // 公共地址.scan_filter_policy BLE_SCAN_FILTER_ALLOW_ALL, // 允许扫描所有设备.scan_interval 0x50,.scan_window 0x30,.scan_duplicate BLE_SCAN_DUPLICATE_DISABLE };#elif (IBEACON_MODE IBEACON_SENDER) static esp_ble_adv_params_t ble_adv_params {.adv_int_min 0x20, // 0x20*0.625ms20msRange: 0x0020 to 0x4000 (20ms to 10240ms).adv_int_max 0x40, // 0x40*0.625ms40ms.adv_type ADV_TYPE_NONCONN_IND, // 不可连接广播// .adv_type ADV_TYPE_DIRECT_IND_HIGH, // 设置为高占空比定向广播// .peer_addr {0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6}, // 目标设备MAC地址// .peer_addr_type BLE_ADDR_TYPE_PUBLIC, // 目标设备的地址类型.own_addr_type BLE_ADDR_TYPE_PUBLIC, // 公共地址.channel_map ADV_CHNL_ALL, // 在 37,38,39 频道广播.adv_filter_policy ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // 允许任何设备扫描和连接 }; #endifstatic void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {esp_err_t err;ESP_LOGI(DEMO_TAG, ESP_GAP_BLE_EVT %d , event);switch (event) { #if (IBEACON_MODE IBEACON_SENDER)case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: { // 原始广播数据设置完成事件if ((err param-adv_data_raw_cmpl.status) ! ESP_BT_STATUS_SUCCESS) {ESP_LOGE(DEMO_TAG, Set raw adv data failed: %s, esp_err_to_name(err));return;}esp_ble_gap_start_advertising(ble_adv_params);break;}case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: { // 广播启动完成事件//adv start complete event to indicate adv start successfully or failedif ((err param-adv_start_cmpl.status) ! ESP_BT_STATUS_SUCCESS) {ESP_LOGE(DEMO_TAG, Adv start failed: %s, esp_err_to_name(err));}break;}case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: { // 广播停止完成事件if ((err param-adv_stop_cmpl.status) ! ESP_BT_STATUS_SUCCESS){ESP_LOGE(DEMO_TAG, Adv stop failed: %s, esp_err_to_name(err));}else {ESP_LOGI(DEMO_TAG, Stop adv successfully);}break;} #endif #if (IBEACON_MODE IBEACON_RECEIVER)case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: { // 扫描参数设置完成事件//the unit of the duration is second, 0 means scan permanentlyuint32_t duration 0;esp_ble_gap_start_scanning(duration);break;}case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: // 扫描启动完成事件//scan start complete event to indicate scan start successfully or failedif ((err param-scan_start_cmpl.status) ! ESP_BT_STATUS_SUCCESS) {ESP_LOGE(DEMO_TAG, Scan start failed: %s, esp_err_to_name(err));} else {is_scanning true;}break;case ESP_GAP_BLE_SCAN_RESULT_EVT: { // 扫描结果准备完毕事件if (is_scanning false) { // 如果没有在扫描则不处理扫描结果ESP_LOGW(DEMO_TAG, Scan is not started yet);break;}esp_ble_gap_cb_param_t *scan_result (esp_ble_gap_cb_param_t *)param;switch (scan_result-scan_rst.search_evt) {case ESP_GAP_SEARCH_INQ_RES_EVT: {/* 搜索 BLE iBeacon 数据包 */if (esp_ble_is_ibeacon_packet(scan_result-scan_rst.ble_adv, scan_result-scan_rst.adv_data_len)) {esp_ble_ibeacon_t *ibeacon_data (esp_ble_ibeacon_t*)(scan_result-scan_rst.ble_adv);ESP_LOGI(DEMO_TAG, ----------iBeacon Found----------);esp_log_buffer_hex(IBEACON_DEMO: Device address:, scan_result-scan_rst.bda, ESP_BD_ADDR_LEN );esp_log_buffer_hex(IBEACON_DEMO: Proximity UUID:, ibeacon_data-ibeacon_vendor.proximity_uuid, ESP_UUID_LEN_128);uint16_t major ENDIAN_CHANGE_U16(ibeacon_data-ibeacon_vendor.major);uint16_t minor ENDIAN_CHANGE_U16(ibeacon_data-ibeacon_vendor.minor);ESP_LOGI(DEMO_TAG, Major: 0x%04x (%d), major, major);ESP_LOGI(DEMO_TAG, Minor: 0x%04x (%d), minor, minor);ESP_LOGI(DEMO_TAG, Measured power (RSSI at a 1m distance):%d dbm, ibeacon_data-ibeacon_vendor.measured_power);ESP_LOGI(DEMO_TAG, RSSI of packet:%d dbm, scan_result-scan_rst.rssi);esp_err_t err esp_ble_gap_stop_scanning();if (err ! ESP_OK) {ESP_LOGE(DEMO_TAG, Stop scaning failed: %s, esp_err_to_name(err));} else {is_scanning false;ESP_LOGI(DEMO_TAG, Stop scaning); }}break;}default:break;}break;}case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: { // 扫描停止完成事件if ((err param-scan_stop_cmpl.status) ! ESP_BT_STATUS_SUCCESS){ESP_LOGE(DEMO_TAG, Scan stop failed: %s, esp_err_to_name(err));}else {ESP_LOGI(DEMO_TAG, Stop scan successfully);}break;} #endifdefault:break;} }void ble_ibeacon_appRegister(void) {esp_err_t status;ESP_LOGI(DEMO_TAG, register callback);/* 注册 GAP 回调函数 */if ((status esp_ble_gap_register_callback(esp_gap_cb)) ! ESP_OK) {ESP_LOGE(DEMO_TAG, gap register error: %s, esp_err_to_name(status));return;}}void ble_ibeacon_init(void) {/* 初始化蓝牙 HOST 层 */esp_bluedroid_init();/* 使能蓝牙 HOST 层 */esp_bluedroid_enable();/* 注册 ibeacon */ble_ibeacon_appRegister(); }void app_main(void) {/* 初始化 NVS */ESP_ERROR_CHECK(nvs_flash_init());/* 释放经典蓝牙 Control 层内存 */ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));/* 初始化 BLE Control 层 */esp_bt_controller_config_t bt_cfg BT_CONTROLLER_INIT_CONFIG_DEFAULT();esp_bt_controller_init(bt_cfg);/* 启动 BLE Control 层 */esp_bt_controller_enable(ESP_BT_MODE_BLE);/* BLE Ibeacon 功能初始化 */ble_ibeacon_init();#if (IBEACON_MODE IBEACON_RECEIVER)/* 设置扫描参数 */esp_ble_gap_set_scan_params(ble_scan_params);#elif (IBEACON_MODE IBEACON_SENDER)esp_ble_ibeacon_t ibeacon_adv_data;/* 填充 ibeacon 数据 */esp_err_t status esp_ble_config_ibeacon_data (vendor_config, ibeacon_adv_data);if (status ESP_OK) {for (int i 0; i sizeof(ibeacon_adv_data); i) {ESP_LOGI(DEMO_TAG, ibeacon_adv_data[%d] 0x%x, i, *((uint8_t*)(ibeacon_adv_data) i));}/* 设置广播原始数据此函数将会触发 ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT 事件 */esp_ble_gap_config_adv_data_raw((uint8_t*)ibeacon_adv_data, sizeof(ibeacon_adv_data));}else {ESP_LOGE(DEMO_TAG, Config iBeacon data failed: %s, esp_err_to_name(status));} #endif } 解析代码流程 现在我们开始捋一遍 ibeacon 工程代码顺序以方便我们后续理解。 NVS 分区 首先是 NVS 分区的初始化他主要用于存储一些 RF射频校准数据以确保无线通信的性能和稳定性。当 ESP32 第一次启动并运行无线功能如 Wi-Fi 或蓝牙时它会进行 RF 校准以确定在当前硬件和环境条件下的最佳射频参数。校准过程的结果会被存储在 NVS 中这样在后续启动时设备可以直接使用这些校准数据避免每次启动都需要重新校准。从而提高设备运行效率。 /* 初始化 NVS */ESP_ERROR_CHECK(nvs_flash_init());为了更为方便的理解 NVS 分区在当前的作用我们可以进行如下实验。我们会发现只有第一次才会产生 RF 校验数据失败而后就将不再出现该信息。这是因为在第一次芯片启动时芯片会去检测 NVS 分区是否存在 RF 校验数据。如果有那么就马上利用该数据进行启动射频模块。如果没有那么就先进行 RF 校准然后将校准数据存储在 NVS 分区方便后续芯片快速启动。 # 将 Flash 全部擦除该命令必须执行否则现象可能无法出现 idf.py erase-flash # 重新烧录程序 idf.py flash monitor # 烧录完成后我们将能够看到这样的日志打印信息 # ------------- W (602) phy_init: failed to load RF calibration data (0x1102), falling back to full calibration W (642) phy_init: saving new calibration data because of checksum failure, mode(2) # ------------- # 看到这条信息后复位芯片我们将看不到这条信息。 idf.py monitorbluedroid 协议栈启动 如下为 bluedroid 协议栈启动代码为什么这样编写我已经在 ESP32 的 BLE 整体架构 这篇博客讲解不再进行赘述。 /* 释放经典蓝牙 Control 层内存 */ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));/* 初始化 BLE Control 层 */esp_bt_controller_config_t bt_cfg BT_CONTROLLER_INIT_CONFIG_DEFAULT();esp_bt_controller_init(bt_cfg);/* 启动 BLE Control 层 */esp_bt_controller_enable(ESP_BT_MODE_BLE);/* BLE Ibeacon 功能初始化 */ble_ibeacon_init();esp_ble_gap_config_adv_data_raw() 设置广播数据 在设置广播数据之前我们需要先知道 BLE 的广播数据包格式是什么样的。下面两张图即可展示出广播包的数据格式具体含义请阅读 BTHome数据格式解析 的 BLE 广播包格式 章节此处不做赘述。 了解了 BLE 广播格式之后现在我们要做的就是分析一下 ibeacon 的广播包 AD Structure 应该如何编写。首先一个 BLE 广播包必须存在 0x01 类型的广播数据该广播主要是用于指示当前设备能进行的一些行为。因为我们当前是单模因此需要置位 bit1 和 bit2因此 AD Data 为 0x06。 bit描述0有限可发现模式1一般可发现模式2不支持 BR/EDR 当前为单模设备3设备同时支持 LE 和 BR/EDR 的 Control4设备同时支持 LE 和 BR/EDR 的 HOST需要注意在Core Specification Supplement 10 该位被取消5~7保留 通过上面分析因此我们可以得到第一个 flags 应该填入的数据内容如下 esp_ble_ibeacon_head_t ibeacon_common_head {.flags {0x02, 0x01, 0x06},// ... };分析完 Flags 的数据包我们再来看看最关键的 ibeacon 数据格式。 byte描述0数据长度固定为 0x1A1AD Type固定为 0xFF 表示厂商自定义数据2~3固定为 0x004C 此为 Apple 公司的标识符。可在Assigned Numbers Document (PDF) 7 Company Identifiers 章节查阅4固定为 0x02这个是由 Apple 公司定义的数据类型5ibeacon 数据长度固定为 0x156~21用户定义的 iBeacon UUID用于唯一标识应用场景22~23用户自定义的主要值用于分组或区域标识24~25用户自定义的次要值用于更精细的分组或区域标识26发射功率可通过该值配合 RSSI 获得当前位置与广播设备距离 通过上述分析我们就可以将固定的报头数据先设置好。 // 注意BLE 广播为小端存储 esp_ble_ibeacon_head_t ibeacon_common_head {.flags {0x02, 0x01, 0x06},.length 0x1A, // iBeacon 数据长度为 26 bytes.type 0xFF, // 自定义数据类型.company_id 0x004C, // Apple 公司的标识符.beacon_type 0x1502 // 0x02 表示 iBeacon 类型0x15 表示接下来的 ibeacon 数据长度为 21 bytes。 };之后我们就可以设置自己想要广播的数据了。 /* Vendor part of iBeacon data*/ esp_ble_ibeacon_vendor_t vendor_config {.proximity_uuid ESP_UUID, // 16 字节用户定义的 iBeacon UUID用于唯一标识应用场景。.major ENDIAN_CHANGE_U16(ESP_MAJOR), // 2 字节用户自定义的主要值用于分组或区域标识。.minor ENDIAN_CHANGE_U16(ESP_MINOR), // 2 字节用户自定义的次要值用于更精细的分组或区域标识。.measured_power 0xC5 // 发射功率为 -59 dBm };一切设置完成后我们只需要调用 esp_ble_config_ibeacon_data() 函数将数据进行填充即可。该函数其实就是对 Payload 段数据进行了一下配置看如下日志打印信息就可知道。如果感兴趣各位可以看一下该函数实现其实是非常简单的。 注意 esp_ble_config_ibeacon_data() 并不是 ESP32 官方的库函数这个是编写例程的人写的自定义函数 I (538) IBEACON_DEMO: ibeacon_adv_data[0] 0x2 I (538) IBEACON_DEMO: ibeacon_adv_data[1] 0x1 I (548) IBEACON_DEMO: ibeacon_adv_data[2] 0x6 I (548) IBEACON_DEMO: ibeacon_adv_data[3] 0x1a I (558) IBEACON_DEMO: ibeacon_adv_data[4] 0xff I (558) IBEACON_DEMO: ibeacon_adv_data[5] 0x4c I (568) IBEACON_DEMO: ibeacon_adv_data[6] 0x0 I (568) IBEACON_DEMO: ibeacon_adv_data[7] 0x2 I (578) IBEACON_DEMO: ibeacon_adv_data[8] 0x15 I (588) IBEACON_DEMO: ibeacon_adv_data[9] 0xfd I (588) IBEACON_DEMO: ibeacon_adv_data[10] 0xa5 I (598) IBEACON_DEMO: ibeacon_adv_data[11] 0x6 I (598) IBEACON_DEMO: ibeacon_adv_data[12] 0x93 I (608) IBEACON_DEMO: ibeacon_adv_data[13] 0xa4 I (608) IBEACON_DEMO: ibeacon_adv_data[14] 0xe2 I (618) IBEACON_DEMO: ibeacon_adv_data[15] 0x4f I (618) IBEACON_DEMO: ibeacon_adv_data[16] 0xb1 I (628) IBEACON_DEMO: ibeacon_adv_data[17] 0xaf I (628) IBEACON_DEMO: ibeacon_adv_data[18] 0xcf I (638) IBEACON_DEMO: ibeacon_adv_data[19] 0xc6 I (638) IBEACON_DEMO: ibeacon_adv_data[20] 0xeb I (648) IBEACON_DEMO: ibeacon_adv_data[21] 0x7 I (648) IBEACON_DEMO: ibeacon_adv_data[22] 0x64 I (658) IBEACON_DEMO: ibeacon_adv_data[23] 0x78 I (668) IBEACON_DEMO: ibeacon_adv_data[24] 0x25 I (668) IBEACON_DEMO: ibeacon_adv_data[25] 0x27 I (678) IBEACON_DEMO: ibeacon_adv_data[26] 0xb7 I (678) IBEACON_DEMO: ibeacon_adv_data[27] 0xf2 I (688) IBEACON_DEMO: ibeacon_adv_data[28] 0x6 I (688) IBEACON_DEMO: ibeacon_adv_data[29] 0xc5配置好要广播的数据后直接调用库函数 esp_ble_gap_config_adv_data_raw() 即可。我们来看看 nrf Connect 结合上述打印信息就会发现这个函数就是将你需要广播的数据存入 Payload 段 。 esp_ble_gap_start_advertising() 启动广播 在上面我们调用 esp_ble_gap_config_adv_data_raw() 函数设置原始广播数据完成之后将会触发 ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT 事件。我们可以在该事件中判断原始广播数据是否设置成功如果设置成功那么我们即可调用 esp_ble_gap_start_advertising() 函数启动广播。在调用 esp_ble_gap_start_advertising() 函数时需要传入如下结构体。 typedef struct {uint16_t adv_int_min; /*! 最小的广告间隔无向和低占空比定向广告。取值范围:0x0020 ~ 0x4000 默认值:N 0x0800(1.28秒)时间 N * 0.625 ms 时间范围: 20 ms to 10.24 s */uint16_t adv_int_max; /*! 无向和低占空比定向广告的最大广告间隔。取值范围:0x0020 ~ 0x4000 默认值:N 0x0800(1.28秒)时间 N * 0.625 ms 时间范围: 20 ms to 10.24 s */esp_ble_adv_type_t adv_type; /*! 广播类型 */esp_ble_addr_type_t own_addr_type; /*! 所有者蓝牙设备地址类型 */esp_bd_addr_t peer_addr; /*! 对端设备蓝牙设备地址 */esp_ble_addr_type_t peer_addr_type; /*! 对端设备蓝牙设备地址类型仅支持公网地址类型和随机地址类型 */esp_ble_adv_channel_t channel_map; /*! 广告频道图 */esp_ble_adv_filter_t adv_filter_policy; /*! 广告过滤策略 */ } esp_ble_adv_params_t;如果是对 BLE HCI 比较熟悉的朋友就会发现这个函数其实就是让 HOST 层向 Control 层发送 LE Set Advertising Parameters command 命令。我们可以打开 Core 5.3 的 2353 页会发现这个命令传入的参数和 esp_ble_gap_start_advertising() 函数传入的参数一模一样。 12. 关于这个命令规范书中的描述如下 HCI_LE_Set_Advertising_Parameters 命令用于设置广播参数。advertissing_interval_min 小于或等于 Advertising_Interval_Max 。advertissing_interval_min 和 Advertising_Interval_Max 不应该是相同的值以使控制器能够确定给定其他活动的最佳广告间隔。对于高占空比定向广告即当 Advertising_Type 为 0x01 (ADV_DIRECT_IND高占空比)时不使用 Advertising_Interval_Min 和 Advertising_Interval_Max 参数应忽略。Advertising_Type 用于确定在启用发布时用于发布的数据包类型。“Own_Address_Type” 参数表示发布报文使用的地址类型。如果 Own_Address_Type 等于 0x02 或 0x03 Peer_Address 参数包含对端设备的身份地址Peer_Address_Type 参数包含对端设备的身份类型(即0x00或0x01)。这些参数用于在解析表中定位相应的本地 IRK此 IRK 用于生成广告中使用的自己的地址。如果是定向广播即当 Advertising_Type 设置为 0x01 (ADV_DIRECT_IND高占空比)或0x04 (ADV_DIRECT_IND低占空比模式)时则 Peer_Address_Type 和 Peer_Address 有效。如果 Own_Address_Type 等于 0x02 或 0x03Control 使用 Peer_Address 参数中包含的对端设备的身份地址和 Peer_Address_Type 参数中包含的对端设备的身份地址类型(即0x00或0x01)对应的对端设备的 IRK 生成对端设备的可解析私有地址。Advertising_Channel_Map 是一个位字段表示发送广播报文时应使用的广告通道索引。在 Advertising_Channel_Map 参数中至少要设置一个通道位。当定向广播被启用时Advertising_Filter_Policy 参数应该被忽略。如果 Control 启用了广播功能则 HOST 不得发出该命令如果启用了广播功能则应使用 命令禁用 错误代码。如果 HOST 提供的发布间隔范围(Advertising_Interval_Min, Advertising_Interval_Max)超出了 Control 支持的发布间隔范围则 Control 将返回不支持的特征或参数值(0x11)错误码。 adv_int_min 和 adv_int_max adv_int_min 和 adv_int_max 用于指示广播的时间间隔。bluedroid 协议栈会选取该范围内的任意值作为广播间隔但是实测后发现他一般选取 adv_int_max 作为广播间隔。 adv_int_min 和 adv_int_max 范围都要求在 0x0020 ~ 0x4000 之间如果没有设置该值默认为 0x0800 (1.28 s) 。时间计算公式为 Time N * 0.625 ms既最终的广播时间范围为 20 ms to 10.24 s。 此时有人可能会有疑问了我代码里面命令设置的最大广播间隔时间为 40ms 啊怎么抓包数据有些广播间隔为 48ms 多呢 这个就需要涉及到 SIG 规定的广播间隔内容了。SIG 规定为了解决多个设备同时广播时的冲突问题从而避免广播包的碰撞确保更加可靠的广播和接收在 BLE 广播过程中存在一个 随机延迟random delay通常称为 广播延迟advertising delay。 static esp_ble_adv_params_t ble_adv_params {.adv_int_min 0x20, // 0x20*0.625ms20msRange: 0x0020 to 0x4000 (20ms to 10240ms).adv_int_max 0x40, // 0x40*0.625ms40ms// ... };如果我们希望一个确切的广播间隔那么就可以让adv_int_min 和 adv_int_max 相等即可。 注 adv_int_min 和 adv_int_max 相等只是让 advInterval 为我们设定的固定值advDelay 依旧会存在而且 SIG 不建议让 adv_int_min 和 adv_int_max 相等 adv_int_max 必须大于 adv_int_min 否则就会出现如下报错。部分日志信息是本例程用于调试写的 I (658) IBEACON_DEMO: ESP_GAP_BLE_EVT 4 E (668) BT_APPL: bta_dm_ble_set_adv_params_all(), fail to set ble adv params. E (678) BT_HCI: hci write adv params error 0x12 I (678) IBEACON_DEMO: ESP_GAP_BLE_EVT 6 E (688) IBEACON_DEMO: Adv start failed: ERRORadv_type 该参数用于设置 BLE 的广播类型。 typedef enum {ADV_TYPE_IND 0x00, // 可连接和可扫描的无定向广告(ADV_IND)(默认)ADV_TYPE_DIRECT_IND_HIGH 0x01, // 可连接的高占空比定向广告(ADV_DIRECT_IND高占空比)ADV_TYPE_SCAN_IND 0x02, // 可扫描的非定向广告(ADV_SCAN_IND)ADV_TYPE_NONCONN_IND 0x03, // 不可连接非定向广告(ADV_NONCONN_IND)ADV_TYPE_DIRECT_IND_LOW 0x04, // 可连接低占空比定向广告(ADV_DIRECT_IND低占空比) } esp_ble_adv_type_t;如果是学习 《低功耗权威指南》或者其他类型的熟记中会发现广播类型只有四种通用广播定向广播不可连接广播可发现广播。这个时候有人肯定会疑问为什么这里的定向广播有两种。这个就设计到版本更替的问题了《低功耗权威指南》是用于讲解 BLE 4.0 的权威书籍但是 ESP32 的 Bluedroid 是支持 BLE 5.0 的。从 BLE 5.0 开始广播拥有第五种类型即可连接低占空比定向广告。现在我就开始分别介绍一下这几种广播的区别 广播类型描述关闭方式ADV_TYPE_IND这种广播是最常用的广播方式。进行通用广播的设备是能够被扫描被连接的。调用 esp_ble_gap_stop_advertising() 函数主动关闭广播或者连接建立。ADV_TYPE_DIRECT_IND_HIGH该广播类型主要针对希望快速建立连接的需求开启定向广播后完整的广播事件必须每 3.75ms 重复一次正因如此之快的广播速率导致该广播包将在占满整个广播信道进而导致该区域内其他设备无法进行广播因此定向广播不可以持续超过 1.28s 之上。该广播只有两种结束方式第一种是收到指定的对端设备连接请求第二种是超过 1.28s。一旦超过 1.28s 还没有建立连接Control 层应该向 HOST 层发送 Advertising Timeout 事件告知广播超时。这里需要注意ESP32 的该广播事件似乎有 bug并不会上报广播超时事件ADV_TYPE_SCAN_IND该类型广播不可以用于发起连接但允许其他设备进行扫描可以理解为将连接功能去除的 ADV_TYPE_IND。调用 esp_ble_gap_stop_advertising() 函数主动关闭广播。ADV_TYPE_NONCONN_IND该类型广播针对的是不想被连接仅进行广播的设备例如本文的 Ibeacon 设备。这也是唯一可用于只有发射机而没有接收机设备的广播类型。调用 esp_ble_gap_stop_advertising() 函数主动关闭广播。ADV_TYPE_DIRECT_IND_LOW该广播属于定向广播但是并不会像 ADV_TYPE_DIRECT_IND_HIGH 那样快速的将整个广播信道占满他是会在 adv_int_min 和 adv_int_max 范围内保持一定的频率进行广播。调用 esp_ble_gap_stop_advertising() 函数主动关闭广播或者和指定的对端设备连接建立。 own_addr_type 这里设置设备的地址类型没有特殊需求直接设置为公共地址即可。 typedef enum {BLE_ADDR_TYPE_PUBLIC 0x00, /*! 公共地址 */BLE_ADDR_TYPE_RANDOM 0x01, /*! 随机设备地址。要设置此地址请使用esp_ble_gap_set_rand_addr(esp_bd_addr_t rand_addr)函数 */BLE_ADDR_TYPE_RPA_PUBLIC 0x02, /*! 具有公共身份地址的可解析私有地址(RPA) */BLE_ADDR_TYPE_RPA_RANDOM 0x03, /*! 带有随机身份地址的可解析私有地址(RPA)。要设置此地址请使用esp_ble_gap_set_rand_addr(esp_bd_addr_t rand_addr)函数 */ } esp_ble_addr_type_t;设备地址类型描述公共地址BLE_ADDR_TYPE_PUBLIC全球唯一且固定的地址需要向 IEEE 组织购买。因为全球唯一因此容易被跟踪静态地址BLE_ADDR_TYPE_RANDOM自己定义上电初始化完成后不能再进行修改。每次芯片启动都可能会更换地址可解析地址BLE_ADDR_TYPE_RPA_PUBLIC通讯双方共享 IRK 生成随机可解析私有地址。只有拥有广播者的 IRK 时才能跟踪其广播活动。目的是为了防止恶意第三方跟踪蓝牙设备。不可解析地址BLE_ADDR_TYPE_RPA_RANDOM定期更新地址SIG 推荐15 min 更新一次更新时间间隔不要超过 1 小时。通常用于设备只需要一次性广播数据且不需要被接收方识别或跟踪。例如发送传感器数据的设备、匿名设备发现、或仅广播某些临时数据的场景。 peer_addr 对端设备 MAC 地址。只有当 adv_type 为 ADV_TYPE_DIRECT_IND_HIGH 或者 ADV_TYPE_DIRECT_IND_LOW 才有效。 peer_addr_type 对端设备地址类型。只有当 adv_type 为 ADV_TYPE_DIRECT_IND_HIGH 或者 ADV_TYPE_DIRECT_IND_LOW 才有效。 channel_map 广播的信道。你可以设置在指定的广播信道进行广播或者是所有广播信道都广播。 typedef enum {ADV_CHNL_37 0x01, // 仅在 37 信道广播ADV_CHNL_38 0x02, // 仅在 38 信道广播ADV_CHNL_39 0x04, // 仅在 39 信道广播ADV_CHNL_ALL 0x07, // 在 37,38,39 信道广播 } esp_ble_adv_channel_t;adv_filter_policy 因为我们是 Ibeacon 所有需要让所有人能够扫描到因此设置为 ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY 。白名单是指的特定的对端设备地址我们可以调用 esp_ble_gap_update_whitelist() 函数更新白名单。 如果开发过 Nordic 的相关芯片会发现一个问题怎么 Nordic 的芯片还可以过滤 UUID名称外观等信息呢这个就是 Nordic 的协议栈中软件实现的和 SIG 相关规定无关如果你希望有这样的功能可以自行实现。 typedef enum {// 允许任何人的扫描和连接请求ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY 0x00,// 只允许来自白名单设备的扫描请求和来自任何人的连接请求ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY,// 只允许任何人的扫描请求和来自白名单设备的连接请求ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST,// 只允许来自白名单设备的扫描和连接请求ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST, } esp_ble_adv_filter_t;广播启动完成 当调用 esp_ble_gap_start_advertising() 函数之后将会触发 ESP_GAP_BLE_ADV_START_COMPLETE_EVT 事件。在该事件中我们可以知道广播是否完成。当广播结束之后将会触发 ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT 事件不过当前的 Ibeacon 例程中不会停止广播因此该事件不会触发。 参考 Apple Ibeacon 官方介绍低功耗蓝牙开发者手册BTHome数据格式解析nRF52832蓝牙iBeacon广播 谷雨文档中心BLE技术揭秘Core 5.3
http://www.w-s-a.com/news/958148/

相关文章:

  • 无锡工程建设招标网站怎么自己建设公司网站
  • 哪个网站可以学做咸菜安卓软件开发需要学什么软件
  • 自有网站建设的团队遂宁市建设局网站
  • 网站建设哪个好一些网站内容导出
  • 什么网站的页面做的比较好看网上做平面设计的网站
  • 网站建设单选网站建设学校培训学校
  • 可以做app的网站logo设计在线生成免费标小智
  • 网站变更备案做酒类网站
  • 网站必须要备案吗东莞市非凡网站建设
  • 太原建网站公司网站设计的流程是怎样的
  • 网站开发交易平台北京网站建设的价格低
  • 捷克注册公司网站搜索引擎广告推广
  • 网站的实用性青岛九二网络科技有限公司
  • 广东备案网站网站反链如何做
  • 做网站的实施过程企业建设H5响应式网站的5大好处6
  • ps制作个人网站首页景安搭建wordpress
  • 常德建设网站制作网站建设推广是什么工作
  • 长春服务好的网站建设百度推广话术全流程
  • 做的网站浏览的越多越挣钱基于jsp的网站开发开题报告
  • 好的做问卷调查的网站好网站调用时间
  • 广州微网站建设平台阿里云国外服务器
  • 如何把做好的网站代码变成网页wordpress shortcode土豆 视频
  • 网站改版竞品分析怎么做中山网站建设文化价格
  • 玉林市网站开发公司电话做网站空间 阿里云
  • 南充做网站略奥网络免费的正能量视频素材网站
  • 电子商务网站开发的基本原则汕头网站制作流程
  • 网站访问量突然增加合肥宣传片制作公司六维时空
  • 建设购物网站流程图怎么找网站
  • 阿里云部署多个网站制作小程序网站源码
  • 博罗东莞网站建设网站免费源代码