BLE透传

BLE工程——透明传输Profile编写(一个特征)

在之前的《BLE工程——透明传输Profile编写(两个特征)》一文中,讲述了透传模块的Profile文件。它包含了一个服务,及这个服务的两个特征,其中一个特征用来发送数据,另一个特征用来接收数据。这个Profile文件功能上虽然没有的任何问题,但是实际上却还不够专业,原因有二:一是它修改自官网例程中的的simpleGATTProfile文件,文件中的变量函数都保留着原先的命名;二是它用了两个特征,实际上一个特征足以,市面上的大多串口透传模块使用的Profile都只使用了一个特征的。所以下面就要重新编写只用一个特征实现的透传模块的Profile文件。

用一个特征实现的Profile文件的图示如下。这个特征实现收发一体的思路是:该特征同时具有可通知(Notify)和无响应写(write with out response)的权限。可通过向这个特征写数据来达到接收数据的功能,特征通过发送通知来实现发送数据的功能。

BLE工程——透明传输Profile编写(一个特征) - ziye334 - ziye334的博客

 下面就按照上述的思路编写Profile文件。

1、透传的方式通常是串口,所以新建两个文件,分别取名为:SeialNetProfile.c和SerialNetProfile.h。

2、打开SeialNetProfile.h文件,这个文件主要做一些相关的定义及相关函数的生命,如下:

(1)定义特征值的参数的索引值。

#define SERIALNETPROFILE_TRX 0

(2)定义回调函数类型。

typedef void (*serialNetChange_t)( uint8 paramID, uint8 len );

typedef struct

{

  serialNetChange_t        pfnSerialNetProfileChange; 

} serialNetProfileCBs_t;

(3)声明函数。

extern bStatus_t SerialNetProfile_AddService( void );

extern bStatus_t SerialNetProfile_RegisterAppCBs( serialNetProfileCBs_t *appCallbacks );

extern bStatus_t SerialNetProfile_GetParameter( uint8 param, void *value, uint8 len );

3、打开SerialNetProfile.c文件,对文件进行编程。

4、添加头文件,如下:

#include "bcomdef.h"

#include "OSAL.h"

#include "linkdb.h"

#include "att.h"

#include "gatt.h"

#include "gatt_uuid.h"

#include "gattservapp.h"

#include "gapbondmgr.h"

#include "SerialNetProfile.h"

5、定义服务及特征的UUID。

(1)定义透传Profile的服务及特征默认的UUID分别为0xFFE0、0xFFE1。

uint16 serialNetProfile_serv_uuid = 0xFFE0;

uint16 serialNetProfile_trx_uuid = 0xFFE1;

(2)用于保存服务特征UUID在属性中的结构。

uint8 serialNetProfileServUUID[ATT_BT_UUID_SIZE];

uint8 serialNetProfileTRxUUID[ATT_BT_UUID_SIZE];

6、定义服务特征相关的静态变量。

(1)定义回调函数。

static serialNetProfileCBs_t *serialNetProfile_AppCBs = NULL;

(2)定义服务属性。

static CONST gattAttrType_t serialNetProfileService = { ATT_BT_UUID_SIZE, serialNetProfileServUUID };

(3)定义特征的属性。

a.特征权限设置为:可通知、无响应写。

static uint8 serialNetProfileTRxProps = GATT_PROP_WRITE_NO_RSP | GATT_PROP_NOTIFY;

(这里的一定要是无响应的写。)

b.特征的特征值。

static uint8 serialNetProfileTRx[20] = { 0 }; 

c.特征的特征配置。

static gattCharCfg_t serialNetProfileTRxConfig[GATT_MAX_NUM_CONN];

d.特征的用户描述

static uint8 serialNetProfileTRxUserDesp[8] = "Tx&Rx\0";

7、定义Profile的属性。

#define SERVAPP_NUM_ATTR_SUPPORTED 5

gattAttribute_t serialNetProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =

{

  ......

}

(1)定义服务的属性。

  { ATT_BT_UUID_SIZE, primaryServiceUUID }, 

  GATT_PERMIT_READ,  

  0, 

  (uint8 *)&serialNetProfileService 

},

(2)定义特征的属性。

a.特征的声明。

  { ATT_BT_UUID_SIZE, characterUUID },

  GATT_PERMIT_READ, 

  0,

  &serialNetProfileTRxProps 

},

b.特征的特征值。

  { ATT_BT_UUID_SIZE, serialNetProfileTRxUUID },

  GATT_PERMIT_READ | GATT_PERMIT_WRITE, 

  0, 

  serialNetProfileTRx 

},

c.特征的特征配置。

  { ATT_BT_UUID_SIZE, clientCharCfgUUID },

  GATT_PERMIT_READ | GATT_PERMIT_WRITE, 

  0, 

  (uint8 *)serialNetProfileTRxConfig 

},

d.特征的用户描述。

  { ATT_BT_UUID_SIZE, charUserDescUUID },

  GATT_PERMIT_READ, 

  0, 

  serialNetProfileTRxUserDesp 

},

8、定义Profile的服务的回调函数,

CONST gattServiceCBs_t serialNetProfileCBs =

{

  NULL,                   /* Read callback function pointer */

  SerialNetProfile_WriteAttrCB,  /* Write callback function pointer */

  NULL                   /* Authorization callback function pointer */

};

由于特征只有无响应写权限和可通知的权限,所以这里只要注册写回调函数。

9、编写注册服务的函数SeialNetProfile_AddSerive()如下:

bStatus_t SerialNetProfile_AddService( void )

{

  uint8 status = SUCCESS;

 

  /* Set service and characteristic UUID for attribute */

  serialNetProfileServUUID[0] = LO_UINT16(serialNetProfile_serv_uuid);

  serialNetProfileServUUID[1] = HI_UINT16(serialNetProfile_serv_uuid);

  serialNetProfileTRxUUID[0] = LO_UINT16(serialNetProfile_trx_uuid);

  serialNetProfileTRxUUID[1] = HI_UINT16(serialNetProfile_trx_uuid);

  

  /* Initialize Client Characteristic Configuration attributes */

  GATTServApp_InitCharCfg( INVALID_CONNHANDLE, serialNetProfileTRxConfig );

 

  /* Register with Link DB to receive link status change callback */

  VOID linkDB_Register( SerialNetProfile_HandleConnStatusCB );  

 

  /* Register GATT attribute list and CBs with GATT Server App */

  status = GATTServApp_RegisterService( serialNetProfileAttrTbl, 

                 GATT_NUM_ATTRS( serialNetProfileAttrTbl ),

                                   &serialNetProfileCBs );

 

  return ( status );

}

10、编写注册应用回调函数的函数SerialNetProfile_RegisterAppCBs(),如下:

bStatus_t SerialNetProfile_RegisterAppCBs( serialNetProfileCBs_t *appCallbacks )

{

  if ( appCallbacks )

  {

    serialNetProfile_AppCBs = appCallbacks;

    

    return ( SUCCESS );

  }

  else

  {

    return ( bleAlreadyInRequestedMode );

  }

}

11、编写获取Profile参数的函数SerialNetProfile_GetParamer(),如下:

bStatus_t SerialNetProfile_GetParameter( uint8 param, void *value, uint8 len )

{

  bStatus_t ret = SUCCESS;

  switch ( param )

  {

    case SERIALNETPROFILE_TRX:

      osal_memcpy(value, serialNetProfileTRx, len);

      break;      

      

    default:

      ret = INVALIDPARAMETER;

      break;

  }

  

  return ( ret );

}

12、编写写特征属性的回调函数SerialNetProfile_WriteAttrCBs(),如下:

static bStatus_t SerialNetProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset )

{

  bStatus_t status = SUCCESS;

  uint8 notifyApp = 0xFF;

  

  /* If attribute permissions require authorization to write, return error */

  if ( gattPermitAuthorWrite( pAttr->permissions ) )

  {

    /* Insufficient authorization */

    return ( ATT_ERR_INSUFFICIENT_AUTHOR );

  }

  

  if ( pAttr->type.len == ATT_BT_UUID_SIZE )

  {

    /* 16-bit UUID */

    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);

    

    if (uuid == serialNetProfile_trx_uuid)

    {

      /* Write the value */

      if ( status == SUCCESS )

      {

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

        osal_memcpy(pCurValue, pValue, len);

 

        if( pAttr->pValue == serialNetProfileTRx )

        {

          notifyApp = SERIALNETPROFILE_TRX;        

        }

      }

    }

    else if (uuid == GATT_CLIENT_CHAR_CFG_UUID)

    {

      status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue,

                              len,offset, GATT_CLIENT_CFG_NOTIFY );

    }

    else

    {

      status = ATT_ERR_ATTR_NOT_FOUND;

    }

  }

  else

  {

    /* 128-bit UUID */

    status = ATT_ERR_INVALID_HANDLE;

  }

 

  if ( (notifyApp != 0xFF ) && serialNetProfile_AppCBs &&

     serialNetProfile_AppCBs->pfnSerialNetProfileChange )

  {

    serialNetProfile_AppCBs->pfnSerialNetProfileChange( notifyApp,  len);  

  }

  

  return ( status );

}

13、编写Profile连接状态改变处理函数SerialNetProfile_HandleConnStatus(),如下:

static void SerialNetProfile_HandleConnStatusCB( uint16 connHandle, uint8 changeType )

  /* Make sure this is not loopback connection */

  if ( connHandle != LOOPBACK_CONNHANDLE )

  {

    /* Reset Client Char Config if connection has dropped */

    if ( ( changeType == LINKDB_STATUS_UPDATE_REMOVED )      ||

         ( ( changeType == LINKDB_STATUS_UPDATE_STATEFLAGS ) && 

           ( !linkDB_Up( connHandle ) ) ) )

    { 

      GATTServApp_InitCharCfg( connHandle, serialNetProfileTRxConfig );

    }

  }

}

如上就是蓝牙透传所需的Profile文件。使用该Profile的蓝牙模块,连接手机后,会显示如下:

BLE工程——透明传输Profile编写(一个特征) - ziye334 - ziye334的博客

 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值