simplegattprofile

 

UUID,就是用来唯一识别一个特征值的ID.

handle,就是对应的attribute的一个句柄。

所有对特征值的操作,都是通过对UUID的搜索得到对应的handle之后,通过handle来操作特征值的。

 

添加新的特征值CHAR6

下面对主要几个文件进行修改

simpleGATTprofile.h文件添加以下定义

#define SIMPLEPROFILE_CHAR6                  5

#define SIMPLEPROFILE_CHAR6_UUID           0xFFF6

#define SIMPLEPROFILE_CHAR6_LEN          5(单字节没这句)

 

 

SIMPLEPROFILE_CHAR6 全大写case参数用到case SIMPLEPROFILE_CHAR6

SIMPLEPROFILE CHAR6

 

simpleGATTprofile.c

1、  添加特征值UUID

 

// Characteristic 6 UUID: 0xFFF6

CONST uint8 simpleProfilechar6UUID[ATT_BT_UUID_SIZE] =

LO_UINT16(SIMPLEPROFILE_CHAR6_UUID),   //低八位

HI_UINT16(SIMPLEPROFILE_CHAR6_UUID) }; //高八位

 

/**************#define HI_UINT16(a)   (((a) >> 8) & 0xFF)*******

/**************#define LO_UINT16(a)  ((a) & 0xFF)*******

 

SIMPLEPROFILE CHAR6 uuid

2、  设置属性    

 

// Simple Profile Characteristic 6 Properties 可读可写(声明而已,只是能让lightblue在列表中显示为可读可写或通知,真正要改在属性表那里改。Props= PropertiesDesp=Description

 

static uint8 simpleProfileChar6Props GATT_PROP_READ | GATT_PROP_WRITE;

 

// Characteristic 6 Value   // simpleProfileChar6是个5位数组,接收数据后存在这

static uint8simpleProfileChar6[SIMPLEPROFILE_CHAR6_LEN] = { 0, 0, 0, 0, 0 };

 

// Simple Profile Characteristic 6 User Description

static uint8 simpleProfileChar6UserDesp[17] = "Characteristic 6\0";

                                                                                                                           

4

3、  属性表 Profile Attributes - Table最重要,添加了这个才会在lightblue中列表出来

 

static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED]

这里要把数组改为

#define SERVAPP_NUM_ATTR_SUPPORTED       20 原来是17

                                     //添加了3组结构体数组CHAR6

simpleProfileAttrTbl表中,可读可写属性都是3个数组,只有char4的通知是4组,多了个// Characteristic 4 configuration

 

5

并把CHAR6添加进去

 // Characteristic 6 Declaration (声明,没加这个lightblue属性表找不到)

   {

     { ATT_BT_UUID_SIZE, characterUUID },

     GATT_PERMIT_READ,

     0,

     &simpleProfileChar6Props

   },

// Characteristic Value 6   (特征值)!!!

     

       { ATT_BT_UUID_SIZE, simpleProfilechar6UUID },

       GATT_PERMIT_READ | GATT_PERMIT_WRITE,  //设置可读可写

       0, 

       simpleProfileChar6 //由于值是5位数组,不用&,一个字节就用

     },

 // Characteristic 6 User Description  //描述

     

       { ATT_BT_UUID_SIZE, charUserDescUUID },

       GATT_PERMIT_READ, 

       0, 

       simpleProfileChar6UserDesp 

     },

 

6

能列出来了但是 点进去会报错,还没设置读写参数simpleProfile_WriteAttrCB, 

simpleProfile_ReadAttrCB

 

 

4、设置参数函数 SimpleProfile_SetParameter函数

 

 

bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )中:

//即修改SimpleProfile_SetParameter();函数

7

 

 

添加以下代码:

case SIMPLEPROFILE_CHAR6:

     if ( len == SIMPLEPROFILE_CHAR6_LEN ) //特征值赋值到数组

     {

       VOID osal_memcpy(simpleProfileChar6, value, SIMPLEPROFILE_CHAR6_LEN );

 //把要改写的数据写到simpleProfileChar6数组来

     }

     else

     {

       ret = bleInvalidRange;

     }

     break;

 

 

8

 

4、  获取参数函数 {SimpleProfile_GetParameterUUID,获取到的值)函数}

                 实际上就是把被新进的值simpleProfileChar6放进value数组

 

bStatus_tSimpleProfile_GetParameter( uint8 param, void *value )中添加:

 

case SIMPLEPROFILE_CHAR6:

     VOID osal_memcpy( value, simpleProfileChar6, SIMPLEPROFILE_CHAR6_LEN );

break;

 

//读取simpleProfileChar6的值放到*value中,char1是单个字节读取,为

*((uint8*)value) = simpleProfileChar1;

9

 

·        6、读写特征值函数2个回调函数

·        这个两个是注册到GATT层的回调函数,GATT初始化的时候注册的.这部分代码封装在库里面.

每当GATT层有数据发过来的时候,会调用simpleProfile_WriteAttrCB, 

每当GATT层收到对方读取数据请求的时候,会调用simpleProfile_ReadAttrCB

这两个函数包含在gattServiceCBs_t类型的结构体里CONST gattServiceCBs_t simpleProfileCBs

simpleProfile_ReadAttrCB

这个设置后就能在lightblue里读出值,值为

simpleProfileChar6[SIMPLEPROFILE_CHAR6_LEN]={数组的数值(16进制显示)}

 

simpleProfile_WriteAttrCB

读取被写进去的值

 

 

 

static uint8 simpleProfile_ReadAttrCB( uint16 connHandle,

                                      gattAttribute_t *pAttr,

                                      uint8 *pValue,  

                                      uint8 *pLen, 

                                      uint16 offset, 

                                      uint8 maxLen )中:

添加 case SIMPLEPROFILE_CHAR6_UUID:

       *pLen = SIMPLEPROFILE_CHAR6_LEN;

       VOID osal_memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR6_LEN );

      break;        //读:pAttr->pValue的内容复制到pValue

      

10

添加单字节char7要在接char13后面,不能加break

11

 

simpleProfile_WriteAttrCB()中添加(添加后发送过去就不会提示出错了)

 case SIMPLEPROFILE_CHAR6_UUID: 

           //Validate the value检测输入数据是否合法

       // Make sure it's not a blob oper

       if ( offset == 0 )//是第一字节

       {

         if ( len != SIMPLEPROFILE_CHAR6_LEN )

         {

           status = ATT_ERR_INVALID_VALUE_SIZE;

         }//若输入长度不对,status

       }

       else

       {

         status = ATT_ERR_ATTR_NOT_LONG;//不是第一字节

       }

    //Write the value一开始定义了status == SUCCESS,若上述条件不符,不会运行到这里。osal_memcpy(目的A,源地址B,长度)复制B内容到A

 

       if ( status == SUCCESS )

        

       VOID osal_memcpy( pAttr->pValue, pValue, SIMPLEPROFILE_CHAR6_LEN );

       notifyApp = SIMPLEPROFILE_CHAR6;

         //写:pValue的内容复制到pAttr->pValue(别弄反了)

       break;

 

 

(下面没用到)osal_memset为字符串集体赋同一数值 return目的存储区地址

void *osal_memset(void *dest, uint8 value , intlen)

{

Return memset(dest,value,len);

}

 

if ( status == SUCCESS )

        

uint8 *pCurValue = (uint8 *)pAttr->pValue;

osal_memset(pCurValue, 0, SIMPLEPROFILE_CHAR6_LEN );

                                         //为新数组pCurValue赋值N0

VOID osal_memcpy(pCurValue, pValue, SIMPLEPROFILE_CHAR6_LEN );

                                   //复制pValue内容到新数组pCurValue                notifyApp = SIMPLEPROFILE_CHAR6;                                                                                           

 }

 break;

 

12

 

7 .simpleBLEperipheral.c添加初始化值

 

void SimpleBLEPeripheral_Init( uint8 task_id )函数中初始化参数

13

 

现在可以在手机设备中读取CHAR6的值为0x0102030405

char6写进0x3344556677 再读取值已经改写为0x3344556677

脱离枯燥的理论来感受ISO15765-4协议

The parameter dataIdentifier (DID) logically represents an object (e.g., Air Inlet Door Position) or collection of objects. This parameter shall be available in the server's memory. The dataIdentifier value shall either exist in fixed memory or temporarily stored in RAM if defined dynamically by the service dynamicallyDefineDataIdentifier. In general, a dataIdentifier is capable of being utilized in many diagnostic service requests including 0x22 (readDataByIdentifier), 0x2E (writeDataByIdentifier), and 0x2F (inputOutputControlByIdentifier). A dataIdentifier is also used in various diagnostic service responses (e.g., positive response to service 0x19 subfunction readDTCSnapshotRecordByDTCNumber).
IMPORTANT — Regardless of which service a dataIdentifier is used with, it shall consistently
represent the same thing (i.e., a given object with a given size / meaning / etc.) on a given ECU.