183 if (api_conn ==
nullptr) {
197 static constexpr size_t MAX_PACKET_SIZE = 1360;
203 esp_gattc_service_elem_t service_result;
204 uint16_t service_count = 1;
205 esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->
gattc_if_, this->
conn_id_,
nullptr,
208 if (service_status != ESP_GATT_OK || service_count == 0) {
209 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
217 uint16_t total_char_count = 0;
218 esp_gatt_status_t char_count_status =
219 esp_ble_gattc_get_attr_count(this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_CHARACTERISTIC,
220 service_result.start_handle, service_result.end_handle, 0, &total_char_count);
222 if (char_count_status != ESP_GATT_OK) {
229 size_t estimated_size = estimate_service_size(total_char_count, use_efficient_uuids);
230 if (!resp.
services.empty() && (current_size + estimated_size > MAX_PACKET_SIZE)) {
237 auto &service_resp = resp.
services.back();
239 fill_gatt_uuid(service_resp.uuid, service_resp.short_uuid, service_result.uuid, use_efficient_uuids);
241 service_resp.handle = service_result.start_handle;
243 if (total_char_count > 0) {
245 service_resp.characteristics.init(total_char_count);
246 uint16_t char_offset = 0;
247 esp_gattc_char_elem_t char_result;
250 while (char_offset < total_char_count) {
251 uint16_t char_count = 1;
252 esp_gatt_status_t char_status =
253 esp_ble_gattc_get_all_char(this->
gattc_if_, this->
conn_id_, service_result.start_handle,
254 service_result.end_handle, &char_result, &char_count, char_offset);
255 if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
258 if (char_status != ESP_GATT_OK) {
263 if (char_count == 0) {
267 service_resp.characteristics.emplace_back();
268 auto &characteristic_resp = service_resp.characteristics.back();
269 fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
270 characteristic_resp.handle = char_result.char_handle;
271 characteristic_resp.properties = char_result.properties;
275 uint16_t total_desc_count = 0;
276 esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
277 this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
279 if (desc_count_status != ESP_GATT_OK) {
284 if (total_desc_count == 0) {
289 characteristic_resp.descriptors.init(total_desc_count);
290 uint16_t desc_offset = 0;
291 esp_gattc_descr_elem_t desc_result;
292 while (desc_offset < total_desc_count) {
293 uint16_t desc_count = 1;
294 esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
295 this->
gattc_if_, this->
conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
296 if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
299 if (desc_status != ESP_GATT_OK) {
304 if (desc_count == 0) {
308 characteristic_resp.descriptors.emplace_back();
309 auto &descriptor_resp = characteristic_resp.descriptors.back();
310 fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
311 descriptor_resp.handle = desc_result.handle;
318 size_t service_size = service_resp.calculate_size() + 1;
321 if (current_size + service_size > MAX_PACKET_SIZE) {
325 ESP_LOGD(TAG,
"[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
331 ESP_LOGV(TAG,
"[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->
connection_index_,
341 current_size += service_size;
347 api_conn->send_message(resp);
377 esp_ble_gattc_cb_param_t *param) {
382 case ESP_GATTC_DISCONNECT_EVT: {
386 param->disconnect.reason);
391 case ESP_GATTC_OPEN_EVT: {
392 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
394 }
else if (this->
connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
401 case ESP_GATTC_CFG_MTU_EVT:
402 case ESP_GATTC_SEARCH_CMPL_EVT: {
414 case ESP_GATTC_READ_DESCR_EVT:
415 case ESP_GATTC_READ_CHAR_EVT: {
416 if (param->read.status != ESP_GATT_OK) {
422 if (api_connection ==
nullptr)
426 resp.
handle = param->read.handle;
427 resp.
set_data(param->read.value, param->read.value_len);
428 api_connection->send_message(resp);
431 case ESP_GATTC_WRITE_CHAR_EVT:
432 case ESP_GATTC_WRITE_DESCR_EVT: {
433 if (param->write.status != ESP_GATT_OK) {
439 if (api_connection ==
nullptr)
443 resp.
handle = param->write.handle;
444 api_connection->send_message(resp);
447 case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
448 if (param->unreg_for_notify.status != ESP_GATT_OK) {
450 param->unreg_for_notify.status);
455 if (api_connection ==
nullptr)
459 resp.
handle = param->unreg_for_notify.handle;
460 api_connection->send_message(resp);
463 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
464 if (param->reg_for_notify.status != ESP_GATT_OK) {
466 param->reg_for_notify.status);
471 if (api_connection ==
nullptr)
475 resp.
handle = param->reg_for_notify.handle;
476 api_connection->send_message(resp);
479 case ESP_GATTC_NOTIFY_EVT: {
481 param->notify.handle);
483 if (api_connection ==
nullptr)
487 resp.
handle = param->notify.handle;
488 resp.
set_data(param->notify.value, param->notify.value_len);
489 api_connection->send_message(resp);