分开蓝牙服务CMD和DATA

This commit is contained in:
OPTOC
2025-09-17 11:45:06 +08:00
parent 3f12c83014
commit 32c932219f
3 changed files with 106 additions and 63 deletions

View File

@@ -75,7 +75,8 @@ static const uint8_t spp_service_uuid[16] = {0x6E,0x40,0x00,0x01,0xB5,0xA3,0xF3,
#define ESP_GATT_UUID_SPP_DATA_RECEIVE {0x6E,0x40,0x00,0x03,0xB5,0xA3,0xF3,0x93,0xE0,0xA9,0xE5,0x0E,0x24,0xDC,0xCA,0x9E} // 透传数据接收
#define ESP_GATT_UUID_SPP_DATA_NOTIFY {0x6E,0x40,0x00,0x02,0xB5,0xA3,0xF3,0x93,0xE0,0xA9,0xE5,0x0E,0x24,0xDC,0xCA,0x9E} // 透传数据发送
// static const int16_t spp_service_cmd_uuid = 0xABF0;
/* 第二个 Service 使用 16-bit UUID示例: 0xBEEFchar 使用 0xBEE1 */
static const int16_t cmd_uuid = 0xABF0;
#define ESP_GATT_UUID_SPP_COMMAND_RECEIVE 0xABF1// 命令接收
#define ESP_GATT_UUID_SPP_COMMAND_NOTIFY 0xABF2// 命令响应的返回。
@@ -153,7 +154,10 @@ static esp_bd_addr_t spp_remote_bda = {
0x0,
};
static uint16_t spp_handle_table[SPP_IDX_NB]; // 特征值表
/* 现有 service 的 handle 表(与你原始的 SPP_IDX_NB 对应) */
static uint16_t spp_handle_table[SPP_IDX_NB];
/* 第二个 service 的 handle 表 */
static uint16_t cmd_handle_table[SPP_IDX_CMD_NB];
static esp_ble_adv_params_t spp_adv_params = {
// 广播出去的信息
@@ -249,12 +253,12 @@ static const uint8_t spp_heart_beat_ccc[2] = {0x00, 0x00};
/// Full HRS Database Description - Used to add attributes into the database
static esp_gatts_attr_db_t const spp_gatt_db[SPP_IDX_NB] = {
// SPP - Service Declaration
[SPP_IDX_SVC] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, // 服务的类型 0X2800
sizeof(spp_service_uuid), sizeof(spp_service_uuid), (uint8_t *)&spp_service_uuid}}, // 服务的ID
// SPP - data receive characteristic Declaration
// SPP - data receive characteristic Declaration
[SPP_IDX_SPP_DATA_RECV_CHAR] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, // 特征值声明的类型 0X2803
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}}, // 特征值属性
@@ -278,6 +282,27 @@ static esp_gatts_attr_db_t const spp_gatt_db[SPP_IDX_NB] = {
[SPP_IDX_SPP_DATA_NTF_CFG] = // Client characteristic configuration UUID 0X2902
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, // 访问权限
sizeof(uint16_t), sizeof(spp_data_notify_ccc), (uint8_t *)spp_data_notify_ccc}},
#ifdef SUPPORT_HEARTBEAT
// SPP - Heart beat characteristic Declaration
[SPP_IDX_SPP_HEARTBEAT_CHAR] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, // 特征值声明的类型 0X2803
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
// SPP - Heart beat characteristic Value
[SPP_IDX_SPP_HEARTBEAT_VAL] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_heart_beat_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(spp_heart_beat_val), sizeof(spp_heart_beat_val), (uint8_t *)spp_heart_beat_val}},
// SPP - Heart beat characteristic - Client Characteristic Configuration Descriptor
[SPP_IDX_SPP_HEARTBEAT_CFG] = // Client characteristic configuration UUID 0X2902
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(uint16_t), sizeof(spp_data_notify_ccc), (uint8_t *)spp_heart_beat_ccc}},
#endif
};
static const esp_gatts_attr_db_t cmd_gatt_db[SPP_IDX_CMD_NB] = {
/* Service Declaration */
[SPP_IDX_CMD] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
sizeof(cmd_uuid), sizeof(cmd_uuid), (uint8_t *)&cmd_uuid}},
// SPP - command characteristic Declaration
[SPP_IDX_SPP_COMMAND_CHAR] =
@@ -303,31 +328,25 @@ static esp_gatts_attr_db_t const spp_gatt_db[SPP_IDX_NB] = {
[SPP_IDX_SPP_STATUS_CFG] = // Client characteristic configuration UUID 0X2902
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(uint16_t), sizeof(spp_status_ccc), (uint8_t *)spp_status_ccc}},
#ifdef SUPPORT_HEARTBEAT
// SPP - Heart beat characteristic Declaration
[SPP_IDX_SPP_HEARTBEAT_CHAR] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, // 特征值声明的类型 0X2803
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
// SPP - Heart beat characteristic Value
[SPP_IDX_SPP_HEARTBEAT_VAL] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_heart_beat_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(spp_heart_beat_val), sizeof(spp_heart_beat_val), (uint8_t *)spp_heart_beat_val}},
// SPP - Heart beat characteristic - Client Characteristic Configuration Descriptor
[SPP_IDX_SPP_HEARTBEAT_CFG] = // Client characteristic configuration UUID 0X2902
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(uint16_t), sizeof(spp_data_notify_ccc), (uint8_t *)spp_heart_beat_ccc}},
#endif
};
/* --------------------------------------------------------------- */
static uint8_t find_char_and_desr_index(uint16_t handle)
{
uint8_t error = 0xff;
for (int i = 0; i < SPP_IDX_NB; i++)
{
if (handle == spp_handle_table[i])
{
return (uint8_t)i;
/* search first service handles */
for(int i = 0; i < SPP_IDX_NB ; i++){
if(handle == spp_handle_table[i]){
return (uint8_t)i; /* 0..SPP_IDX_NB-1 */
}
}
/* search second service handles;*/
for(int i = 0; i < SPP_IDX_CMD_NB ; i++){
if(handle == cmd_handle_table[i]){
return (uint8_t)( (uint8_t)i);
}
}
@@ -458,12 +477,14 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
}
esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, SPP_SVC_INST_ID);
esp_ble_gatts_create_attr_tab(cmd_gatt_db, gatts_if, SPP_IDX_CMD_NB, 1);
break;
case ESP_GATTS_READ_EVT:
res = find_char_and_desr_index(p_data->read.handle);
if (res == SPP_IDX_SPP_STATUS_VAL)
{ // 读状态特征
// TODO:client read the status characteristic
if(res == SPP_IDX_SPP_DATA_NTY_VAL ){
//TODO:client read the status characteristic for service1
} else if (res == SPP_IDX_SPP_STATUS_VAL) {
//TODO: client read char A of service2
}
break;
case ESP_GATTS_WRITE_EVT:
@@ -471,18 +492,9 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
res = find_char_and_desr_index(p_data->write.handle); // 哪个特征值引发event
if (p_data->write.is_prep == false)
{
if (res == SPP_IDX_SPP_COMMAND_VAL) // 收到命令
{
SYS_LOG_INF("ESP_GATTS_WRITE_EVT : do os_pipe_fifo_fill()");
SYS_LOG_DUMP(p_data->write.value, p_data->write.len, 0, 0);
__ble_port_data_t *port_data = s_port_cmd.data;
size_t len = os_pipe_fifo_fill(&port_data->pipe_obj, p_data->write.value, p_data->write.len);
if (len < p_data->write.len)
{
SYS_LOG_WRN("Pipeline cache exceeded %d bytes", p_data->write.len - len);
}
}
else if (res == SPP_IDX_SPP_DATA_NTF_CFG) // 收到客户端发过来的设置信息
//表示第一个表
/* 来自 service2 的写(高位标记) */
if (res == SPP_IDX_SPP_DATA_NTF_CFG) // 收到客户端发过来的设置信息
{
if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x01) && (p_data->write.value[1] == 0x00))
{
@@ -493,6 +505,17 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
enable_data_ntf = false;
}
}
else if (res == SPP_IDX_SPP_DATA_RECV_VAL) // 收到客户端发过来的数据
{
SYS_LOG_INF("ESP_GATTS_WRITE_EVT : do os_pipe_fifo_fill()");
SYS_LOG_DUMP(p_data->write.value, p_data->write.len, 0, 0);
__ble_port_data_t *port_data = s_port_val.data;
size_t len = os_pipe_fifo_fill(&port_data->pipe_obj, p_data->write.value, p_data->write.len);
if (len < p_data->write.len)
{
SYS_LOG_WRN("read Pipeline cache exceeded %d bytes", p_data->write.len - len);
}
}
#ifdef SUPPORT_HEARTBEAT
else if (res == SPP_IDX_SPP_HEARTBEAT_CFG) // 开启心跳
{
@@ -513,23 +536,24 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
}
}
#endif
else if (res == SPP_IDX_SPP_DATA_RECV_VAL) // 收到客户端发过来的数据
{
SYS_LOG_INF("ESP_GATTS_WRITE_EVT : do os_pipe_fifo_fill()");
SYS_LOG_DUMP(p_data->write.value, p_data->write.len, 0, 0);
__ble_port_data_t *port_data = s_port_val.data;
size_t len = os_pipe_fifo_fill(&port_data->pipe_obj, p_data->write.value, p_data->write.len);
if (len < p_data->write.len)
{
SYS_LOG_WRN("read Pipeline cache exceeded %d bytes", p_data->write.len - len);
}
}
else
{
// TODO:
}
//第二个表
if (res == SPP_IDX_SPP_COMMAND_VAL) // 收到命令
{
SYS_LOG_INF("ESP_GATTS_WRITE_EVT : do os_pipe_fifo_fill()");
SYS_LOG_DUMP(p_data->write.value, p_data->write.len, 0, 0);
__ble_port_data_t *port_data = s_port_cmd.data;
size_t len = os_pipe_fifo_fill(&port_data->pipe_obj, p_data->write.value, p_data->write.len);
if (len < p_data->write.len)
{
SYS_LOG_WRN("Pipeline cache exceeded %d bytes", p_data->write.len - len);
}
}
}
else if ((p_data->write.is_prep == true) && (res == SPP_IDX_SPP_DATA_RECV_VAL))
else if((p_data->write.is_prep == true) && (res == SPP_IDX_SPP_DATA_RECV_VAL))
{
SYS_LOG_INF("ESP_GATTS_WRITE_EVT : do os_fifo_put()");
SYS_LOG_DUMP(p_data->write.value, p_data->write.len, 0, 0);
@@ -646,14 +670,20 @@ static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
{
SYS_LOG_ERR("Create attribute table failed, error code=0x%x", param->add_attr_tab.status);
}
else if (param->add_attr_tab.num_handle != SPP_IDX_NB)
else if (param->add_attr_tab.num_handle == SPP_IDX_NB)
{
SYS_LOG_ERR("Create attribute table abnormally, num_handle (%d) doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, SPP_IDX_NB);
memcpy(spp_handle_table, param->add_attr_tab.handles, param->add_attr_tab.num_handle * sizeof(uint16_t));
esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]);
}
else if (param->add_attr_tab.num_handle == SPP_IDX_CMD_NB)
{
memcpy(cmd_handle_table, param->add_attr_tab.handles, param->add_attr_tab.num_handle * sizeof(uint16_t));
esp_ble_gatts_start_service(cmd_handle_table[SPP_IDX_CMD]);
}
else
{
memcpy(spp_handle_table, param->add_attr_tab.handles, sizeof(spp_handle_table));
esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]); // 开启服务
SYS_LOG_ERR("Create attribute table abnormally, num_handle (%d) doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, SPP_IDX_NB);
}
break;
}
@@ -879,7 +909,7 @@ static int _port_write_cmd(sb_data_port_t *port, const void *data, uint32_t size
{
if (esp_ble_gatts_send_indicate(spp_gatts_if,
spp_conn_id,
spp_handle_table[SPP_IDX_SPP_STATUS_VAL],
cmd_handle_table[SPP_IDX_SPP_STATUS_VAL],
wsize,
(uint8_t *)data,
false) != ESP_OK)

View File

@@ -32,13 +32,6 @@ enum
SPP_IDX_SPP_DATA_NTY_VAL,
SPP_IDX_SPP_DATA_NTF_CFG,
SPP_IDX_SPP_COMMAND_CHAR,
SPP_IDX_SPP_COMMAND_VAL,
SPP_IDX_SPP_STATUS_CHAR,
SPP_IDX_SPP_STATUS_VAL,
SPP_IDX_SPP_STATUS_CFG,
#ifdef SUPPORT_HEARTBEAT
SPP_IDX_SPP_HEARTBEAT_CHAR,
SPP_IDX_SPP_HEARTBEAT_VAL,
@@ -47,3 +40,16 @@ enum
SPP_IDX_NB,
};
enum
{
SPP_IDX_CMD = SPP_IDX_NB,
SPP_IDX_SPP_COMMAND_CHAR,
SPP_IDX_SPP_COMMAND_VAL,
SPP_IDX_SPP_STATUS_CHAR,
SPP_IDX_SPP_STATUS_VAL,
SPP_IDX_SPP_STATUS_CFG,
SPP_IDX_CMD_NB,
};

View File

@@ -110,7 +110,14 @@ void app_thread(void* arg)
}
resend_recv_data(&sertrf.resend_device,0);
// uint32_t app_size = app_device_get_rx_length(&sertrf.device);
// if(app_size > 0)
// {
// uint8_t data[app_size];
// app_device_read(&sertrf.device, data, app_size,0);
// // printf("data:%d:%s\n", app_size,data);
// }
os_thread_sleep(1);
}