172 if (api_conn ==
nullptr) {
186 static constexpr size_t MAX_PACKET_SIZE = 1360;
189 size_t current_size = 0;
195 esp_gattc_service_elem_t service_result;
196 uint16_t service_count = 1;
197 esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->
gattc_if_, this->
conn_id_,
nullptr,
200 if (service_status != ESP_GATT_OK || service_count == 0) {
201 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
203 service_status != ESP_GATT_OK ?
"error" :
"missing", service_status, service_count, this->
send_service_);
209 uint16_t total_char_count = 0;
210 esp_gatt_status_t char_count_status =
211 esp_ble_gattc_get_attr_count(this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_CHARACTERISTIC,
212 service_result.start_handle, service_result.end_handle, 0, &total_char_count);
214 if (char_count_status != ESP_GATT_OK) {
221 size_t estimated_size = estimate_service_size(total_char_count, use_efficient_uuids);
222 if (!resp.
services.empty() && (current_size + estimated_size > MAX_PACKET_SIZE)) {
229 auto &service_resp = resp.
services.back();
231 fill_gatt_uuid(service_resp.uuid, service_resp.short_uuid, service_result.uuid, use_efficient_uuids);
233 service_resp.handle = service_result.start_handle;
235 if (total_char_count > 0) {
237 service_resp.characteristics.reserve(total_char_count);
238 uint16_t char_offset = 0;
239 esp_gattc_char_elem_t char_result;
241 uint16_t char_count = 1;
242 esp_gatt_status_t char_status =
243 esp_ble_gattc_get_all_char(this->
gattc_if_, this->
conn_id_, service_result.start_handle,
244 service_result.end_handle, &char_result, &char_count, char_offset);
245 if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
248 if (char_status != ESP_GATT_OK) {
253 if (char_count == 0) {
257 service_resp.characteristics.emplace_back();
258 auto &characteristic_resp = service_resp.characteristics.back();
260 fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
262 characteristic_resp.handle = char_result.char_handle;
263 characteristic_resp.properties = char_result.properties;
267 uint16_t total_desc_count = 0;
268 esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
269 this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
271 if (desc_count_status != ESP_GATT_OK) {
276 if (total_desc_count == 0) {
282 characteristic_resp.descriptors.reserve(total_desc_count);
283 uint16_t desc_offset = 0;
284 esp_gattc_descr_elem_t desc_result;
286 uint16_t desc_count = 1;
287 esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
288 this->
gattc_if_, this->
conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
289 if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
292 if (desc_status != ESP_GATT_OK) {
297 if (desc_count == 0) {
301 characteristic_resp.descriptors.emplace_back();
302 auto &descriptor_resp = characteristic_resp.descriptors.back();
304 fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
306 descriptor_resp.handle = desc_result.handle;
314 service_resp.calculate_size(service_sizer);
315 size_t service_size = service_sizer.
get_size() + 1;
318 if (current_size + service_size > MAX_PACKET_SIZE) {
322 ESP_LOGD(TAG,
"[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
328 ESP_LOGV(TAG,
"[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->
connection_index_,
338 current_size += service_size;
375 esp_ble_gattc_cb_param_t *param) {
380 case ESP_GATTC_DISCONNECT_EVT: {
384 case ESP_GATTC_CLOSE_EVT: {
388 case ESP_GATTC_OPEN_EVT: {
389 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
391 }
else if (this->
connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
398 case ESP_GATTC_CFG_MTU_EVT:
399 case ESP_GATTC_SEARCH_CMPL_EVT: {
411 case ESP_GATTC_READ_DESCR_EVT:
412 case ESP_GATTC_READ_CHAR_EVT: {
413 if (param->read.status != ESP_GATT_OK) {
420 resp.
handle = param->read.handle;
421 resp.
set_data(param->read.value, param->read.value_len);
425 case ESP_GATTC_WRITE_CHAR_EVT:
426 case ESP_GATTC_WRITE_DESCR_EVT: {
427 if (param->write.status != ESP_GATT_OK) {
434 resp.
handle = param->write.handle;
438 case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
439 if (param->unreg_for_notify.status != ESP_GATT_OK) {
441 param->unreg_for_notify.status);
447 resp.
handle = param->unreg_for_notify.handle;
451 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
452 if (param->reg_for_notify.status != ESP_GATT_OK) {
454 param->reg_for_notify.status);
460 resp.
handle = param->reg_for_notify.handle;
464 case ESP_GATTC_NOTIFY_EVT: {
466 param->notify.handle);
469 resp.
handle = param->notify.handle;
470 resp.
set_data(param->notify.value, param->notify.value_len);