分开蓝牙服务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_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} // 透传数据发送 #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_RECEIVE 0xABF1// 命令接收
#define ESP_GATT_UUID_SPP_COMMAND_NOTIFY 0xABF2// 命令响应的返回。 #define ESP_GATT_UUID_SPP_COMMAND_NOTIFY 0xABF2// 命令响应的返回。
@@ -153,7 +154,10 @@ static esp_bd_addr_t spp_remote_bda = {
0x0, 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 = { 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 /// Full HRS Database Description - Used to add attributes into the database
static esp_gatts_attr_db_t const spp_gatt_db[SPP_IDX_NB] = { static esp_gatts_attr_db_t const spp_gatt_db[SPP_IDX_NB] = {
// SPP - Service Declaration // SPP - Service Declaration
[SPP_IDX_SVC] = [SPP_IDX_SVC] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, // 服务的类型 0X2800 {{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 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] = [SPP_IDX_SPP_DATA_RECV_CHAR] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, // 特征值声明的类型 0X2803 {{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}}, // 特征值属性 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 [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, // 访问权限 {{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}}, 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 - command characteristic Declaration
[SPP_IDX_SPP_COMMAND_CHAR] = [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 [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}}, {{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) static uint8_t find_char_and_desr_index(uint16_t handle)
{ {
uint8_t error = 0xff; uint8_t error = 0xff;
for (int i = 0; i < SPP_IDX_NB; i++) /* search first service handles */
{ for(int i = 0; i < SPP_IDX_NB ; i++){
if (handle == spp_handle_table[i]) if(handle == spp_handle_table[i]){
{ return (uint8_t)i; /* 0..SPP_IDX_NB-1 */
return (uint8_t)i; }
}
/* 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(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; break;
case ESP_GATTS_READ_EVT: case ESP_GATTS_READ_EVT:
res = find_char_and_desr_index(p_data->read.handle); res = find_char_and_desr_index(p_data->read.handle);
if (res == SPP_IDX_SPP_STATUS_VAL) if(res == SPP_IDX_SPP_DATA_NTY_VAL ){
{ // 读状态特征 //TODO:client read the status characteristic for service1
// TODO:client read the status characteristic } else if (res == SPP_IDX_SPP_STATUS_VAL) {
//TODO: client read char A of service2
} }
break; break;
case ESP_GATTS_WRITE_EVT: 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 res = find_char_and_desr_index(p_data->write.handle); // 哪个特征值引发event
if (p_data->write.is_prep == false) if (p_data->write.is_prep == false)
{ {
if (res == SPP_IDX_SPP_COMMAND_VAL) // 收到命令 //表示第一个表
{ /* 来自 service2 的写(高位标记) */
SYS_LOG_INF("ESP_GATTS_WRITE_EVT : do os_pipe_fifo_fill()"); if (res == SPP_IDX_SPP_DATA_NTF_CFG) // 收到客户端发过来的设置信息
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) // 收到客户端发过来的设置信息
{ {
if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x01) && (p_data->write.value[1] == 0x00)) 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; 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 #ifdef SUPPORT_HEARTBEAT
else if (res == SPP_IDX_SPP_HEARTBEAT_CFG) // 开启心跳 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 #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 else
{ {
// TODO: // 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_INF("ESP_GATTS_WRITE_EVT : do os_fifo_put()");
SYS_LOG_DUMP(p_data->write.value, p_data->write.len, 0, 0); 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); 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 else
{ {
memcpy(spp_handle_table, param->add_attr_tab.handles, sizeof(spp_handle_table)); 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);
esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]); // 开启服务
} }
break; 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, if (esp_ble_gatts_send_indicate(spp_gatts_if,
spp_conn_id, spp_conn_id,
spp_handle_table[SPP_IDX_SPP_STATUS_VAL], cmd_handle_table[SPP_IDX_SPP_STATUS_VAL],
wsize, wsize,
(uint8_t *)data, (uint8_t *)data,
false) != ESP_OK) false) != ESP_OK)

View File

@@ -32,13 +32,6 @@ enum
SPP_IDX_SPP_DATA_NTY_VAL, SPP_IDX_SPP_DATA_NTY_VAL,
SPP_IDX_SPP_DATA_NTF_CFG, 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 #ifdef SUPPORT_HEARTBEAT
SPP_IDX_SPP_HEARTBEAT_CHAR, SPP_IDX_SPP_HEARTBEAT_CHAR,
SPP_IDX_SPP_HEARTBEAT_VAL, SPP_IDX_SPP_HEARTBEAT_VAL,
@@ -47,3 +40,16 @@ enum
SPP_IDX_NB, 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); 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); os_thread_sleep(1);
} }