博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BLE4.0教程四 新增特征值(CC2541)
阅读量:5159 次
发布时间:2019-06-13

本文共 9417 字,大约阅读时间需要 31 分钟。

  注:(本文基于我自己定义的一个服务TEMProfile,但适用其他服务)

 

1.特征值是什么

  一个蓝牙协议栈中,包含了多个服务,一个服务里又包含了多个特征值,每个特征值都有其相关的一些信息。

  我们与蓝牙进行通信的时候,就是通过读写这些特征值,来获得数据。

 

2.特征值的属性

  一个特征值里面基本需要的变量是——

  1.UUID码  

  2.权限属性 :基本就是 可读、可写、可通知这些了。(通知是表示允许数据主动发送)

  3.内容

  4.描述:这个特征值的名称

 

3.属性表

  一个服务里,所有的特征值中的每个变量都有相应的属性,所有的属性都放在一个数组中,这个数组称之为属性表

  

 

  一个变量的属性表包含四个内容,

  1.type   2.permission   3.handle   4.pValue

  

  属性表其实就是定义了一个 gattAttribute_t类型的数组。

 

  需要注意的是,属性表中,除了特征值的属性,第一个还要添加服务的属性

 

1   //TEMProfile Service2   {3     {ATT_BT_UUID_SIZE,primaryServiceUUID},    //type4     GATT_PERMIT_READ,                         //permissions5     0,                                        //handle6     (uint8*)&TEMProfileService                //pValue7   },

 

 

4.增添一个新的特征值

  (1)Define出配置属性的数值,用以填写配置属性。

1 // Profile Parameters 2 #define TEMPROFILE_CHAR1                      0 3 #define TEMPROFILE_CHAR2                      1 4  5 // Simple Profile Service UUID 6 #define TEMPROFILE_SERV_UUID                  0xFF00 7  8 // Key Pressed UUID 9 #define TEMPROFILE_CHAR1_UUID                 0xFF0110 #define TEMPROFILE_CHAR2_UUID                 0xFF0211 12 // Simple Keys Profile Services bit fields13 #define TEMPROFILE_SERVICE                    0x0000000114 15 // Length of Characteristic 2 in bytes16 #define TEMPROFILE_CHAR2_LEN                  12

 

  其中UUID号有特定的范围,应避免与其他服务UUID冲突。

  这里增添了两个特征值,特征值2是数组型的,所以需要定义一个长度TEMPROFILE_CHAR2_LEN。                  

  

 (2)定义每个特征值的属性变量(以特征值2为例)

 

1 static  uint8 TEMProfileChar2Prop = GATT_PROP_READ ;2 // TEM Profile char2 Value3 static  uint8 TEMProfileChar2[TEMPROFILE_CHAR2_LEN] = {
0};4 // TEM Profile char2 Description5 static uint8 TEMProfileChar2Desp[6]="Data\0";

  配置权限,内容,描述。

  

 (3)由于属性表中的Value属性比较特殊,需要将其UUID号定义出来。具体原因暂时不是很理解。

1 CONST uint8 TEMProfilechar2UUID[ATT_BT_UUID_SIZE]=2 {3   LO_UINT16(TEMPROFILE_CHAR2_UUID),HI_UINT16(TEMPROFILE_CHAR2_UUID)4 };

  

 (4)填写属性表

1 static gattAttribute_t  TEMProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED]= 2 { 3   //TEMProfile Service 4   { 5     {ATT_BT_UUID_SIZE,primaryServiceUUID},   //type 6     GATT_PERMIT_READ,                        //permissions 7     0,                                       //handle 8     (uint8*)&TEMProfileService              //pValue 9   },10   11   //char 1 Declaration12   {13     {ATT_BT_UUID_SIZE,characterUUID},   14     GATT_PERMIT_READ,                        15     0,                                       16     &TEMProfileChar1Prop              17   },  18   19   //char 1 Value20   {21     {ATT_BT_UUID_SIZE,TEMProfilechar1UUID},   // !! Attribue Value UUID need definition  22     GATT_PERMIT_READ  | GATT_PERMIT_WRITE,                        23     0,                                       24     &TEMProfileChar1              25   },  26   27   //char 1 Description28    {29     {ATT_BT_UUID_SIZE,charUserDescUUID},   30     GATT_PERMIT_READ,                        31     0,                                       32     TEMProfileChar1Desp              33   },  34   35   //char 2 Declaration36   {37     {ATT_BT_UUID_SIZE,characterUUID},   38     GATT_PERMIT_READ,                        39     0,                                       40     &TEMProfileChar2Prop              41   },  42   43   //char 2 Value44   {45     {ATT_BT_UUID_SIZE,TEMProfilechar2UUID},   // !! Attribue Value UUID need definition  46     GATT_PERMIT_READ,                        47     0,                                       48     TEMProfileChar2              49   },  50   51   //char 2 Description  52     {53     {ATT_BT_UUID_SIZE,charUserDescUUID},   54     GATT_PERMIT_READ,                        55     0,                                       56     TEMProfileChar2Desp              57     },  58    59 };

  注意:  这里每个属性都有一个权限属性(如GATT_PERMIT_READ),之前定义特征值时也有一个权限变量(如GATT_PROP_WRITE) 两者作用对象不一样。

       可以这样理解,每个特征值都是一个大宝箱,里面还有许多个小宝箱,要打开他们需要不同的钥匙。

 

 

  至此,一个特征值的基本定义和声明就已经做完了。但我们需要使用这个特征值,所以要在调用到特征值的函数中,添加上它。

 

(5)修改Get_Parameter函数和Set_Parameter函数、ReadAttrCB函数、WriteAttrCB函数

  在服务中,基本是通过这四个函数对特征值进行读写。后两个是回调函数。

  在TEMProfile_SetParameter()函数中,新增一个case。

1 bStatus_t TEMProfile_SetParameter(  uint8 param, uint8 len,  void *value) 2 { 3   bStatus_t ret = SUCCESS; 4   switch  ( param ) 5   { 6     case TEMPROFILE_CHAR1 : 7       if( len == sizeof(uint8)  ) 8       { 9         TEMProfileChar1 = *((uint8*)value);10       }11       else12       {13         ret = bleInvalidRange;14       }15       break;16     17     case TEMPROFILE_CHAR2 :18       if( len == TEMPROFILE_CHAR2_LEN )19       {20          VOID osal_memcpy( TEMProfileChar2, value, TEMPROFILE_CHAR2_LEN );21       }22       else23       {24         ret = bleInvalidRange;25       }26       break;  27       28     default  :29       ret = INVALIDPARAMETER;30       break;31   }32   33   return ret;34 35  }

  这是一个设置特征值内容的函数,参数param是特征值,len是内容的长度,value是新内容的地址。

  以特征值2为例,先判断新内容的长度是否符合原先特征值定义的内容长度。如果一致,则将新内容填写进入特征值的内容TEMProfileChar2。

   

  TEMProfile_GetParameter()函数同理

1 bStatus_t TEMProfile_GetParameter(  uint8 param,  void  *value) 2 { 3   bStatus_t ret = SUCCESS; 4   switch  ( param ) 5   { 6   case TEMPROFILE_CHAR1 : 7     *((uint8*)value)  = TEMProfileChar1; 8     break; 9     10   case TEMPROFILE_CHAR2 :11     VOID osal_memcpy( value, TEMProfileChar2, TEMPROFILE_CHAR2_LEN );12     break;13 14   default:15     ret = INVALIDPARAMETER;16     break;17   }18    19   return  (ret);20 }

 

然后是TEMProfile_WriteAttrCB()函数

1 static  bStatus_t TEMProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, 2                                        uint8 *pValue, uint8 len, uint16 offset ) 3 { 4    bStatus_t status  = SUCCESS; 5    uint8 notifyApp = 0xFF; 6        7    if  ( gattPermitAuthorWrite( pAttr->permissions ) ) 8    { 9       return ( ATT_ERR_INSUFFICIENT_AUTHOR );10    }11       12    if ( pAttr->type.len == ATT_BT_UUID_SIZE )13    {14       uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);15       switch  (uuid)16       {17          case TEMPROFILE_CHAR1_UUID:18              19            if( offset  ==  0 )    20            {21                if( len !=  1 )22                {23                   status = ATT_ERR_INVALID_VALUE_SIZE;24                }25            }26            else27            {28              status = ATT_ERR_ATTR_NOT_LONG;29            }30          31          32             if ( status == SUCCESS )33             {34               uint8 *pCurValue = (uint8 *)pAttr->pValue;        35               *pCurValue = pValue[0];36               notifyApp = TEMPROFILE_CHAR1;        37             }38         39          break;40 41          default:42             status = ATT_ERR_ATTR_NOT_FOUND;43          break;44        }         45     }46     else47     {48       status = ATT_ERR_INVALID_HANDLE;49     }50           51   if ( (notifyApp != 0xFF ) && TEMProfile_AppCBs && TEMProfile_AppCBs->pfnTEMProfileChange )52   {53     TEMProfile_AppCBs->pfnTEMProfileChange( notifyApp );  54   }55   56   return ( status );     57 }

以及ReadAttrCb函数

1 static  uint8 TEMProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,  2                                     uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ) 3 { 4   bStatus_t status  = SUCCESS; 5    6   if( gattPermitAuthorRead( pAttr->permissions)) 7   { 8     return  (ATT_ERR_INSUFFICIENT_AUTHOR); 9   }10       11   if( offset  > 0)12   {13     return  (ATT_ERR_ATTR_NOT_LONG);14   }15   16   if ( pAttr->type.len == ATT_BT_UUID_SIZE )  17   {18     uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);19     switch( uuid )20     {21       //must have read permisson22     case TEMPROFILE_CHAR1_UUID:23         *pLen =1;24         pValue[0] = *pAttr->pValue;25         break;26     27     case TEMPROFILE_CHAR2_UUID:28         *pLen = TEMPROFILE_CHAR2_LEN;29         VOID osal_memcpy( pValue, pAttr->pValue, TEMPROFILE_CHAR2_LEN );30         break; 31         32     default:33         *pLen = 0;34         status=ATT_ERR_ATTR_NOT_FOUND;35         break;36     }37   }38   else39   {40     *pLen = 0;41     status=ATT_ERR_INVALID_HANDLE;42   }43       44     return  (status);45       46 }

 

至此服务的特征值已经修改完,接下来需要去应用层进行设置。

(6)在SimpleBLEPeripheral_Init()函数中,初始化特征值。

1   uint8 TEMProfile_Char1Vaule=1;2   uint8 TEMProfile_Char2Value[TEMPROFILE_CHAR2_LEN]="2017.03.11\0";3   TEMProfile_SetParameter(  TEMPROFILE_CHAR1, sizeof(uint8),  &TEMProfile_Char1Vaule );4   TEMProfile_SetParameter(  TEMPROFILE_CHAR2, TEMPROFILE_CHAR2_LEN,  TEMProfile_Char2Value );

 

(7)回调函数simpleProfileChangeCB( )中增添特征值。

  该函数是当特征值改变时,即会被调用。

  本例中,当特征值改变时,LCD上的数据也会随之改变。

1 static void simpleProfileChangeCB( uint8 paramID ) 2 { 3   uint8 newValue; 4  5   switch( paramID ) 6   { 7     case SIMPLEPROFILE_CHAR1: 8       SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, &newValue ); 9 10       #if (defined HAL_LCD) && (HAL_LCD == TRUE)11         HalLcdWriteStringValue( "Char 1:", (uint16)(newValue), 10,  HAL_LCD_LINE_3 );12       #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)13 14       break;15 16     case SIMPLEPROFILE_CHAR3:17       SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR3, &newValue );18 19       #if (defined HAL_LCD) && (HAL_LCD == TRUE)20         HalLcdWriteStringValue( "Char 3:", (uint16)(newValue), 10,  HAL_LCD_LINE_3 );21       #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)22 23       break;24 25     default:26       // should not reach here!27       break;28   }29 }

 

 

 

至此,特征值的新增即完成了。

APP中已可以发现这两个特征值。

 

转载于:https://www.cnblogs.com/asam/p/6535374.html

你可能感兴趣的文章
新建jsp项目
查看>>
简易封装confirm $.confirm
查看>>
java笔记 chapter3 包装类,类型转换,程序的运行流程,面向对象的三大特征
查看>>
.Net基础篇_学习笔记_第四天_关系运算符和逻辑运算符
查看>>
send_signal函数注解
查看>>
模拟练习1
查看>>
判断App是否在后台运行
查看>>
为什么要在onNewIntent的时候要显示的去调用setIntent
查看>>
hive优化实战
查看>>
Django 1.10 中文文档------3.2.1 模型Models
查看>>
ip地址
查看>>
re模块的高级用法
查看>>
Intro to Python for Data Science Learning 2 - List
查看>>
js闭包
查看>>
Jenkins常用插件之Deploy Plugin
查看>>
Shell基础
查看>>
LA 3177 长城守卫
查看>>
UVa 1151 (枚举 + MST) Buy or Build
查看>>
UVa 10601 (Polya计数 等价类计数) Cubes
查看>>
数据库SQL优化大总结
查看>>