1.att容器数据结构需要考虑到的东西
1.1属性类型
UUID
- 公开的数据有许多不同的类型,数据的类型称为属性类型
- 为了区分如此多的属性类型,可以用一串128b的通用唯一识别码(UUID)来标识属性的类型。这样识别数据类型需要发送长达16B的数据。
- 为了提高传输速率,蓝牙技术联盟(SIG)定义了一个称为“蓝牙UUID基数”的128b通用唯一识别码,结合一个较短的16b数使用。在设备间传输常用的UUID时,只发送较短的16b版本,接收后补上蓝牙UUID的基数即可。
蓝牙UUID基数为:
00000000 - 000 - 1000 - 800 - 00805F9B34FB
要发送16b识别码xxxx时,完整的128b的UUID为:
0000xxxx - 000 - 1000 - 800 - 00805F9B34FB 蓝牙基础UUID数组设计的时候要注意是小印第安序来存放的
// Buetooth Base UUID 00000000-0000-1000-8000-00805F9B34FB in little endian
static const uint8_t bluetooth_base_uuid[] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
小印第安序:数据的低地址上存放的是这个整数的低位字节,在高地址上存放的是整数的高位字节。
地址 | 0x0000 | 0x0001 | 0x0002 | 0x0003 |
---|---|---|---|---|
Big endian | 0x12 | 0x34 | 0x56 | 0x78 |
little endian | 0x78 | 0x56 | 0x34 | 0x12 |
1.2属性句柄
handle
- 服务器上的所有属性都会分配一个非零的属性句柄。客户端与服务器之间的操作使用句柄来区分属性
- 新的属性不能被分配一个已使用的句柄,即使曾使用过这个句柄的属性已被删除。这可以保证客户端总是可以获取一个唯一独特的额属性句柄
- 一旦一个属性被分配了一个句柄,那么任何时候都应该保持这个句柄不变,以使得客户端可以使用同一个句柄持续访问相应的属性
- 属性服务器的属性按照句柄来排序。句柄0x0000被保留,0xFFFF是最大的属性句柄
1.3属性值
value value_len
- 属性值是一个包含属性实际值得8b组阵列。属性长度可以是固定的,也可以不定的。固定长度时,长度可以是8b,16b和32b。不定长度时,属性值得长度可以是0B到最长512B。
- 一个协议数据单元(PDU)只能传输一个属性值,属性值过长可以分拆到多个协议数据单元中传输。
1.4数据结构的设计
采用一种新型的java形态的设计方法
typedef struct att_iterator{
//private
uint8_t cosnt *att_ptr;//数据的起始
//public
uint16_t size;
uint16_t flags;//用来确定是16位的还是128位的UUID
uint16_t handle;//属性句柄
uint8_t const *uuid;
uint16_t value_len;
uint8_t const *value;
}att_iterator_t;
static void att_iterator_init(att_iterator_t *it){
it->att_ptr = att_db;
}
static int att_iterator_has_next(att_iterator_t *it){
return it->att_ptr != NULL;//判断时候有下一个属性
}
static void att_iterator_fetch_next(att_iterator_it *it){
it->size = read_little_endian_16(it->att_ptr, 0);
if(it->size == 0){
it->flags = 0;
it->handle = 0;
it->uuid = NULL;
it->value_len = 0;
it->value = NULL;
it->att_ptr = NULL;
return;//读取这个空的属性就可以返回了
}
it->flags = read_little_endian_16(it->att_ptr, 2);
it->handle = read_little_endian_16(it->att_ptr, 4);
it->uuid = &it->att_ptr[6];
if(it->flags & ATT_PROPERTY_UUID128){//当flag == 0x02时候成立
it->value_len = it->size - 22;
it->value = &it->att_ptr[22];
}else{
it->value_len = it->size - 8;
it->value = &it->att_ptr[8];
}
it->att_ptr += it->size;
}
#define read_little_endian_16(buffer, pos) (((uint16_t)buffer[pos]) || (((uint16_t)(buffer[(pos) + 1]) << 8))
#define ATT_PROPERTY_UUID128 0x200
ATT连接
void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
buffer[pos++] = value;
buffer[pos++] = value >> 8;
}
typedef struct att_connection {
uint16_t con_handle;
uint16_t mtu; // initialized to ATT_DEFAULT_MTU (23), negotiated during MTU exchange
uint16_t max_mtu; // local maximal L2CAP_MTU, set to l2cap_max_le_mtu()
uint8_t encryption_key_size;
uint8_t authenticated;
uint8_t authorized;
} att_connection_t;