1、 gattAttribute_t 是一个结构体数据类型,里面存放了各种类型的数据。 现在 看看 TI 是怎么描述的,如下:
1 /** 2 * @brief GATT Attribute format. 3 * 4 * @note 5 * The list must start with a Service attribute followed by 6 * all attributes associated with this Service attribute. 7 */ 8 typedef struct attAttribute_t 9 { 10 gattAttrType_t type; //!< Attribute type (2 or 16 octet UUIDs) 11 uint8 permissions; //!< Attribute permissions 12 uint16 handle; //!< Attribute handle - assigned internally by attribute server 13 uint8* const pValue; //!< Attribute value - encoding of the octet array is defined in 14 //!< the applicable profile. The maximum length of an attribute 15 //!< value shall be 512 octets. 16 } gattAttribute_t;
表1-0
上面 解释的 第一个 成员可能 不是很详细,我们 来看下 源码:
/// @brief GATT Attribute Type format. typedef struct { uint8 len; //!< Length of UUID (2 or 16) 长度是 两个字节 或者 16个字节 const uint8 *uuid; //!< Pointer to UUID 指向 2个 或者 16个字节 buff 指针 } gattAttrType_t;
gattAttrType_t: Where length can be eitherATT_BT_UUID_SIZE
(2 bytes), orATT_UUID_SIZE
(16 bytes). The *uuid is a pointer to a
number either reserved by Bluetooth SIG (defined in gatt_uuid.c) or a custom UUID defined in the profile.
总结: 这个成员 实际含义 是 描述 服务的 类型, 服务类型 也是 UUID , 官方蓝牙组织 SIG 规定, UUID 值 0x2800 代表 主服务,UUID 值 0x2803 代表 特征值, 详细看下表
表 1-1
2、TI 在 simple_gatt_profile.c 文件中 利用 这个gattAttribute_t 数据类型 定义了一个 数组 simpleProfileAttrTbl , 这个数组 暂且理解为 存放 我们自定义的 蓝牙服务 以及该服务 拥有 的 特征值 。
/********************************************************************* * Profile Attributes - Table */ static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED];
那 这个 数组 放了 什么 东西 那 , 我 们 来 分析 分析 。
- 这个 数组 的 第一个 元素 如下:(按照 上面 gattAttribute_t 结构体 中文 解释 分析 ,看下面注释)
// Simple Profile Service,1 1 { { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type 值是0x2800,即属性类型是 主服务类型, 更多类型看 上面的 表1-1*/ GATT_PERMIT_READ, /* permissions,权限为可读权限,意思是:允许GATT客户端在设置权限的情况下读取此服务 */ 0, /* handle 默认为0,因为这个句柄是协议栈自动分配的,不可以自定义,因此默认初始化为0*/ (uint8 *)&simpleProfileService /* pValue: 是一个 gattAttrType_t 类型的值,即 {2,0xFFF0} */ },
总结: 该 元素是 一个 主服务类型, 服务的 UUID 的值 是 0xFFF0 ,该服务 具有 可读权限。
UUID : 具有以下几种含义
- 服务或者特征值的 唯一ID
- 用于 区分 是 服务 还是特征值 还是 …………具体 看 上面的 表 1-1
- 这个数组的 第二个 元素如下:(注:我 的是这个 ,其他的我删除了,同个类型的 没啥 差别)
// Characteristic 5 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, /* type,属性类型 是特征值类型,详看 表1-1 */ GATT_PERMIT_READ, /* 可读 */ 0, &simpleProfileChar5Props /* 这个 查看定义是 uint8 simpleProfileChar5Props = GATT_PROP_WRITE; 应该理解为 特征值 具有可写的属性 */ },
总结 : 这里 有 歧义, GATT_PERMIT_READ 这个描述的 是 数组 这个元素 具有的 权限 是 可读 或者 可写(详见表1-0), simpleProfileChar5Props 这个变量 描述 的 是 该数组元素 代表的特征值 具有 可写 的属性 (详见表1-2) ,一个是权限 一个 是 属性。
这个 元素 可以理解为 : 描述 特征值 uuid 为 0XFFF1 具有 写入的属性,即 手机APP 可以 往这个 特征值写入数据。
表 1-2
- 该数组 第三个 元素 是 如
// Characteristic Value 5 { { ATT_BT_UUID_SIZE, simpleProfilechar5UUID }, /* 该类型设置为自定义的simpleProfilechar1 UUID(0xFFF5)。 */ GATT_PERMIT_WRITE, /* 属性表中特征值的属性必须与特征值声明中的属性匹配,这里的意思是: 改特征值 具有 可以 写的权限 , 要和 第二元素 中 的uint8 simpleProfileChar5Props = GATT_PROP_WRITE 可写的 属性 必须保持一致,否则就会造成系统混乱 */
0,
simpleProfileChar5 },
总结 :
/* 属性表中特征值的属性必须与特征值声明中的属性匹配,这里的意思是: 改特征值 具有 可以 写的权限 , 要和 第二元素 中 的uint8 simpleProfileChar5Props = GATT_PROP_WRITE 可写的 属性 必须保持一致,否则就会造成系统混乱 */