mirror of
https://github.com/esphome/esphome.git
synced 2025-07-28 06:06:33 +00:00
Optimize bluetooth_proxy memory copy and reduce reallocs (#8723)
This commit is contained in:
parent
45d019a7e4
commit
00f20c1e55
@ -73,9 +73,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
|||||||
resp.address = this->address_;
|
resp.address = this->address_;
|
||||||
resp.handle = param->read.handle;
|
resp.handle = param->read.handle;
|
||||||
resp.data.reserve(param->read.value_len);
|
resp.data.reserve(param->read.value_len);
|
||||||
for (uint16_t i = 0; i < param->read.value_len; i++) {
|
// Use bulk insert instead of individual push_backs
|
||||||
resp.data.push_back(param->read.value[i]);
|
resp.data.insert(resp.data.end(), param->read.value, param->read.value + param->read.value_len);
|
||||||
}
|
|
||||||
this->proxy_->get_api_connection()->send_bluetooth_gatt_read_response(resp);
|
this->proxy_->get_api_connection()->send_bluetooth_gatt_read_response(resp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -127,9 +126,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
|||||||
resp.address = this->address_;
|
resp.address = this->address_;
|
||||||
resp.handle = param->notify.handle;
|
resp.handle = param->notify.handle;
|
||||||
resp.data.reserve(param->notify.value_len);
|
resp.data.reserve(param->notify.value_len);
|
||||||
for (uint16_t i = 0; i < param->notify.value_len; i++) {
|
// Use bulk insert instead of individual push_backs
|
||||||
resp.data.push_back(param->notify.value[i]);
|
resp.data.insert(resp.data.end(), param->notify.value, param->notify.value + param->notify.value_len);
|
||||||
}
|
|
||||||
this->proxy_->get_api_connection()->send_bluetooth_gatt_notify_data_response(resp);
|
this->proxy_->get_api_connection()->send_bluetooth_gatt_notify_data_response(resp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,9 @@ bool BluetoothProxy::parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_p
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
api::BluetoothLERawAdvertisementsResponse resp;
|
api::BluetoothLERawAdvertisementsResponse resp;
|
||||||
|
// Pre-allocate the advertisements vector to avoid reallocations
|
||||||
|
resp.advertisements.reserve(count);
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
auto &result = advertisements[i];
|
auto &result = advertisements[i];
|
||||||
api::BluetoothLERawAdvertisement adv;
|
api::BluetoothLERawAdvertisement adv;
|
||||||
@ -65,9 +68,8 @@ bool BluetoothProxy::parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_p
|
|||||||
|
|
||||||
uint8_t length = result.adv_data_len + result.scan_rsp_len;
|
uint8_t length = result.adv_data_len + result.scan_rsp_len;
|
||||||
adv.data.reserve(length);
|
adv.data.reserve(length);
|
||||||
for (uint16_t i = 0; i < length; i++) {
|
// Use a bulk insert instead of individual push_backs
|
||||||
adv.data.push_back(result.ble_adv[i]);
|
adv.data.insert(adv.data.end(), &result.ble_adv[0], &result.ble_adv[length]);
|
||||||
}
|
|
||||||
|
|
||||||
resp.advertisements.push_back(std::move(adv));
|
resp.advertisements.push_back(std::move(adv));
|
||||||
|
|
||||||
@ -85,21 +87,34 @@ void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &devi
|
|||||||
if (!device.get_name().empty())
|
if (!device.get_name().empty())
|
||||||
resp.name = device.get_name();
|
resp.name = device.get_name();
|
||||||
resp.rssi = device.get_rssi();
|
resp.rssi = device.get_rssi();
|
||||||
for (auto uuid : device.get_service_uuids()) {
|
|
||||||
|
// Pre-allocate vectors based on known sizes
|
||||||
|
auto service_uuids = device.get_service_uuids();
|
||||||
|
resp.service_uuids.reserve(service_uuids.size());
|
||||||
|
for (auto uuid : service_uuids) {
|
||||||
resp.service_uuids.push_back(uuid.to_string());
|
resp.service_uuids.push_back(uuid.to_string());
|
||||||
}
|
}
|
||||||
for (auto &data : device.get_service_datas()) {
|
|
||||||
|
// Pre-allocate service data vector
|
||||||
|
auto service_datas = device.get_service_datas();
|
||||||
|
resp.service_data.reserve(service_datas.size());
|
||||||
|
for (auto &data : service_datas) {
|
||||||
api::BluetoothServiceData service_data;
|
api::BluetoothServiceData service_data;
|
||||||
service_data.uuid = data.uuid.to_string();
|
service_data.uuid = data.uuid.to_string();
|
||||||
service_data.data.assign(data.data.begin(), data.data.end());
|
service_data.data.assign(data.data.begin(), data.data.end());
|
||||||
resp.service_data.push_back(std::move(service_data));
|
resp.service_data.push_back(std::move(service_data));
|
||||||
}
|
}
|
||||||
for (auto &data : device.get_manufacturer_datas()) {
|
|
||||||
|
// Pre-allocate manufacturer data vector
|
||||||
|
auto manufacturer_datas = device.get_manufacturer_datas();
|
||||||
|
resp.manufacturer_data.reserve(manufacturer_datas.size());
|
||||||
|
for (auto &data : manufacturer_datas) {
|
||||||
api::BluetoothServiceData manufacturer_data;
|
api::BluetoothServiceData manufacturer_data;
|
||||||
manufacturer_data.uuid = data.uuid.to_string();
|
manufacturer_data.uuid = data.uuid.to_string();
|
||||||
manufacturer_data.data.assign(data.data.begin(), data.data.end());
|
manufacturer_data.data.assign(data.data.begin(), data.data.end());
|
||||||
resp.manufacturer_data.push_back(std::move(manufacturer_data));
|
resp.manufacturer_data.push_back(std::move(manufacturer_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
this->api_connection_->send_bluetooth_le_advertisement(resp);
|
this->api_connection_->send_bluetooth_le_advertisement(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,11 +176,27 @@ void BluetoothProxy::loop() {
|
|||||||
}
|
}
|
||||||
api::BluetoothGATTGetServicesResponse resp;
|
api::BluetoothGATTGetServicesResponse resp;
|
||||||
resp.address = connection->get_address();
|
resp.address = connection->get_address();
|
||||||
|
resp.services.reserve(1); // Always one service per response in this implementation
|
||||||
api::BluetoothGATTService service_resp;
|
api::BluetoothGATTService service_resp;
|
||||||
service_resp.uuid = get_128bit_uuid_vec(service_result.uuid);
|
service_resp.uuid = get_128bit_uuid_vec(service_result.uuid);
|
||||||
service_resp.handle = service_result.start_handle;
|
service_resp.handle = service_result.start_handle;
|
||||||
uint16_t char_offset = 0;
|
uint16_t char_offset = 0;
|
||||||
esp_gattc_char_elem_t char_result;
|
esp_gattc_char_elem_t char_result;
|
||||||
|
// Get the number of characteristics directly with one call
|
||||||
|
uint16_t total_char_count = 0;
|
||||||
|
esp_gatt_status_t char_count_status = esp_ble_gattc_get_attr_count(
|
||||||
|
connection->get_gattc_if(), connection->get_conn_id(), ESP_GATT_DB_CHARACTERISTIC,
|
||||||
|
service_result.start_handle, service_result.end_handle, 0, &total_char_count);
|
||||||
|
|
||||||
|
if (char_count_status == ESP_GATT_OK && total_char_count > 0) {
|
||||||
|
// Only reserve if we successfully got a count
|
||||||
|
service_resp.characteristics.reserve(total_char_count);
|
||||||
|
} else if (char_count_status != ESP_GATT_OK) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Error getting characteristic count, status=%d", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str(), char_count_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now process characteristics
|
||||||
while (true) { // characteristics
|
while (true) { // characteristics
|
||||||
uint16_t char_count = 1;
|
uint16_t char_count = 1;
|
||||||
esp_gatt_status_t char_status = esp_ble_gattc_get_all_char(
|
esp_gatt_status_t char_status = esp_ble_gattc_get_all_char(
|
||||||
@ -187,6 +218,23 @@ void BluetoothProxy::loop() {
|
|||||||
characteristic_resp.handle = char_result.char_handle;
|
characteristic_resp.handle = char_result.char_handle;
|
||||||
characteristic_resp.properties = char_result.properties;
|
characteristic_resp.properties = char_result.properties;
|
||||||
char_offset++;
|
char_offset++;
|
||||||
|
|
||||||
|
// Get the number of descriptors directly with one call
|
||||||
|
uint16_t total_desc_count = 0;
|
||||||
|
esp_gatt_status_t desc_count_status =
|
||||||
|
esp_ble_gattc_get_attr_count(connection->get_gattc_if(), connection->get_conn_id(), ESP_GATT_DB_DESCRIPTOR,
|
||||||
|
char_result.char_handle, service_result.end_handle, 0, &total_desc_count);
|
||||||
|
|
||||||
|
if (desc_count_status == ESP_GATT_OK && total_desc_count > 0) {
|
||||||
|
// Only reserve if we successfully got a count
|
||||||
|
characteristic_resp.descriptors.reserve(total_desc_count);
|
||||||
|
} else if (desc_count_status != ESP_GATT_OK) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Error getting descriptor count for char handle %d, status=%d",
|
||||||
|
connection->get_connection_index(), connection->address_str().c_str(), char_result.char_handle,
|
||||||
|
desc_count_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now process descriptors
|
||||||
uint16_t desc_offset = 0;
|
uint16_t desc_offset = 0;
|
||||||
esp_gattc_descr_elem_t desc_result;
|
esp_gattc_descr_elem_t desc_result;
|
||||||
while (true) { // descriptors
|
while (true) { // descriptors
|
||||||
|
Loading…
x
Reference in New Issue
Block a user