自定义杰理AC63系列BLE数据发送函数

自定义BLE数据发送函数,就是将数据发送、数据发送前的检查、以及conn_handle查询等封装在一起,脱离SDK中的相关回调函数,在程序任意位置实现发送数据功能。

1. SDK中的BLE数据发送函数

BLE的数据发送函数定义在apps\common\third_party_profile\jieli\gatt_common\le_gatt_common.c文件里。

int ble_comm_att_send_data(u16 conn_handle, u16 att_handle, u8 *data, u16 len, att_op_type_e op_type)
{
    gatt_op_ret_e ret = GATT_OP_RET_SUCESS;
    u16 tmp_16;

    if (!conn_handle) {
        return GATT_CMD_PARAM_ERROR;
    }

    switch (op_type) {
    case ATT_OP_READ:
        tmp_16  = 0x55A1;//fixed
        ret = ble_op_multi_att_send_data(conn_handle, att_handle, &tmp_16, 2, op_type);
        break;

    case ATT_OP_READ_LONG:
        tmp_16  = 0x55A2;//fixed
        ret = ble_op_multi_att_send_data(conn_handle, att_handle, &tmp_16, 2, op_type);
        break;

    default:
        ret = ble_op_multi_att_send_data(conn_handle, att_handle, data, len, op_type);
        break;
    }

    if (ret) {
        const char *err_string;

        int error_id = (int)0 - (int)GATT_CMD_RET_BUSY + (int)ret;
        if (error_id >= 0 && error_id < sizeof(gatt_op_error_string) / sizeof(char *)) {
            err_string = gatt_op_error_string[error_id];
        } else {
            err_string = "UNKNOW GATT_ERROR";
        }

        log_error("att_send_fail: %d!!!,%s", ret, err_string);
        log_error("param:%04x, %04x, %02x,len= %d", conn_handle, att_handle, op_type, len);
        /* put_buf(data,len); */
    }
    return ret;
}

该数据发送函数出现在apps\spp_and_le\examples\trans_data\ble_trans.c文件下的write_callback 回调函数里。写入回调函数如下,注意,无关代码已经省略。

2. ATT写入回调函数

在手机或其他设备(Client角色)发送数据到AC63时,会进入注册过的回调函数trans_att_write_callback( );SDK例程中在该回调函数里执行了自动收发测试代码。

static int trans_att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)
{
    int result = 0;
    u16 tmp16;
    u16 handle = att_handle;
    switch (handle) {
     		//...此处省略1万字
	   case ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE:

        log_info("\n-ae01_rx(%d):", buffer_size);
        put_buf(buffer, buffer_size);        
        //收发测试,自动发送收到的数据;for test
        if (ble_comm_att_check_send(connection_handle, buffer_size) &&
            ble_gatt_server_characteristic_ccc_get(trans_con_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE)) {
            log_info("-loop send1\n");
            ble_comm_att_send_data(connection_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, buffer, buffer_size, ATT_OP_AUTO_READ_CCC);
        }
        break;
 		//...此处省略1万字
    default:
        break;
    }
    return 0;
}

自动收发测试代码里使用ble_comm_att_check_send( )函数检查发送缓存够不够用,同时使用ble_gatt_server_characteristic_ccc_get( )函数检查特征的NOTIFY属性是否得到了Client端的许可。如果任意一个条件不满足,均不会发送数据。

3. 发送缓存检查

为了避免内存溢出,导致不可预见的异常发生,必须检查数组长度是否超出了可用缓存大小。

/********************************************************************/
/*!
 *  \brief      检查预备发送的数据包长度是否能填入
/*******************************************************/
bool ble_comm_att_check_send(u16 conn_handle, u16 pre_send_len)
{
    if (ble_comm_cbuffer_vaild_len(conn_handle) >= pre_send_len) {
        return true;
    } else {
        return false;
    }
}

/******************************************************************/
/*!
 *  \brief       获取配置的cbuffer 可以填入数据长度
 */
/**************************************************************/
u32 ble_comm_cbuffer_vaild_len(u16 conn_handle)
{
    u32 vaild_len = 0;
    ble_op_multi_att_get_remain(conn_handle, &vaild_len);
    return vaild_len;
}

4. NOTIFY属性是否得到许可检查

NOTIFY属性是需要在建立连接后,由手机端写入1许可通知的。该函数用于检查是否得到Client许可。

/*************************************************************************************************/
/*!
 *  \brief      获取 notify or indicate 通知使能值
 *
 *  \param      [in]
 *
 *  \return     return
 GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE
 GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION
 GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION
 *
 *  \note
 */
/*************************************************************************************************/
u16 ble_gatt_server_characteristic_ccc_get(u16 conn_handle, u16 att_ccc_handle)
{
    return multi_att_get_ccc_config(conn_handle, att_ccc_handle);
}

5. 查询当前连接的handle

该函数返回值为连接的句柄。如果当前没有连接,则返回0。index是句柄在数组里的序号,默认从0开始。如果只有一个连接,则index为0。role是连接状态下的角色,分为server和client两种。

/*************************************************************************************************/
/*!
 -  \brief      获取index对应的连接 handle
 */
/*************************************************************************************************/
u16 ble_comm_dev_get_handle(u8 index, u8 role)
{
    u16 *group_handle;
    u8 count;

    if (GATT_ROLE_SERVER == role) {
        group_handle = gatt_server_conn_handle;
        count = SUPPORT_MAX_GATT_SERVER;
    } else {
        group_handle = gatt_client_conn_handle;
        count = SUPPORT_MAX_GATT_CLIENT;
    }

    if (index < count) {
        return group_handle[index];
    } else {
        return 0;
    }
}

6. 自定义BLE发送数据函数

  • 先查询当前是否建立了BLE连接,如果无连接,则直接返回。
  • 检查发送缓存是否够用,如果不够,则直接返回。
  • 检查NOTIFY值是否被Client开启,如未开启,则直接返回。
/*****************************************************************************/
/*!
 -  \brief      user defined ble data send fun
 - u8* sdata	point of data to be send 
 - u8 len		the size of data to be send 
 */
/***************************************************************************/

void my_ble_send_data(u8* sdata,u8 len)
{
    //先查明当前连接的conn_handle
    u16 connection_handle = ble_comm_dev_get_handle(0, GATT_ROLE_SERVER);
    printf("connection_handle: %04x\n",connection_handle);
    if(connection_handle==0)//无连接
    {
        return;
    }
        //检查预备发送的数据包长度是否能填入,并且获取 notify or indicate 通知使能值
    if (ble_comm_att_check_send(connection_handle, len) &&
    ble_gatt_server_characteristic_ccc_get(connection_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE))
    {
        printf("permit send...\n");
        //使用notify方式发送
        ble_comm_att_send_data(connection_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, sdata, len, ATT_OP_NOTIFY);
    }
}

7. 小结

自定义BLE数据发送函数是将原来SDK中分散的几个函数集合到一起,完成独立的数据发送功能。其中 ble_comm_att_send_data( )函数是最主要的,其他几个是辅助该函数完成任务的。
BLE发送函数里,有个需要注意的地方是ATT的handle,这个值是由BLEprofile里的服务特征表里的数值决定的,如果该值不一致,数据发送会失败。
BLE的profile文件在:apps\spp_and_le\examples\trans_data\ble_trans_profile.h。服务特征表如下:

static const uint8_t trans_profile_data[] = {
    //
    //
    // 0x0001 PRIMARY_SERVICE  1800
    //
    //
    0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18,

    /* CHARACTERISTIC,  2a00, READ | WRITE | DYNAMIC, */
    // 0x0002 CHARACTERISTIC 2a00 READ | WRITE | DYNAMIC
    0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0a, 0x03, 0x00, 0x00, 0x2a,
    // 0x0003 VALUE 2a00 READ | WRITE | DYNAMIC
    0x08, 0x00, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x2a,

    //
    //
    // 0x0004 PRIMARY_SERVICE  1801
    //
    //
    0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x01, 0x18,

    /* CHARACTERISTIC,  2a05, INDICATE, */
    // 0x0005 CHARACTERISTIC 2a05 INDICATE
    0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x20, 0x06, 0x00, 0x05, 0x2a,
    // 0x0006 VALUE 2a05 INDICATE
    0x08, 0x00, 0x20, 0x00, 0x06, 0x00, 0x05, 0x2a,
    // 0x0007 CLIENT_CHARACTERISTIC_CONFIGURATION
    0x0a, 0x00, 0x0a, 0x01, 0x07, 0x00, 0x02, 0x29, 0x00, 0x00,

    //
    //
    // 0x0008 PRIMARY_SERVICE  ae30
    //
    //
    0x0a, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x28, 0x30, 0xae,

    /* CHARACTERISTIC,  ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */
    // 0x0009 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC
    0x0d, 0x00, 0x02, 0x00, 0x09, 0x00, 0x03, 0x28, 0x04, 0x0a, 0x00, 0x31, 0xae,
    // 0x000a VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC
    0x08, 0x00, 0x04, 0x01, 0x0a, 0x00, 0x31, 0xae,

    /* CHARACTERISTIC,  ae02, NOTIFY, */
    // 0x000b CHARACTERISTIC ae02 NOTIFY
    0x0d, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x28, 0x10, 0x0c, 0x00, 0x32, 0xae,
    // 0x000c VALUE ae02 NOTIFY
    0x08, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x32, 0xae,
    // 0x000d CLIENT_CHARACTERISTIC_CONFIGURATION
    0x0a, 0x00, 0x0a, 0x01, 0x0d, 0x00, 0x02, 0x29, 0x00, 0x00,
    
//...此处省略1万字

   // END
    0x00, 0x00,
};

你可能感兴趣的:(蓝牙,BLE,蓝牙,杰理,AC63,数据发送)