FuShenxiao 发表于 2024-8-25 16:43

小熊派BearPi-Pico H2821星闪开发板测评(五)——BLE串口透传测试

本帖最后由 FuShenxiao 于 2024-8-27 09:14 编辑

<p><span style="font-size:18px;"><b>官方案例实现</b></span></p>

<p>官方案例两块开发板实现BLE数据传输测试,A开发板通过串口接收数据,然后通过BLE传输给B开发板,B开发板通过串口将接收到的数据打印出来;同样,B开发板通过串口接收数据,然后通过BLE传输给A开发板,A开发板通过串口将接收到的数据打印出来。在测试中需要一块开发板做为Server端,另外一块开发板做为Client端,两块开发板配对后即可互发消息。连接方式如下</p>

<p align="center"> &nbsp;</p>

<p><span style="font-size:16px;"><b>配置</b><b>BLE UART Server</b></span></p>

<p>选择BLE UART Server样例</p>

<p align="center"> &nbsp;</p>

<p align="center"> &nbsp;</p>

<p>选择协议</p>

<p align="center"> &nbsp;</p>

<p align="center"> &nbsp;</p>

<p>完成配置,退出配置环境进行编译</p>

<p><span style="font-size:16px;"><b>配置</b><b>BLE UART Client</b></span></p>

<p>选择BLE UART Client样例</p>

<p align="center"> &nbsp;</p>

<p>选择协议</p>

<p align="center"> &nbsp;</p>

<p>完成配置,退出配置环境进行编译</p>

<p><span style="font-size:16px;"><b>Server</b><b>初始化</b></span></p>

<p>首先进行SDK初始化</p>

<p align="center"> &nbsp;</p>

<p>初始化并启动BLE任务</p>

<p align="center"> &nbsp;</p>

<p>配置并启动ADV,最终开启BLE服务</p>

<p style="text-align: center;"> &nbsp;</p>

<p><span style="font-size:16px;"><b>Client</b><b>初始化</b></span></p>

<p>首先进行SDK初始化</p>

<p align="center"> &nbsp;</p>

<p>交换mtu信息,并与Server建立联系</p>

<p align="center"> &nbsp;</p>

<p>Client发现特征</p>

<p align="center"> &nbsp;</p>

<p>Client发现特征描述符</p>

<p align="center"> &nbsp;</p>

<p>Client收到读响应</p>

<p align="center"> &nbsp;</p>

<p><span style="font-size:16px;"><b>Client</b><b>初始化完成后</b><b>Server</b><b>的日志显示</b></span></p>

<p>可以看到mtu交换</p>

<p align="center"> &nbsp;</p>

<p><span style="font-size:16px;"><b>发送测试</b></span></p>

<p><b>Server发送</b><b>Client接收</b></p>

<p align="center"> &nbsp;</p>

<p><b>Client</b><b>发送</b><b>Server</b><b>接收</b></p>

<p align="center"></p>

<p align="center">&nbsp;</p>

<p style="text-align: justify;"><span style="font-size:18px;"><strong>代码实现</strong></span></p>

<p style="text-align: justify;"><strong><span style="font-size:16px;">ble_uart_server代码</span></strong></p>

<pre>
<code>#include "osal_addr.h"
#include "osal_debug.h"
#include "product.h"
#include "securec.h"
#include "errcode.h"
#include "uart.h"
#include "bts_def.h"
#include "bts_device_manager.h"
#include "bts_gatt_stru.h"
#include "bts_gatt_server.h"
#include "bts_le_gap.h"
#include "ble_uart_server_adv.h"
#include "ble_uart_server.h"

/* uart gatt server id */
#define BLE_UART_SERVER_ID                         1
/* uart ble connect id */
#define BLE_SINGLE_LINK_CONNECT_ID         1
/* octets of 16 bits uart */
#define UART16_LEN                                         2
/* invalid attribute handle */
#define INVALID_ATT_HDL                         0
/* invalid server ID */
#define INVALID_SERVER_ID                         0

#define BLE_UART_SERVER_LOG ""
#define BLE_UART_SERVER_ERROR ""
#define BLE_UART_SERVICE_NUM 3

static uint16_t g_ble_uart_conn_id;
static uint8_t g_ble_uart_name_value[] = { 'b', 'l', 'e', '_', 'u', 'a', 'r', 't', '\0' };
static uint8_t g_uart_server_app_uuid[] = { 0x00, 0x00 };
static uint8_t g_ble_uart_server_addr[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
static uint8_t g_server_id = INVALID_SERVER_ID;
static uint8_t g_connection_state = 0;
static uint16_t g_notify_indicate_handle = 0;
static uint8_t g_service_num = 0;

/* 将uint16的uuid数字转化为bt_uuid_t */
static void bts_data_to_uuid_len2(uint16_t uuid_data, bt_uuid_t *out_uuid)
{
    out_uuid-&gt;uuid_len = UART16_LEN;
    out_uuid-&gt;uuid = (uint8_t)(uuid_data &gt;&gt; 8); /* 8: octet bit num */
    out_uuid-&gt;uuid = (uint8_t)(uuid_data);
}

/* 设置注册服务时的name */
void ble_uart_set_device_name_value(const uint8_t *name, const uint8_t len)
{
    size_t len_name = sizeof(g_ble_uart_name_value);
    if (memcpy_s(g_ble_uart_name_value, len_name, name, len) != EOK) {
      osal_printk("%s memcpy name fail\n", BLE_UART_SERVER_ERROR);
    }
}

/* 创建服务 */
static void ble_uart_add_service(void)
{
    bt_uuid_t uart_service_uuid = { 0 };
    bts_data_to_uuid_len2(BLE_UART_UUID_SERVER_SERVICE, &amp;uart_service_uuid);
    gatts_add_service(BLE_UART_SERVER_ID, &amp;uart_service_uuid, true);
}

/* 添加uart发送服务的所有特征和描述符 */
static void ble_uart_add_tx_characters_and_descriptors(uint8_t server_id, uint16_t srvc_handle)
{
    osal_printk("%s TX characters:%d srv_handle:%d \n", BLE_UART_SERVER_LOG, server_id, srvc_handle);
    bt_uuid_t characters_uuid = { 0 };
    uint8_t characters_value[] = { 0x12, 0x34 };
    bts_data_to_uuid_len2(BLE_UART_CHARACTERISTIC_UUID_TX, &amp;characters_uuid);
    gatts_add_chara_info_t character;
    character.chara_uuid = characters_uuid;
    character.properties = GATT_CHARACTER_PROPERTY_BIT_NOTIFY | GATT_CHARACTER_PROPERTY_BIT_READ;
    character.permissions = GATT_ATTRIBUTE_PERMISSION_READ | GATT_ATTRIBUTE_PERMISSION_WRITE;
    character.value_len = sizeof(characters_value);
    character.value = characters_value;
    gatts_add_characteristic(server_id, srvc_handle, &amp;character);
    osal_printk("%s characters_uuid:%2x %2x\n", BLE_UART_SERVER_LOG, characters_uuid.uuid, characters_uuid.uuid);

    static uint8_t ccc_val[] = { 0x01, 0x00 }; // notify
    bt_uuid_t ccc_uuid = { 0 };
    bts_data_to_uuid_len2(BLE_UART_CLIENT_CHARACTERISTIC_CONFIGURATION, &amp;ccc_uuid);
    gatts_add_desc_info_t descriptor;
    descriptor.desc_uuid = ccc_uuid;
    descriptor.permissions = GATT_ATTRIBUTE_PERMISSION_READ | GATT_CHARACTER_PROPERTY_BIT_WRITE |
      GATT_ATTRIBUTE_PERMISSION_WRITE;
    descriptor.value_len = sizeof(ccc_val);
    descriptor.value = ccc_val;
    gatts_add_descriptor(server_id, srvc_handle, &amp;descriptor);
    osal_printk("%s ccc_uuid:%2x %2x\n", BLE_UART_SERVER_LOG, characters_uuid.uuid, characters_uuid.uuid);
}

/* 添加uart接收服务的所有特征和描述符 */
static void ble_uart_add_rx_characters_and_descriptors(uint8_t server_id, uint16_t srvc_handle)
{
    osal_printk("%s RX characters:%d srv_handle: %d \n", BLE_UART_SERVER_LOG, server_id, srvc_handle);
    bt_uuid_t characters_uuid = { 0 };
    uint8_t characters_value[] = { 0x12, 0x34 };
    bts_data_to_uuid_len2(BLE_UART_CHARACTERISTIC_UUID_RX, &amp;characters_uuid);
    gatts_add_chara_info_t character;
    character.chara_uuid = characters_uuid;
    character.properties = GATT_CHARACTER_PROPERTY_BIT_READ | GATT_CHARACTER_PROPERTY_BIT_WRITE_NO_RSP;
    character.permissions = GATT_ATTRIBUTE_PERMISSION_READ | GATT_ATTRIBUTE_PERMISSION_WRITE;
    character.value_len = sizeof(characters_value);
    character.value = characters_value;
    gatts_add_characteristic(server_id, srvc_handle, &amp;character);
    osal_printk("%s characters_uuid:%2x %2x\n", BLE_UART_SERVER_LOG, characters_uuid.uuid, characters_uuid.uuid);

    bt_uuid_t ccc_uuid = { 0 };
    /* uart client characteristic configuration value for test */
    static uint8_t ccc_val[] = { 0x00, 0x00 };
    bts_data_to_uuid_len2(BLE_UART_CLIENT_CHARACTERISTIC_CONFIGURATION, &amp;ccc_uuid);
    gatts_add_desc_info_t descriptor;
    descriptor.desc_uuid = ccc_uuid;
    descriptor.permissions = GATT_ATTRIBUTE_PERMISSION_READ | GATT_ATTRIBUTE_PERMISSION_WRITE;
    descriptor.value_len = sizeof(ccc_val);
    descriptor.value = ccc_val;
    gatts_add_descriptor(server_id, srvc_handle, &amp;descriptor);
    osal_printk("%s ccc_uuid:%2x %2x\n", BLE_UART_SERVER_LOG, characters_uuid.uuid, characters_uuid.uuid);
}

bool bts_uart_compare_uuid(bt_uuid_t *uuid1, bt_uuid_t *uuid2)
{
    if (uuid1-&gt;uuid_len != uuid2-&gt;uuid_len) {
      return false;
    }
    if (memcmp(uuid1-&gt;uuid, uuid2-&gt;uuid, uuid1-&gt;uuid_len) != 0) {
      return false;
    }
    return true;
}

/* 服务添加回调 */
static void ble_uart_server_service_add_cbk(uint8_t server_id, bt_uuid_t *uuid, uint16_t handle, errcode_t status)
{
    osal_printk("%s add characters_and_descriptors cbk service:%d, srv_handle:%d, uuid_len:%d, status:%d, uuid:",
                BLE_UART_SERVER_LOG, server_id, handle, uuid-&gt;uuid_len, status);
    for (int8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x ", uuid-&gt;uuid);
    }
    osal_printk("\n");
    ble_uart_add_tx_characters_and_descriptors(server_id, handle);
    ble_uart_add_rx_characters_and_descriptors(server_id, handle);
    gatts_start_service(server_id, handle);
}

/* 特征添加回调 */
static void ble_uart_server_characteristic_add_cbk(uint8_t server_id, bt_uuid_t *uuid, uint16_t service_handle,
                                                   gatts_add_character_result_t *result, errcode_t status)
{
    osal_printk("%s add character cbk service:%d service_hdl: %d char_hdl: %d char_val_hdl: %d uuid_len: %d \n",
                BLE_UART_SERVER_LOG, server_id, service_handle, result-&gt;handle, result-&gt;value_handle, uuid-&gt;uuid_len);
    osal_printk("uuid:");
    for (int8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x ", uuid-&gt;uuid);
    }
    bt_uuid_t characters_cbk_uuid = { 0 };
    bts_data_to_uuid_len2(BLE_UART_CHARACTERISTIC_UUID_TX, &amp;characters_cbk_uuid);
    characters_cbk_uuid.uuid_len = uuid-&gt;uuid_len;
    if (bts_uart_compare_uuid(uuid, &amp;characters_cbk_uuid)) {
      g_notify_indicate_handle = result-&gt;value_handle;
    }
    osal_printk("%s status:%d indicate_handle:%d\n", BLE_UART_SERVER_LOG, status, g_notify_indicate_handle);
}

/* 描述符添加回调 */
static void ble_uart_server_descriptor_add_cbk(uint8_t server_id, bt_uuid_t *uuid, uint16_t service_handle,
                                             uint16_t handle, errcode_t status)
{
    osal_printk("%s service:%d service_hdl: %d desc_hdl: %d uuid_len: %d \n",
                BLE_UART_SERVER_LOG, server_id, service_handle, handle, uuid-&gt;uuid_len);
    osal_printk("uuid:");
    for (int8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x ", (uint8_t)uuid-&gt;uuid);
    }
    osal_printk("%s status:%d\n", BLE_UART_SERVER_LOG, status);
}

/* 开始服务回调 */
static void ble_uart_server_service_start_cbk(uint8_t server_id, uint16_t handle, errcode_t status)
{
    g_service_num++;
    if ((g_service_num == BLE_UART_SERVICE_NUM) &amp;&amp; (status == 0)) {
      osal_printk("%s start service cbk , start adv\n", BLE_UART_SERVER_LOG);
      ble_uart_set_adv_data();
      ble_uart_start_adv();
    }
    osal_printk("%s start service:%2d service_hdl: %d status: %d\n",
                BLE_UART_SERVER_LOG, server_id, handle, status);
}

static void ble_uart_receive_write_req_cbk(uint8_t server_id, uint16_t conn_id, gatts_req_write_cb_t *write_cb_para,
                                           errcode_t status)
{
    osal_printk("%s ble uart write cbk server_id:%d, conn_id:%d, status%d\n",
      BLE_UART_SERVER_LOG, server_id, conn_id, status);
    osal_printk("%s ble uart write cbk len:%d, data:%s\n",
                BLE_UART_SERVER_LOG, write_cb_para-&gt;length, write_cb_para-&gt;value);
    if ((write_cb_para-&gt;length &gt; 0) &amp;&amp; write_cb_para-&gt;value) {
      uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(write_cb_para-&gt;value), write_cb_para-&gt;length, 0);
    }
}

static void ble_uart_receive_read_req_cbk(uint8_t server_id, uint16_t conn_id, gatts_req_read_cb_t *read_cb_para,
    errcode_t status)
{
    osal_printk("%s ReceiveReadReq--server_id:%d conn_id:%d\n", BLE_UART_SERVER_LOG, server_id, conn_id);
    osal_printk("%s request_id:%d, att_handle:%d offset:%d, need_rsp:%d, is_long:%d\n",
                BLE_UART_SERVER_LOG, read_cb_para-&gt;request_id, read_cb_para-&gt;handle, read_cb_para-&gt;offset,
                read_cb_para-&gt;need_rsp, read_cb_para-&gt;is_long);
    osal_printk("%s status:%d\n", BLE_UART_SERVER_LOG, status);
}

static void ble_uart_mtu_changed_cbk(uint8_t server_id, uint16_t conn_id, uint16_t mtu_size, errcode_t status)
{
    osal_printk("%s MtuChanged--server_id:%d conn_id:%d\n", BLE_UART_SERVER_LOG, server_id, conn_id);
    osal_printk("%s mtusize:%d, status:%d\n", BLE_UART_SERVER_LOG, mtu_size, status);
}

static void ble_uart_server_adv_enable_cbk(uint8_t adv_id, adv_status_t status)
{
    osal_printk("%s adv enable cbk adv_id:%d status:%d\n", BLE_UART_SERVER_LOG, adv_id, status);
}

static void ble_uart_server_adv_disable_cbk(uint8_t adv_id, adv_status_t status)
{
    osal_printk("%s adv disable adv_id: %d, status:%d\n", BLE_UART_SERVER_LOG, adv_id, status);
}

void ble_uart_server_connect_change_cbk(uint16_t conn_id, bd_addr_t *addr, gap_ble_conn_state_t conn_state,
                                        gap_ble_pair_state_t pair_state, gap_ble_disc_reason_t disc_reason)
{
    g_ble_uart_conn_id = conn_id;
    g_connection_state = (uint8_t)conn_state;
    osal_printk("%s connect state change conn_id: %d, status: %d, pair_status:%d, addr %x disc_reason %x\n",
                BLE_UART_SERVER_LOG, conn_id, conn_state, pair_state, addr, disc_reason);
    if (conn_state == GAP_BLE_STATE_CONNECTED) {
      return;
    } else if (conn_state == GAP_BLE_STATE_DISCONNECTED) {
      ble_uart_set_adv_data();
      ble_uart_start_adv();
    }
}
void ble_uart_server_pair_result_cb(uint16_t conn_id, const bd_addr_t *addr, errcode_t status)
{
    osal_printk("%s pair result conn_id: %d, status: %d, addr %x \n",
                BLE_UART_SERVER_LOG, conn_id, status, addr);
}

void ble_uart_server_power_on_cbk(uint8_t status)
{
    osal_printk("ble power on: %d\n", status);
    enable_ble();
}

void ble_uart_server_enable_cbk(uint8_t status)
{
    osal_printk("ble enable: %d\n", status);
    errcode_t ret = 0;
    bt_uuid_t app_uuid = { 0 };
    bd_addr_t ble_addr = { 0 };
    app_uuid.uuid_len = sizeof(g_uart_server_app_uuid);
    if (memcpy_s(app_uuid.uuid, app_uuid.uuid_len, g_uart_server_app_uuid, sizeof(g_uart_server_app_uuid)) != EOK) {
      osal_printk("%s add server app uuid memcpy failed\n", BLE_UART_SERVER_ERROR);
      return;
    }
    ble_addr.type = BLE_PUBLIC_DEVICE_ADDRESS;
    if (memcpy_s(ble_addr.addr, BD_ADDR_LEN, g_ble_uart_server_addr, sizeof(g_ble_uart_server_addr)) != EOK) {
      osal_printk("%s add server app addr memcpy failed\n", BLE_UART_SERVER_ERROR);
      return;
    }
    gap_ble_set_local_name(g_ble_uart_name_value, sizeof(g_ble_uart_name_value));
    gap_ble_set_local_addr(&amp;ble_addr);
    ret = gatts_register_server(&amp;app_uuid, &amp;g_server_id);
    if ((ret != ERRCODE_BT_SUCCESS) || (g_server_id == INVALID_SERVER_ID)) {
      osal_printk("%s add server failed\r\n", BLE_UART_SERVER_ERROR);
      return;
    }
    ble_uart_add_service(); /* 添加uart服务 */
    osal_printk("%s beginning add service\r\n", BLE_UART_SERVER_LOG);
    bth_ota_init();
}

static errcode_t ble_uart_server_register_callbacks(void)
{
    bts_dev_manager_callbacks_t dev_mgr_cb = { 0 };
    gap_ble_callbacks_t gap_cb = { 0 };
    gatts_callbacks_t service_cb = { 0 };

    dev_mgr_cb.power_on_cb = ble_uart_server_power_on_cbk;
    dev_mgr_cb.ble_enable_cb = ble_uart_server_enable_cbk;
    gap_cb.start_adv_cb = ble_uart_server_adv_enable_cbk;
    gap_cb.conn_state_change_cb = ble_uart_server_connect_change_cbk;
    gap_cb.stop_adv_cb = ble_uart_server_adv_disable_cbk;
    gap_cb.pair_result_cb = ble_uart_server_pair_result_cb;
    errcode_t ret = gap_ble_register_callbacks(&amp;gap_cb);
    ret |= bts_dev_manager_register_callbacks(&amp;dev_mgr_cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg gap cbk failed ret = %d\n", BLE_UART_SERVER_ERROR, ret);
      return ret;
    }

    service_cb.add_service_cb = ble_uart_server_service_add_cbk;
    service_cb.add_characteristic_cb = ble_uart_server_characteristic_add_cbk;
    service_cb.add_descriptor_cb = ble_uart_server_descriptor_add_cbk;
    service_cb.start_service_cb = ble_uart_server_service_start_cbk;
    service_cb.read_request_cb = ble_uart_receive_read_req_cbk;
    service_cb.write_request_cb = ble_uart_receive_write_req_cbk;
    service_cb.mtu_changed_cb = ble_uart_mtu_changed_cbk;
    ret = gatts_register_callbacks(&amp;service_cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg service cbk failed ret = %d\n", BLE_UART_SERVER_ERROR, ret);
      return ret;
    }
#if (CORE_NUMS &lt; 2)
    enable_ble();
#endif
    return ret;
}

void ble_uart_server_init(void)
{
    ble_uart_server_register_callbacks();
}

/* device向host发送数据:input report */
errcode_t ble_uart_server_send_input_report(uint8_t *data, uint16_t len)
{
    gatts_ntf_ind_t param = { 0 };
    uint16_t conn_id = g_ble_uart_conn_id;
    param.attr_handle = g_notify_indicate_handle;
    param.value_len = len;
    param.value = data;
    osal_printk("%s send input report indicate_handle:%d\n", BLE_UART_SERVER_LOG, g_notify_indicate_handle);
    gatts_notify_indicate(BLE_UART_SERVER_ID, conn_id, &amp;param);
    return ERRCODE_BT_SUCCESS;
}

uint8_t ble_uart_get_connection_state(void)
{
    return g_connection_state;
}</code></pre>

<p style="text-align: justify;"><strong><span style="font-size:16px;">ble_uart_server_adv代码</span></strong></p>

<pre>
<code>#include "osal_addr.h"
#include "securec.h"
#include "errcode.h"
#include "osal_debug.h"
#include "bts_def.h"
#include "bts_le_gap.h"
#include "ble_uart_server_adv.h"


/* Ble Adv type Flag length */
#define BLE_ADV_FLAG_LEN 0x03
/* Ble Adv data length */
#define BLE_GENERAL_BYTE_1 1
/* Ble Adv appearance length */
#define BLE_ADV_APPEARANCE_LENGTH 4
/* Ble Adv appearance type */
#define BLE_ADV_APPEARANCE_DATA_TYPE 0x19
/* Ble uart appearance type */
#define BLE_ADV_CATEGORY_UART_VALUE 0x0080
/* Ble uart categorylength */
#define BLE_ADV_CATEGORY_LEN 2
/* Ble name adv param type length */
#define BLE_ADV_PARAM_DATATYPE_LENGTH 1
/* Ble name adv name type */
#define BLE_ADV_LOCAL_NAME_DATA_TYPE 0x09
/* Ble name adv tx power type */
#define BLE_ADV_TX_POWER_LEVEL       0x0A
/* Ble name adv tx power response type */
#define BLE_SCAN_RSP_TX_POWER_LEVEL_LEN 0x03
/* Ble adv flag data */
#define BLE_ADV_FLAG_DATA 0x05

/* Ble adv min interval */
#define BLE_ADV_MIN_INTERVAL 0x30
/* Ble adv max interval */
#define BLE_ADV_MAX_INTERVAL 0x60
/* Ble adv handle */
#define BTH_GAP_BLE_ADV_HANDLE_DEFAULT 0x01
/* Ble adv duration */
#define BTH_GAP_BLE_ADV_FOREVER_DURATION 0

#define MAX_NAME_LENGTH 15
#define EXT_ADV_OR_SCAN_RSP_DATA_LEN 251
#define ADV_APPEA_CATOGORY_HIGH 8

#define BLE_UART_ADV_LOG ""

typedef enum ble_adv_filter_policy {
    BLE_ADV_FILTER_POLICY_SCAN_ANY_CONNECT_ANY =                     0x00,
    BLE_ADV_FILTER_POLICY_SCAN_WHITE_LIST_CONNECT_ANY =            0x01,
    BLE_ADV_FILTER_POLICY_SCAN_ANY_CONNECT_WHITE_LIST =            0x02,
    BLE_ADV_FILTER_POLICY_SCAN_WHITE_LIST_CONNECT_WHITE_LIST =       0x03
} ble_adv_filter_policy_t;

typedef enum ble_adverting_type {
    BLE_ADV_TYPE_CONNECTABLE_UNDIRECTED =                            0x00,
    BLE_ADV_TYPE_CONNECTABLE_HIGH_DUTY_CYCLE_DIRECTED =            0x01,
    BLE_ADV_TYPE_SCANNABLE_UNDIRECTED =                              0x02,
    BLE_ADV_TYPE_NON_CONNECTABLE_UNDIRECTED =                        0x03,
    BLE_ADV_TYPE_CONNECTABLE_LOW_DUTY_CYCLE_DIRECTED =               0x04
} ble_adverting_type_t;

typedef enum ble_adv_channel_map {
    BLE_ADV_CHANNEL_MAP_CH_37 =                      0x01,
    BLE_ADV_CHANNEL_MAP_CH_38 =                      0x02,
    BLE_ADV_CHANNEL_MAP_CH_39 =                      0x04,
    BLE_ADV_CHANNEL_MAP_CH_37_CH_38 =                0x03,
    BLE_ADV_CHANNEL_MAP_CH_37_CH_39 =                0x05,
    BLE_ADV_CHANNEL_MAP_CH_38_CH_39 =                0x06,
    BLE_ADV_CHANNEL_MAP_CH_DEFAULT =               0x07
} ble_adv_channel_map_t;

typedef struct {
    uint8_t length;             /* 广播数据类型长度 */
    uint8_t adv_data_type;      /* 广播数据类型 */
    uint8_t flags;            /* 广播数据标志 */
} ble_adv_flag;

typedef struct {
    uint8_t length;                           /* 设备外观数据类型长度 */
    uint8_t adv_data_type;                      /* 设备外观数据类型 */
    uint8_t catogory_id;/* 设备外观数据 */
} ble_appearance_t;

typedef struct {
    uint8_t length;             /* 广播设备名称类型长度 */
    uint8_t adv_data_type;      /* 设备名称类型 */
    int8_t *name;               /* 设备名称数据指针 */
} ble_local_name_t;

typedef struct {
    uint8_t length;             /* 广播发送功率长度 */
    uint8_t adv_data_type;      /* 广播发送数据类型 */
    uint8_t tx_power_value;   /* 广播发送数据 */
} ble_tx_power_level_t;

uint8_t g_uart_local_name[ MAX_NAME_LENGTH] = { 'b', 'l', 'e', '_', 'u', 'a', 'r', 't', '_', 's',
    'e', 'r', 'v', 'e', 'r' };

static inline uint8_t u16_low_u8(uint16_t val)
{
    return (uint8_t)((uint16_t)(val) &amp; 0xff);
}

static inline uint8_t u16_high_u8(uint16_t val)
{
    return (uint8_t)(((uint16_t)(val) &gt;&gt; ADV_APPEA_CATOGORY_HIGH) &amp; 0xff);
}

static uint8_t ble_set_adv_flag_data(uint8_t *set_adv_data_position, uint8_t max_len)
{
    ble_adv_flag adv_flags = {
      .length = BLE_ADV_FLAG_LEN - BLE_GENERAL_BYTE_1,
      .adv_data_type = 1,
      .flags = BLE_ADV_FLAG_DATA
    };
    if (memcpy_s(set_adv_data_position, max_len, &amp;adv_flags, BLE_ADV_FLAG_LEN) != EOK) {
      return 0;
    }
    return BLE_ADV_FLAG_LEN;
}

static uint8_t ble_set_adv_appearance(uint8_t *set_adv_data_position, uint8_t max_len)
{
    ble_appearance_t adv_appearance_data = {
      .length = BLE_ADV_APPEARANCE_LENGTH - BLE_GENERAL_BYTE_1,
      .adv_data_type = BLE_ADV_APPEARANCE_DATA_TYPE,
      .catogory_id = { u16_low_u8(BLE_ADV_CATEGORY_UART_VALUE), u16_high_u8(BLE_ADV_CATEGORY_UART_VALUE) }
    };
    if (memcpy_s(set_adv_data_position, max_len, &amp;adv_appearance_data, BLE_ADV_APPEARANCE_LENGTH) != EOK) {
      return 0;
    }
    return BLE_ADV_APPEARANCE_LENGTH;
}

static uint8_t ble_set_adv_name(uint8_t *set_adv_data_position, uint8_t max_len)
{
    uint8_t len = BLE_ADV_PARAM_DATATYPE_LENGTH + BLE_ADV_PARAM_DATATYPE_LENGTH;
    ble_local_name_t adv_local_name_data = {
      .length = (uint8_t)(BLE_ADV_PARAM_DATATYPE_LENGTH + sizeof(g_uart_local_name)),
      .adv_data_type = BLE_ADV_LOCAL_NAME_DATA_TYPE
    };

    if (memcpy_s(set_adv_data_position, max_len, &amp;adv_local_name_data, len) != EOK) {
      return 0;
    }
    if (memcpy_s((set_adv_data_position+len), (size_t)(max_len-len),
               g_uart_local_name, sizeof(g_uart_local_name)) != EOK) {
      return 0;
    }
    len = (uint8_t)(len + sizeof(g_uart_local_name));
    return len;
}

static uint8_t ble_set_adv_appearance_data(uint8_t *set_adv_data_position, uint8_t max_len)
{
    uint8_t idx = 0;

    idx += ble_set_adv_appearance(set_adv_data_position, max_len);
    idx += ble_set_adv_name(set_adv_data_position + idx, (max_len - idx));
    return idx;
}

static uint16_t ble_uart_server_set_adv_data(uint8_t *set_adv_data, uint8_t adv_data_max_len)
{
    uint8_t idx = 0;

    if ((set_adv_data == NULL) || (adv_data_max_len == 0)) {
      return 0;
    }

    idx += ble_set_adv_flag_data(set_adv_data, adv_data_max_len);
    idx += ble_set_adv_appearance_data(&amp;set_adv_data, adv_data_max_len - idx);
    return idx;
}

static uint16_t ble_set_scan_response_data(uint8_t *scan_rsp_data, uint8_t scan_rsp_data_max_len)
{
    uint8_t idx = 0;

    if (scan_rsp_data == NULL || scan_rsp_data_max_len == 0) {
      return 0;
    }

    /* tx power level */
    ble_tx_power_level_t tx_power_level = {
      .length = BLE_SCAN_RSP_TX_POWER_LEVEL_LEN - BLE_GENERAL_BYTE_1,
      .adv_data_type = BLE_ADV_TX_POWER_LEVEL,
      .tx_power_value = 0
    };

    if (memcpy_s(scan_rsp_data, scan_rsp_data_max_len, &amp;tx_power_level, sizeof(ble_tx_power_level_t)) != EOK) {
      return 0;
    }

    idx += BLE_SCAN_RSP_TX_POWER_LEVEL_LEN;

    /* set local name */
    scan_rsp_data = sizeof(g_uart_local_name) + BLE_GENERAL_BYTE_1;
    scan_rsp_data = BLE_ADV_LOCAL_NAME_DATA_TYPE;
    if ((idx + sizeof(g_uart_local_name)) &gt; scan_rsp_data_max_len) {
      return 0;
    }
    if (memcpy_s(&amp;scan_rsp_data, scan_rsp_data_max_len - idx, g_uart_local_name,
               sizeof(g_uart_local_name)) != EOK) {
      return 0;
    }
    idx += sizeof(g_uart_local_name);
    return idx;
}

uint8_t ble_uart_set_adv_data(void)
{
    uint8_t set_adv_data = { 0 };
    uint8_t set_scan_rsp_data = { 0 };
    gap_ble_config_adv_data_t cfg_adv_data;

    /* set adv data */
    uint16_t adv_data_len = ble_uart_server_set_adv_data(set_adv_data, EXT_ADV_OR_SCAN_RSP_DATA_LEN);
    if ((adv_data_len &gt; EXT_ADV_OR_SCAN_RSP_DATA_LEN) || (adv_data_len == 0)) {
      return 0;
    }
    /* set scan response data */
    uint16_t scan_rsp_data_len = ble_set_scan_response_data(set_scan_rsp_data, EXT_ADV_OR_SCAN_RSP_DATA_LEN);
    if ((scan_rsp_data_len &gt; EXT_ADV_OR_SCAN_RSP_DATA_LEN) || (scan_rsp_data_len == 0)) {
      return 0;
    }
    cfg_adv_data.adv_data = set_adv_data;
    cfg_adv_data.adv_length = adv_data_len;

    cfg_adv_data.scan_rsp_data = set_scan_rsp_data;
    cfg_adv_data.scan_rsp_length = scan_rsp_data_len;
    osal_printk("%s ble_uart_set_adv_data adv_handle %d, len:%d, data:%s\n",
                BLE_UART_ADV_LOG, BTH_GAP_BLE_ADV_HANDLE_DEFAULT, adv_data_len, set_adv_data);
    return gap_ble_set_adv_data(BTH_GAP_BLE_ADV_HANDLE_DEFAULT, &amp;cfg_adv_data);
}

uint8_t ble_uart_start_adv(void)
{
    errcode_t ret = ERRCODE_BT_SUCCESS;
    int adv_id = BTH_GAP_BLE_ADV_HANDLE_DEFAULT;

    gap_ble_adv_params_t adv_para = {
      .min_interval = BLE_ADV_MIN_INTERVAL,
      .max_interval = BLE_ADV_MAX_INTERVAL,
      .duration = BTH_GAP_BLE_ADV_FOREVER_DURATION,
      .peer_addr.type = BLE_PUBLIC_DEVICE_ADDRESS,
      /* 广播通道选择bitMap, 可参考BleAdvChannelMap */
      .channel_map = BLE_ADV_CHANNEL_MAP_CH_DEFAULT,
      .adv_type = BLE_ADV_TYPE_CONNECTABLE_UNDIRECTED,
      .adv_filter_policy = BLE_ADV_FILTER_POLICY_SCAN_ANY_CONNECT_ANY
    };

    (void)memset_s(&amp;adv_para.peer_addr.addr, BD_ADDR_LEN, 0, BD_ADDR_LEN);
    osal_printk("%s ble_uart_start_adv adv_id %d\n", BLE_UART_ADV_LOG, adv_id);
    ret |= gap_ble_set_adv_param(adv_id, &amp;adv_para);
    ret |= gap_ble_start_adv(adv_id);
    return ret;
}</code></pre>

<p style="text-align: justify;"><strong><span style="font-size:16px;">ble_uart_client代码</span></strong></p>

<pre>
<code>#include "securec.h"
#include "product.h"
#include "osal_debug.h"
#include "osal_addr.h"
#include "uart.h"
#include "bts_le_gap.h"
#include "bts_device_manager.h"
#include "bts_gatt_client.h"
#include "ble_uart_client_scan.h"
#include "ble_uart_client.h"

#define UUID16_LEN 2
/* Characteristic UUID */
#define BLE_UART_CHARACTER_CLIENT_UUID_TX                  0xEFEF
#define BLE_UART_CLIENT_LOG ""
#define BLE_UART_CLIENT_ERROR ""

/* client id, invalid client id is "0" */
static uint8_t g_uart_client_id = 0;
/* connection id, invalid client id is "0" */
static uint16_t g_uart_conn_id = 0;
/* max transport unit, default is 100 */
static uint16_t g_uart_mtu = 100;
/* characteristic handle */
static uint16_t g_ble_uart_chara_hanle_write_value = 0;

/* uart client app uuid for test */
static bt_uuid_t g_client_app_uuid = { UUID16_LEN, { 0 } };

/* server address for client connect */
static uint8_t g_ble_server_addr_connect[] = { 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 };

static void bts_data_to_uuid_len2(uint16_t uuid_data, bt_uuid_t *out_uuid)
{
    out_uuid-&gt;uuid_len = UUID16_LEN;
    out_uuid-&gt;uuid = (uint8_t)(uuid_data &gt;&gt; 8); /* 8: octet bit num */
    out_uuid-&gt;uuid = (uint8_t)(uuid_data);
}

/* ble client discover all service */
errcode_t ble_uart_client_discover_all_service(uint16_t conn_id)
{
    bt_uuid_t service_uuid = { 0 }; /* uuid length is zero, discover all service */
    return gattc_discovery_service(g_uart_client_id, conn_id, &amp;service_uuid);
}

/* ble client write data to server */
errcode_t ble_uart_client_write_cmd(uint8_t *data, uint16_t len, uint16_t handle)
{
    gattc_handle_value_t uart_handle_value = { 0 };
    uart_handle_value.handle = handle;
    uart_handle_value.data_len = len;
    uart_handle_value.data = data;
    osal_printk("%s ble_uart_client_write_cmd len: %d, g_uart_client_id: %x\n",
                BLE_UART_CLIENT_LOG, len, g_uart_client_id);
    for (uint16_t i = 0; i &lt; len; i++) {
      osal_printk("%02x", data);
    }
    osal_printk("\n");
    errcode_t ret = gattc_write_cmd(g_uart_client_id, g_uart_conn_id, &amp;uart_handle_value);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s gattc_write_cmd failed\n", BLE_UART_CLIENT_LOG);
      return ERRCODE_BT_FAIL;
    }
    return ERRCODE_BT_SUCCESS;
}

/* ble client set scan param callback */
void ble_uart_client_set_scan_param_cbk(errcode_t status)
{
    osal_printk("%s set scan param status: %d\n", BLE_UART_CLIENT_LOG, status);
    gap_ble_remove_all_pairs();
    ble_uart_start_scan();
}

/* ble client scan result callback */
void ble_uart_client_scan_result_cbk(gap_scan_result_data_t *scan_result_data)
{
    if (memcmp(g_ble_server_addr_connect, scan_result_data-&gt;addr.addr, sizeof(g_ble_server_addr_connect)) == 0) {
      gap_ble_stop_scan();
      osal_printk("\naddr:");
      for (uint8_t i = 0; i &lt; BD_ADDR_LEN; i++) {
            osal_printk(" %02x: ", scan_result_data-&gt;addr.addr);
      }
      bd_addr_t bt_uart_client_addr = { 0 };
      bt_uart_client_addr.type = scan_result_data-&gt;addr.type;
      if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, scan_result_data-&gt;addr.addr, BD_ADDR_LEN) != EOK) {
            osal_printk("%s add server app addr memcpy failed\r\n", BLE_UART_CLIENT_ERROR);
            return;
      }
      gap_ble_connect_remote_device(&amp;bt_uart_client_addr);
    }
}

/* ble client connect state change callback */
void ble_uart_client_connect_change_cbk(uint16_t conn_id, bd_addr_t *addr, gap_ble_conn_state_t conn_state,
                                        gap_ble_pair_state_t pair_state, gap_ble_disc_reason_t disc_reason)
{
    bd_addr_t bt_uart_client_addr = { 0 };
    bt_uart_client_addr.type = addr-&gt;type;
    g_uart_conn_id = conn_id;
    if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, addr-&gt;addr, BD_ADDR_LEN) != EOK) {
      osal_printk("%s add server app addr memcpy failed\r\n", BLE_UART_CLIENT_ERROR);
      return;
    }
    osal_printk("%s connect state change conn_id: %d, status: %d, pair_status:%d, disc_reason %x\n",
                BLE_UART_CLIENT_LOG, conn_id, conn_state, pair_state, disc_reason);

    if (conn_state == GAP_BLE_STATE_CONNECTED&amp;&amp;pair_state == GAP_BLE_PAIR_NONE) {
      osal_printk("%s connect change cbk conn_id =%d \n", BLE_UART_CLIENT_LOG, conn_id);
      gattc_exchange_mtu_req(g_uart_client_id, g_uart_conn_id, g_uart_mtu);
    } else if (conn_state == GAP_BLE_STATE_DISCONNECTED) {
      osal_printk("%s connect change cbk conn disconnected \n", BLE_UART_CLIENT_LOG);
      ble_uart_start_scan();
      return;
    }
}

/* ble client pair result callback */
void ble_uart_client_pair_result_cb(uint16_t conn_id, const bd_addr_t *addr, errcode_t status)
{
    osal_printk("%s pair result conn_id: %d,status: %d \n", BLE_UART_CLIENT_LOG, conn_id, status);
    osal_printk("addr:\n");
    for (uint8_t i = 0; i &lt; BD_ADDR_LEN; i++) {
      osal_printk("%2x", addr-&gt;addr);
    }
    osal_printk("\n");
    gattc_exchange_mtu_req(g_uart_client_id, g_uart_conn_id, g_uart_mtu);
}

void ble_uart_client_power_on_cbk(uint8_t status)
{
    osal_printk("ble power on: %d\n", status);
    enable_ble();
}

/* ble client bt stack enable callback */
void ble_uart_client_enable_cbk(uint8_t status)
{
    osal_printk("ble enable: %d\n", status);
    gattc_register_client(&amp;g_client_app_uuid, &amp;g_uart_client_id);
    ble_uart_set_scan_parameters();
}

/* ble client service discovery callback */
static void ble_uart_client_discover_service_cbk(uint8_t client_id, uint16_t conn_id,
                                                 gattc_discovery_service_result_t *service, errcode_t status)
{
    gattc_discovery_character_param_t param = { 0 };
    osal_printk("%s Discovery service callback client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s start handle:%d end handle:%d uuid_len:%d uuid:\n",
                BLE_UART_CLIENT_LOG, service-&gt;start_hdl, service-&gt;end_hdl, service-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; service-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", service-&gt;uuid.uuid);
    }
    osal_printk("\n %s status:%d\n", BLE_UART_CLIENT_LOG, status);
    param.service_handle = service-&gt;start_hdl;
    param.uuid.uuid_len = service-&gt;uuid.uuid_len; /* uuid length is zero, discover all character */
    if (memcpy_s(param.uuid.uuid, param.uuid.uuid_len, service-&gt;uuid.uuid, service-&gt;uuid.uuid_len) != 0) {
      osal_printk("%s memcpy error\n", BLE_UART_CLIENT_ERROR);
    }
    gattc_discovery_character(g_uart_client_id, conn_id, &amp;param);
}

/* ble client character discovery callback */
static void ble_uart_client_discover_character_cbk(uint8_t client_id, uint16_t conn_id,
                                                   gattc_discovery_character_result_t *character, errcode_t status)
{
    for (uint8_t i = 0; i &lt; character-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", character-&gt;uuid.uuid);
    }
    osal_printk("\n%s discover character declare_handle:%d, value_handle:%d, properties:%2x\n",
                BLE_UART_CLIENT_LOG, character-&gt;declare_handle, character-&gt;value_handle, character-&gt;properties);
    osal_printk("%s client_id:%d, conn_id = %d, status:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id, status);
    bt_uuid_t write_uuid = { 0 };
    bts_data_to_uuid_len2(BLE_UART_CHARACTER_CLIENT_UUID_TX, &amp;write_uuid);
    write_uuid.uuid_len = BT_UUID_MAX_LEN;
    if (memcmp(character-&gt;uuid.uuid, write_uuid.uuid, character-&gt;uuid.uuid_len) == 0) {
      g_ble_uart_chara_hanle_write_value = character-&gt;value_handle;
      osal_printk("%s write declare_handle:%d, value_handle:%d, properties:%2x\n",
                  BLE_UART_CLIENT_LOG, character-&gt;declare_handle, character-&gt;value_handle, character-&gt;properties);
    }
    gattc_discovery_descriptor(g_uart_client_id, conn_id, character-&gt;declare_handle);
}

/* ble client descriptor discovery callback */
static void ble_uart_client_discover_descriptor_cbk(uint8_t client_id, uint16_t conn_id,
    gattc_discovery_descriptor_result_t *descriptor, errcode_t status)
{
    osal_printk("%s Discovery descriptor----client:%d conn_id:%d uuid len:%d, uuid:\n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, descriptor-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; descriptor-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", descriptor-&gt;uuid.uuid);
    }
    osal_printk("\n%s descriptor handle:%d, status:%d\n", BLE_UART_CLIENT_LOG, descriptor-&gt;descriptor_hdl, status);

    gattc_read_req_by_uuid_param_t paramsss = { 0 };
    paramsss.uuid = descriptor-&gt;uuid;
    paramsss.start_hdl = descriptor-&gt;descriptor_hdl;
    paramsss.end_hdl = descriptor-&gt;descriptor_hdl;
    gattc_read_req_by_uuid(client_id, conn_id, &amp;paramsss);
}

/* ble client compare service uuid */
static void ble_uart_client_discover_service_compl_cbk(uint8_t client_id, uint16_t conn_id, bt_uuid_t *uuid,
                                                       errcode_t status)
{
    osal_printk("%s Discovery service complete----client:%d conn_id:%d uuid len:%d uuid:\n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, uuid-&gt;uuid_len);
    for (uint8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x", uuid-&gt;uuid);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}

/* ble client character discovery complete callback */
static void ble_uart_client_discover_character_compl_cbk(uint8_t client_id, uint16_t conn_id,
                                                         gattc_discovery_character_param_t *param, errcode_t status)
{
    osal_printk("%s Discovery character complete----client:%d conn_id:%d uuid len:%d uuid: \n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, param-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; param-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", param-&gt;uuid.uuid);
    }
    osal_printk("\n%s service handle:%d status:%d\n", BLE_UART_CLIENT_LOG, param-&gt;service_handle, status);
}

/* ble client descriptor discovery complete callback */
static void ble_uart_client_discover_descriptor_compl_cbk(uint8_t client_id, uint16_t conn_id,
                                                          uint16_t character_handle, errcode_t status)
{
    osal_printk("%s Discovery descriptor complete----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s charatcer handle:%d, status:%d\n", BLE_UART_CLIENT_LOG, character_handle, status);
}

/* Callback invoked when receive read response */
static void ble_uart_client_read_cfm_cbk(uint8_t client_id, uint16_t conn_id, gattc_handle_value_t *read_result,
                                       gatt_status_t status)
{
    osal_printk("%s Read result client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s handle:%d data_len:%d\ndata:", BLE_UART_CLIENT_LOG, read_result-&gt;handle, read_result-&gt;data_len);
    for (uint8_t i = 0; i &lt; read_result-&gt;data_len; i++) {
      osal_printk("%02x", read_result-&gt;data);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}

/* Callback invoked when read complete */
static void ble_uart_client_read_compl_cbk(uint8_t client_id, uint16_t conn_id, gattc_read_req_by_uuid_param_t *param,
                                           errcode_t status)
{
    osal_printk("%s Read by uuid complete----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s start handle:%d end handle:%d uuid len:%d uuid:\n",
                BLE_UART_CLIENT_LOG, param-&gt;start_hdl, param-&gt;end_hdl, param-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; param-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", param-&gt;uuid.uuid);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}

/* Callback invoked when receive write response */
static void ble_uart_client_write_cfm_cbk(uint8_t client_id, uint16_t conn_id, uint16_t handle, gatt_status_t status)
{
    osal_printk("%s Write result----client:%d conn_id:%d handle:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id, handle);
    osal_printk("%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}

/* Callback invoked when change MTU complete */
static void ble_uart_client_mtu_changed_cbk(uint8_t client_id, uint16_t conn_id, uint16_t mtu_size, errcode_t status)
{
    osal_printk("%s Mtu changed----client:%d conn_id:%d, mtu size:%d, status:%d\n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, mtu_size, status);
    ble_uart_client_discover_all_service(conn_id);
}

/* Callback invoked when receive server notification */
static void ble_uart_client_notification_cbk(uint8_t client_id, uint16_t conn_id, gattc_handle_value_t *data,
                                             errcode_t status)
{
    osal_printk("%s Receive notification----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s handle:%d data_len:%d\ndata:", BLE_UART_CLIENT_LOG, data-&gt;handle, data-&gt;data_len);
    osal_printk("%s ble_uart_client_notification_cbk %s", BLE_UART_CLIENT_LOG, data-&gt;data);
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
    uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(data-&gt;data), data-&gt;data_len, 0);
}

/* Callback invoked when receive server indication */
static void ble_uart_client_indication_cbk(uint8_t client_id, uint16_t conn_id, gattc_handle_value_t *data,
                                           errcode_t status)
{
    osal_printk("%s Receive indication----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s handle:%d data_len:%d\ndata:", BLE_UART_CLIENT_LOG, data-&gt;handle, data-&gt;data_len);
    for (uint8_t i = 0; i &lt; data-&gt;data_len; i++) {
      osal_printk("%02x", data-&gt;data);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}

/* register gatt and gap callback */
errcode_t ble_uart_client_callback_register(void)
{
    errcode_t ret = 0;
    bts_dev_manager_callbacks_t dev_cb = { 0 };
    gap_ble_callbacks_t gap_cb = { 0 };
    gattc_callbacks_t cb = { 0 };

    gap_cb.set_scan_param_cb = ble_uart_client_set_scan_param_cbk;
    gap_cb.scan_result_cb = ble_uart_client_scan_result_cbk;
    gap_cb.conn_state_change_cb = ble_uart_client_connect_change_cbk;
    gap_cb.pair_result_cb = ble_uart_client_pair_result_cb;
    dev_cb.power_on_cb = ble_uart_client_power_on_cbk;
    dev_cb.ble_enable_cb = ble_uart_client_enable_cbk;
    ret |= bts_dev_manager_register_callbacks(&amp;dev_cb);
    ret |= gap_ble_register_callbacks(&amp;gap_cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg gap cbk failed ret = %d\n", BLE_UART_CLIENT_ERROR, ret);
    }

    cb.discovery_svc_cb = ble_uart_client_discover_service_cbk;
    cb.discovery_svc_cmp_cb = ble_uart_client_discover_service_compl_cbk;
    cb.discovery_chara_cb = ble_uart_client_discover_character_cbk;
    cb.discovery_chara_cmp_cb = ble_uart_client_discover_character_compl_cbk;
    cb.discovery_desc_cb = ble_uart_client_discover_descriptor_cbk;
    cb.discovery_desc_cmp_cb = ble_uart_client_discover_descriptor_compl_cbk;
    cb.read_cb = ble_uart_client_read_cfm_cbk;
    cb.read_cmp_cb = ble_uart_client_read_compl_cbk;
    cb.write_cb = ble_uart_client_write_cfm_cbk;
    cb.mtu_changed_cb = ble_uart_client_mtu_changed_cbk;
    cb.notification_cb = ble_uart_client_notification_cbk;
    cb.indication_cb = ble_uart_client_indication_cbk;
    ret = gattc_register_callbacks(&amp;cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg gatt cbk failed ret = %d\n", BLE_UART_CLIENT_ERROR, ret);
    }
#if (CORE_NUMS &lt; 2)
    enable_ble();
#endif
    return ret;
}

/* ble uart client init */
errcode_t ble_uart_client_init(void)
{
    errcode_t ret = ble_uart_client_callback_register();
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s init failed ret = %d\n", BLE_UART_CLIENT_ERROR, ret);
    }
    return ret;
}

uint16_t ble_uart_get_write_vlaue_handle(void)
{
    return g_ble_uart_chara_hanle_write_value;
}</code></pre>

<p style="text-align: justify;"><strong><span style="font-size:16px;">ble_uart_client_scan代码</span></strong></p>

<pre>
<code>#include "errcode.h"
#include "bts_def.h"
#include "bts_le_gap.h"
#include "ble_uart_client_scan.h"

static uint16_t g_uart_scan_interval = 0x48;
static uint16_t g_uart_scan_window = 0x48;
static uint8_t g_uart_scan_type = 0x00;
static uint8_t g_uart_scan_phy = 0x01;
static uint8_t g_uart_scan_filter_policy = 0x00;

errcode_t ble_uart_set_scan_parameters(void)
{
    gap_ble_scan_params_t ble_uart_scan_params = { 0 };
    ble_uart_scan_params.scan_interval = g_uart_scan_interval;
    ble_uart_scan_params.scan_window = g_uart_scan_window;
    ble_uart_scan_params.scan_type = g_uart_scan_type;
    ble_uart_scan_params.scan_phy = g_uart_scan_phy;
    ble_uart_scan_params.scan_filter_policy = g_uart_scan_filter_policy;
    return gap_ble_set_scan_parameters(&amp;ble_uart_scan_params);
}

errcode_t ble_uart_start_scan(void)
{
    return gap_ble_start_scan();
}</code></pre>

<p style="text-align: justify;"><span style="font-size:16px;"><strong>ble_uart代码</strong></span></p>

<pre>
<code>#include "securec.h"
#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "uart.h"
#if defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_SERVER)
#include "bts_gatt_server.h"
#include "ble_uart_server.h"
#elif defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT)
#include "bts_gatt_client.h"
#include "ble_uart_client.h"
#endif /* CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT */

#define BLE_UART_BT_STACK_POWER_MS      10000

typedef struct {
    uint8_t *value;
    uint16_t value_len;
} msg_data_t;
unsigned long mouse_msg_queue = 0;
unsigned int msg_rev_size = sizeof(msg_data_t);

#if defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_SERVER)
static void ble_uart_read_int_handler(const void *buffer, uint16_t length, bool error)
{
    osal_printk("ble_uart_read_int_handler server.\r\n");
    unused(error);
    if (ble_uart_get_connection_state() != 0) {
      msg_data_t msg_data = { 0 };
      void* buffer_cpy = osal_vmalloc(length);
      if (memcpy_s(buffer_cpy, length, buffer, length) != EOK) {
            osal_vfree(buffer_cpy);
            return;
      }
      msg_data.value = (uint8_t *)buffer_cpy;
      msg_data.value_len = length;
      osal_msg_queue_write_copy(mouse_msg_queue, (void *)&amp;msg_data, msg_rev_size, 0);
    }
}

static void *ble_uart_server_task(const char *arg)
{
    unused(arg);
    ble_uart_server_init();
    errcode_t ret = uapi_uart_register_rx_callback(CONFIG_BLE_UART_BUS,
                                                   UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
                                                   1, ble_uart_read_int_handler);
    if (ret != ERRCODE_SUCC) {
      osal_printk("Register uart callback fail.");
      return NULL;
    }
    while (1) {
      msg_data_t msg_data = { 0 };
      int msg_ret = osal_msg_queue_read_copy(mouse_msg_queue, &amp;msg_data, &amp;msg_rev_size, OSAL_WAIT_FOREVER);
      if (msg_ret != OSAL_SUCCESS) {
            osal_printk("msg queue read copy fail.");
            if (msg_data.value != NULL) {
                osal_vfree(msg_data.value);
            }
            continue;
      }
      if (msg_data.value != NULL) {
            ble_uart_server_send_input_report(msg_data.value, msg_data.value_len);
            osal_vfree(msg_data.value);
      }
    }
    return NULL;
}
#elif defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT)
static void ble_uart_read_int_handler(const void *buffer, uint16_t length, bool error)
{
    osal_printk("ble_uart_read_int_handler client.\r\n");
    unused(error);
    msg_data_t msg_data = { 0 };
    void* buffer_cpy = osal_vmalloc(length);
    if (memcpy_s(buffer_cpy, length, buffer, length) != EOK) {
      osal_vfree(buffer_cpy);
      return;
    }
    msg_data.value = (uint8_t *)buffer_cpy;
    msg_data.value_len = length;
    osal_msg_queue_write_copy(mouse_msg_queue, (void *)&amp;msg_data, msg_rev_size, 0);
}

static void *ble_uart_client_task(const char *arg)
{
    unused(arg);
    ble_uart_client_init();
    errcode_t ret = uapi_uart_register_rx_callback(CONFIG_BLE_UART_BUS,
                                                   UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
                                                   1, ble_uart_read_int_handler);
    if (ret != ERRCODE_SUCC) {
      osal_printk("Register uart callback fail.");
      return NULL;
    }
    while (1) {
      msg_data_t msg_data = { 0 };
      int msg_ret = osal_msg_queue_read_copy(mouse_msg_queue, &amp;msg_data, &amp;msg_rev_size, OSAL_WAIT_FOREVER);
      if (msg_ret != OSAL_SUCCESS) {
            osal_printk("msg queue read copy fail.");
            if (msg_data.value != NULL) {
                osal_vfree(msg_data.value);
            }
            continue;
      }
      if (msg_data.value != NULL) {
            uint16_t write_handle = ble_uart_get_write_vlaue_handle();
            ble_uart_client_write_cmd(msg_data.value, msg_data.value_len, write_handle);
            osal_vfree(msg_data.value);
      }
    }
    return NULL;
}
#endif/* CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT */

static void ble_uart_entry(void)
{
    char *arg = NULL;
    int msg_ret = osal_msg_queue_create("task_msg", msg_rev_size, &amp;mouse_msg_queue, 0, msg_rev_size);
    if (msg_ret != OSAL_SUCCESS) {
      osal_printk("msg queue create fail.");
      return;
    }
#if defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_SERVER)
    ble_uart_server_task(arg);
#elif defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT)
    ble_uart_client_task(arg);
#endif /* CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT */
}

/* Run the ble_uart_entry. */
app_run(ble_uart_entry);</code></pre>

<p style="text-align: justify;"><span style="font-size:18px;"><strong>代码解读</strong></span></p>

<p>代码首先进入ble_uart.c的ble_uart_entry任务入口,代码如下</p>

<pre>
<code>static void ble_uart_entry(void)
{
    char *arg = NULL;
    int msg_ret = osal_msg_queue_create("task_msg", msg_rev_size, &amp;mouse_msg_queue, 0, msg_rev_size);
    if (msg_ret != OSAL_SUCCESS) {
      osal_printk("msg queue create fail.");
      return;
    }
#if defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_SERVER)
    ble_uart_server_task(arg);
#elif defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT)
    ble_uart_client_task(arg);
#endif /* CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT */
}

/* Run the ble_uart_entry. */
app_run(ble_uart_entry);
</code></pre>

<p>在其中分别创建Server任务和Client任务</p>

<p style="text-align: justify;"><span style="font-size:16px;"><strong>Server任务</strong></span></p>

<p style="text-align: justify;">对于Server任务,需要完成初始化,并定义接收信息时的中断回调函数,具体代码实现如下</p>

<pre>
<code>#if defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_SERVER)
static void ble_uart_read_int_handler(const void *buffer, uint16_t length, bool error)
{
    osal_printk("ble_uart_read_int_handler server.\r\n");
    unused(error);
    if (ble_uart_get_connection_state() != 0) {
      msg_data_t msg_data = { 0 };
      void* buffer_cpy = osal_vmalloc(length);
      if (memcpy_s(buffer_cpy, length, buffer, length) != EOK) {
            osal_vfree(buffer_cpy);
            return;
      }
      msg_data.value = (uint8_t *)buffer_cpy;
      msg_data.value_len = length;
      osal_msg_queue_write_copy(mouse_msg_queue, (void *)&amp;msg_data, msg_rev_size, 0);
    }
}

static void *ble_uart_server_task(const char *arg)
{
    unused(arg);
    ble_uart_server_init();
    errcode_t ret = uapi_uart_register_rx_callback(CONFIG_BLE_UART_BUS,
                                                   UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
                                                   1, ble_uart_read_int_handler);
    if (ret != ERRCODE_SUCC) {
      osal_printk("Register uart callback fail.");
      return NULL;
    }
    while (1) {
      msg_data_t msg_data = { 0 };
      int msg_ret = osal_msg_queue_read_copy(mouse_msg_queue, &amp;msg_data, &amp;msg_rev_size, OSAL_WAIT_FOREVER);
      if (msg_ret != OSAL_SUCCESS) {
            osal_printk("msg queue read copy fail.");
            if (msg_data.value != NULL) {
                osal_vfree(msg_data.value);
            }
            continue;
      }
      if (msg_data.value != NULL) {
            ble_uart_server_send_input_report(msg_data.value, msg_data.value_len);
            osal_vfree(msg_data.value);
      }
    }
    return NULL;
}
#elif defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT)
</code></pre>

<p style="text-align: justify;">对于Server初始化,具体代码如下:</p>

<pre>
<code>static errcode_t ble_uart_server_register_callbacks(void)
{
    bts_dev_manager_callbacks_t dev_mgr_cb = { 0 };
    gap_ble_callbacks_t gap_cb = { 0 };
    gatts_callbacks_t service_cb = { 0 };

    dev_mgr_cb.power_on_cb = ble_uart_server_power_on_cbk;
    dev_mgr_cb.ble_enable_cb = ble_uart_server_enable_cbk;
    gap_cb.start_adv_cb = ble_uart_server_adv_enable_cbk;
    gap_cb.conn_state_change_cb = ble_uart_server_connect_change_cbk;
    gap_cb.stop_adv_cb = ble_uart_server_adv_disable_cbk;
    gap_cb.pair_result_cb = ble_uart_server_pair_result_cb;
    errcode_t ret = gap_ble_register_callbacks(&amp;gap_cb);
    ret |= bts_dev_manager_register_callbacks(&amp;dev_mgr_cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg gap cbk failed ret = %d\n", BLE_UART_SERVER_ERROR, ret);
      return ret;
    }

    service_cb.add_service_cb = ble_uart_server_service_add_cbk;
    service_cb.add_characteristic_cb = ble_uart_server_characteristic_add_cbk;
    service_cb.add_descriptor_cb = ble_uart_server_descriptor_add_cbk;
    service_cb.start_service_cb = ble_uart_server_service_start_cbk;
    service_cb.read_request_cb = ble_uart_receive_read_req_cbk;
    service_cb.write_request_cb = ble_uart_receive_write_req_cbk;
    service_cb.mtu_changed_cb = ble_uart_mtu_changed_cbk;
    ret = gatts_register_callbacks(&amp;service_cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg service cbk failed ret = %d\n", BLE_UART_SERVER_ERROR, ret);
      return ret;
    }
#if (CORE_NUMS &lt; 2)
    enable_ble();
#endif
    return ret;
}
</code></pre>

<p style="text-align: justify;"><strong>设备初始化</strong></p>

<p style="text-align: justify;">1. 使用ble_uart_server_power_on_cbk使能BLE协议栈</p>

<pre>
<code>void ble_uart_server_power_on_cbk(uint8_t status)
{
    osal_printk("ble power on: %d\n", status);
    enable_ble();
}
</code></pre>

<p>2. 使用ble_uart_server_enable_cbk使能Server</p>

<pre>
<code>void ble_uart_server_enable_cbk(uint8_t status)
{
    osal_printk("ble enable: %d\n", status);
    errcode_t ret = 0;
    bt_uuid_t app_uuid = { 0 };
    bd_addr_t ble_addr = { 0 };
    app_uuid.uuid_len = sizeof(g_uart_server_app_uuid);
    if (memcpy_s(app_uuid.uuid, app_uuid.uuid_len, g_uart_server_app_uuid, sizeof(g_uart_server_app_uuid)) != EOK) {
      osal_printk("%s add server app uuid memcpy failed\n", BLE_UART_SERVER_ERROR);
      return;
    }
    ble_addr.type = BLE_PUBLIC_DEVICE_ADDRESS;
    if (memcpy_s(ble_addr.addr, BD_ADDR_LEN, g_ble_uart_server_addr, sizeof(g_ble_uart_server_addr)) != EOK) {
      osal_printk("%s add server app addr memcpy failed\n", BLE_UART_SERVER_ERROR);
      return;
    }
    gap_ble_set_local_name(g_ble_uart_name_value, sizeof(g_ble_uart_name_value));
    gap_ble_set_local_addr(&amp;ble_addr);
    ret = gatts_register_server(&amp;app_uuid, &amp;g_server_id);
    if ((ret != ERRCODE_BT_SUCCESS) || (g_server_id == INVALID_SERVER_ID)) {
      osal_printk("%s add server failed\r\n", BLE_UART_SERVER_ERROR);
      return;
    }
    ble_uart_add_service(); /* 添加uart服务 */
    osal_printk("%s beginning add service\r\n", BLE_UART_SERVER_LOG);
    bth_ota_init();
}
</code></pre>

<p>在这一步中,需要完成的内容如下:</p>

<ul>
        <li>使用gap_ble_set_local_name设置本地设备名称</li>
        <li>使用gap_ble_set_local_addr设置本地设备地址</li>
        <li>使用gatts_register_server注册GATT服务端</li>
        <li>使用GATT创建uart服务</li>
        <li>使用bth_ota_init初始化bth ota通道</li>
</ul>

<p>3. 使用bts_dev_manager_register_callbacks注册BT device manager回调函数</p>

<p><strong>GAP参数初始化</strong></p>

<p>1.&nbsp;使用ble_uart_server_adv_enable_cbk使能Server的ADV</p>

<pre>
<code>static void ble_uart_server_adv_enable_cbk(uint8_t adv_id, adv_status_t status)
{
    osal_printk("%s adv enable cbk adv_id:%d status:%d\n", BLE_UART_SERVER_LOG, adv_id, status);
}
</code></pre>

<p style="text-align: justify;">2.&nbsp;使用ble_uart_server_connect_change_cbk初始化ADV</p>

<pre>
<code>void ble_uart_server_connect_change_cbk(uint16_t conn_id, bd_addr_t *addr, gap_ble_conn_state_t conn_state,
                                        gap_ble_pair_state_t pair_state, gap_ble_disc_reason_t disc_reason)
{
    g_ble_uart_conn_id = conn_id;
    g_connection_state = (uint8_t)conn_state;
    osal_printk("%s connect state change conn_id: %d, status: %d, pair_status:%d, addr %x disc_reason %x\n",
                BLE_UART_SERVER_LOG, conn_id, conn_state, pair_state, addr, disc_reason);
    if (conn_state == GAP_BLE_STATE_CONNECTED) {
      return;
    } else if (conn_state == GAP_BLE_STATE_DISCONNECTED) {
      ble_uart_set_adv_data();
      ble_uart_start_adv();
    }
}
</code></pre>

<p>其中,需要完成设置ADV信息-&gt;设置扫描反馈信息-&gt;启动ADV</p>

<pre>
<code>uint8_t ble_uart_set_adv_data(void)
{
    uint8_t set_adv_data = { 0 };
    uint8_t set_scan_rsp_data = { 0 };
    gap_ble_config_adv_data_t cfg_adv_data;

    /* set adv data */
    uint16_t adv_data_len = ble_uart_server_set_adv_data(set_adv_data, EXT_ADV_OR_SCAN_RSP_DATA_LEN);
    if ((adv_data_len &gt; EXT_ADV_OR_SCAN_RSP_DATA_LEN) || (adv_data_len == 0)) {
      return 0;
    }
    /* set scan response data */
    uint16_t scan_rsp_data_len = ble_set_scan_response_data(set_scan_rsp_data, EXT_ADV_OR_SCAN_RSP_DATA_LEN);
    if ((scan_rsp_data_len &gt; EXT_ADV_OR_SCAN_RSP_DATA_LEN) || (scan_rsp_data_len == 0)) {
      return 0;
    }
    cfg_adv_data.adv_data = set_adv_data;
    cfg_adv_data.adv_length = adv_data_len;

    cfg_adv_data.scan_rsp_data = set_scan_rsp_data;
    cfg_adv_data.scan_rsp_length = scan_rsp_data_len;
    osal_printk("%s ble_uart_set_adv_data adv_handle %d, len:%d, data:%s\n",
                BLE_UART_ADV_LOG, BTH_GAP_BLE_ADV_HANDLE_DEFAULT, adv_data_len, set_adv_data);
    return gap_ble_set_adv_data(BTH_GAP_BLE_ADV_HANDLE_DEFAULT, &amp;cfg_adv_data);
}

uint8_t ble_uart_start_adv(void)
{
    errcode_t ret = ERRCODE_BT_SUCCESS;
    int adv_id = BTH_GAP_BLE_ADV_HANDLE_DEFAULT;

    gap_ble_adv_params_t adv_para = {
      .min_interval = BLE_ADV_MIN_INTERVAL,
      .max_interval = BLE_ADV_MAX_INTERVAL,
      .duration = BTH_GAP_BLE_ADV_FOREVER_DURATION,
      .peer_addr.type = BLE_PUBLIC_DEVICE_ADDRESS,
      /* 广播通道选择bitMap, 可参考BleAdvChannelMap */
      .channel_map = BLE_ADV_CHANNEL_MAP_CH_DEFAULT,
      .adv_type = BLE_ADV_TYPE_CONNECTABLE_UNDIRECTED,
      .adv_filter_policy = BLE_ADV_FILTER_POLICY_SCAN_ANY_CONNECT_ANY
    };

    (void)memset_s(&amp;adv_para.peer_addr.addr, BD_ADDR_LEN, 0, BD_ADDR_LEN);
    osal_printk("%s ble_uart_start_adv adv_id %d\n", BLE_UART_ADV_LOG, adv_id);
    ret |= gap_ble_set_adv_param(adv_id, &amp;adv_para);
    ret |= gap_ble_start_adv(adv_id);
    return ret;
}
</code></pre>

<p style="text-align: justify;">3. 使用ble_uart_server_pair_result_cb初始化配对成功后的输出信息</p>

<pre>
<code>void ble_uart_server_pair_result_cb(uint16_t conn_id, const bd_addr_t *addr, errcode_t status)
{
    osal_printk("%s pair result conn_id: %d, status: %d, addr %x \n",
                BLE_UART_SERVER_LOG, conn_id, status, addr);
}
</code></pre>

<p style="text-align: justify;">4. 使用gap_ble_register_callbacks注册BLE GAP回调函数</p>

<p style="text-align: justify;"><strong>创建任务回调函数初始化</strong></p>

<p style="text-align: justify;">1. 使用ble_uart_server_service_add_cbk创建服务添加回调函数,使用ble_uart_server_characteristics_add_cbk创建特征添加回调函数,使用ble_uart_server_descriptor_add_cbk创建描述符添加回调函数,使用ble_uart_service_start_cbk创建开始服务回调函数</p>

<pre>
<code>/* 服务添加回调 */
static void ble_uart_server_service_add_cbk(uint8_t server_id, bt_uuid_t *uuid, uint16_t handle, errcode_t status)
{
    osal_printk("%s add characters_and_descriptors cbk service:%d, srv_handle:%d, uuid_len:%d, status:%d, uuid:",
                BLE_UART_SERVER_LOG, server_id, handle, uuid-&gt;uuid_len, status);
    for (int8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x ", uuid-&gt;uuid);
    }
    osal_printk("\n");
    ble_uart_add_tx_characters_and_descriptors(server_id, handle);
    ble_uart_add_rx_characters_and_descriptors(server_id, handle);
    gatts_start_service(server_id, handle);
}

/* 特征添加回调 */
static void ble_uart_server_characteristic_add_cbk(uint8_t server_id, bt_uuid_t *uuid, uint16_t service_handle,
                                                   gatts_add_character_result_t *result, errcode_t status)
{
    osal_printk("%s add character cbk service:%d service_hdl: %d char_hdl: %d char_val_hdl: %d uuid_len: %d \n",
                BLE_UART_SERVER_LOG, server_id, service_handle, result-&gt;handle, result-&gt;value_handle, uuid-&gt;uuid_len);
    osal_printk("uuid:");
    for (int8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x ", uuid-&gt;uuid);
    }
    bt_uuid_t characters_cbk_uuid = { 0 };
    bts_data_to_uuid_len2(BLE_UART_CHARACTERISTIC_UUID_TX, &amp;characters_cbk_uuid);
    characters_cbk_uuid.uuid_len = uuid-&gt;uuid_len;
    if (bts_uart_compare_uuid(uuid, &amp;characters_cbk_uuid)) {
      g_notify_indicate_handle = result-&gt;value_handle;
    }
    osal_printk("%s status:%d indicate_handle:%d\n", BLE_UART_SERVER_LOG, status, g_notify_indicate_handle);
}

/* 描述符添加回调 */
static void ble_uart_server_descriptor_add_cbk(uint8_t server_id, bt_uuid_t *uuid, uint16_t service_handle,
                                             uint16_t handle, errcode_t status)
{
    osal_printk("%s service:%d service_hdl: %d desc_hdl: %d uuid_len: %d \n",
                BLE_UART_SERVER_LOG, server_id, service_handle, handle, uuid-&gt;uuid_len);
    osal_printk("uuid:");
    for (int8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x ", (uint8_t)uuid-&gt;uuid);
    }
    osal_printk("%s status:%d\n", BLE_UART_SERVER_LOG, status);
}

/* 开始服务回调 */
static void ble_uart_server_service_start_cbk(uint8_t server_id, uint16_t handle, errcode_t status)
{
    g_service_num++;
    if ((g_service_num == BLE_UART_SERVICE_NUM) &amp;&amp; (status == 0)) {
      osal_printk("%s start service cbk , start adv\n", BLE_UART_SERVER_LOG);
      ble_uart_set_adv_data();
      ble_uart_start_adv();
    }
    osal_printk("%s start service:%2d service_hdl: %d status: %d\n",
                BLE_UART_SERVER_LOG, server_id, handle, status);
}
</code></pre>

<p style="text-align: justify;">2. 创建接收读信息/接收写信息时日志信息</p>

<pre>
<code>static void ble_uart_receive_write_req_cbk(uint8_t server_id, uint16_t conn_id, gatts_req_write_cb_t *write_cb_para,
                                           errcode_t status)
{
    osal_printk("%s ble uart write cbk server_id:%d, conn_id:%d, status%d\n",
      BLE_UART_SERVER_LOG, server_id, conn_id, status);
    osal_printk("%s ble uart write cbk len:%d, data:%s\n",
                BLE_UART_SERVER_LOG, write_cb_para-&gt;length, write_cb_para-&gt;value);
    if ((write_cb_para-&gt;length &gt; 0) &amp;&amp; write_cb_para-&gt;value) {
      uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(write_cb_para-&gt;value), write_cb_para-&gt;length, 0);
    }
}

static void ble_uart_receive_read_req_cbk(uint8_t server_id, uint16_t conn_id, gatts_req_read_cb_t *read_cb_para,
    errcode_t status)
{
    osal_printk("%s ReceiveReadReq--server_id:%d conn_id:%d\n", BLE_UART_SERVER_LOG, server_id, conn_id);
    osal_printk("%s request_id:%d, att_handle:%d offset:%d, need_rsp:%d, is_long:%d\n",
                BLE_UART_SERVER_LOG, read_cb_para-&gt;request_id, read_cb_para-&gt;handle, read_cb_para-&gt;offset,
                read_cb_para-&gt;need_rsp, read_cb_para-&gt;is_long);
    osal_printk("%s status:%d\n", BLE_UART_SERVER_LOG, status);
}
</code></pre>

<p style="text-align: justify;">3.&nbsp;创建mtu交换日志信息</p>

<pre>
<code>static void ble_uart_mtu_changed_cbk(uint8_t server_id, uint16_t conn_id, uint16_t mtu_size, errcode_t status)
{
    osal_printk("%s MtuChanged--server_id:%d conn_id:%d\n", BLE_UART_SERVER_LOG, server_id, conn_id);
    osal_printk("%s mtusize:%d, status:%d\n", BLE_UART_SERVER_LOG, mtu_size, status);
}
</code></pre>

<p style="text-align: justify;">4. 使用gatts_register_callbacks注册回调函数</p>

<p style="text-align: justify;">完成以上Server初始化步骤后,使用uapi_uart_register_rx_callback注册接收回调函数,就完成了Server的任务创建。</p>

<p style="text-align: justify;"><strong><span style="font-size:16px;">Client任务</span></strong></p>

<p>对于Client任务,也需要完成初始化,并定义接收信息时的中断回调函数,具体代码实现如下</p>

<pre>
<code>#elif defined(CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT)
static void ble_uart_read_int_handler(const void *buffer, uint16_t length, bool error)
{
    osal_printk("ble_uart_read_int_handler client.\r\n");
    unused(error);
    msg_data_t msg_data = { 0 };
    void* buffer_cpy = osal_vmalloc(length);
    if (memcpy_s(buffer_cpy, length, buffer, length) != EOK) {
      osal_vfree(buffer_cpy);
      return;
    }
    msg_data.value = (uint8_t *)buffer_cpy;
    msg_data.value_len = length;
    osal_msg_queue_write_copy(mouse_msg_queue, (void *)&amp;msg_data, msg_rev_size, 0);
}

static void *ble_uart_client_task(const char *arg)
{
    unused(arg);
    ble_uart_client_init();
    errcode_t ret = uapi_uart_register_rx_callback(CONFIG_BLE_UART_BUS,
                                                   UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
                                                   1, ble_uart_read_int_handler);
    if (ret != ERRCODE_SUCC) {
      osal_printk("Register uart callback fail.");
      return NULL;
    }
    while (1) {
      msg_data_t msg_data = { 0 };
      int msg_ret = osal_msg_queue_read_copy(mouse_msg_queue, &amp;msg_data, &amp;msg_rev_size, OSAL_WAIT_FOREVER);
      if (msg_ret != OSAL_SUCCESS) {
            osal_printk("msg queue read copy fail.");
            if (msg_data.value != NULL) {
                osal_vfree(msg_data.value);
            }
            continue;
      }
      if (msg_data.value != NULL) {
            uint16_t write_handle = ble_uart_get_write_vlaue_handle();
            ble_uart_client_write_cmd(msg_data.value, msg_data.value_len, write_handle);
            osal_vfree(msg_data.value);
      }
    }
    return NULL;
}
#endif/* CONFIG_SAMPLE_SUPPORT_BLE_UART_CLIENT */
</code></pre>

<p>对于Client初始化,需要完成GATT注册和GAP回调函数定义,具体代码如下</p>

<pre>
<code>errcode_t ble_uart_client_callback_register(void)
{
    errcode_t ret = 0;
    bts_dev_manager_callbacks_t dev_cb = { 0 };
    gap_ble_callbacks_t gap_cb = { 0 };
    gattc_callbacks_t cb = { 0 };

    gap_cb.set_scan_param_cb = ble_uart_client_set_scan_param_cbk;
    gap_cb.scan_result_cb = ble_uart_client_scan_result_cbk;
    gap_cb.conn_state_change_cb = ble_uart_client_connect_change_cbk;
    gap_cb.pair_result_cb = ble_uart_client_pair_result_cb;
    dev_cb.power_on_cb = ble_uart_client_power_on_cbk;
    dev_cb.ble_enable_cb = ble_uart_client_enable_cbk;
    ret |= bts_dev_manager_register_callbacks(&amp;dev_cb);
    ret |= gap_ble_register_callbacks(&amp;gap_cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg gap cbk failed ret = %d\n", BLE_UART_CLIENT_ERROR, ret);
    }

    cb.discovery_svc_cb = ble_uart_client_discover_service_cbk;
    cb.discovery_svc_cmp_cb = ble_uart_client_discover_service_compl_cbk;
    cb.discovery_chara_cb = ble_uart_client_discover_character_cbk;
    cb.discovery_chara_cmp_cb = ble_uart_client_discover_character_compl_cbk;
    cb.discovery_desc_cb = ble_uart_client_discover_descriptor_cbk;
    cb.discovery_desc_cmp_cb = ble_uart_client_discover_descriptor_compl_cbk;
    cb.read_cb = ble_uart_client_read_cfm_cbk;
    cb.read_cmp_cb = ble_uart_client_read_compl_cbk;
    cb.write_cb = ble_uart_client_write_cfm_cbk;
    cb.mtu_changed_cb = ble_uart_client_mtu_changed_cbk;
    cb.notification_cb = ble_uart_client_notification_cbk;
    cb.indication_cb = ble_uart_client_indication_cbk;
    ret = gattc_register_callbacks(&amp;cb);
    if (ret != ERRCODE_BT_SUCCESS) {
      osal_printk("%s reg gatt cbk failed ret = %d\n", BLE_UART_CLIENT_ERROR, ret);
    }
#if (CORE_NUMS &lt; 2)
    enable_ble();
#endif
    return ret;
}
</code></pre>

<p style="text-align: justify;"><strong>定义GAP相关的回调函数</strong></p>

<p style="text-align: justify;">1. 使用ble_uart_client_set_scan_param_cbk设置扫描参数回调,在这一步中,需要Client首先删除所有BLE配对设备,然后开始扫描</p>

<pre>
<code>void ble_uart_client_set_scan_param_cbk(errcode_t status)
{
    osal_printk("%s set scan param status: %d\n", BLE_UART_CLIENT_LOG, status);
    gap_ble_remove_all_pairs();
    ble_uart_start_scan();
}
</code></pre>

<p style="text-align: justify;">2. 使用ble_uart_client_scan_result_cbk设置扫描结果回调,在这一步中,Client与Server的连接地址匹配,则停止扫描,转而与设备建立连接</p>

<pre>
<code>void ble_uart_client_scan_result_cbk(gap_scan_result_data_t *scan_result_data)
{
    if (memcmp(g_ble_server_addr_connect, scan_result_data-&gt;addr.addr, sizeof(g_ble_server_addr_connect)) == 0) {
      gap_ble_stop_scan();
      osal_printk("\naddr:");
      for (uint8_t i = 0; i &lt; BD_ADDR_LEN; i++) {
            osal_printk(" %02x: ", scan_result_data-&gt;addr.addr);
      }
      bd_addr_t bt_uart_client_addr = { 0 };
      bt_uart_client_addr.type = scan_result_data-&gt;addr.type;
      if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, scan_result_data-&gt;addr.addr, BD_ADDR_LEN) != EOK) {
            osal_printk("%s add server app addr memcpy failed\r\n", BLE_UART_CLIENT_ERROR);
            return;
      }
      gap_ble_connect_remote_device(&amp;bt_uart_client_addr);
    }
}
</code></pre>

<p style="text-align: justify;">3. 使用ble_uart_client_connect_change_cbk实现连接状态回调,这一步用于展示连接设备的相关参数,包括conn_id,status,pair_status</p>

<pre>
<code>void ble_uart_client_connect_change_cbk(uint16_t conn_id, bd_addr_t *addr, gap_ble_conn_state_t conn_state,
                                        gap_ble_pair_state_t pair_state, gap_ble_disc_reason_t disc_reason)
{
    bd_addr_t bt_uart_client_addr = { 0 };
    bt_uart_client_addr.type = addr-&gt;type;
    g_uart_conn_id = conn_id;
    if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, addr-&gt;addr, BD_ADDR_LEN) != EOK) {
      osal_printk("%s add server app addr memcpy failed\r\n", BLE_UART_CLIENT_ERROR);
      return;
    }
    osal_printk("%s connect state change conn_id: %d, status: %d, pair_status:%d, disc_reason %x\n",
                BLE_UART_CLIENT_LOG, conn_id, conn_state, pair_state, disc_reason);

    if (conn_state == GAP_BLE_STATE_CONNECTED&amp;&amp;pair_state == GAP_BLE_PAIR_NONE) {
      osal_printk("%s connect change cbk conn_id =%d \n", BLE_UART_CLIENT_LOG, conn_id);
      gattc_exchange_mtu_req(g_uart_client_id, g_uart_conn_id, g_uart_mtu);
    } else if (conn_state == GAP_BLE_STATE_DISCONNECTED) {
      osal_printk("%s connect change cbk conn disconnected \n", BLE_UART_CLIENT_LOG);
      ble_uart_start_scan();
      return;
    }
}
</code></pre>

<p style="text-align: justify;">4. 使用ble_uart_client_pair_result_cb实现匹配结果回调,在这一步中,Client需要向Server发送交换mtu请求</p>

<pre>
<code>void ble_uart_client_pair_result_cb(uint16_t conn_id, const bd_addr_t *addr, errcode_t status)
{
    osal_printk("%s pair result conn_id: %d,status: %d \n", BLE_UART_CLIENT_LOG, conn_id, status);
    osal_printk("addr:\n");
    for (uint8_t i = 0; i &lt; BD_ADDR_LEN; i++) {
      osal_printk("%2x", addr-&gt;addr);
    }
    osal_printk("\n");
    gattc_exchange_mtu_req(g_uart_client_id, g_uart_conn_id, g_uart_mtu);
}
</code></pre>

<p style="text-align: justify;">5. 使用gap_ble_register_callback注册BLE GAP回调函数</p>

<p style="text-align: justify;"><strong>定义设备相关的回调函数</strong></p>

<p style="text-align: justify;">1. 使用ble_uart_client_power_on_cbk使能BLE协议栈</p>

<pre>
<code>void ble_uart_client_power_on_cbk(uint8_t status)
{
    osal_printk("ble power on: %d\n", status);
    enable_ble();
}
</code></pre>

<p style="text-align: justify;">2. 使用ble_uart_client_enable_cbk启动Client的bt堆栈,在这一步中需要完成GATT客户端注册和设置扫描参数</p>

<pre>
<code>void ble_uart_client_enable_cbk(uint8_t status)
{
    osal_printk("ble enable: %d\n", status);
    gattc_register_client(&amp;g_client_app_uuid, &amp;g_uart_client_id);
    ble_uart_set_scan_parameters();
}
</code></pre>

<p style="text-align: justify;">3. 使用bts_dev_manager_register_callbacks注册BT device manager回调函数</p>

<p style="text-align: justify;"><strong>注册GATT回调函数</strong></p>

<p style="text-align: justify;">1. 使用ble_uart_client_discover_service_cbk发现特征</p>

<pre>
<code>static void ble_uart_client_discover_service_cbk(uint8_t client_id, uint16_t conn_id,
                                                 gattc_discovery_service_result_t *service, errcode_t status)
{
    gattc_discovery_character_param_t param = { 0 };
    osal_printk("%s Discovery service callback client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s start handle:%d end handle:%d uuid_len:%d uuid:\n",
                BLE_UART_CLIENT_LOG, service-&gt;start_hdl, service-&gt;end_hdl, service-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; service-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", service-&gt;uuid.uuid);
    }
    osal_printk("\n %s status:%d\n", BLE_UART_CLIENT_LOG, status);
    param.service_handle = service-&gt;start_hdl;
    param.uuid.uuid_len = service-&gt;uuid.uuid_len; /* uuid length is zero, discover all character */
    if (memcpy_s(param.uuid.uuid, param.uuid.uuid_len, service-&gt;uuid.uuid, service-&gt;uuid.uuid_len) != 0) {
      osal_printk("%s memcpy error\n", BLE_UART_CLIENT_ERROR);
    }
    gattc_discovery_character(g_uart_client_id, conn_id, &amp;param);
}
</code></pre>

<p style="text-align: justify;">2. 使用ble_uart_client_discover_service_compl_cbk发现特征描述符</p>

<pre>
<code>static void ble_uart_client_discover_character_cbk(uint8_t client_id, uint16_t conn_id,
                                                   gattc_discovery_character_result_t *character, errcode_t status)
{
    for (uint8_t i = 0; i &lt; character-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", character-&gt;uuid.uuid);
    }
    osal_printk("\n%s discover character declare_handle:%d, value_handle:%d, properties:%2x\n",
                BLE_UART_CLIENT_LOG, character-&gt;declare_handle, character-&gt;value_handle, character-&gt;properties);
    osal_printk("%s client_id:%d, conn_id = %d, status:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id, status);
    bt_uuid_t write_uuid = { 0 };
    bts_data_to_uuid_len2(BLE_UART_CHARACTER_CLIENT_UUID_TX, &amp;write_uuid);
    write_uuid.uuid_len = BT_UUID_MAX_LEN;
    if (memcmp(character-&gt;uuid.uuid, write_uuid.uuid, character-&gt;uuid.uuid_len) == 0) {
      g_ble_uart_chara_hanle_write_value = character-&gt;value_handle;
      osal_printk("%s write declare_handle:%d, value_handle:%d, properties:%2x\n",
                  BLE_UART_CLIENT_LOG, character-&gt;declare_handle, character-&gt;value_handle, character-&gt;properties);
    }
    gattc_discovery_descriptor(g_uart_client_id, conn_id, character-&gt;declare_handle);
}
</code></pre>

<p style="text-align: justify;">3. 使用ble_uart_client_discover_descriptor_cbk发起按照uuid读取请求</p>

<pre>
<code>static void ble_uart_client_discover_descriptor_cbk(uint8_t client_id, uint16_t conn_id,
    gattc_discovery_descriptor_result_t *descriptor, errcode_t status)
{
    osal_printk("%s Discovery descriptor----client:%d conn_id:%d uuid len:%d, uuid:\n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, descriptor-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; descriptor-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", descriptor-&gt;uuid.uuid);
    }
    osal_printk("\n%s descriptor handle:%d, status:%d\n", BLE_UART_CLIENT_LOG, descriptor-&gt;descriptor_hdl, status);

    gattc_read_req_by_uuid_param_t paramsss = { 0 };
    paramsss.uuid = descriptor-&gt;uuid;
    paramsss.start_hdl = descriptor-&gt;descriptor_hdl;
    paramsss.end_hdl = descriptor-&gt;descriptor_hdl;
    gattc_read_req_by_uuid(client_id, conn_id, &amp;paramsss);
}
</code></pre>

<p style="text-align: justify;">4. 使用ble_uart_client_discover_service_compl_cbk用于对比Client和Service的uuid</p>

<pre>
<code>static void ble_uart_client_discover_service_compl_cbk(uint8_t client_id, uint16_t conn_id, bt_uuid_t *uuid,
                                                       errcode_t status)
{
    osal_printk("%s Discovery service complete----client:%d conn_id:%d uuid len:%d uuid:\n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, uuid-&gt;uuid_len);
    for (uint8_t i = 0; i &lt; uuid-&gt;uuid_len; i++) {
      osal_printk("%02x", uuid-&gt;uuid);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}
</code></pre>

<p style="text-align: justify;">5. 使用ble_uart_client_discover_character_compl_cbk作为Client完成发现特征的回调函数</p>

<pre>
<code>static void ble_uart_client_discover_character_compl_cbk(uint8_t client_id, uint16_t conn_id,
                                                         gattc_discovery_character_param_t *param, errcode_t status)
{
    osal_printk("%s Discovery character complete----client:%d conn_id:%d uuid len:%d uuid: \n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, param-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; param-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", param-&gt;uuid.uuid);
    }
    osal_printk("\n%s service handle:%d status:%d\n", BLE_UART_CLIENT_LOG, param-&gt;service_handle, status);
}
</code></pre>

<p style="text-align: justify;">6. 使用ble_uart_client_discover_descriptor_compl_cbk作为Client完成发现特征描述符的回调函数</p>

<pre>
<code>static void ble_uart_client_discover_descriptor_compl_cbk(uint8_t client_id, uint16_t conn_id,
                                                          uint16_t character_handle, errcode_t status)
{
    osal_printk("%s Discovery descriptor complete----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s charatcer handle:%d, status:%d\n", BLE_UART_CLIENT_LOG, character_handle, status);
}
</code></pre>

<p style="text-align: justify;">7. 使用ble_uart_client_read_cfm_cbk作为接收到读请求触发的回调函数</p>

<pre>
<code>static void ble_uart_client_read_cfm_cbk(uint8_t client_id, uint16_t conn_id, gattc_handle_value_t *read_result,
                                       gatt_status_t status)
{
    osal_printk("%s Read result client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s handle:%d data_len:%d\ndata:", BLE_UART_CLIENT_LOG, read_result-&gt;handle, read_result-&gt;data_len);
    for (uint8_t i = 0; i &lt; read_result-&gt;data_len; i++) {
      osal_printk("%02x", read_result-&gt;data);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}
</code></pre>

<p style="text-align: justify;">8. 使用ble_uart_client_read_compl_cbk作为完成读触发的回调函数</p>

<pre>
<code>static void ble_uart_client_read_compl_cbk(uint8_t client_id, uint16_t conn_id, gattc_read_req_by_uuid_param_t *param,
                                           errcode_t status)
{
    osal_printk("%s Read by uuid complete----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s start handle:%d end handle:%d uuid len:%d uuid:\n",
                BLE_UART_CLIENT_LOG, param-&gt;start_hdl, param-&gt;end_hdl, param-&gt;uuid.uuid_len);
    for (uint8_t i = 0; i &lt; param-&gt;uuid.uuid_len; i++) {
      osal_printk("%02x", param-&gt;uuid.uuid);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}
</code></pre>

<p style="text-align: justify;">9. 使用ble_uart_client_write_cfm_cbk作为接收到写请求触发的回调函数</p>

<pre>
<code>static void ble_uart_client_write_cfm_cbk(uint8_t client_id, uint16_t conn_id, uint16_t handle, gatt_status_t status)
{
    osal_printk("%s Write result----client:%d conn_id:%d handle:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id, handle);
    osal_printk("%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}
</code></pre>

<p style="text-align: justify;">10. 使用ble_uart_client_mtu_change_cbk作为完成mtu交换触发的回调函数,同时Client发现conn_id下的服务</p>

<pre>
<code>static void ble_uart_client_mtu_changed_cbk(uint8_t client_id, uint16_t conn_id, uint16_t mtu_size, errcode_t status)
{
    osal_printk("%s Mtu changed----client:%d conn_id:%d, mtu size:%d, status:%d\n",
                BLE_UART_CLIENT_LOG, client_id, conn_id, mtu_size, status);
    ble_uart_client_discover_all_service(conn_id);
}
</code></pre>

<p style="text-align: justify;">11. 使用ble_uart_client_notification_cbk作为接收到Server的notification触发的回调函数</p>

<pre>
<code>static void ble_uart_client_notification_cbk(uint8_t client_id, uint16_t conn_id, gattc_handle_value_t *data,
                                             errcode_t status)
{
    osal_printk("%s Receive notification----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s handle:%d data_len:%d\ndata:", BLE_UART_CLIENT_LOG, data-&gt;handle, data-&gt;data_len);
    osal_printk("%s ble_uart_client_notification_cbk %s", BLE_UART_CLIENT_LOG, data-&gt;data);
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
    uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(data-&gt;data), data-&gt;data_len, 0);
}
</code></pre>

<p style="text-align: justify;">12. 使用ble_uart_client_indication_cbk作为接收到Server的indication触发的回调函数</p>

<pre>
<code>static void ble_uart_client_indication_cbk(uint8_t client_id, uint16_t conn_id, gattc_handle_value_t *data,
                                           errcode_t status)
{
    osal_printk("%s Receive indication----client:%d conn_id:%d\n", BLE_UART_CLIENT_LOG, client_id, conn_id);
    osal_printk("%s handle:%d data_len:%d\ndata:", BLE_UART_CLIENT_LOG, data-&gt;handle, data-&gt;data_len);
    for (uint8_t i = 0; i &lt; data-&gt;data_len; i++) {
      osal_printk("%02x", data-&gt;data);
    }
    osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
}
</code></pre>

<p style="text-align: justify;">13. 使用gattc_register_callbacks注册GATT客户端回调函数</p>

<p>完成以上Client初始化步骤后,使用uapi_uart_register_rx_callback注册接收回调函数,就完成了Client的任务创建。</p>

<p><strong><span style="font-size:18px;">总结</span></strong></p>

<p>以上就是在小熊派上完成蓝牙BLE的数据传输,这个过程和一般的BLE传输逻辑基本是一致的。本文的内容是我根据目前的经验和对代码的理解翻译而来的,有些理解不到位的或者翻译有误的,希望大家能批评指正。</p>

wangerxian 发表于 2024-8-27 14:17

<p>我觉得可以测试一下传输速率。</p>

FuShenxiao 发表于 2024-8-27 14:30

wangerxian 发表于 2024-8-27 14:17
我觉得可以测试一下传输速率。

<p>下一篇测评帖子就是测试了,打算测一下功耗和传输速率(距离和丢包都测一下)</p>
页: [1]
查看完整版本: 小熊派BearPi-Pico H2821星闪开发板测评(五)——BLE串口透传测试