From d5ff8f611785d158889c0af4677e6dd29e686ebf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 28 Nov 2022 18:14:29 -1000 Subject: [PATCH] Reduce memory needed to send the services list (#4110) --- .../bluetooth_proxy/bluetooth_proxy.cpp | 62 ++++++++++++++----- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index 188e3dd5a5..602edc2fa6 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -86,31 +86,59 @@ void BluetoothProxy::loop() { api::BluetoothGATTService service_resp; service_resp.uuid = {service->uuid.get_128bit_high(), service->uuid.get_128bit_low()}; service_resp.handle = service->start_handle; - if (!service->parsed) - service->parse_characteristics(); - for (auto &characteristic : service->characteristics) { + uint16_t char_offset = 0; + esp_gattc_char_elem_t char_result; + while (true) { // characteristics + uint16_t char_count = 1; + esp_gatt_status_t char_status = + esp_ble_gattc_get_all_char(connection->get_gattc_if(), connection->get_conn_id(), service->start_handle, + service->end_handle, &char_result, &char_count, char_offset); + if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) { + break; + } + if (char_status != ESP_GATT_OK) { + ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", connection->get_connection_index(), + connection->address_str().c_str(), char_status); + break; + } + if (char_count == 0) { + break; + } api::BluetoothGATTCharacteristic characteristic_resp; - characteristic_resp.uuid = {characteristic->uuid.get_128bit_high(), characteristic->uuid.get_128bit_low()}; - characteristic_resp.handle = characteristic->handle; - characteristic_resp.properties = characteristic->properties; - if (!characteristic->parsed) - characteristic->parse_descriptors(); - for (auto &descriptor : characteristic->descriptors) { + auto char_uuid = espbt::ESPBTUUID::from_uuid(char_result.uuid); + characteristic_resp.uuid = {char_uuid.get_128bit_high(), char_uuid.get_128bit_low()}; + characteristic_resp.handle = char_result.char_handle; + characteristic_resp.properties = char_result.properties; + char_offset++; + uint16_t desc_offset = 0; + esp_gattc_descr_elem_t desc_result; + while (true) { // descriptors + uint16_t desc_count = 1; + esp_gatt_status_t desc_status = + esp_ble_gattc_get_all_descr(connection->get_gattc_if(), connection->get_conn_id(), + char_result.char_handle, &desc_result, &desc_count, desc_offset); + if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) { + break; + } + if (desc_status != ESP_GATT_OK) { + ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_get_all_descr error, status=%d", connection->get_connection_index(), + connection->address_str().c_str(), desc_status); + break; + } + if (desc_count == 0) { + break; + } api::BluetoothGATTDescriptor descriptor_resp; - descriptor_resp.uuid = {descriptor->uuid.get_128bit_high(), descriptor->uuid.get_128bit_low()}; - descriptor_resp.handle = descriptor->handle; + auto desc_uuid = espbt::ESPBTUUID::from_uuid(desc_result.uuid); + descriptor_resp.uuid = {desc_uuid.get_128bit_high(), desc_uuid.get_128bit_low()}; + descriptor_resp.handle = desc_result.handle; characteristic_resp.descriptors.push_back(std::move(descriptor_resp)); + desc_offset++; } service_resp.characteristics.push_back(std::move(characteristic_resp)); } resp.services.push_back(std::move(service_resp)); api::global_api_server->send_bluetooth_gatt_services(resp); - // Descriptors are rarely used and can be quite large so we clear them - // after sending them to save memory. If something actually needs them - // it can parse them again. - for (auto &characteristic : service->characteristics) { - characteristic->release_descriptors(); - } connection->send_service_++; } }