首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【消息序列】详解(1):SERVICES WITHOUT CONNECTION REQUEST应用剖析

【消息序列】详解(1):SERVICES WITHOUT CONNECTION REQUEST应用剖析

作者头像
用户12001910
发布2026-01-20 20:46:08
发布2026-01-20 20:46:08
70
举报

在蓝牙通信中,通常情况下,设备之间的交互往往需要通过建立连接来实现,例如ACL连接。然而,“无连接请求的服务(SERVICES WITHOUT CONNECTION REQUEST )” 提供了一种不同的交互方式,它允许设备在不建立完整的、传统意义上的连接的情况下,获取特定的信息或执行某些功能。

一、远程名称请求(Remote Name Request)

远程名称请求服务用于在不需要建立ACL(Asynchronous Connection-Less,异步连接)连接的情况下,查找远程设备的名称。

这种服务模式的优势在于:

  • 资源节约:无需建立完整的连接,减少了资源消耗和连接建立的时间。
  • 高效性:能够快速获取所需信息,提高设备发现、识别和管理的效率。
  • 灵活性:适用于多种应用场景,如设备发现、管理、社交互动、智能家居、安全验证等。

1.1. 步骤1:配置事件掩码与远程名称请求

主机发送一个 “主机控制器接口设置事件掩码”(HCI_Set_Event_Mask)命令,将 “远程主机支持特性通知事件”(Remote Host Supported Features Notification event)对应的位(第 60 位)置位,同时发送一个 “主机控制器接口远程名称请求”(HCI_Remote_Name_Request)命令,期望其本地设备会自动尝试连接到远程设备。【0x0001】HCI_Set_Event_Mask详解-CSDN博客

在这个步骤中,主机通过配置事件掩码(HCI_Set_Event_Mask)来告诉蓝牙控制器它感兴趣的事件类型,这里特别关注的是远程主机支持的功能通知事件(通常是为了确保蓝牙控制器能够报告关于远程设备能力的信息)。接着,主机发送远程名称请求命令(HCI_Remote_Name_Request),这个命令的目的是获取远程设备的名称,而且这个过程不需要先建立ACL连接。因为蓝牙规范允许在没有完整连接建立的情况下,通过一种称为“page扫描”的机制来查询远程设备的名称。【0x0019】HCI_Remote_Name_Request详解-CSDN博客

需要注意的是,虽然这个服务允许在不建立完整ACL连接的情况下获取远程设备名称,但在实际应用中,如果远程设备设置了隐私模式或者其他安全措施,可能会导致无法成功获取名称。此外,即使成功获取了名称,也不意味着可以立即与远程设备进行数据交换,因为还需要建立ACL连接来进行数据传输。

1.2. 步骤2:无ACL连接与存在ACL连接的2种情况下设备名称的获取

当设备A与设备B之间不存在ACL连接时,设备A通过寻呼等过程获取设备B的名称;而当ACL连接已经存在时,设备A则直接利用该连接来获取设备B的名称。

1.2.1. 步骤2a:设备间不存在ACL连接

如果设备A与设备B之间不存在ACL连接,设备A会对设备B进行寻呼(Paging)。在完成基带寻呼程序后,本地设备(设备A)会尝试获取远程设备(设备B)的扩展功能,发送一个HCI_Remote_Host_Supported_Features_Notification事件,获取远程设备的名称,然后断开连接,并将远程设备的名称返回给主机。

在这个步骤中,详细过程如下:

  • 寻呼过程:设备A通过蓝牙基带层发送寻呼信号给设备B。用于在设备之间建立初步的通信链接。
  • 获取远程设备扩展功能:一旦设备B响应了寻呼信号,设备A会尝试获取设备B的扩展功能信息。通常包括设备B支持的蓝牙特性、服务等。
  • 发送支持功能通知事件:设备A的蓝牙控制器会向主机发送一个HCI_Remote_Host_Supported_Features_Notification事件,通知主机设备B的扩展功能信息。【0x3D】HCI_Remote_Host_Supported_Features_Notification事件详解-CSDN博客
  • 获取远程名称:在获取了设备B的扩展功能信息后,设备A会尝试获取设备B的名称。通常是通过发送HCI_Remote_Name_Request命令来完成的。
  • 断开连接:一旦设备A成功获取了设备B的名称,它会断开与设备B之间的临时链接。这个断开过程是为了节省资源,因为设备A只是需要设备B的名称,而不是与它进行持续的数据通信。
  • 返回远程设备名称:最后,设备A的蓝牙控制器会将设备B的名称返回给主机。这样,主机就能够在不建立完整ACL连接的情况下,获取到远程设备的名称。

需要注意的是,这个过程可能受到多种因素的影响,包括远程设备的隐私设置、蓝牙版本和特性支持等。因此,在实际应用中,可能需要考虑这些因素来确保过程的顺利进行。

1.2.2. 步骤2b:ACL连接已存在

如果在发出请求时已经存在ACL连接,那么远程名称请求过程将作为一个可选服务来执行。此时,不会进行寻呼操作,也不会断开ACL连接。

在这个步骤中,详细过程如下:

  • ACL连接存在:当主机发出远程名称请求时,如果本地设备与远程设备之间已经存在一个ACL连接,那么这个过程就会利用这个现有的连接来执行。
  • 执行远程名称请求:由于ACL连接已经存在,本地设备可以直接通过这个连接来发送远程名称请求的命令给远程设备。这个过程不需要进行寻呼操作,因为寻呼通常用于在没有现有连接的情况下建立初步的通信。
  • 获取远程名称:远程设备在接收到请求后,会将其名称通过ACL连接发送回本地设备。
  • 无需断开ACL连接:由于整个远程名称请求过程是在现有的ACL连接上进行的,因此在完成请求后,不需要断开这个连接。这个连接可以继续用于其他的数据通信任务。
  • 返回远程设备名称:最后,本地设备的蓝牙控制器会将获取到的远程设备名称返回给主机。这样,主机就能够在不干扰现有ACL连接的情况下,获取到远程设备的名称。

需要注意的是,虽然在这种情况下不需要进行寻呼和断开ACL连接,但仍然需要确保远程设备支持并愿意提供其名称信息。此外,如果远程设备设置了隐私模式或其他安全措施,可能会限制名称的获取。因此,在实际应用中,可能需要考虑这些因素来确保过程的顺利进行。

1.3. 示例代码

远程名称请求流程的实现细节涉及到与蓝牙硬件的交互,通常需要使用特定的蓝牙协议栈(如BlueZ、BLuedroid等)或硬件供应商提供的SDK。此外,蓝牙通信的许多方面(如事件处理、回调机制等)通常通过异步方式处理。

下面给一个简化的概念性示例,帮助理解流程。请注意,这个示例不会直接编译或运行,因为它省略了实际的蓝牙协议栈调用和错误处理,而且假设已经有了处理蓝牙事件的机制。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
 
// 假设这些函数是由蓝牙协议栈提供的,用于处理事件和发送命令
extern void register_event_callback(void (*callback)(uint16_t event, void *data));
extern int send_hci_command(uint16_t opcode, void *data, int len);
extern int get_remote_name(bdaddr_t *bdaddr, char *name, int len);
 
// 事件回调函数
void handle_event(uint16_t event, void *data) {
    // 根据事件类型处理事件
    // ...
    // 例如,处理远程主机支持特性通知事件
    if (event == EVT_REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION) {
        // 解析数据并处理
        // ...
    }
    // 或者处理其他事件
    // ...
}
 
// 远程名称请求函数
int remote_name_request(bdaddr_t *bdaddr) {
    char name[249]; // 蓝牙名称的最大长度是248个字符加上一个空终止符
 
    // 检查是否存在ACL连接(在实际应用中,这可能需要查询蓝牙协议栈的状态)
    // 这里我们假设不存在ACL连接,因此执行步骤2a
    int acl_connected = 0; // 0表示未连接,1表示已连接
 
    if (!acl_connected) {
        // 执行寻呼、获取扩展功能、获取名称、断开连接等步骤
        // 这些步骤在实际中通常是通过异步事件和回调来处理的
        // 这里我们简化为一个假设的函数调用
        printf("Paging remote device...\n");
        // 寻呼过程(在实际中,这是由蓝牙协议栈处理的)
        // ...
 
        // 假设我们已经成功获取了名称(在实际中,通常是通过事件回调来完成的)
        // 这里我们直接调用一个假设的函数来获取名称
        int result = get_remote_name(bdaddr, name, sizeof(name));
        if (result == 0) {
            printf("Remote device name: %s\n", name);
            return 0; // 成功
        } else {
            printf("Failed to get remote device name\n");
            return -1; // 失败
        }
    } else {
        // 如果ACL连接已存在,则直接获取名称
        printf("ACL connection exists, getting remote device name...\n");
        int result = get_remote_name(bdaddr, name, sizeof(name));
        if (result == 0) {
            printf("Remote device name: %s\n", name);
            return 0; // 成功
        } else {
            printf("Failed to get remote device name\n");
            return -1; // 失败
        }
    }
}
 
int main() {
    bdaddr_t bdaddr;
    str2ba("XX:XX:XX:XX:XX:XX", &bdaddr); // 将蓝牙地址替换为实际的远程设备地址
 
    // 注册事件回调函数
    register_event_callback(handle_event);
 
    // 发送远程名称请求
    int result = remote_name_request(&bdaddr);
    if (result == 0) {
        printf("Remote name request succeeded\n");
    } else {
        printf("Remote name request failed\n");
    }
 
    return 0;
}

重要说明

  • 这个示例代码是高度简化的,并且省略了许多实际的实现细节。
  • register_event_callbacksend_hci_commandget_remote_name 函数是假设存在的,需要使用实际使用的蓝牙协议栈或SDK提供的实际函数来替换。
  • 异步事件处理通常是通过回调函数来完成的,这些回调函数会在特定事件发生时被蓝牙协议栈调用。
  • 在实际的应用程序中,需要处理各种错误情况,例如设备不可达、超时、连接失败等。
  • 需要确保开发环境已经配置了适当的蓝牙开发库和头文件。

为了编写一个完整的、可运行的程序,需要查阅所使用的蓝牙协议栈或SDK的文档,并了解如何正确地与蓝牙硬件进行交互。

1.4. 应用场景

获取远程蓝牙设备的名称这一特性在多个应用场景中发挥着重要作用。以下是一些具体的应用场景。

1.4.1. 蓝牙设备发现与识别

场景描述:在蓝牙设备的初始扫描阶段,如智能手机蓝牙设置中搜索附近设备时,用户希望快速查看并识别周围有哪些蓝牙设备可用。通过远程名称请求服务,手机可以快速获取并展示附近蓝牙设备的名称,如耳机、智能手环、蓝牙音箱等,方便用户选择想要连接的设备。

优势

  • 提高设备发现的效率,无需建立完整连接即可获取设备名称。
  • 方便用户快速定位并识别自己想要连接的设备。
1.4.2. 设备管理与监控

场景描述:在企业或机构的物联网环境中,存在大量蓝牙传感器设备,如温度传感器、湿度传感器、人员定位标签等。系统管理员需要定期检查这些设备的工作状态和身份信息。通过远程名称请求服务,可以在不建立数据传输连接的情况下,快速获取设备名称,进行设备清单核对和状态监控。

优势

  • 高效地对大量设备进行初步检查和管理,减少不必要的连接操作。
  • 快速识别设备,便于后续的配置、维修或更换。
1.4.3. 安全与访问控制

场景描述:在对安全要求较高的蓝牙应用场景中,如金融机构的蓝牙支付终端或企业的安全门禁系统,系统需要在允许设备进行深入连接之前进行身份验证。通过远程名称请求服务,系统可以获取设备名称,并与预先授权的设备名单进行比对,只有名称匹配的设备才会被允许进行后续的连接和操作。

优势

  • 提供初步的安全筛选层,快速判断设备是否合法。
  • 提高安全系统的效率和安全性,防止未经授权的设备进行非法连接。
1.4.4. 蓝牙广播应用

场景描述:在蓝牙广播应用场景中,如商场的室内定位系统或基于蓝牙的广告推送系统,广播设备需要获取周围接收设备的名称,以便根据设备类型或用户自定义名称进行有针对性的信息推送。

优势

  • 实现更精准的信息推送,提高广播应用的效果。
  • 根据接收设备的名称,了解目标用户或设备的特征,提供更符合需求的信息。
1.4.5. 社交与互动应用

场景描述:在社交或互动应用中,用户希望查找并连接附近的蓝牙设备以进行数据传输、游戏互动或共享资源。通过远程名称请求服务,用户可以快速识别并连接目标设备,提高应用的互动性和便捷性。

优势

  • 简化设备查找和连接过程,提高用户体验。
  • 促进用户之间的互动和资源共享。
1.4.6. 智能家居与物联网

场景描述:在智能家居或物联网环境中,设备之间需要相互识别以进行协同工作。通过远程名称请求服务,设备可以快速获取其他设备的名称,建立正确的通信关系和协作机制。

优势

  • 促进设备间的协同工作,提高系统的整体性能。
  • 简化设备配置和连接过程,降低用户操作难度。
1.4.7. 蓝牙设备调试与测试

场景描述:在蓝牙设备的调试和测试过程中,工程师需要频繁地查找和识别设备名称。通过远程名称请求服务,工程师可以简化这一过程,提高调试和测试的效率。

优势

  • 简化设备查找和识别过程,提高调试和测试效率。
  • 降低调试和测试成本,加速产品开发周期。

远程名称请求服务在蓝牙技术的多个应用领域中都发挥着重要作用,随着蓝牙技术的不断发展和普及,其应用场景还将不断拓展和深化。

二、 一次性查询(One-time Inquiry)

一次性查询(One-time Inquiry)是用于检测和收集附近蓝牙设备的一种机制。在蓝牙通信中,当一个设备(通常称为主机或查询设备)想要发现其通信范围内的其他蓝牙设备时,它会执行一次性查询操作。这个过程不涉及建立完整的连接,而是简单地扫描并收集附近设备的地址和名称等信息。

2.1. 步骤 1:主机发送 HCI_Inquiry 命令

在这一步中,主机(即执行查询的设备)通过其蓝牙控制器接口(HCI)发送一个 HCI_Inquiry 命令。这个命令包含了查询的一些参数,如查询的持续时间、需要返回的响应数量(即最大设备数)、以及是否请求远程设备的名称等。

  • HCI_Inquiry 命令参数
    • 持续时间:指定查询应该持续多长时间。这个时间通常是以 1.25 秒的倍数来表示的。
    • 最大设备数:指定在查询期间应该返回的最大设备数量。一旦达到这个数量,查询就会提前结束。
    • 请求名称:指定是否应该请求远程设备的名称。如果设置为是,则蓝牙控制器会在查询到设备后,尝试通过远程名称请求服务(Remote Name Request Service)获取设备的名称。
  • 发送过程
    • 主机通过其蓝牙驱动和 HCI 层向蓝牙控制器发送 HCI_Inquiry 命令。【0x0001】HCI_Inquiry命令详解-CSDN博客
    • 蓝牙控制器接收到命令后,开始执行查询操作,扫描其通信范围内的蓝牙设备。

发送 HCI_Inquiry 是整个设备发现过程的起始动作,类似于我们在一个房间里大声询问 “有谁在呀”,周边能听到这个询问并且愿意回应的设备(在蓝牙语境下就是那些设置为可被发现的蓝牙设备)就会接收到这个命令,并根据自身的配置和状态决定是否以及如何做出回应。

2.2. 步骤 2:控制器启动基带查询过程

蓝牙控制器会根据指定的查询访问码(Inquiry Access Code, IAC)和查询时长(Inquiry Length)来启动基带查询(Baseband Inquiry)过程。这个过程是蓝牙协议栈中基带层(Baseband Layer)的一部分,负责实际扫描和发现附近的蓝牙设备。

  • 查询访问码(IAC):查询访问码是一个特定的码字,用于在查询过程中区分不同的查询请求。
    • 它类似于一种 “识别暗号”。不同类型的蓝牙设备或者不同的应用场景可能会设置特定的查询访问码,只有当周边设备所配置的相应识别码与主机发出的这个查询访问码匹配时,那些设备才会对此次查询做出响应。
    • 例如,在一些特定的蓝牙设备群组(比如某企业内部定制的蓝牙设备用于特定业务场景)中,会设置统一且独特的查询访问码,以此来区分普通的公开可发现设备,确保只有同群组内的设备能相互发现并响应查询,增强设备发现的针对性和安全性。
  • 查询时长(Inquiry Length):决定了这次基带查询程序持续的时间长度。
    • 这个时间通常以时隙(slot)为单位来计量,一个时隙大约是0.625毫秒。查询长度越长,控制器就有更多的时间来扫描和发现附近的设备。
    • 合理设置查询时长很重要,如果时长过短,可能导致还没来得及接收到周边所有可响应设备的反馈,就结束了查询,从而遗漏一些设备;而时长过长又可能会消耗过多的电量和系统资源,影响设备的续航以及整体运行效率。
    • 比如在手机上进行蓝牙设备搜索时,一般会有一个默认的、相对合适的查询时长,既能保证发现周边大部分处于可发现状态的常用蓝牙设备,又不会让手机电量和性能受到较大影响。

当控制器启动基带查询过程后,会开始监听来自附近蓝牙设备的查询响应。这些响应包含了设备的地址、类别以及其他可能的信息(如设备名称的哈希值,如果设备支持的话)。

  • 信息提取与返回:一旦控制器接收到查询响应,就会从中提取出所需的信息,并通过一个或多个HCI_Inquiry_Result事件将这些信息返回给主机。每个HCI_Inquiry_Result事件都包含了一个或多个发现设备的详细信息,如设备的蓝牙地址、设备类型(经典蓝牙设备或低功耗蓝牙设备)、设备类别(如果可用)以及设备名称的哈希值(如果请求了名称并且设备支持的话)。
  • HCI_Inquiry_Result事件:HCI_Inquiry_Result事件是蓝牙HCI层定义的一种事件类型,用于向主机报告查询过程中发现的设备信息。这些事件通常按照发现的顺序被发送回主机,以便主机可以处理这些信息。【0x01】HCI_Inquiry_Complete事件详解-CSDN博客
  • 处理流程:主机接收到HCI_Inquiry_Result事件后,会解析事件中的数据,并根据需要将这些信息存储在设备列表中、显示给用户、或者用于后续的连接操作。

蓝牙控制器根据指定的查询访问码和查询长度来启动基带查询过程,并监听来自附近设备的查询响应。一旦接收到响应,控制器就会提取出所需的信息,并通过HCI_Inquiry_Result事件将这些信息返回给主机进行处理。

2.3. 步骤3:查询过程的取消与完成

在某些情况下,主机可能希望提前终止查询过程,这时可以使用HCI_Inquiry_Cancel命令。该命令会立即停止蓝牙控制器的查询程序,避免不必要的资源占用和后续操作的干扰。另一方面,当查询过程因为获取到的设备信息数量满足要求或查询时长到期而完成时,蓝牙系统会返回一个HCI_Inquiry_Complete事件给主机。主机接收到这个事件后,就知道查询操作已经结束,并可以根据此事件来决定后续的操作,如筛选设备信息、发起配对连接等。这些机制确保了蓝牙查询过程的高效性和灵活性。

2.3.1. HCI_Inquiry_Cancel

在某些情况下,主机可能由于各种原因(比如已经找到了想要连接的设备、不再需要继续搜索其他设备、系统资源紧张等)希望提前终止这个查询过程,可以使用 HCI_Inquiry_Cancel 命令。

当主机向蓝牙控制器发送这个命令后,蓝牙控制器会接收到指令并立即停止正在进行的查询程序,停止向周围发送查询请求以及处理查询响应等相关操作,使得整个查询过程能够快速、干净地结束,避免不必要的资源占用和对后续操作可能产生的干扰。并可能通过HCI层返回一个命令完成事件,以确认查询已被取消。【0x0002】HCI_Inquiry_Cancel命令详解-CSDN博客

2.3.3. HCI_Inquiry_Complete事件

当查询过程因为以下两个原因之一而完成时:

  • 结果数量满足要求:在蓝牙查询过程中,主机会向周围发送查询请求以获取其他蓝牙设备的信息。这个过程可能会预先设定一个期望获取的结果数量。当获取到的设备信息数量达到这个预设值时,查询就会结束。例如,主机可能只需要找到周围的 3 个可连接的蓝牙设备信息,一旦找到 3 个符合条件的设备(比如设备支持特定的蓝牙服务、设备类型符合要求等),查询操作就会终止。
  • 查询时长到期:除了结果数量的限制,还会有时间上的限制,即 “Inquiry Length”。这是一个预先设定的查询时间长度,一旦查询操作开始后的持续时间达到这个设定值,查询也会结束。例如,设定的查询时长为 10 秒,从主机开始发送查询请求起,10 秒后无论是否获取到足够的设备信息,查询都会终止。这种时间限制有助于避免查询过程过长而浪费资源或者影响其他操作。

当满足上述两种结束条件中的任意一种时,蓝牙系统会返回一个 “HCI_Inquiry_Complete” 事件给主机。【0x01】HCI_Inquiry_Complete事件详解-CSDN博客

主机接收到这个事件后,就知道查询操作已经结束。它可以根据这个事件来决定后续的操作,比如开始对获取到的设备信息进行筛选、发起配对连接等操作。

2.4. 示例代码

下面的代码示例是一个高度简化的版本,旨在展示基本流程而非实际可用的代码。请注意,下面的代码示例并非实际可运行的代码,而是用于说明如何组织这样的查询过程。实际实现将依赖于特定的蓝牙库和硬件平台。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

// 假设这是蓝牙库提供的函数原型(这些函数在实际中是不存在的,仅用于说明)
void hci_send_inquiry_command(uint8_t duration, uint8_t max_devices, bool request_names);
void hci_cancel_inquiry_command(void);
void hci_event_callback(void *callback_data, uint8_t event_code, uint8_t *event_data, uint16_t data_length);

// 假设的回调函数数据结构体
typedef struct {
    bool inquiry_complete;
    // 其他可能需要的数据
} CallbackData;

// 回调函数,用于处理来自HCI层的事件
void handle_hci_event(void *callback_data, uint8_t event_code, uint8_t *event_data, uint16_t data_length) {
    CallbackData *cb_data = (CallbackData *)callback_data;

    switch (event_code) {
        case HCI_INQUIRY_RESULT_EVENT: // 假设这是HCI_Inquiry_Result事件的代码
            // 处理查询结果事件,解析event_data
            // ...
            break;

        case HCI_INQUIRY_COMPLETE_EVENT: // 假设这是HCI_Inquiry_Complete事件的代码
            cb_data->inquiry_complete = true;
            // 查询完成,可以在这里执行后续操作
            printf("Inquiry complete.\n");
            break;

        // 其他事件处理...

        default:
            // 未知事件
            break;
    }
}

int main() {
    CallbackData cb_data = {false};

    // 注册回调函数(在实际实现中,通常是通过某种形式的注册机制完成的)
    // hci_register_event_callback(handle_hci_event, &cb_data);

    // 发送查询命令
    hci_send_inquiry_command(8, 10, true); // 例如:查询持续时间为8 * 1.25秒,最大设备数为10,请求名称

    // 在这里,通常会有一个循环来等待事件回调
    // 由于这是一个简化的示例,我们将使用一个简单的忙等待循环
    while (!cb_data.inquiry_complete) {
        // 在实际实现中,这里应该有一个事件循环或者等待机制
        // 例如:使用select()、poll()、epoll()等,或者库提供的事件等待函数

        // 在这里什么也不做,只是模拟等待回调
    }

    // 查询完成后的后续操作
    // ...

    return 0;
}

// 假设的蓝牙库函数实现(在实际中,这些函数是由蓝牙协议栈或芯片制造商提供的)
// 这里只是占位符,不会实际执行任何操作
void hci_send_inquiry_command(uint8_t duration, uint8_t max_devices, bool request_names) {
    // 发送HCI查询命令的实现
    // ...
}

void hci_cancel_inquiry_command(void) {
    // 取消HCI查询命令的实现
    // ...
}

void hci_event_callback(void *callback_data, uint8_t event_code, uint8_t *event_data, uint16_t data_length) {
    // 实际上,这个函数应该由蓝牙库调用,而不是在这里调用
    // 它只是用来模拟回调机制
    handle_hci_event(callback_data, event_code, event_data, data_length);
}

  • 使用特定的蓝牙库或协议栈API来替代示例中的hci_send_inquiry_commandhci_cancel_inquiry_commandhci_event_callback函数。
  • 实现一个事件循环或等待机制来等待HCI事件的回调,而不是使用简单的忙等待循环。
  • 解析HCI事件数据,并根据事件类型执行相应的操作。
  • 处理错误情况和异常情况,例如查询失败、设备响应超时等。

此外,由于蓝牙协议栈的复杂性和不同平台之间的差异,实际代码可能会更加复杂,并且需要深入了解蓝牙规范和特定平台的API文档。

2.5. 使用场景

HCI_Inquiry是蓝牙技术中的一个重要环节,主要用于发现和搜集附近的蓝牙设备。以下是HCI_Inquiry的主要使用场景。

2.5.1. 蓝牙设备初次配对

场景描述:当用户需要将新的蓝牙设备(如耳机、音箱等)与手机或其他蓝牙设备进行配对时,会启动蓝牙设备搜索过程。这一过程依赖于HCI_Inquiry命令,它允许设备主动发送查询请求,以发现和识别附近的蓝牙设备。

优势

  • 快速发现附近的可配对蓝牙设备,避免手动输入设备地址等繁琐操作。
  • 短时间扫描周边设备,不长时间占用系统资源,使配对过程更加高效。
2.5.2. 物联网设备部署与连接

场景描述:在物联网环境中,如智能家居系统部署时,智能网关需要连接多个蓝牙传感器设备。通过发送HCI_Inquiry命令,智能网关可以快速找到并连接这些传感器设备,如温度传感器、门窗传感器等。

优势

  • 快速确定范围内所有可连接的物联网蓝牙设备,方便大规模部署。
  • 灵活设置查询参数,适应不同规模的设备部署场景。
2.5.3. 蓝牙设备维护与管理

场景描述:在企业或机构中管理大量蓝牙设备时,需要定期检查设备的连接状态和可用性。通过发送HCI_Inquiry命令,管理员可以快速检查设备的存在性和基本状态,如蓝牙打印机、蓝牙扫描枪等。

优势

  • 非侵入式检查方式,不干扰设备正常工作。
  • 及时发现设备失联等问题,采取相应维护措施。
2.5.4. 蓝牙设备应用开发与测试

场景描述:蓝牙设备软件开发人员在开发和测试过程中,需要频繁查找和连接不同的蓝牙设备来验证软件功能。通过发送HCI_Inquiry命令,开发人员可以快速找到并连接测试设备,如运动手环等。

优势

  • 提供便捷方式查找测试设备,加快开发和测试进度。
  • 灵活调整查询参数,快速定位需要测试的设备。
2.5.5.安全性与隐私保护

场景描述:在某些情况下,HCI_Inquiry还可以用于设备认证过程,通过比较搜索到的设备信息与已知的、受信任的设备信息库中的条目,验证设备的身份和合法性。同时,用户也需要注意隐私保护问题,可以在不需要时关闭蓝牙设备的可发现性模式或限制搜索范围。

优势

  • 设备认证过程增加安全性。
  • 用户可控制设备可发现性,保护隐私。

HCI_Inquiry在蓝牙技术中具有广泛的应用场景,涵盖了设备配对与连接、物联网设备部署与连接、蓝牙设备维护与管理、蓝牙设备应用开发与测试以及安全性与隐私保护等多个方面。通过合理使用HCI_Inquiry命令,用户可以更高效地管理蓝牙设备,提升使用体验。

三、 周期性查询(Periodic inquiry

“Periodic inquiry” 是在蓝牙通信场景中,当需要周期性地重复执行查询(inquiry)程序时所采用的一种机制。通过这种方式,主机能够按照一定的时间间隔不断地去搜索周围可连接的蓝牙设备,以获取最新的设备信息或者查找新出现的可连接设备等,适用于一些需要持续监控周边蓝牙设备状态变化的应用场景,比如在某些蓝牙设备管理系统、动态发现新设备的应用中会用到。

3.1. 步骤1:启动周期性查询模式(发送 HCI_Periodic_Inquiry_Mode 命令)

当主机希望蓝牙设备以周期性的方式执行查询操作时,它会向蓝牙控制器发送一个HCI_Periodic_Inquiry_Mode命令。这个命令的目的是告诉蓝牙控制器启动周期性查询模式,并按照预设的参数(如查询间隔、查询窗口大小、需要查找的设备类型等)来执行查询。

周期性查询模式在需要持续监控蓝牙设备环境的应用场景中非常有用,比如蓝牙音箱、蓝牙耳机等需要随时准备与其他蓝牙设备建立连接的设备。通过周期性查询,这些设备可以及时发现并响应其他设备的连接请求,从而提供更好的用户体验。

需要注意的是,周期性查询会消耗一定的系统资源,因此在实际应用中需要根据具体需求来合理设置查询参数,以平衡资源消耗和查询效率之间的关系。

3.2. 步骤2:控制器开始周期性查询并返回HCI_Inquiry_Result事件

一旦蓝牙控制器接收到HCI_Periodic_Inquiry_Mode命令并确认无误,就会开始按照指定的参数执行周期性查询。在查询周期内,控制器会不断向周围发送查询请求,并处理接收到的查询响应。每当发现新的蓝牙设备或更新现有设备的信息时,控制器都会向主机返回一个或多个HCI_Inquiry_Result事件。这些事件包含了发现设备的详细信息,如设备地址、设备名称、设备类型等。

3.3. 步骤3:查询周期结束时返回HCI_Inquiry_Complete事件

当当前周期性查询周期结束时,无论是否发现了新的设备,蓝牙控制器都会向主机返回一个HCI_Inquiry_Complete事件。这个事件标志着当前查询周期的结束,并允许主机根据查询结果进行后续操作,如选择设备进行连接等。

3.4. 步骤4:停止周期性查询(HCI_Exit_Periodic_Inquiry_Mode命令)

如果主机希望停止周期性查询,可以发送HCI_Exit_Periodic_Inquiry_Mode命令给蓝牙控制器。一旦接收到此命令,控制器将停止当前的周期性查询模式,并准备接收其他命令。

3.5. 示例代码

以下是一个简化代码示例,用于展示如何实现蓝牙周期性查询。请注意,这只是一个示例,并非完整的蓝牙应用程序代码。在实际应用中,需要与蓝牙协议栈(如BlueZ、bluedroid等)进行交互,并且需要处理更多的错误检查和状态管理。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// 假设这些是蓝牙HCI命令和事件的伪定义,实际使用时需要替换为实际的蓝牙栈API
#define HCI_PERIODIC_INQUIRY_MODE 0x0043
#define HCI_EXIT_PERIODIC_INQUIRY_MODE 0x0044
#define HCI_INQUIRY_RESULT 0x02
#define HCI_INQUIRY_COMPLETE 0x01

// 假设的蓝牙设备地址结构
typedef struct {
    uint8_t bd_addr[6];
} bd_addr_t;

// 假设的HCI命令结构
typedef struct {
    uint16_t opcode;
    uint8_t  param_len;
    // 周期性查询参数(示例中未详细列出)
    // ...
} hci_command_t;

// 假设的HCI事件结构
typedef struct {
    uint8_t  evt;
    uint8_t  plen;
    // 事件数据(示例中未详细列出)
    // ...
} hci_event_t;

// 发送HCI命令的伪函数(实际使用时需要替换为与蓝牙协议栈交互的函数)
void send_hci_command(const hci_command_t *command) {
    // 发送HCI命令到蓝牙控制器(示例代码省略实现细节)
    printf("Sending HCI command: opcode=0x%04X\n", command->opcode);
}

// 处理HCI事件的伪函数(实际使用时需要替换为处理蓝牙栈事件的函数)
void handle_hci_event(const hci_event_t *event) {
    switch (event->evt) {
        case HCI_INQUIRY_RESULT:
            // 处理查询结果事件(示例代码省略实现细节)
            printf("Received HCI Inquiry Result\n");
            break;
        case HCI_INQUIRY_COMPLETE:
            // 处理查询完成事件(示例代码省略实现细节)
            printf("Received HCI Inquiry Complete\n");
            break;
        // 处理其他事件...
        default:
            printf("Received unknown HCI event: evt=0x%02X\n", event->evt);
            break;
    }
}

// 周期性查询的主函数
void periodic_inquiry(uint16_t interval, uint16_t window, uint8_t length) {
    // 构建HCI周期性查询模式命令
    hci_command_t periodic_inquiry_command = {
        .opcode = HCI_PERIODIC_INQUIRY_MODE,
        .param_len = // 设置参数长度(根据实际需要填写)
        // .param = // 设置查询参数(如interval, window, length等,示例中省略)
    };

    // 发送周期性查询模式命令
    send_hci_command(&periodic_inquiry_command);

    // 模拟周期性查询过程(实际使用时需要等待蓝牙控制器的响应)
    while (1) {
        // 在这里可以添加代码来处理其他任务或检查是否应该停止查询

        // 假设接收到一个HCI事件(在实际应用中,这通常是通过回调函数或事件循环来实现的)
        hci_event_t event;
        // ...(从蓝牙控制器获取事件并填充到event结构中)

        // 处理接收到的HCI事件
        handle_hci_event(&event);

        // 如果接收到查询完成事件且需要停止查询,则跳出循环
        if (event.evt == HCI_INQUIRY_COMPLETE && /* 其他停止条件 */) {
            break;
        }

        // 根据interval和window参数模拟等待时间(实际使用时应该使用定时器)
        sleep(interval / 1000); // 注意:这里假设interval的单位是毫秒,实际使用时需要转换
    }

    // 构建并发送HCI退出周期性查询模式命令
    hci_command_t exit_periodic_inquiry_command = {
        .opcode = HCI_EXIT_PERIODIC_INQUIRY_MODE,
        .param_len = 0 // 通常退出命令没有参数
    };

    // 发送退出周期性查询模式命令
    send_hci_command(&exit_periodic_inquiry_command);
}

int main() {
    // 设置周期性查询的参数(示例值)
    uint16_t interval = 1280; // 查询间隔(单位:1.25ms)
    uint16_t window = 11250;  // 查询窗口大小(单位:1.25ms,通常设置为小于或等于interval的倍数)
    uint8_t  length = 8;      // 查询响应的最大设备数

    // 启动周期性查询
    periodic_inquiry(interval, window, length);

    return 0;
}

注意

  • 上述代码是一个高度简化的示例,仅用于展示周期性查询的基本流程。在实际应用中,需要与具体的蓝牙协议栈进行交互,并使用该栈提供的API来发送HCI命令和处理HCI事件。
  • 示例中的send_hci_commandhandle_hci_event函数是伪函数,需要替换为实际蓝牙协议栈交互的实际函数。
  • 示例中的sleep函数用于模拟等待时间,但在实际应用中,应该使用定时器来更精确地控制查询间隔和窗口大小。
  • 示例中的查询参数(如interval, window, length)是示例值,需要根据实际应用需求进行调整。
  • 蓝牙HCI命令和事件的格式以及参数的具体含义可能因蓝牙栈的不同而有所差异,请参考所使用的蓝牙协议栈的文档以获取详细信息。

3.6. 使用场景

周期性查询(Periodic Inquiry)在多个领域和场景中都有广泛的应用,以下是一些典型的应用和场景。

3.6.1. 蓝牙通信与设备管理
  • 企业设备管理
    • 应用场景:蓝牙打印机、扫描枪、耳机等设备的管理。
    • 功能:通过周期性查询监控设备连接状态和可用性,及时发现并处理设备故障。
    • 优势:提高设备可靠性和稳定性,减少工作中断。
  • 医疗设备监测
    • 应用场景:便携式医疗监测设备(如血糖仪、血压计)的数据传输。
    • 功能:确保设备在监测范围内,及时获取并分析数据,发出异常警报。
    • 优势:提高管理效率,保障患者安全,减少医护人员工作量。
3.6.2. 智能家居与物联网
  • 智能家居设备自动连接
    • 应用场景:智能音箱、灯泡、窗帘等设备的自动连接。
    • 功能:通过周期性查询寻找可连接设备,实现自动连接和互动。
    • 优势:提供便捷智能化体验,提高设备响应速度。
  • 智能家居设备状态更新
    • 应用场景:智能插座、摄像头等设备的状态监控。
    • 功能:定期获取设备状态信息,如电量、开关状态等。
    • 优势:实现实时监控,方便远程控制,及时发现异常情况。
3.6.3. 智能交通与车联网
  • 车辆间通信
    • 应用场景:协同驾驶、避免碰撞等功能的实现。
    • 功能:通过周期性查询建立车辆间的临时通信连接,共享信息。
    • 优势:提高交通安全性,减少交通事故,提高交通效率。
  • 交通设施监测
    • 应用场景:红绿灯、交通标志等交通设施的通信。
    • 功能:车辆通过查询获取实时交通信息,如红绿灯状态、路况等。
    • 优势:提高交通信息准确性和实时性,帮助驾驶员做出明智决策。
3.6.4. 可穿戴设备与健康管理
  • 与手机的连接
    • 应用场景:智能手表、健身手环等设备的连接。
    • 功能:通过周期性查询实现与手机的自动连接和数据同步。
    • 优势:提供便捷使用体验,确保数据及时同步。
  • 运动状态监测
    • 应用场景:心率监测、步频监测等运动数据的获取。
    • 功能:通过周期性查询连接其他运动设备,获取准确运动数据。
    • 优势:提高运动数据准确性和全面性,提供专业运动指导。
3.6.5. 数据库管理与数据分析
  • 数据库管理
    • 应用场景:销售数据、客户信息等数据的定期检索和分析。
    • 功能:通过周期性查询定期从数据库中获取数据,生成报告或分析趋势。
    • 优势:及时了解市场动态,制定和调整销售策略。
  • 数据分析与监控
    • 应用场景:金融交易、物联网传感器数据的监控。
    • 功能:通过周期性查询实时监控数据变化,检测异常或欺诈行为。
    • 优势:及时发现潜在问题,确保系统稳定性和安全性。
3.6.6. 业务决策支持与科学研究
  • 业务决策支持
    • 应用场景:市场数据、客户数据等信息的定期查询和分析。
    • 功能:通过周期性查询获取关键信息,制定和调整业务策略。
    • 优势:基于数据做出明智决策,提高市场竞争力。
  • 科学研究
    • 应用场景:气象数据、实验数据的定期查询和收集。
    • 功能:通过周期性查询获取研究所需数据,推动科学研究进展。
    • 优势:更好地理解自然现象和生物过程,推动科学发现。
3.6.7. 其他应用场景
  • 能源管理:监测能源消耗和分布。
  • 交通管理:监控交通流量和道路状况。
  • 网络安全:检测网络攻击和异常行为。

周期性查询在多个领域和场景中都有广泛的应用和重要的价值。通过定期查询和分析数据,企业、科研机构和个人可以更好地了解市场动态、设备状态、业务趋势等关键信息,从而做出更加明智的决策和行动。

四、无连接服务的未来发展趋势

4.1. 与其他技术的融合

  • 随着物联网技术的不断发展,无连接请求的服务可能会与其他技术融合,提供更加丰富的功能和应用场景。例如,与 Wi-Fi、NFC 等其他无线通信技术结合,实现更加灵活的设备连接和交互。
  • 与人工智能和大数据技术结合,无连接请求的服务可以为智能设备提供更加智能化的服务。例如,通过分析周围设备的信息,智能设备可以自动调整自己的设置和行为,以适应不同的环境和用户需求。

4.2. 安全性的提升

  • 随着对安全问题的关注度不断提高,未来无连接请求的服务可能会采用更加先进的安全技术,如基于硬件的安全模块、量子加密等,以确保信息的安全性和隐私性。
  • 同时,标准化组织和行业协会也可能会制定更加严格的安全规范和标准,以规范无连接请求的服务的使用和发展。

4.3. 性能的优化

  • 随着蓝牙技术的不断进步,无连接请求的服务的性能也将不断优化。例如,提高查询速度、降低功耗、增加可发现设备的数量等。这将使得无连接请求的服务在更多的应用场景中得到广泛应用。
  • 优化无连接请求的服务的性能还可以通过改进蓝牙协议栈的实现、提高硬件性能等方式来实现。例如,采用更高效的算法和数据结构、使用低功耗的蓝牙芯片等。

五、总结

综上所述,“SERVICES WITHOUT CONNECTION REQUEST” 即无连接请求的服务在蓝牙通信中具有重要的作用和广泛的应用前景。通过这种服务模式,可以在不建立完整连接的情况下,实现设备之间的信息获取和交互,提高系统的效率、灵活性和安全性。随着技术的不断发展,无连接请求的服务将不断完善和创新,为蓝牙通信和物联网应用带来更多的价值。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、远程名称请求(Remote Name Request)
    • 1.1. 步骤1:配置事件掩码与远程名称请求
    • 1.2. 步骤2:无ACL连接与存在ACL连接的2种情况下设备名称的获取
      • 1.2.1. 步骤2a:设备间不存在ACL连接
      • 1.2.2. 步骤2b:ACL连接已存在
    • 1.3. 示例代码
    • 1.4. 应用场景
      • 1.4.1. 蓝牙设备发现与识别
      • 1.4.2. 设备管理与监控
      • 1.4.3. 安全与访问控制
      • 1.4.4. 蓝牙广播应用
      • 1.4.5. 社交与互动应用
      • 1.4.6. 智能家居与物联网
      • 1.4.7. 蓝牙设备调试与测试
  • 二、 一次性查询(One-time Inquiry)
    • 2.1. 步骤 1:主机发送 HCI_Inquiry 命令
    • 2.2. 步骤 2:控制器启动基带查询过程
    • 2.3. 步骤3:查询过程的取消与完成
      • 2.3.1. HCI_Inquiry_Cancel
      • 2.3.3. HCI_Inquiry_Complete事件
    • 2.4. 示例代码
    • 2.5. 使用场景
      • 2.5.1. 蓝牙设备初次配对
      • 2.5.2. 物联网设备部署与连接
      • 2.5.3. 蓝牙设备维护与管理
      • 2.5.4. 蓝牙设备应用开发与测试
      • 2.5.5.安全性与隐私保护
  • 三、 周期性查询(Periodic inquiry)
    • 3.1. 步骤1:启动周期性查询模式(发送 HCI_Periodic_Inquiry_Mode 命令)
    • 3.2. 步骤2:控制器开始周期性查询并返回HCI_Inquiry_Result事件
    • 3.3. 步骤3:查询周期结束时返回HCI_Inquiry_Complete事件
    • 3.4. 步骤4:停止周期性查询(HCI_Exit_Periodic_Inquiry_Mode命令)
    • 3.5. 示例代码
    • 3.6. 使用场景
      • 3.6.1. 蓝牙通信与设备管理
      • 3.6.2. 智能家居与物联网
      • 3.6.3. 智能交通与车联网
      • 3.6.4. 可穿戴设备与健康管理
      • 3.6.5. 数据库管理与数据分析
      • 3.6.6. 业务决策支持与科学研究
      • 3.6.7. 其他应用场景
  • 四、无连接服务的未来发展趋势
    • 4.1. 与其他技术的融合
    • 4.2. 安全性的提升
    • 4.3. 性能的优化
  • 五、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档