蓝牙核心规范(V5.2)7.5-深入详解之ATT(属性协议)
目录
本部分定义了属性协议;一种用于在对端设备上发现、读和写属性的协议。
ATT协议和服务器、客户端直接的关系
属性协议允许被称为服务器的设备将一组属性及其关联的值公开给被称为客户端的对等设备。服务器公开的这些属性可以由客户端发现、读取和写入,并可以由服务器指示和通知。
1.ATT协议速读
属性协议定义了两个角色:服务器角色和客户端角色。它允许服务器向使用属性协议可访问的客户端公开一组属性。
- a)属性类型,由UUID
- b)属性句柄
- c)由利用该属性的每个更高级层规范定义的一组权限;不能使用属性协议访问这些权限。
属性类型指定属性表示什么。蓝牙SIG定义的属性类型在已分配的数字中定义,并由相关的高层规范使用。也可以定义非蓝牙SIG属性类型。
客户端可以向服务器发送属性协议请求,并且服务器应响应其接收到的所有请求。设备可以同时实现客户端和服务器角色,并且这两个角色可以在同一设备中以及在同一设备之间同时工作。每个蓝牙设备上应只有一个服务器实例;这意味着所有支持支架的属性句柄应相同。对于给定的客户端,服务器应具有一组属性。该服务器可以支持多个客户端。
注意:通过为每个服务分配不同的句柄范围,可以在单个服务器上公开多个服务。这些句柄范围的发现由更高的层规范定义。
属性协议具有通知和指示功能,提供了一种向客户端发送属性值的有效方式,而不需要读取它们.
所有属性协议请求都通过ATT承载发送。在两个设备之间可以建立多个ATT载体。每个ATT承载都使用一个单独的L2CAP通道,并且可以有不同的配置。
在LE中,有一个ATT承载使用ACL连接建立后可用的固定通道。可以使用L2CAP建立额外的ATT载体。
在LE中,有一个ATT承载使用ACL连接建立后可用的固定通道。可以使用L2CAP建立额外的ATT载体。
2.ATT协议
每个属性都有一个属性类型,通过UUID(通用唯一标识符)标识属性代表什么,以便客户端能够理解服务器公开的属性。每个属性都有一个用于访问服务器上的属性的属性句柄,以及一个属性值。
可以使用其属性句柄访问一个属性值。属性句柄由客户端使用属性协议PDU(协议数据单元)发现。具有相同属性类型的属性可能在服务器中存在多次。属性还具有一组权限,可以控制它们是否可以读取或写,或者属性值是否应该通过加密的链接发送。
属性类型
通用唯一标识符(UUID)用于标识每种属性类型。一个UUID被认为在所有的空间和时间上都是唯一的。UUID可以由任何人独立创建,并根据需要进行分发或发布。uuid没有中心注册表,因为它们是基于不重复的唯一标识符。属性协议允许设备使用uuid来识别属性类型,而不考虑用于在读请求或写请求中识别它们的本地句柄。
当属性UUID包含在ATT PDU中时,所有32位属性Uuid都应转换为128位Uuid。
属性句柄
属性句柄是一个16位的值,由每个服务器分配给它自己的属性,以允许客户端引用这些属性。当客户端与其服务器之间存在ATT承载时,不得重用属性句柄。
任何给定服务器上的属性句柄都应具有唯一的非零值。属性按属性句柄进行排序。
保留一个值为0x0000的属性句柄以供将来使用。值为0xFFFF的属性句柄称为最大属性句柄。
注意:当ATT承载处于活动状态时,可以添加或删除属性,但是,当ATT承载处于活动状态时,已删除的属性不能被替换为具有相同句柄的另一个属性。
属性处理分组
分组是由放置在与该属性分组的其他属性范围的开头的特定属性定义的,这是由更高的层规范定义的。客户端可以请求与一组属性相关联的第一个和最后一个句柄。
属性值
属性值是固定或可变长度的八位组数组。例如,它可以是一个八位值,或四个八位整数,或一个可变长度的字符串。属性可能包含的值太大,无法在单个PDU中传输,并且可以使用多个PDU发送。传输的值对属性协议不透明。这些八位组数组的编码由属性类型定义。
当在请求、响应、通知或指示中发送属性值时,属性值长度不会在大多数pdu的任何字段中发送。这些PDU中的可变长度字段的长度隐式地由携带该PDU的数据包的长度给出。这意味着:
a)只能将一个属性值放置在单个请求、响应、通知或指示中,除非该属性值具有服务器和客户端都已知的由属性类型定义的长度。
b)此属性值将始终是请求、响应、通知或指示的唯一可变长度字段。
c)承载协议(例如L2CAP)保留了数据报的边界。
注意:有些响应包括多个属性值,例如,当客户端请求多个属性读取时。要让客户端确定属性值的边界,属性值必须具有由属性类型定义的固定大小。
在一些pDU中,属性值的长度作为PDU中的一个字段包含,因此上述含义不适用于这些pDU。
属性权限
属性具有一组与其关联的权限值。权限与属性关联指定可以读取和/或写入属性。与该属性关联的权限指定读取和/或写入访问以及通知和/或指示所需的安全级别。给定属性的权限由更高的层规范定义,并且不能使用属性协议来发现。
如果访问安全属性需要经过身份验证的链接,并且客户端尚未使用具有足够安全性的服务器进行身份验证,则应使用错误代码“身份验证不足”发送ATT_ERROR_RSPPDU。当客户端收到此错误代码时,它可能会尝试对该链接进行身份验证,如果身份验证成功,那么它就可以访问该安全属性。
如果访问一个安全属性需要一个加密的链路,且该链接没有被加密,则应使用错误代码发送一个ATT_ERROR_RSPPDU,且加密不足。当客户端收到此错误代码时,它可能会尝试加密链接,如果加密成功,它就可以访问安全属性。
如果访问一个安全属性需要一个加密的链路,并且该链接是加密的,但其加密密钥大小太短,无法达到所需的安全级别,则应发送一个ATT_ERROR_RSPPDU,其错误密码为加密密钥大小不足。当客户端收到此错误代码时,它可能会尝试用更大的密钥大小加密链接,如果加密成功,它就可以访问安全属性。
属性权限是访问权限、加密权限、身份验证权限和授权权限的组合。
可以获得以下访问权限:可读可读和可写。
可能具有以下加密权限:不需要加密,而不需要加密
可能具有以下身份验证权限:不需要身份验证,而不需要身份验证
可能具有以下身份验证权限:不需要身份验证,而不需要身份验证。
加密、身份验证和授权权限可能有不同的可能性;例如,特定属性可能需要特定类型的身份验证或特定的最小加密密钥长度。属性能具有应用的多个权限组合;例如,特定属性可以允许以下任何一个:加密读取(不需要验证)写入验证,加密验证和授权读写(不管加密)。
服务器使用访问权限来确定客户端是否可以读取和/或写入属性值。
服务器使用身份验证权限来确定当客户端试图访问一个属性时,是否需要经过身份验证的物理链接。服务器还可以使用身份验证权限,以便在向客户端发送通知或指示之前,确定是否需要经过身份验证的物理链接。
授权权限确定在访问属性值之前是否需要授权客户端。
控制点属性
不能读取但只能写入、通知或指示的属性称为控制点属性。这些控制点属性可以被高层用于启用设备特定的过程,例如写入命令或设备上给定过程完成时的指示。
交换MTU大小
ATT_MTU被定义为在客户端和服务器之间发送的任何数据包的最大大小。更高的层规范定义了默认的ATT_MTU值。
当使用具有固定CID的L2CAP通道时,客户端和服务器可选择地交换可使用ATT_EXCHANGE_MTU_REQ和ATT_EXCHANGE_MTU_RSPpdu接收到的数据包的最大大小。然后,这两个设备都使用这些交换值中的最小值来进行所有进一步的通信(见第3.4.2节)。同时充当服务器和客户端的设备应对客户端RxMTU和服务器RxMTU使用相同的值。
当使用带有动态分配CID的L2CAP通道时,ATT_MTU应设置为L2CAPMTU大小。
ATT_MTU值是每个ATT承载值。具有多个ATT承载的设备可以为每个ATT承载具有不同的ATT_MTU值。
长属性值
可以在单个数据包中发送的最长属性的大小是(ATT_MTU-1)八进制。属性PDU中至少包含属性操作码。
属性值可以定义为大小大于(ATT_MTU-1)八进制。这些属性被称为长属性。
要读取大于(ATT_MTU-1)八位制的属性的整个值,请使用ATT_READ_BLOB_REQPDU。可以使用ATT_READ_REQPDU读取长属性值的第一个(ATT_MTU-1)八位节。
要写入大于(ATT_MTU-3)八位制的属性的整个值,将使用ATT_PREPARE_WRITE_REQ和ATT_EXECUTE_WRITE_REQpdu。可以使用ATT_WRITE_CMDPDU写入长属性值的第一个(ATT_MTU-3)八位制。
属性值的最大长度应为512八进制。
注意:在使用多个属性协议pdu读取该值时,对属性值发生变化的保护是更高层的责任。
原子操作
服务器应将每个请求或命令视为一个原子操作,不受同时发送请求或命令的其他ATT承载的影响。如果ATT承载因任何原因(用户操作或丢失无线电链路)被断开,则任何修改后的属性的值都由更高的层规范负责。
不能在单个原子操作中读取或写长属性。
ATT承载器
ATT承载是一种用于发送属性协议pdu的通道。每个ATT承载器都使用一个L2CAP通道。设备可以具有到对等设备的任意数量的ATT载体。
L2CAP信道模式决定了属性协议在该ATT承载上的行为。如果L2CAP信道模式使用增强的基于信用的流量控制模式,则ATT承载被称为增强的ATT承载。任何不是增强的ATT承载的ATT承载,使用任何其他L2CAT通道模式,都被称为未增强的ATT承载。
除明确说明外,使用增强信用流量控制模式的增强ATT承载的行为应与不使用增强信用流量控制模式的ATT承载的行为相同。
当L2CAP通道(如果动态分配)或底层物理链路断开时,ATT承载被终止。
注:LE固定通道只能通过终止物理链路来终止。
一个更高层的规范可能需要一个增强的ATT承载器
3.属性pdu
属性PDU有六种类型之一,它们由PDU名称的后缀表示,如表3.1所示:
类型 | 意义 | 后缀 |
Commands | 由不调用响应的客户机发送给服务器的pdu。 | CMD |
Requests | 由调用响应的客户端发送到服务器的pdu。 | REQ |
Responses | 由服务器响应请求发送给客户端的pdu。 | RSP |
Notifications | 由未调用确认的服务器发送给客户端的未经请求的pdu。 | NTF |
Indications | 由调用确认的服务器发送到客户端的未经请求的PDU。 | IND |
Confirmations | 由客户端发送到服务器的pdu,以确认收到指示。 | CFM |
服务器应能够接收并正确地响应以下请求pdu:
属性PDU格式
名称 | 长度 | 描述 |
属性操作码 | 1 | 属性PDU操作代码 位7:身份验证签名标志 位6:命令标志 位5-0:方法 |
属性参数 | 0-(ATT_MTU - X) | 属性PDU参数 如果属性操作码的身份验证签名标志为0,则为X=1 X=13如果属性操作码的身份验证签名标志为1 |
身份验证签名 | 0或者12 | 属性选项码和属性参数的可选身份验证签名 |
顺序协议
许多属性协议pdu使用一个顺序的请求-响应协议.
一旦客户端向服务器发送请求,该客户端应在收到响应PDU之前,不向同一ATT承载上的同一服务器发送其他请求。
从服务器发送的指示也使用顺序指示确认协议。在收到确认PDU之前,不得从同一ATT承载上向同一客户端发送其他指示。但是,客户端可以在发送确认之前自由地发送命令和请求。
对于没有响应PDU的通知,没有流控制,可以随时发送通知。
对于没有响应PDU的命令,没有流控制,可以随时发送命令。
注意:服务器可能充斥着大量命令,更高的层规范可以定义如何防止这种情况发生。
由于缓冲区溢出或不知道更改的客户端而接收到但无法处理的命令的命令应被丢弃。因此,必须认为这些pdu是不可靠的。
在未增强的ATT承载上,应丢弃由于缓冲区溢出而无法处理的通知。因此,必须认为这些pdu是不可靠的。
在增强的ATT承载上,通知应在收到时始终被处理。因此,这些pdu是可靠的。
注意:每个客户端和服务器的流控制都是独立的。
注意:服务器可以接收一个请求,发送一个或多个通知,然后进行对原始请求的响应。请求的流量控制不受通知传输的影响。
注意:在响应原始请求之前,服务器可以接收请求,然后还可以接收命令。请求的流控制不受命令传输的影响。
注意:在发送了指示,但未收到确认之后,可以发送来自服务器的通知。指示的流量控制不受通知传输的影响。
注意:客户端可以从服务器接收指示,然后在发送原始指示的确认之前向该服务器发送请求或命令。
交易
属性协议请求和响应或指示确认对被认为是单个事务。交易应始终在一个ATT持有人上进行,并且不得在多个ATT持有人上进行分割。
在客户端上,应在客户端发送请求时开始交易。交易应在客户收到响应时完成。
在服务器上,事务应在服务器收到请求时开始。服务器应在发送响应时完成事务。
在服务器上,事务应在服务器发送指示时开始。当服务器收到确认后,应完成交易。
在客户上,交易应在客户收到指示时开始。当客户发送确认书后,应完成交易。
在30秒内未完成的交易应超时。该交易应被视为失败,当地高层应失败通知此故障。不得再向此ATT承载器上的目标设备发送属性协议请求、命令、指示或通知。
注意:要发送另一个属性协议PDU,必须在这些设备之间建立一个新的ATT承载。在建立新的ATT承载之前,现有的ATT承载可能需要断开或终止承载。
如果ATT承载在事务期间断开连接,则该事务应被视为已关闭,并且服务器上正在修改的任何值都将处于未确定状态。
注意:每个ATT_PREPARE_WRITE_REQ和每个ATT_READ_BLOB_REQPDU都会启动一个单独的请求,因此也会启动一个单独的事务。
4.属性协议pdus
4.1 错误处理
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x01=ATT_ERROR_RSPPDU |
请求操作码出错 | 1 | 生成此ATT_ERROR_RSPPDU的请求 |
属性句柄出错 | 2 | 生成此ATT_ERROR_RSPPDU的属性句柄 |
错误代码 | 1 | 请求生成ATT_ERROR_RSPPDU的原因 |
“错误中的请求选项码”参数应设置为生成此错误的请求的属性选项码。
“错误中的属性句柄”参数应设置为生成此错误的原始请求中的属性句柄。如果原始请求中没有属性句柄,或者不支持该请求,则此字段应使用值0x0000。
错误代码参数应设置为以下值之一:
名称 | 错误码 | 描述 |
无效句柄 | 0x01 | 给定的属性句柄在此服务器上无效。 |
没有权限读 | 0x02 | 无法读取该属性。 |
没有权限写 | 0x03 | 无法写入该属性。 |
无效PDU | 0x04 | 属性PDU无效 |
身份验证不足 | 0x05 | 该属性需要在读写之前才能进行身份验证。 |
不支持请求 | 0x06 | 属性服务器不支持从客户端接收到的请求 |
无效偏移量 | 0x07 | 指定的偏移量超过了属性 |
授权不足 | 0x08 | 该属性需要授权才能读写它。 |
准备队列已满 | 0x09 | 排队的准备写入数太多。 |
未找到属性 | 0x0A | 在给定属性句柄范围内未找到属性。 |
属性不长 | 0x0B | 无法使用ATT_READ_BLOB_REQPDU读取该属性。 |
加密密钥大小不足 | 0x0C | 用于加密此链路的加密密钥大小不足。 |
属性值长度无效 | 0x0D | 该操作的属性值长度无效。 |
不太可能的错误 | 0x0E | 所请求的属性请求遇到了不太可能出现的错误,因此无法按要求完成。 |
加密不足 | 0x0F | 该属性需要加密才能进行读写。 |
不支持的组类型 | 0x10 | 属性类型不是由更高级层规范定义的受支持的分组属性。 |
资源不足 | 0x11 | 由于资源不足,无法完成该请求。 |
数据库不同步 | 0x12 | 服务器请求客户端重新发现数据库。 |
不允许值 | 0x13 | 不允许使用该属性的参数值。 |
应用程序错误 | 0x80-0x9f | 由更高层规范定义的应用程序错误代码。 |
通用配置文件和服务 错误代码 |
0xE0--0xff | 在核心规范补充,B部分中定义的常见配置文件和服务错误代码。 |
预留供将来使用 | 所有其他值 | 预留供将来使用 |
如果在ATT_ERROR_RSPPDU中接收到一个客户端不理解的错误代码,例如保留供将来使用的错误代码,那么ATT_ERROR_RSPPDU仍应被视为由于未知原因不能执行给定的请求。
注意:发送ATT_ERROR_RSPPDU不应导致ATT服务器断开与客户端的连接。客户端可以升级安全性并重试请求,因此服务器应该给客户机足够的时间来执行这样的升级。
4.2 MTU交换
ATT_EXCHANGE_MTU_REQ
客户端使用ATT_EXCHANGE_MTU_REQPDU通知服务器客户端的最大接收MTU大小,并请求服务器以其最大接收MTU大小进行响应.
参数 长度 描述 属性操作码 1 0x02 = ATT_EXCHANGE_MTU_REQMTU接收客户端 2 客户端接收MTU大小 客户端RxMTU应大于或等于默认的ATT_MTU。
在客户端连接期间,此请求只能发送一次。Cli ent Rx MTU参数应设置为客户端可以接收的属性proto col PDU的最大大小。
ATT_EXCHANGE_MTU_RSP PDU。作为对收到的ATT EX、CHANGE MTU REQ PDU的回复发送。
参数 | 长度 | 描述 |
属性操作码 | 1 |
0x03 = ATT_EXCHANGE_MTU_RSP
|
服务器RxMTU | 2 | 属性服务器接收MTU大小 |
服务器RxMTU应大于或等于默认的ATT_MTU。
服务器RxMTU参数应设置为服务器可以接收到的属性协议PDU的最大大小。
服务器和客户端应将ATT_MTU设置为客户端RxMTU和服务器RxMTU的最小值。大小相同,以确保客户端能够正确检测到长属性读取的最终数据包。
此ATT_MTU值应在发送此响应后和发送任何其他属性协议PDU之前应用于服务器中。
此ATT_MTU值应在收到此响应后和发送任何其他属性协议PDU之前应用于客户端。
如果客户端RxMTU或服务RxMTU不正确地小于默认ATT_MTU,则ATT_MTU不应被更改,而ATT_MTU应为默认ATT_MTU。
如果设备同时是客户端和服务器,则应适用以下规则:
1.设备的ATT_EXCHANGE_MTU_REQPDU应包含与设备的ATT_EXCHANGE_MTU_RSPPDU相同的MTU(即MTU应为对称)。
2.如果MTU在一个方向上交换,这对于两个方向都足够了。
3.允许使用(但没有必要,请参见2)。在两个方向上交换MTU,但在每个方向上的MTU应相同(见1)。
4.如果在MTU交换请求发送之后和MTU交换响应收到之前收到了属性协议请求,则相关的属性协议响应应使用默认的MTU。图3.1显示了此规则所涵盖的一个示例。在这种情况下,设备A和设备B都使用默认的属性协议响应MTU。
5.一旦发送了MTU交换请求,启动设备就不应在收到MTU交换响应后才会发送属性协议指示或通知。注意:这将停止对指示或通知的MTU大小未知的交叉条件的风险。
4.3 查找信息
ATT_FIND_INFORMATION_REQPDU用于获取属性处理柄及其关联类型的映射。这允许客户端在服务器上发现属性及其类型的列表。
参数 | 长度 | 描述 |
属性可选代码 | 1 |
0x04 = ATT_FIND_INFORMA-TION_REQ
|
开始句柄 | 2 | 第一个请求的处理号 |
结束句柄 | 2 | 最后请求的处理号 |
只返回具有属性句柄的属性,包括开始句柄参数和结束句柄参数。要读取所有属性,起始手柄参数设置为0x0001,结束手柄参数设置为0xFFFF。起始手柄参数应小于或等于结束手柄参数。
如果将返回一个或多个属性,则应发送一个ATT_FIND_INFORMATION_RSPPDU。
如果服务器接收到的ATT_FIND_INFORMATION_REQPDU参数大于“结束手柄”参数或“起始手柄”参数0x0000,应发送带错误代码“错误手柄”的ATT_ERROR_RSPPDU;“属性手柄”参数应设置为“起始手柄”参数。
如果不返回任何属性,则应发送ATT_ERROR_RSPPDU,并显示错误代码“找不到属性”;“错误中的属性句柄”参数应设置为“起始句柄”参数。
服务器不得使用ATT_ERROR_RSPPDU响应ATT_FIND_INFORMATION_REQPDU,其错误代码为认证不足、授权不足、加密密钥大小不足或应用程序错误。
ATT_FIND_INFORMATION_RSPPDU将响应接收到的ATT_FIND_INFORMATION_REQPDU,并包含有关此服务器的信息。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x05=ATT_FIND_INFORMATION_RSP |
格式 | 1 | 信息数据的格式 |
信息数据 | 4到ATT_MMT-2 | 其格式是由“格式”字段确定的信息数据 |
查找信息响应应具有完整的手柄-UUID对。这种对不应跨响应分组进行分割;这也意味着一个车把UUID对应适合到单个响应分组中。句柄-UUID对应按属性句柄的升序返回。
格式参数可以包含两个可能的值中的一个.
名称 | 格式 | 描述 |
句柄和16位蓝牙UUID | 0x01 | 具有16位蓝牙uuid的1个或多个句柄的列表 |
句柄和128位UUID | 0x02 | 1个或多个包含128位uuid的句柄的列表 |
句柄 | 16位蓝牙UUID |
2个字节 | 2个字节 |
句柄 | 128位蓝牙UUID |
2个字节 | 16个字节 |
如果顺序属性具有不同的UUID大小,ATT_FIND_-INFORMATION_RSPPDU将以对的第一个属性结束,即使这可能意味着它没有填充最大可能的数量(句柄、UUID)对。这是因为不可能在单个响应包中包含具有不同UUID大小的属性。在这种情况下,客户端必须使用另一个ATT_FIND_INFORMATION_REQPDU并更新其启动句柄,以获取该对的第二个属性以及其原始请求中的任何其他属性。
ATT_FIND_BY_TYPE_VALUE_REQPDU用于获取具有16位UUID属性类型和属性值的属性的句柄。这允许在属性类型决定一组属性的分组时发现与给定属性相关联的句柄范围。
注意:通用属性配置文件按属性类型定义了属性的分组。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x06=ATT_FIND_BY_TYPE_VALUE_REQPDU |
开始句柄 | 2 | 第一个请求的处理号 |
结束句柄 | 2 | 最后请求的处理号 |
属性形式 | 2 | 2字节UUID需要被发现 |
属性值 | 0 to (ATT_MTU-7) | 要找到的属性值 |
只返回具有属性句柄的属性,其中包括起始句柄参数和符合请求的属性类型和具有足够权限允许读取的属性值。要读取所有属性,起始手柄参数设置为0x0001,结束手柄参数设置为0xFFFF。
如果将返回一个或多个句柄,则应发送一个ATT_FIND_BY_TYPE_VALUE_RSPPDU。
注意:属性值将根据长度和二进制表示法进行比较。
注意:不能对值大于(ATT_MTU-7)的属性使用此请求。
如果服务器接收到的ATT_FIND_BY_TYPE_VALUE_REQPDU的启动句柄参数大于结束句柄参数或启动句柄参数为0x0000,则应发送具有错误代码无效句柄的ATT_ERROR_RSPPDU。错误中的属性句柄参数应设置为起始句柄参数。
如果不返回任何属性,则服务器应发送ATT_ERROR_RSPPDU,错误代码为未找到ATT_ERROR_RSPPDU。错误中的属性句柄参数应设置为起始句柄。
服务器不得使用ATT_ERROR_RSPPDU响应ATT_FIND_BY_TYPE_VALUE_REQPDU,其错误代码为认证不足、授权不足、加密密钥大小不足、加密不足或应用程序错误。
ATT_FIND_BY_TYPE_VALUE_RSPPDU将响应接收到的ATT_FIND_BY_TYPE_VALUE_REQPDU,并包含有关此服务器的信息。
参数 | 长度 | 描述 |
属性操作码 | 1 |
0x07 = ATT_FIND_BY_TYPE_VALUE_RSP PDU
|
句柄信息列表 | 4 to (ATT_MTU-1) | 包含1个或多个句柄信息的列表 |
句柄信息段范围:
找到属性句柄 | 群组末端句柄 |
2 | 2 |
ATT_FIND_BY_TYPE_VALUE_RSPPDU应包含一个或多个完整的处理信息。此类处理信息不得被分开响应数据包。句柄信息列表将根据已找到的属性句柄按顺序排序。
对于与ATT_FIND_BY_TYPE_VALUE_REQPDU中的属性类型和属性值相匹配的每个句柄,应返回一个句柄信息。“找到的属性句柄”应设置为具有来自ATT_FIND_BY_-TYPE_VALUE_REQPDU的确切属性类型和属性值的属性的句柄。如果ATT_FIND_BY_TYPE_-VALUE_REQPDU中的属性类型是由高层规范定义的分组属性,则组结束句柄应由更高的层规范定义。如果ATT_FIND_BY_TYPE_VALUE_REQPDU中的属性类型不是由更高级层规范定义的分组属性,则组结束句柄应等于已找到的属性句柄。
注意:组结束句柄可能大于ATT_FIND_BY_TYPE_VALUE_REQ PDU中的结束句柄。
如果服务器接收到ATT_FIND_BY_TYPE_VALUE_REQPDU,服务器应使用ATT_FIND_BY_TYPE_VALUE_REQPDU响应,其中包含尽可能多的句柄,匹配的属性与服务器中存在的属性类型和属性值符合最大PDU大小(ATT_MTU-1)。
4.4 读属性
ATT_READ_BY_TYPE_REQPDU用于获取属性类型已知但句柄不知道的属性的值。
参数 | 长度 | 描述 |
属性操作码 | 1 | |
2 | ||
2 | ||
2 or 16 | 2 或者16字节UUID |
将只返回具有属性句柄之间的属性,包括开始句柄和与给定的属性类型相同的属性类型相同的结束句柄。搜索所有属性,起始手柄设置为0x0001,结束手柄设置为0xFFFF。
注意:所有属性类型都可以有效地与128位uuid进行比较,即使在此请求中提供了16位UUID或为属性定义了UUID。
起始句柄应小于或等于结束句柄。如果服务器接收到的ATT_READ_BY_TYPE_REQPDU参数大于“结束句柄”参数或“起始手柄”参数为0x0000,则应发送ATT_ERROR_RSPPDU,且错误代码为“错误句柄”;“属性句柄”参数应设置为“起始句柄”参数。
如果在句柄范围内不存在给定类型的属性,则不会返回属性句柄和值,并发送包含错误代码的ATT_ERROR_RSPPDU。错误中的属性句柄参数应设置为起始句柄。
返回的属性应为句柄范围内句柄最低的属性。这些属性被称为所请求的属性。
如果在句柄范围内具有所请求类型的属性具有相同长度的属性值,那么这些属性都可以在单个请求中读取。
属性服务器应在响应中包含尽可能多的属性,以尽量减少读取相同类型的属性所需的pdu数量。
注意:如果在句柄范围内具有所请求类型的属性具有不同长度的属性值,则必须发出多个ATT_READ_BY_TYPE_REQPDU。
当多个属性匹配时,应将以下规则依次应用于每个规则。
- 只能在ATT_READ_BY_-TYPE_RSPPDU中返回可读取的属性。
- 如果请求的属性集中的一个属性会导致ATT_ERROR_RSPPDU,那么该属性不能包含在ATT_READ_BY_TYPE_RSPPDU中,并且应该返回该属性之前的属性。
- 如果请求属性集中的第一个属性会导致ATT_ERROR_RSPPDU,则不能考虑请求属性中的其他属性。
如果所请求的属性有足够的权限来允许读取,则服务器应使用ATT_READ_BY_TYPE_RSPPDU进行响应。
如果客户端没有足够的安全性来读取所请求的属性,则应发送具有错误代码的ATT_ERROR_RSPPDU,且认证不足。错误中的属性句柄参数应设置为导致错误的属性的句柄。
ATT_READ_BY_TYPE_RSP
发送ATT_READ_BY_TYPE_RSP PDU以回复收到的ATT_READ_BY_TYPE_REQ PDU,并包含已读取属性的句柄和值。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x09=ATT_READ_BY_TYPE_RSPPDU |
长度 | 1 | 每个属性句柄对的大小 |
属性数据列表 | 2 to (ATT_MUT-2) | 属性数据列表 |
ATT_READ_BY_TYPE_RSPPDU应包含完整的手柄值对。这些数据对不得跨响应数据包进行分组。句柄值对应根据属性句柄按顺序返回。
长度参数应设置为一个属性句柄值对的大小。
属性句柄值对的最大长度为255字节,以一个八进制的长度参数为限。因此,在此响应中返回的属性值的最大长度是(长度-2)=253字节。
属性句柄值对应设置为请求内句柄范围内的属性类型标识的属性的值。如果属性值大于(ATT_MTU-4)或253字节,以较小者为准,则第一个(ATT_MTU-4)或253字节应包含在此响应中。
ATT_READ_REQ
ATT_READ_REQPDU用于请求服务器读取属性的值,并在ATT_READ_RSPPDU中返回其值。
参数 | 长度 | 描述 |
属性操作码 | 1 |
0x0A = ATT_READ_REQ PDU
|
属性值 | 2 | 要读取的属性的句柄 |
如果客户端没有足够的权限读取请求的属性,则应以错误代码发送ATT_ERROR_RSPPDU。
如果客户端没有足够的安全性来读取所请求的属性,则应发送具有错误代码的ATT_ERROR_RSP PDU,且认证不足。
如果客户端的加密密钥大小不足,无法读取所请求的属性,则应发送一个ATT_ERROR_RSPPDU,其错误代码为加密密钥大小不足。
如果客户端没有启用加密,并且需要加密才能读取所请求的属性,则应发送一个ATT_ERROR_RSP PDU,错误代码为加密不足。
如果句柄无效,则应发送具有错误代码无效句柄的ATT_ERROR_RSP PDU。
如果由于权限而无法读取属性值,则应使用错误代码发送ATT_ERROR_RSP PDU。
参数 | 长度 | 描述 |
属性操作码 | 1 |
0x0B = ATT_READ_RSP PDU
|
属性值 | 0 to ATT_MTU-1 | 具有给定句柄的属性的值 |
属性值应设置为请求中属性句柄标识的属性值。如果属性值大于(ATT_MTU-1),则应将第一个(ATT_MTU-1)包含在此响应中。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x0C=ATT_READ_BLOB_REQPDU |
属性句柄 | 2 | 要读取的属性的句柄 |
偏移量 | 2 | 要读取的第一个字节的偏移量 |
属性句柄参数应设置为一个有效的句柄
如果客户端没有足够的安全性来读取所请求的属性,则应发送具有错误代码的ATT_ERROR_RSPPDU,且认证不足。
如果客户端没有足够的权限读取请求的属性,则应以错误代码发送ATT_ERROR_RSPPDU。
如果客户端的加密密钥大小不足,无法读取所请求的属性,则应发送一个ATT_ERROR_RSP PDU,其错误代码为加密密钥大小不足。
如果客户端没有启用加密,并且需要加密才能读取所请求的属性,则应发送一个ATT_ERROR_RSP PDU,错误代码为加密不足。
如果句柄无效,则应发送具有错误代码无效句柄的ATT_ERROR_RSP PDU。
如果由于权限而无法读取属性值,则应使用错误代码发送ATT_ERROR_RSP PDU。
如果读取Blob请求的偏移值大于属性值的长度,则应发送带有错误码的ATT_ERROR_RSP PDU无效偏移的ATT_ERROR_RSP PDU。
如果属性值的固定长度小于或等于(ATT_MTU-1)八位节,则可以使用错误代码属性长短发送ATT_ERROR_RSPPDU。
如果ATT_READ_BLOB_REQPDU的值偏移量等于属性值的长度,则响应中的零件属性值的长度应为零。
注意:如果属性大于(ATT_MTU-1)八进制,则ATT_READ_-BLOB_REQPDU是读取长属性的附加八进制的唯一方法。第一个(ATT_MTU-1)八进制可以使用ATT_READ_RSP、ATT_HANDLE_VALUE_NTF或ATT_HANDLE_VALUE_INDPDU来读取。
ATT_READ_BLOB_RSP
ATT_READ_BLOB_RSPPDU是响应接收到的ATT_READ_BLOB_REQPDU,并包含已读取的属性的部分值。
参数 | 值 | 描述 |
属性操作值 | 1 |
0x0D = ATT_READ_BLOB_RSP
|
部分属性值 |
0 to (ATT_MTU -1)
|
具有给定句柄的属性值的一部分 |
ATT_READ_MULTIPLE_REQ PDU用于请求服务器读取一组属性的两个或多个值,并在ATT_READ_MULTIPLE_RSP PDU中返回其值。只能读取具有已知固定长度的值,除了最后一个可以具有可变长度的值。关于属性是否具有已知的固定大小的知识将在更高的层规范中定义。
参数 | 值 | 描述 |
属性操作值 | 1 |
0x0E = ATT_READ_MULTIPLE_REQ PDU
|
属性句柄 |
4 to (ATT_MTU -1)
|
一组两个或多个属性句柄。 |
如果所有句柄都有效,并且所有属性都有足够的权限允许读取,则服务器应使用ATT_READ_MULTIPLE_RSPPDU进行响应。
注意:处理集参数中属性的属性值不必都具有相同的大小。
注意:“手柄集”参数中的属性句柄不必按属性句柄的顺序排列;它们按响应中需要的值的顺序排列。
如果客户端没有足够的授权来读取任何属性,则应与错误代码和授权不足一起发送ATT_ERROR_RSPPDU。
ATT_READ_MULTIPLE_RSPPDU是响应接收到的ATT_READ_MULTIPLE_REQPDU,并包含已读取的属性的值。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x0F=ATT_READ_MULTIPLE_RSPPDU |
值集 | 0 to (ATT_MUT-1) | 一组两个或多个值的值 |
值集参数应该是请求中每个属性句柄的属性值的连接。如果“各值集”参数大于(ATT_MTU-1),则只有第一个(ATT_MTU-1)八位位包含在此响应中。
注意:当“各值集”参数可能为(ATT_MTU-1)时,客户端不应使用此属性请求,因为无法确定最后一个属性值是否完成,或者是否溢出。
ATT_READ_BY_GROUP_TYPE_REQPDU用于获取属性类型已知的属性的值,由更高层规范定义的分组属性的类型,但句柄不知道。
参数 | 长度 | 描述 |
属性操作值 | 1 |
0x10 = ATT_READ_BY_GROUP_TYPE_REQ PDU
|
开始句柄 | 2 | 第一个请求的处理号 |
结束句柄 | 2 | 最后请求的处理号 |
属性组类型 | 2 or 16 | 2或者16字节UUID |
只返回具有属性句柄的属性,包括开始句柄和与属性类型给出的属性组类型相同的结束句柄。搜索所有属性,起始手柄设置为0x0001,结束手柄设置为0xFFFF。
注意:所有属性类型都可以有效地与128位uuid进行比较,即使在此请求中提供了16位UUID或为属性定义了UUID。
起始句柄应小于或等于结束句柄。如果服务器接收到的ATT_READ_BY_GROUP_TYPE_REQPDU的起始句柄参数大于“结束句柄”参数或“起始句柄”参数为0x0000,则应发送ATT_ERROR_RSPPDU,并包含错误代码“无效句柄”错误代码。错误中的属性句柄参数应设置为起始句柄参数。
如果属性组类型不是由高层规范定义的支持的分组属性,则应使用错误代码发送ATT_ERROR_RSP PDU,代码为不支持的组PDU。“错误中的属性句柄”参数应设置为起始句柄。
如果在句柄范围内不存在给定类型的属性,则不会返回属性句柄和值,并发送包含错误代码的ATT_ERROR_RSP PDU。错误中的属性句柄参数应设置为起始句柄。
返回的属性应为句柄范围内句柄最低的属性。这些属性被称为所请求的属性。
如果在句柄范围内具有所请求类型的属性具有相同长度的属性值,那么这些属性都可以在单个请求中读取。
属性服务器应在响应中包含尽可能多的属性,以尽量减少读取相同类型的属性所需的pdu数量。
注意:如果在句柄范围内具有所请求类型的属性具有不同长度的属性值,则必须发送多个ATT_READ_BY_GROUP_-TYPE_REQPDU。
当多个属性匹配时,应将以下规则依次应用于每个规则。
- 只能在ATT_READ_BY_GROUP_TYPE_RSP PDU中返回可读取的属性。
- 如果请求属性集中的属性会导致ATT_ERROR_RSPPDU,则该属性不能包含在ATT_READ_BY_GROUP_TYPE_RSP PDU中,并且应返回该属性之前的属性。
- 如果请求属性集中的第一个属性会导致ATT_ERROR_RSPPDU,则不能考虑请求属性中的其他属性。
如果所请求的属性有足够的权限来允许读取,则服务器应使用ATT_READ_BY_GROUP_TYPE_RSPPDU进行响应。
如果客户端没有足够的权限读取请求的属性,则应以错误代码发送ATT_ERROR_RSPPDU。错误中的属性句柄参数应设置为导致错误的属性的句柄。
如果客户端没有足够的安全性来读取所请求的属性,则应发送具有错误代码的ATT_ERROR_RSPPDU,且认证不足。错误中的属性句柄参数应设置为导致错误的属性的句柄。
如果客户端的加密密钥大小不足,无法读取所请求的属性,则应发送一个ATT_ERROR_RSPPDU,其错误代码为加密密钥大小不足。错误中的属性句柄参数应设置为导致错误的属性的句柄。
如果客户端没有启用加密,并且需要加密才能读取请求的属性,则应发送ATT_ERROR_RSPPDU,错误代码加密不足。错误中的属性句柄参数应设置为导致错误的属性的句柄。
如果由于权限而无法读取所请求属性的值,则ATT_ERROR_RSPPDU应发送错误代码不允许读取PDU。错误中的属性句柄参数应设置为导致错误的属性的句柄。
注意:如果在句柄范围内有多个请求类型的属性,并且客户端希望获得请求类型的下一个属性,它必须发布另一个启动句柄更新的ATT_READ_BY_GROUP_TYPE_REQPDU。一旦客户端获得一个没有找到错误代码属性的ATT_ERROR_RSPPDU,客户端就不再剩下这样的属性了。
ATT_READ_BY_GROUP_TYPE_RSPPDU是响应接收到的ATT_READ_BY_GROUP_TYPE_REQPDU,并包含已读取的属性的句柄和值。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x11=ATT_READ_BY_GROUP_-TYPE_RSP PDU |
长度 | 1 | 每个属性数据的大小 |
属性数据列表 | 4 to (ATT_MTU-2) | 属性数据的列表 |
ATT_READ_BY_GROUP_TYPE_RSPPDU应包含完整的属性数据。属性数据不应跨响应数据包进行分割。属性数据列表将根据属性句柄按顺序排序。
长度参数应设置为一个属性数据的大小.
属性数据的最大长度为255八进制,由一个八进制的长度参数为限。因此,在此响应中返回的属性值的最大长度是(长度-4)=251个字节。
ATT_READ_MULTIPLE_VARIABLE_REQ
ATT_READ_MULTIPLE_VARIABLE_REQPDU用于请求服务器读取一组具有变量或未知值长度的属性的两个或多个值,并在ATT_READ_MULTIPLE_-VARIABLE_RSPPDU中返回它们的值。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x20=ATT_READ_MULTIPLE_VARIABLE_REQPDU |
句柄集 |
4 to (ATT_MTU-1)
|
一组两个或多个属性句柄 |
ATT_READ_MULTIPLE_VARIABLE_RSP
ATT_READ_MULTIPLE_VARIABLE_RSPPDU是响应接收到的ATT_READ_MULTIPLE_VARIABLE_REQPDU,并包含已读取的属性的长度和值。
参数 | 长度 | 描述 |
属性操作码 | 1 | 0x21=ATT_READ_MULTIPLE_VARIABLE_RSP |
长度值图列表 |
4 to (ATT_MTU-1)
|
长度值元组的列表 |
长度值元组列表应该是请求中每个属性句柄的请求顺序的长度值元组的连接。如果长度值元组列表大于(ATT_MTU-1)八位符,则应在长度值元组的开头对(长度值-1)之后,或者在长度值元组的值长度字段内的长度值元组进行截断。
4.5 写属性
写入请求用于请求服务器将属性值写入并通过发送写入响应完成。写入请求格式如下
属性句柄设置为有效句柄。属性值应设置为该属性新的值,如果长度可变,该属性值应该截断或延长来匹配属性值参数中的长度。
ATT_WRITE_RSP(写响应)
写响应用于回复有效写入请求并确认属性被写入成功。写响应格式如下:
如果句柄有效,属性有足够的的权限允许写入,属性值大小和格式有效,并且写入该属性成功,那么服务器使用写入响应回复。
4.6 队列写
预备写入响应被服务器用于回应收到预备写入请求,确认该值被成功接收并放在预备写入请求队列中。格式如下
属性句柄、偏移量和部分属性值参数应设置为与相应预备希尔请求相同值。之所以近乎偏执的重复这些数据,就是为了保证数据传递的可靠性。客户端可以对比响应和请求的字段值,保证数据被正确接收。
ATT_EXECUTE_WRITE_REQ(执行写入请求)
执行写入请求用于服务器写入或取消写入当前来自客户端的预备队列中的值。格式如下
接收完所有的预备写入请求,服务器将拥有一个随时可以执行的准备写入队列。服务器可在一次原子操作中写入所有值。当标志参数设置为0x01时,之前的预备写入请求队列的值安相应接收顺序写入,然后队列清除,服务器发送执行人写入响应。当标志参数为0x00时,所有该客户端等待的预备写入值被丢弃,队列被清除,服务器发送执行写入响应。
执行写入响应用于回应收到的执行写入请求。格式:
属性写入服务器后应立刻发送执行写入响应。
4.7 已启动服务器
ATT_HANDLE_VALUE_NTF(句柄值通知)
句柄值通知是服务器向客户端的一条通知,用来告知某属性的当前值。句柄值通知格式:
服务器向客户端发送快速的属性状态更新时,可以放一条句柄通知。对比客户端周期性询问的方法,用通知获取新的属性值显得更加迅速有效。一般来说,服务器会为所有的绑定设备配置通知。这样做的好处在于客户端重新与设备建立链接时,该设备上的服务器能够立即将自己当前状态通知该客户端。该通知可以在任何时间发送,同时也是不可靠的。
句柄值指示是服务器发向客户端的一条指示,用来告知某属性当前值。格式如下
句柄值指示类似于句柄值通知,不同的是客户端收到指示后回复。服务器一次只能发送一条指示,并且只有收到确认响应后才发起下一条指示。
句柄值确认不含任何数据,主要用于流控。因为具备了确认机制,指示可以视为可靠传输。一旦服务器收到了确认信息,便确定客户端收到了指示。
服务器可以随时发送两个或多个属性值的通知。格式如下
手柄长度值元组列表应是针对被通知的每个属性的手柄长度值元组的连接。
服务器不应截断句柄长度值元组。
句柄长度值元组中的属性句柄字段应设置为被通知的属性的句柄。手柄长度值元组中的“值长度”字段应设置为“属性值”字段的长度。句柄长度值元组中的属性值字段应设置为被通知的属性的值。
如果属性句柄或属性值无效,则客户端在收到此通知时应忽略该属性。
4.8 属性操作值总结
属性PDU名称 | 属性操作值 | 参数 |
ATT_ERROR_RSP
|
0x01
|
请求操作码错误, 属性句柄在错误, 错误代码 |
ATT_EXCHANGE_MTU_REQ
|
0x02
|
客户端RxMTU |
ATT_EXCHANGE_MTU_RSP
|
0x03 | 服务器RxMTU |
ATT_FIND_INFORMATION_REQ
|
0x04 | 开始句柄, 结束句柄 |
ATT_FIND_INFORMATION_RSP
|
0x05 | 格式、 信息数据 |
ATT_FIND_BY_TYPE_VALUE_REQ
|
0x06 | 起始句柄、 结束句柄、 属性类型、 属性值 |
ATT_FIND_BY_TYPE_VALUE_RSP
|
0x07 | 句柄信息表 |
ATT_READ_BY_TYPE_REQ
|
0x08 | 起始句柄, 结束句柄, UUID |
ATT_READ_BY_TYPE_RSP
|
0x09 | 长度, 属性数据列表 |
ATT_READ_REQ
|
0x0A | 属性句柄 |
ATT_READ_RSP
|
0x0B | 属性值 |
ATT_READ_BLOB_REQ
|
0x0C | 属性句柄, 值偏移 |
ATT_READ_BLOB_RSP
|
0x0D | 部分属性值 |
ATT_READ_MULTIPLE_REQ
|
0x0E | 句柄集 |
ATT_READ_MULTIPLE_RSP
|
0x0F | 值集 |
ATT_READ_BY_GROUP_TYPE_REQ
|
0x10 | 起始句柄 结束句柄 UUID |
ATT_READ_BY_GROUP_TYPE_RSP
|
0X11 | 长度 属性值表 |
ATT_WRITE_REQ
|
0X12 | 属性句柄 属性值 |
ATT_WRITE_RSP
|
0X13 | - |
ATT_WRITE_CMD
|
0X52 | 属性句柄 属性值 |
ATT_PREPARE_WRITE_REQ
|
0X16 | 属性句柄 值偏移 部分属性值 |
ATT_PREPARE_WRITE_RSP
|
0X17 | 属性句柄 值偏移 部分属性值 |
ATT_EXECUTE_WRITE_REQ
|
0X18 | 标志位 |
ATT_EXECUTE_WRITE_RSP
|
0X19 | - |
ATT_READ_MULTIPLE_VARIABLE_-
REQ
|
0X20 | 句柄集 |
ATT_READ_MULTIPLE_VARIABLE_-
RSP
|
0X21 | 长度值图列表 |
ATT_MULTIPLE_HANDLE_VALUE_-
NTF
|
0X23 | 句柄长度值元组列表 |
ATT_HANDLE_VALUE_NTF
|
0X1B | 属性句柄、属性值 |
ATT_HANDLE_VALUE_IND
|
0X1D | 属性句柄、属性值 |
ATT_HANDLE_VALUE_CFM
|
0X1E | - |
ATT_SIGNED_WRITE_CMD
|
0XD2 | 属性句柄、 属性值 身份验证签名 |
4.9 属性PDU响应总结
表给出了允许的属性PDU方法响应的摘要。每个方法都表示应该作为成功响应发送的方法,以及是否可以作为响应发送ATT_ERROR_RSPPDU。如果可以发送ATT_ERROR_RSPPDU,那么表还指示了对于给定方法在此ATT_ERROR_RSPPDU中有效的错误码。
属性PDU方法 | 成功的响应PDU | 允许ATT_ERROR_RSP | 有效错误码 |
ATT_EXCHANGE_ MTU_REQ
|
ATT_EXCHANGE_MTU_RSP
|
Yes | 不支持请求 |
ATT_FIND_- INFORMATION_- REQ
|
ATT_FIND_INFORMATION_
RSP
|
Yes | 句柄无效, 数据库不同步, 不支持请求, 未找到属性 |
ATT_FIND_BY_- TYPE_- VALUE_REQ
|
ATT_FIND_BY_TYPE_VALUE_-
RSP
|
Yes | 句柄无效、 数据库不同步、 请求不支持、 未找到属性、 授权不足、 身份验证不足、 加密不足、 加密密钥大小不足 不允许读取、 应用程序错误 |
ATT_READ_REQ
|
ATT_READ_RSP
|
Yes | 句柄无效、 数据库不同步、 授权不足、 身份验证不足、 加密不足、 加密密钥大小不足、 允许读取、 应用程序错误 |
ATT_READ_ BLOB_REQ
|
ATT_READ_BLOB_RSP
|
Yes | 无效句柄、 数据库不同步、 请求不支持、 授权不足、 身份验证不足、 加密不足、 加密密钥大小不足、 不允许读取、 无效偏移量、 属性不长、 应用程序错误 |
ATT_READ_ MULTIPLE_REQ
|
ATT_READ_MULTIPLE_RSP
|
Yes | 句柄无效、 数据库不同步、 请求不支持、 授权不足、 认证不足、 加密不足、 加密密钥大小不足、 允许读取、 应用程序错误 |
ATT_READ_BY_ GROUP_TYPE_-
REQ
|
ATT_READ_BY_GROUP_TYPE_RSP
|
Yes | 句柄无效、 数据库不同步、 请求不支持、 未找到属性、 授权不足、 身份验证不足、 加密不足、 加密密钥大小读取不足、不支持的组类型、 应用程序错误 |
ATT_READ_- MULTIPLE_ VARIABLE_REQ
|
ATT_READ_-MULTIPLE_VARIABLE_RSP
|
Yes | 句柄无效、 数据库不同步、 请求不支持、 授权不足、 认证不足、 加密不足、 加密密钥大小不足、 允许读取、 应用程序错误 |
ATT_WRITE_REQ
|
ATT_WRITE_-
RSP
|
Yes | 句柄无效、 数据库不同步、 请求不支持、 授权不足、 身份验证不足、 加密不足、 加密密钥大小不足、 不允许写入、 属性值长度无效、 应用程序错误 |
ATT_WRITE_CMD
|
N/A
|
NO | |
ATT_SIGNED_ WRITE_CMD
|
N/A | NO | |
ATT_PREPARE_ WRITE_REQ
|
ATT_PREPARE _WRITE_RSP
|
Yes | 无效的句柄、 数据库不同步、 请求不支持、 授权不足、 身份验证不足、 不允许写入、 准备队列完整、 加密不足、 加密密钥大小不足、应用程序错误 |
ATT_EXECUTE_ WRITE_REQ
|
ATT_EXECUTE _WRITE_RSP
|
Yes | 应用程序错误, 无效的偏移量, 属性值长度无效 |
ATT_HANDLE_ VALUE_NTF
|
N/A | NO | |
ATT_HANDLE_ VALUE_IND
|
ATT_HANDLE_VALUE_CFM
|
NO | |
ATT_MULTIPLE_ HANDLE_VALUE_-
NTF
|
N/A | NO |
5.安全
属性协议可用于访问在属性被读写之前可能需要授权和经过身份验证和加密的物理链接的信息。
如果在客户端未被授权访问此信息时发出此类请求,服务器应发送一个错误代码设置为授权不足的ATT_ERROR_RSPPDU。本部分中未定义访问给定属性的授权要求。每个设备的实现都将决定授权发生的方式。授权程序在GAP中定义,并可以在更高的层规范中进一步细化。
如果在物理链路未经身份验证时发出这样的请求,服务器应发送一个ATT_ERROR_RSPPDU,错误代码设置为认证不足。想要读写此属性的客户端可以请求对物理链接进行身份验证,一旦完成,将再次发送该请求。
属性协议可用于通知或指示在执行属性通知或指示之前可能需要经过身份验证和加密的物理链接的属性的值。想要通知或指示此属性的服务器可以请求对物理链接进行身份验证,一旦完成,就发送通知或指示。
设备支持的属性列表不被认为是私有或机密信息,因此应始终允许ATT_FIND_INFORMATION_REQPDU。这意味着在ATT_FIND_INFORMATION_REQPDU的ATT_ERROR_RSPPDU中不应使用错误代码授权不足或授权不足的身份验证。
例如,属性值可以允许任何设备读取,但只能由经过身份验证的设备写入。实现应该考虑到这一点,而不是假设仅仅因为它可以读取属性的值,它就将能够写入该值。类似地,仅仅因为一个属性值可以被写入,并不意味着一个属性值也可以被读取。每个单独属性都可能有不同的安全要求。
当客户端访问属性时,在服务器上执行的检查顺序将产生安全影响。在执行任何其他检查之前,服务器应检查身份验证和授权要求。
注意:例如,如果不先执行身份验证和授权要求检查,则可以通过发送客户端无法访问的属性的重复ATT_READ_BLOB_REQpdu来确定属性的大小,因为将返回错误代码无效偏移或身份验证不足。
文章来源: xintiaobao.blog.csdn.net,作者:心跳包,版权归原作者所有,如需转载,请联系作者。
原文链接:xintiaobao.blog.csdn.net/article/details/120493123
- 点赞
- 收藏
- 关注作者
评论(0)