蓝牙BLE基础知识

低功耗蓝牙是一项强大的技术,但并非总是最容易有效地理解和使用。它不像传统的蓝牙那样具有预定义的一组官方配置文件供您选择;尽管蓝牙SIG指定了预定义(也称为“已采用”) 配置文件,但这些只是冰山一角,是您可以通过BLE实现的功能的一小部分。

在许多(或什至大多数)情况下,最好的选择是为您的应用程序创建自己的自定义配置文件。这为您提供了最大的灵活性,甚至不花任何钱。实际上,它比使用采用的概要文件之一甚至更容易,因为您可以准确定义所有东西如何协同工作,而不是使应用程序符合已定义的内容。另外,由于在BLE世界中没有像传统蓝牙中的SPP那样的官方通用“串行端口配置文件”,因此有时自定义实现是满足您需要的唯一选择。

为了有效地做到这一点,重要的是要了解BLE连接的工作方式,所涉及设备扮演的角色以及如何将数据从空中准确地从一个设备传输到另一个设备。使用了许多术语,它们通常是不可互换的: 主, 从, 中央, 外围设备, 客户端, 服务器, 广告, 扫描, 读取, 写入,通知和指示均表示不同的意思。了解它们之间的区别将使描述和构建BLE应用程序变得更加容易。

快速概述

本文介绍的内容如下:

主 (或“ 中央 ”)设备扫描其他设备。通常,主机是智能手机/平板电脑/ PC。

从设备 (或“ 外围设备 ”)通告并等待连接。通常,从站是EFR32设备的BGMxxx模块。

客户端 设备使用GATT协议通过BLE链接访问远程资源。通常,主人也是客户。

服务器 设备具有本地数据库和访问控制方法,并向远程客户端提供资源。通常,从服务器也是服务器。

您可以使用 读取, 写入, 通知或 指示 操作来在客户端和服务器之间移动数据。

读取 和 写入 操作是由客户端请求和服务器响应(或确认)。

通知 并 指示 操作由客户端启用但由服务器启动,从而提供了一种 将数据推送到客户端的方法。

通知 是 联合国承认的,同时 迹象 得到确认。因此,通知速度更快,但可靠性较低。

主站与从站-连接角色

BLE连接中的一个重要概念是主 设备和 从 设备之间的区别 。这些术语分别表示什么?首先,意识到它们 不能 与客户端/服务器互换,下面将对此进行说明。实际上,在BLE世界中,主/从差异非常容易定义和识别:

主/中央 -BLE设备,向广告外围设备发起传出连接请求

从站/外围设备 -BLE设备,在发布广告后接受传入的连接请求

这些术语对是上面列表中唯一实际上可以互换的术语。对“主”或“中央”设备的引用描述了相同的事物,而对“从”或“外围”设备的引用也各自描述了同一事物。 Apple为iOS开发提供的 CoreBluetooth API中,使用了“中央”和“外围”命名法。在这种情况下,您通常不会看到对主设备或从设备的引用。

BLE规范不限制主机可以连接的从机数量,但始终存在实际限制,尤其是在小型嵌入式模块上。 如果配置正确(默认值为4),我们的2.8.1 BLE堆栈最多可支持 8个同时连接设备。我们的协议栈支持双拓扑和多主设备连接(这是Bluetooth 4.1规范的一部分),这意味着设备可以同时是主设备和从设备,并且还可以连接到多个主设备(从设备)。无论角色如何,连接限制都适用于连接总数。

连接角色(无论设备是主设备还是从设备)是在建立连接时定义的。我们的堆栈能够充当主设备或从设备。如果设备作为从设备运行,则需要进行广告发布(通过gecko_cmd_le_gap_start_advertising 命令在我们的BLE堆栈中完成 );如果它作为主机运行,则可以选择扫描设备(通过gecko_cmd_le_gap_start_discovery在我们的堆栈中完成),并发起到另一个设备的连接请求(通过gecko_cmd_le_gap_connect在我们的堆栈中完成)。

客户端与服务器-GATT功能

BLE设计中的另一个重要概念是GATT服务器 和 GATT客户端之间的区别 (其中GATT表示通用ATTribute配置文件)。这些角色不是相互排斥的,尽管通常您的设备只能是其中一个。您的设备将担任哪个角色取决于您需要它如何工作。这是每种功能的基本摘要:

GATT客户端 -通过读取,写入,通知或指示操作访问远程GATT服务器上的数据的设备

GATT服务器 -一种在本地存储数据并向远程GATT客户端提供数据访问方法的设备

与先前定义的主/从区别不同,根据应用程序定义连接每一侧的数据结构和流的方式,很容易看出一个设备实际上可能同时兼有这两种功能。从设备(外围设备)成为GATT服务器,而主设备(中心)成为GATT客户端是最常见的,但这不是必需的。 设备的GATT功能在逻辑上与主/从角色分开。主/从角色控制如何管理BLE无线电连接,而客户端/服务器角色则由数据的存储和流来决定。

SDK档案库中的大多数示例项目,以及 在线 实现设计为GATT服务器的从(外围)设备。使用我们的Blue Gecko应用程序 (适用于 Android 和 iOS),可以轻松测试这些内容 。但是,也有一些示例实现了连接的主(中央)端,这些示例被设计为GATT客户端。

接收与发送-移动数据

现在,我们已经确定了主设备和从设备以及GATT客户端和GATT服务器之间的区别,我们如何实际定义GATT结构,以及如何使用它将数据从设备A移动到设备B,这是否意味着服务器到客户端还是客户端到服务器?当然,这两个方向都是可能的。

在使用我们的蓝牙SDK构建的BLE项目中,可以使用Simplicity Studio中的内置工具(称为Visual GATT编辑器)来配置GATT结构。这可以在Application Builder的“ 常规”或“ 蓝牙配置器”选项卡 上找到。除了其他配置外,还可以存储GATT结构的配置文件,位于.isc-extension表示的项目文件夹中。在Visual GATT编辑器中按生成后,将生成gatt_db.c / .h和gatt.xml文件。

数据的结构和流总是在GATT服务器上定义的,客户端只需利用服务器公开的内容即可。

关贸总协定的结构

GATT数据库实现一个或多个 配置文件,每个配置文件由一个或多个 服务组成,而每个服务由一个或多个 特征组成。例如,以大纲形式:

资料1

服务A

特征a

特征b

特征c

服务B

特性d

特征e

资料2

服务C

特性f

特性g

特征h

服务D

特色我

特征j

资料3

服务E

特征k

特点l

特征m

服务F

特征n

特点o

您可以根据需要实现任意数量的概要文件,服务和特征。这些可以完全自定义,在这种情况下,它们将使用Visual GATT编辑器生成的您自己的128位UUID 。或者,您可以通过引用Bluetooth SIG的配置文件,服务和特征的在线定义来创建实施已采用规范的项目。(如果这样做,从概要文件级别开始并从那里进行深入研究通常是最有意义的,因为完整的特性列表包括许多与设计毫无关系的内容。)您也可以将两者结合,使用一些采用的配置文件/服务以及您自己的专有配置文件/服务。

每个充当GATT服务器的BLE设备都必须实现官方的 通用访问服务。这包括两个强制性特征:“ 设备名称” 和“ 外观”。这些类似于 经典蓝牙使用的 友好名称 和 设备类别值。这是一个绝对最小GATT定义的示例定义,如Visual GATT编辑器所示:

关贸总协定的定义

仅此一项就足够了,但是 除了告诉GATT客户您自己是谁,您什么都做不到。我们仍然需要探索可以使用的基本数据传输方法。首先,在属性和特征之间进行一些次要说明。

属性和特征

您可能偶尔会听到或看到“属性”和“特征”这两个术语互换使用,虽然这并非完全错误,但并不完全准确,可能会造成混淆。请记住, 服务 是由一个或多个 特征组成的。但是,一个单独的 特征(通常是我们定义GATT结构的最具体的层次)可能包含许多不同的 属性。

每个 属性 都有一个唯一的数字句柄,GATT客户端可以使用该数字句柄来引用,访问和修改它。每个特征都有一个主要属性,该属性允许访问该特征存储在数据库中的实际值。当您阅读有关“向该特征写入值”或“读取该特征的值”时,实际上是对主数据属性执行了读/写操作。

其他一些相关属性是只读的(例如“ 特征用户描述” 属性),一些控制特征的行为(例如 用于启用通知 或 指示 操作的“ 客户端特征配置”属性 )。我们的BLE堆栈和SDK工具根据Visual GATT编辑器中配置的设置根据需要生成这些。

每个属性都有一个UUID。这些可以是16位(例如“ 180a ”)或128位(例如“ e7add780-b042-4876-aae1-112855353cc1 ”)。所有16位UUID由Bluetooth SIG定义,被称为 采用的 UUID。所有128位UUID都是自定义的,未经蓝牙SIG批准,可以用于任何目的。您将看到两个非常常见的16位UUID,分别是 2901(“特性用户描述”属性(在GATT编辑器的“用户描述”字段中定义)和 2902(“客户特性配置”属性)(由我们的SDK在“ 通知 ” 时创建)或“ 表明 ”已启用特性)。

重要说明之一是,某些属性UUID从技术上讲不需要唯一。它们的 句柄 始终是唯一的,但UUID有时会重叠。例如,每个客户端特征配置属性的UUID为 0x2902,即使在单个GATT数据库中可能有十多个。您应该 始终为自己的自定义特征提供完全唯一的UUID,但是如果您正在使用BGTool测试原型,执行描述符发现操作并突然看到相同的UUID的多个实例,请不要惊慌。这很正常。

数据传输方式

在BLE中移动数据有 四个基本操作: 读取, 写入, 通知和 指示。BLE协议规范允许这些操作的最大数据有效载荷大小为 247个字节,在读取操作的情况下为 249个字节。BLE专为低功耗而设计,可用于不经常的短突发数据传输。可以发送大量数据,但是当试图实现最大吞吐量时,通常最终效率不如传统蓝牙。以下是有关您将需要使用哪种数据传输方式的一些一般准则:

如果客户端需要将数据发送到服务器,请使用 write。

如果客户端需要按需从服务器获取数据(即轮询),请使用 read。

如果服务器需要将数据发送到客户端,而不在客户端请求首先它,使用 通知 或 指示。(客户端必须先 订阅 这些更新,然后才能传输任何数据。)

服务器无法直接从客户端提取数据。如果有必要,服务器必须使用 通知 或 指示 将预先安排的请求数据发送给客户端,然后客户端可以进行 写 操作以将服务器需要的任何数据发回。

这里描述了以上四个BLE数据传输操作。必须发送的命令与堆栈生成的事件分开显示。例如,可以通过“文档”选项卡上的Simplicity Studio启动器找到完整的API参考。

GATT客户端在GATT服务器公开的特定属性上请求此操作,然后服务器以请求的值进行响应。在我们的BLE堆栈中,这些API方法通常涉及读取操作:

gecko_cmd_gatt_read_characteristic_value 命令

使用给定的句柄读取远程属性的值。 如果特征值适合一个ATT PDU,则会生成单个gecko_evt_gatt_characteristic_value 事件。否则,将生成多个gecko_evt_gatt_characteristic_value事件,因为固件将自动使用“长读” GATT过程。 这是GATT客户端用来读取单个属性值的最常用方法。

gecko_cmd_gatt_read_characteristic_value_by_uuid 命令

通过提供特征的UUID和包含该特征的服务的句柄,从远程GATT数据库读取服务的特征值。如果特征值适合一个ATT PDU,则会生成gecko_evt_gatt_characteristic_value事件。否则,将生成多个gecko_evt_gatt_characteristic_value事件,因为固件将自动使用“长读” GATT过程。

gecko_cmd_gatt_read_multiple_characteristic_values 命令

该命令可用于一次从远程GATT数据库读取多个特征的值。当值由远程GATT服务器返回时,会生成gecko_evt_gatt_characteristic_value事件。

gecko_evt_gatt_server_user_read_request 事件 当客户端请求从“类型”值设置为“用户”的特征中读取数据时 ,在GATT服务器上

生成 。通常,该操作由堆栈自动处理,并且存储在模块上RAM中的特征值将被发送回客户端。但是具有“用户”特征,这种数据存储和检索完全取决于您。堆栈只是让您知道何时请求它,然后您必须获取它(或生成它),然后以所需的任何格式将其发送回(或不发送回去)。例如,这对于立即读取I / O状态很有用,因此,与其一直在内存中维护值或不进行轮询以使其始终保持“新鲜”状态,不如直接等待请求并读取I / O。当它进入时 即为O状态。(仅在给定特征的GATT编辑器中设置了value type =“ user”时适用 )

gecko_cmd_gatt_server_send_user_read_response 命令

用于当客户机对“用户”特征的请求生成gecko_evt_gatt_server_user_read_request时用于发送回所需的数据。该命令采用结果代码和实际值(如果有)发送回去。(仅 在给定特征的GATT编辑器中设置了value type =“ user”时适用 )

GATT客户端 在GATT服务器公开的特定属性上请求此操作 ,并同时提供要写入的新值。然后,服务器存储新值,并(可选)将写操作确认回客户端。在我们的BLE堆栈中,这些API方法通常涉及写入操作:

gecko_cmd_gatt_write_characteristic_value 命令

将远程属性的值写入GATT服务器。这将执行 确认的 写入操作,因此服务器将在成功写入值后作出响应。如果给定值不适合一个ATT PDU,则将自动使用“长写” GATT程序。这是GATT客户端用来写入单个属性值的最常用方法。

gecko_evt_gatt_procedure_completed 事件

此事件表明当前的GATT过程已成功完成或因错误而失败。除gecko_cmd_gatt_write_characteristic_value_without_response和gecko_cmd_gatt_send_characteristic_confirmation外的所有GATT命令都会触发此事件,因此应用程序必须在发出另一个GATT命令之前排除此事件(上述两个例外除外)。此事件对于根据关键操作是否已经完成来控制程序流很有用。

gecko_cmd_gatt_write_characteristic_value_without_response 命令

将远程属性的值写入GATT服务器。这与上面的命令完全相同,只是 未被确认。完成后将不会有任何回应。像“通知”操作一样,这意味着它更快(可以在单个连接间隔内执行多个未确认的写操作),但是不如确认的写操作可靠。

gecko_cmd_gatt_prepare_characteristic_value_write 命令

可用于将特征值添加到远程GATT服务器的写入队列。如果需要写入很长的属性,或者需要自动写入一组值,则可以使用此命令。至多 245(ATT_MTU - 5)的数据量可以一次发送。准备完成后,将发生gecko_evt_gatt_procedure_completed事件。在所有要传输的数据量都适合BGAPI有效负载的情况下,建议使用命令gecko_cmd_gatt_write_characteristic_value写入长值,因为它透明地执行“ prepare_write”和“ execute_write”命令。

这是排队写入流程的一个示例:

gecko_cmd_gatt_prepare_characteristic_value_write

等待gecko_cmd_gatt_prepare_characteristic_value_write响应

等待gecko_evt_gatt_procedure_completed事件

gecko_cmd_gatt_prepare_characteristic_value_write

等待gecko_cmd_gatt_prepare_characteristic_value_write响应

等待gecko_evt_gatt_procedure_completed事件

gecko_cmd_gatt_execute_characteristic_value_write(1)

等待gecko_cmd_gatt_execute_characteristic_value_write响应

等待gecko_evt_gatt_procedure_completed事件

gecko_cmd_gatt_execute_characteristic_value_write 命令

执行(argument = 1)或取消(argument = 0)与gecko_cmd_gatt_prepare_characteristic_value_write排队的所有未决写操作。当您运行此命令时,堆栈会自动处理以多个数据包形式发送已排队的写操作,这将占用必要的连接间隔。执行完成后,将发生gecko_evt_gatt_procedure_completed事件。在服务器端,这看起来像一系列快速的写操作,并且以相同的方式处理(确认每个操作)。

gecko_evt_gatt_server_attribute_value 事件 当客户端向特定特性写入新值时,在GATT服务器上

触发 。这是一个事件,您可以用来告知特性何时已更新,然后做出相应的响应(解析命令数据的新值,根据存储的数据设置I / O引脚,关闭连接,开始读取ADC测量值,等等。 )。

gecko_evt_gatt_server_user_write_request 事件

如果为给定特征设置了type =“ user”,则将生成此事件,而不是gecko_evt_gatt_server_attribute_value。来自客户端的新写入值将作为此事件的参数之一提供,但是该值本身不会由堆栈自动存储在RAM中。您可以存储或以其他方式处理该值,并在必要时进行确认。参数att_opcode描述了使用哪个GATT程序来更改值。

gecko_cmd_gatt_server_send_user_write_response 命令

用于当客户端对“用户”特征的写操作生成gecko_evt_gatt_server_user_write_request事件时,用于发送回适当的确认结果代码。如果需要此手动确认,则通常应使用与相关gecko_evt_gatt_server_user_write_request事件的事件处理程序相同的代码调用此命令。(仅 在给定特征的GATT编辑器中设置了value type =“ user”时适用 )

通知

当将新值写入启用通知的特性时,服务器将启动此操作 。如果客户端已订阅有关该特征的通知,则在写入新值时会将新值推送到客户端。通知不会被确认,因此您可以在一个连接间隔内发送多个通知,这有助于最大化吞吐量。服务器无法启用通知;它们必须由客户端启用,以便进行实际的数据传输。在我们的BLE堆栈中,这些API方法通常涉及 通知 操作:

gecko_cmd_gatt_server_write_attribute_value 命令

将本地属性的值写入GATT服务器。如果本地GATT数据库的特征的值具有指示或通知的属性并且客户端已启用通知或指示,则写入本地GATT数据库的特征的值将不会触发向远程GATT客户端的通知或指示。使用gecko_cmd_gatt_server_send_characteristic_notification命令将通知和指示发送到远程GATT客户端。

gecko_evt_gatt_server_characteristic_status 事件

此事件表明远程GATT客户端已更改了本地客户端特征配置描述符,或者在成功接收到指示后收到了来自远程GATT客户端的确认。Status_flags参数指示是否更改了客户端特征配置或是否收到确认(0x02)。Client_config_flags具有配置的新值。如果更新的配置标志等于 1,则启用通知。如果等于 2,则启用指示。如果等于 0,则两者都不启用。

gecko_evt_gatt_characteristic_value 事件

此事件表明已接收到远程GATT服务器中的特征值。此事件是由多个命令(例如gecko_cmd_gatt_read_characteristic_value和gecko_cmd_gatt_read_multiple_characteristic_values)触发的;以及启用gatt_set_characteristic_notification的通知后,远程GATT服务器发送指示或通知的时间。参数att_opcode揭示了触发此事件的GATT事务类型。特别是,如果att_opcode类型为handle_value_indication(0x1d),则应用程序需要使用gecko_cmd_gatt_send_characteristic_confirmation确认指示。此事件是客户端如何知道已收到更新值的方式。 推送的数据将作为事件参数的一部分提供。

表明

的 指示 操作等同于一个 通知 ,除了操作 指示被确认, 而通知是不。这以速度为代价提高了可靠性。在我们的BLE堆栈中,这些API方法通常涉及 指示 操作:

gecko_cmd_gatt_server_write_attribute_value 命令

将本地属性的值写入GATT服务器。如果本地GATT数据库的特征的值具有指示或通知的属性并且客户端已启用通知或指示,则写入本地GATT数据库的特征的值将不会触发向远程GATT客户端的通知或指示。使用gecko_cmd_gatt_server_send_characteristic_notification命令将通知和指示发送到远程GATT客户端。请记住, 指示已得到确认,因此您只能在给定的连接间隔内执行一次。当确认从GATT客户端返回时,将跟随gecko_evt_gatt_server_characteristic_status事件,其状态标志为0x2。

gecko_evt_gatt_server_characteristic_status 事件

此事件表明远程GATT客户端已更改了本地客户端特征配置描述符,或者在成功接收到指示后收到了来自远程GATT客户端的确认。Status_flags参数指示是否更改了客户端特征配置或是否收到确认(0x02)。Client_config_flags具有配置的新值。如果更新的配置标志等于 1,则启用通知。如果等于 2,则启用指示。如果等于 0,则两者都不启用。

gecko_evt_gatt_characteristic_value 事件

此事件表明已接收到远程GATT服务器中的特征值。此事件是由多个命令(例如gecko_cmd_gatt_read_characteristic_value和gecko_cmd_gatt_read_multiple_characteristic_values)触发的;以及启用gatt_set_characteristic_notification的通知后,远程GATT服务器发送指示或通知的时间。参数att_opcode揭示了触发此事件的GATT事务类型。特别是,如果att_opcode类型为handle_value_indication(0x1d),则应用程序需要使用gecko_cmd_gatt_send_characteristic_confirmation确认指示。此事件是客户端如何知道已收到更新值的方式。 推送的数据将作为事件参数的一部分提供。

gecko_cmd_gatt_send_characteristic_confirmation 命令

在指示值到达客户端后,将GATT客户端的指示确认发送回远程GATT服务器。gecko_evt_gatt_characteristic_value带有包含handle_value_indication(0x1d)的att_opcode,它表明已收到指示,并且必须通过此命令进行确认。需要在30秒内发送确认,否则客户端和服务器之间的GATT事务将中断。有时,您需要非常仔细地处理特定的数据流控制触发器。精确控制确认发生的时间以及确认之前和之后发生的事情可能很有价值。

gecko_evt_gatt_server_characteristic_status

此事件表明远程GATT客户端更改了本地客户端特征配置描述符,或者在成功接收到指示后收到了来自远程GATT客户端的确认。通常,此事件被忽略,但是如前一项所述,有时出于数据流控制的目的,准确地知道何时发生此事件很有价值。

通常,GATT服务器功能由一侧提供,而客户端功能完全在另一侧,但可能是双方都提供了两种功能。对于设计良好且高效的BLE项目,这通常不会带来任何优势-通常会不必要地使实现复杂化-因此,我们在这里不再赘述。

(上述文章阐述归伦茨科技公司所有,转载请注明出处,更多相关信息欢迎关注微信公众号:lenze_tech或微信号:lenzetech,点击http://www.lenzetech.com/)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值