小熊派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"> </p>
<p><span style="font-size:16px;"><b>配置</b><b>BLE UART Server</b></span></p>
<p>选择BLE UART Server样例</p>
<p align="center"> </p>
<p align="center"> </p>
<p>选择协议</p>
<p align="center"> </p>
<p align="center"> </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"> </p>
<p>选择协议</p>
<p align="center"> </p>
<p>完成配置,退出配置环境进行编译</p>
<p><span style="font-size:16px;"><b>Server</b><b>初始化</b></span></p>
<p>首先进行SDK初始化</p>
<p align="center"> </p>
<p>初始化并启动BLE任务</p>
<p align="center"> </p>
<p>配置并启动ADV,最终开启BLE服务</p>
<p style="text-align: center;"> </p>
<p><span style="font-size:16px;"><b>Client</b><b>初始化</b></span></p>
<p>首先进行SDK初始化</p>
<p align="center"> </p>
<p>交换mtu信息,并与Server建立联系</p>
<p align="center"> </p>
<p>Client发现特征</p>
<p align="center"> </p>
<p>Client发现特征描述符</p>
<p align="center"> </p>
<p>Client收到读响应</p>
<p align="center"> </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"> </p>
<p><span style="font-size:16px;"><b>发送测试</b></span></p>
<p><b>Server发送</b><b>Client接收</b></p>
<p align="center"> </p>
<p><b>Client</b><b>发送</b><b>Server</b><b>接收</b></p>
<p align="center"></p>
<p align="center"> </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->uuid_len = UART16_LEN;
out_uuid->uuid = (uint8_t)(uuid_data >> 8); /* 8: octet bit num */
out_uuid->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, &uart_service_uuid);
gatts_add_service(BLE_UART_SERVER_ID, &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, &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, &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, &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, &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, &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, &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, &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, &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->uuid_len != uuid2->uuid_len) {
return false;
}
if (memcmp(uuid1->uuid, uuid2->uuid, uuid1->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->uuid_len, status);
for (int8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x ", uuid->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->handle, result->value_handle, uuid->uuid_len);
osal_printk("uuid:");
for (int8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x ", uuid->uuid);
}
bt_uuid_t characters_cbk_uuid = { 0 };
bts_data_to_uuid_len2(BLE_UART_CHARACTERISTIC_UUID_TX, &characters_cbk_uuid);
characters_cbk_uuid.uuid_len = uuid->uuid_len;
if (bts_uart_compare_uuid(uuid, &characters_cbk_uuid)) {
g_notify_indicate_handle = result->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->uuid_len);
osal_printk("uuid:");
for (int8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x ", (uint8_t)uuid->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) && (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->length, write_cb_para->value);
if ((write_cb_para->length > 0) && write_cb_para->value) {
uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(write_cb_para->value), write_cb_para->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->request_id, read_cb_para->handle, read_cb_para->offset,
read_cb_para->need_rsp, read_cb_para->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(&ble_addr);
ret = gatts_register_server(&app_uuid, &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(&gap_cb);
ret |= bts_dev_manager_register_callbacks(&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(&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 < 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, &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) & 0xff);
}
static inline uint8_t u16_high_u8(uint16_t val)
{
return (uint8_t)(((uint16_t)(val) >> ADV_APPEA_CATOGORY_HIGH) & 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, &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, &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, &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(&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, &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)) > scan_rsp_data_max_len) {
return 0;
}
if (memcpy_s(&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 > 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 > 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, &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(&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, &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->uuid_len = UUID16_LEN;
out_uuid->uuid = (uint8_t)(uuid_data >> 8); /* 8: octet bit num */
out_uuid->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, &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 < len; i++) {
osal_printk("%02x", data);
}
osal_printk("\n");
errcode_t ret = gattc_write_cmd(g_uart_client_id, g_uart_conn_id, &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->addr.addr, sizeof(g_ble_server_addr_connect)) == 0) {
gap_ble_stop_scan();
osal_printk("\naddr:");
for (uint8_t i = 0; i < BD_ADDR_LEN; i++) {
osal_printk(" %02x: ", scan_result_data->addr.addr);
}
bd_addr_t bt_uart_client_addr = { 0 };
bt_uart_client_addr.type = scan_result_data->addr.type;
if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, scan_result_data->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(&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->type;
g_uart_conn_id = conn_id;
if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, addr->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&&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 < BD_ADDR_LEN; i++) {
osal_printk("%2x", addr->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(&g_client_app_uuid, &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->start_hdl, service->end_hdl, service->uuid.uuid_len);
for (uint8_t i = 0; i < service->uuid.uuid_len; i++) {
osal_printk("%02x", service->uuid.uuid);
}
osal_printk("\n %s status:%d\n", BLE_UART_CLIENT_LOG, status);
param.service_handle = service->start_hdl;
param.uuid.uuid_len = service->uuid.uuid_len; /* uuid length is zero, discover all character */
if (memcpy_s(param.uuid.uuid, param.uuid.uuid_len, service->uuid.uuid, service->uuid.uuid_len) != 0) {
osal_printk("%s memcpy error\n", BLE_UART_CLIENT_ERROR);
}
gattc_discovery_character(g_uart_client_id, conn_id, &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 < character->uuid.uuid_len; i++) {
osal_printk("%02x", character->uuid.uuid);
}
osal_printk("\n%s discover character declare_handle:%d, value_handle:%d, properties:%2x\n",
BLE_UART_CLIENT_LOG, character->declare_handle, character->value_handle, character->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, &write_uuid);
write_uuid.uuid_len = BT_UUID_MAX_LEN;
if (memcmp(character->uuid.uuid, write_uuid.uuid, character->uuid.uuid_len) == 0) {
g_ble_uart_chara_hanle_write_value = character->value_handle;
osal_printk("%s write declare_handle:%d, value_handle:%d, properties:%2x\n",
BLE_UART_CLIENT_LOG, character->declare_handle, character->value_handle, character->properties);
}
gattc_discovery_descriptor(g_uart_client_id, conn_id, character->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->uuid.uuid_len);
for (uint8_t i = 0; i < descriptor->uuid.uuid_len; i++) {
osal_printk("%02x", descriptor->uuid.uuid);
}
osal_printk("\n%s descriptor handle:%d, status:%d\n", BLE_UART_CLIENT_LOG, descriptor->descriptor_hdl, status);
gattc_read_req_by_uuid_param_t paramsss = { 0 };
paramsss.uuid = descriptor->uuid;
paramsss.start_hdl = descriptor->descriptor_hdl;
paramsss.end_hdl = descriptor->descriptor_hdl;
gattc_read_req_by_uuid(client_id, conn_id, &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->uuid_len);
for (uint8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x", uuid->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->uuid.uuid_len);
for (uint8_t i = 0; i < param->uuid.uuid_len; i++) {
osal_printk("%02x", param->uuid.uuid);
}
osal_printk("\n%s service handle:%d status:%d\n", BLE_UART_CLIENT_LOG, param->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->handle, read_result->data_len);
for (uint8_t i = 0; i < read_result->data_len; i++) {
osal_printk("%02x", read_result->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->start_hdl, param->end_hdl, param->uuid.uuid_len);
for (uint8_t i = 0; i < param->uuid.uuid_len; i++) {
osal_printk("%02x", param->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->handle, data->data_len);
osal_printk("%s ble_uart_client_notification_cbk %s", BLE_UART_CLIENT_LOG, data->data);
osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(data->data), data->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->handle, data->data_len);
for (uint8_t i = 0; i < data->data_len; i++) {
osal_printk("%02x", data->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(&dev_cb);
ret |= gap_ble_register_callbacks(&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(&cb);
if (ret != ERRCODE_BT_SUCCESS) {
osal_printk("%s reg gatt cbk failed ret = %d\n", BLE_UART_CLIENT_ERROR, ret);
}
#if (CORE_NUMS < 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(&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 *)&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, &msg_data, &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 *)&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, &msg_data, &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, &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, &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 *)&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, &msg_data, &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(&gap_cb);
ret |= bts_dev_manager_register_callbacks(&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(&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 < 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(&ble_addr);
ret = gatts_register_server(&app_uuid, &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. 使用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. 使用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信息->设置扫描反馈信息->启动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 > 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 > 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, &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(&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, &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->uuid_len, status);
for (int8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x ", uuid->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->handle, result->value_handle, uuid->uuid_len);
osal_printk("uuid:");
for (int8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x ", uuid->uuid);
}
bt_uuid_t characters_cbk_uuid = { 0 };
bts_data_to_uuid_len2(BLE_UART_CHARACTERISTIC_UUID_TX, &characters_cbk_uuid);
characters_cbk_uuid.uuid_len = uuid->uuid_len;
if (bts_uart_compare_uuid(uuid, &characters_cbk_uuid)) {
g_notify_indicate_handle = result->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->uuid_len);
osal_printk("uuid:");
for (int8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x ", (uint8_t)uuid->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) && (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->length, write_cb_para->value);
if ((write_cb_para->length > 0) && write_cb_para->value) {
uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(write_cb_para->value), write_cb_para->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->request_id, read_cb_para->handle, read_cb_para->offset,
read_cb_para->need_rsp, read_cb_para->is_long);
osal_printk("%s status:%d\n", BLE_UART_SERVER_LOG, status);
}
</code></pre>
<p style="text-align: justify;">3. 创建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 *)&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, &msg_data, &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(&dev_cb);
ret |= gap_ble_register_callbacks(&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(&cb);
if (ret != ERRCODE_BT_SUCCESS) {
osal_printk("%s reg gatt cbk failed ret = %d\n", BLE_UART_CLIENT_ERROR, ret);
}
#if (CORE_NUMS < 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->addr.addr, sizeof(g_ble_server_addr_connect)) == 0) {
gap_ble_stop_scan();
osal_printk("\naddr:");
for (uint8_t i = 0; i < BD_ADDR_LEN; i++) {
osal_printk(" %02x: ", scan_result_data->addr.addr);
}
bd_addr_t bt_uart_client_addr = { 0 };
bt_uart_client_addr.type = scan_result_data->addr.type;
if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, scan_result_data->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(&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->type;
g_uart_conn_id = conn_id;
if (memcpy_s(bt_uart_client_addr.addr, BD_ADDR_LEN, addr->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&&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 < BD_ADDR_LEN; i++) {
osal_printk("%2x", addr->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(&g_client_app_uuid, &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->start_hdl, service->end_hdl, service->uuid.uuid_len);
for (uint8_t i = 0; i < service->uuid.uuid_len; i++) {
osal_printk("%02x", service->uuid.uuid);
}
osal_printk("\n %s status:%d\n", BLE_UART_CLIENT_LOG, status);
param.service_handle = service->start_hdl;
param.uuid.uuid_len = service->uuid.uuid_len; /* uuid length is zero, discover all character */
if (memcpy_s(param.uuid.uuid, param.uuid.uuid_len, service->uuid.uuid, service->uuid.uuid_len) != 0) {
osal_printk("%s memcpy error\n", BLE_UART_CLIENT_ERROR);
}
gattc_discovery_character(g_uart_client_id, conn_id, &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 < character->uuid.uuid_len; i++) {
osal_printk("%02x", character->uuid.uuid);
}
osal_printk("\n%s discover character declare_handle:%d, value_handle:%d, properties:%2x\n",
BLE_UART_CLIENT_LOG, character->declare_handle, character->value_handle, character->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, &write_uuid);
write_uuid.uuid_len = BT_UUID_MAX_LEN;
if (memcmp(character->uuid.uuid, write_uuid.uuid, character->uuid.uuid_len) == 0) {
g_ble_uart_chara_hanle_write_value = character->value_handle;
osal_printk("%s write declare_handle:%d, value_handle:%d, properties:%2x\n",
BLE_UART_CLIENT_LOG, character->declare_handle, character->value_handle, character->properties);
}
gattc_discovery_descriptor(g_uart_client_id, conn_id, character->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->uuid.uuid_len);
for (uint8_t i = 0; i < descriptor->uuid.uuid_len; i++) {
osal_printk("%02x", descriptor->uuid.uuid);
}
osal_printk("\n%s descriptor handle:%d, status:%d\n", BLE_UART_CLIENT_LOG, descriptor->descriptor_hdl, status);
gattc_read_req_by_uuid_param_t paramsss = { 0 };
paramsss.uuid = descriptor->uuid;
paramsss.start_hdl = descriptor->descriptor_hdl;
paramsss.end_hdl = descriptor->descriptor_hdl;
gattc_read_req_by_uuid(client_id, conn_id, &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->uuid_len);
for (uint8_t i = 0; i < uuid->uuid_len; i++) {
osal_printk("%02x", uuid->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->uuid.uuid_len);
for (uint8_t i = 0; i < param->uuid.uuid_len; i++) {
osal_printk("%02x", param->uuid.uuid);
}
osal_printk("\n%s service handle:%d status:%d\n", BLE_UART_CLIENT_LOG, param->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->handle, read_result->data_len);
for (uint8_t i = 0; i < read_result->data_len; i++) {
osal_printk("%02x", read_result->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->start_hdl, param->end_hdl, param->uuid.uuid_len);
for (uint8_t i = 0; i < param->uuid.uuid_len; i++) {
osal_printk("%02x", param->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->handle, data->data_len);
osal_printk("%s ble_uart_client_notification_cbk %s", BLE_UART_CLIENT_LOG, data->data);
osal_printk("\n%s status:%d\n", BLE_UART_CLIENT_LOG, status);
uapi_uart_write(CONFIG_BLE_UART_BUS, (uint8_t *)(data->data), data->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->handle, data->data_len);
for (uint8_t i = 0; i < data->data_len; i++) {
osal_printk("%02x", data->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>
<p>我觉得可以测试一下传输速率。</p>
wangerxian 发表于 2024-8-27 14:17
我觉得可以测试一下传输速率。
<p>下一篇测评帖子就是测试了,打算测一下功耗和传输速率(距离和丢包都测一下)</p>
页:
[1]