上一回我们谈到了数据传输的过程以及如何发送和接收数据,那么今天我们谈谈特征值。


首先看一下SIG给出的定义


一个特点是用属性以及如何访问该值的配置信息和关于如何的值是显示或为代表的信息服务中的值。


特征值在GATT的分类,再来看SIG的定义:


在GATT层中,一个特征是由其特性的定义定义的。特征定义包含特性的宣言、 特征属性和一个值,并且可能包含描述符描述的值或允许的特点对服务器的配置。


我们再看看 特征值是如何在协议栈中实现的。


首先我们看一下关于特征值定义的一些宏。

// Primary Service UUID  主服务的UUID  相当于一辆公交车的车牌,公交车里面又有不同的乘客,这些乘客就是主服务携带的信息 
 
 
 

   CONST uint8 primaryServiceUUID[ATT_BT_UUID_SIZE] = 
 
 
 

   { 
 
 
 

     LO_UINT16( GATT_PRIMARY_SERVICE_UUID ), HI_UINT16( GATT_PRIMARY_SERVICE_UUID ) 
 
 
 

   }; 
 
 

   // Simple GATT Profile Service UUID: 0xFFF0 
 
 
 

   CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] = 
 
 
 

   {  
 
 
 

     LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID) 
 
 
 

   }; 
 
 

   // Simple Profile Service attribute 
 
 
 

   static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID }; 
 
 
 
 
 
 
 
 
 
 
 

  //Profile  参数 

 

  #define SIMPLEPROFILE_CHAR1                    0    //RW uint8 - Profile Characteristic 1 value  

 

   // Simple Profile Service UUID   
 
 
 

   #define SIMPLEPROFILE_SERV_UUID               0xFFF0  //service 的 UUID 
 
 

   // Key Pressed UUID 
 
 
 

   #define SIMPLEPROFILE_CHAR1_UUID            0xFFF1 
 
 
 
 
 
 
  
 
 

   // Simple Profile Characteristic 1 Properties  特征值属性(读/写) 
 
 
 

   static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE; 
 
 
 
 
  
 
 

   // Characteristic 1 Value 特征值的值 
 
 
 

   static uint8 simpleProfileChar1 = 0; 
 
 
 
 
  
 
 

   // Simple Profile Characteristic 1 User Description 特征值的用户说明 
 
 
 

   static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1\0"; 
 
 
 
 
 

  定义了特征值所需要的相关宏以后,我们需要将特征值填写到特征值列表中, 

 
 
  
 
 

   static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =  
 
 
 

   { 
 
 
 

     // Simple Profile Service 
 
 
 

     {  
 
 
 

       { ATT_BT_UUID_SIZE, primaryServiceUUID }, 
 
 
 

       GATT_PERMIT_READ,                         
 
 
 

       0,                                         
 
 
 

       (uint8 *)&simpleProfileService             
 
 
 

     },//公交车信息。。。。。。。。。。。。。。。。。。。。。。。 
 
 
 
 
  
 
 

       // Characteristic 1 Declaration   声明特征值 
 
 
 

       {  
 
 
 

         { ATT_BT_UUID_SIZE, characterUUID }, 
 
 
 

         GATT_PERMIT_READ,  
 
 
 

         0, 
 
 
 

         &simpleProfileChar1Props  
 
 
 

       }, 
 
 
 
 
  
 
 

         // Characteristic Value 1  值 
 
 
 

         {  
 
 
 

           { ATT_BT_UUID_SIZE, simpleProfilechar1UUID }, 
 
 
 

           GATT_PERMIT_READ | GATT_PERMIT_WRITE,  
 
 
 

           0,  
 
 
 

           &simpleProfileChar1  
 
 
 

         }, 
 
 
 
 
  
 
 

         // Characteristic 1 User Description特征值的用户说明 
 
 
 

         {  
 
 
 

           { ATT_BT_UUID_SIZE, charUserDescUUID }, 
 
 
 

           GATT_PERMIT_READ,  
 
 
 

           0,  
 
 
 

           simpleProfileChar1UserDesp  
 
 
 

         },       
 
 

  };

这样 就把特征值添加到列表中了,如果我们需要添加其他的一些特征值,可以直接在Characteristic 1后 类似的连接Characteristic 2 Characteristic 3 Characteristic 4 等等。是不是很简单啊,照葫芦画瓢,一看就会, 是吧?


读取服务的值,需要知道服务的UUID或者Handle;写服务的值,需要知道服务的Hanle;写服务描述符,需要知道该Descriptor的Hanle。



如何知道一个服务的Handle?



根据服务的UUID调用API函数GATT_ReadUsingCharUUID协议栈会返回该服务的Handle。特别注意的是,一个服务的Descriptor的Handle总是该服务的Handle+1,如电池电量服务的Handle是0x0025,那么它的Descriptor的Handle是0x0026。


获取Handle:

attReadByTypeReq_t req; 

 

           simpleBLEDiscState = BLE_DISC_STATE_CHAR; 
 
 
 

           req.startHandle = simpleBLESvcStartHdl; 
 
 
 

           req.endHandle = simpleBLESvcEndHdl; 
 
 
 

           req.type.len = ATT_BT_UUID_SIZE; 
 
 
 

           req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID); 
 
 
 

           req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID); 
 
 
 

           GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId );


把读到的数据拆包,提取handle的值:


 simpleBLECharHdl = 


BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] );



写数据:


attWriteReq_t req;     
 
 
 

               req.handle = simpleBLECharHdl; 
 
 
 

               req.len = 1; 
 
 
 

               req.value[0] = simpleBLECharVal; 
 
 
 

               req.sig = 0; 
 
 
 

               req.cmd = 0; 
 
 
 

               status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );


最后说一下我的理解:


特征值就是蓝牙提供给外设进行数据交互的接口。通过写摸个特征值,就可以把数据传给对方,通过读特征值就能读到对方的数据。



其实刚刚还想到点什么  被一同学打个岔   结果忘了。。。。  先救这样凑合吧,至少这是我对特征值的了解,不过不过全面,希望有缘的朋友能够给予补充。