169 if (api_conn ==
nullptr) {
183 static constexpr size_t MAX_PACKET_SIZE = 1360;
189 esp_gattc_service_elem_t service_result;
190 uint16_t service_count = 1;
191 esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->
gattc_if_, this->
conn_id_,
nullptr,
194 if (service_status != ESP_GATT_OK || service_count == 0) {
195 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
203 uint16_t total_char_count = 0;
204 esp_gatt_status_t char_count_status =
205 esp_ble_gattc_get_attr_count(this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_CHARACTERISTIC,
206 service_result.start_handle, service_result.end_handle, 0, &total_char_count);
208 if (char_count_status != ESP_GATT_OK) {
215 size_t estimated_size = estimate_service_size(total_char_count, use_efficient_uuids);
216 if (!resp.
services.empty() && (current_size + estimated_size > MAX_PACKET_SIZE)) {
223 auto &service_resp = resp.
services.back();
225 fill_gatt_uuid(service_resp.uuid, service_resp.short_uuid, service_result.uuid, use_efficient_uuids);
227 service_resp.handle = service_result.start_handle;
229 if (total_char_count > 0) {
231 service_resp.characteristics.init(total_char_count);
232 uint16_t char_offset = 0;
233 esp_gattc_char_elem_t char_result;
235 uint16_t char_count = 1;
236 esp_gatt_status_t char_status =
237 esp_ble_gattc_get_all_char(this->
gattc_if_, this->
conn_id_, service_result.start_handle,
238 service_result.end_handle, &char_result, &char_count, char_offset);
239 if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
242 if (char_status != ESP_GATT_OK) {
247 if (char_count == 0) {
251 service_resp.characteristics.emplace_back();
252 auto &characteristic_resp = service_resp.characteristics.back();
253 fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
254 characteristic_resp.handle = char_result.char_handle;
255 characteristic_resp.properties = char_result.properties;
259 uint16_t total_desc_count = 0;
260 esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
261 this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
263 if (desc_count_status != ESP_GATT_OK) {
268 if (total_desc_count == 0) {
273 characteristic_resp.descriptors.init(total_desc_count);
274 uint16_t desc_offset = 0;
275 esp_gattc_descr_elem_t desc_result;
277 uint16_t desc_count = 1;
278 esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
279 this->
gattc_if_, this->
conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
280 if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
283 if (desc_status != ESP_GATT_OK) {
288 if (desc_count == 0) {
292 characteristic_resp.descriptors.emplace_back();
293 auto &descriptor_resp = characteristic_resp.descriptors.back();
294 fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
295 descriptor_resp.handle = desc_result.handle;
302 size_t service_size = service_resp.calculate_size() + 1;
305 if (current_size + service_size > MAX_PACKET_SIZE) {
309 ESP_LOGD(TAG,
"[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
315 ESP_LOGV(TAG,
"[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->
connection_index_,
325 current_size += service_size;
331 api_conn->send_message(resp);
361 esp_ble_gattc_cb_param_t *param) {
366 case ESP_GATTC_DISCONNECT_EVT: {
370 param->disconnect.reason);
375 case ESP_GATTC_CLOSE_EVT: {
377 param->close.reason);
383 case ESP_GATTC_OPEN_EVT: {
384 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
386 }
else if (this->
connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
393 case ESP_GATTC_CFG_MTU_EVT:
394 case ESP_GATTC_SEARCH_CMPL_EVT: {
406 case ESP_GATTC_READ_DESCR_EVT:
407 case ESP_GATTC_READ_CHAR_EVT: {
408 if (param->read.status != ESP_GATT_OK) {
414 if (api_connection ==
nullptr)
418 resp.
handle = param->read.handle;
419 resp.
set_data(param->read.value, param->read.value_len);
420 api_connection->send_message(resp);
423 case ESP_GATTC_WRITE_CHAR_EVT:
424 case ESP_GATTC_WRITE_DESCR_EVT: {
425 if (param->write.status != ESP_GATT_OK) {
431 if (api_connection ==
nullptr)
435 resp.
handle = param->write.handle;
436 api_connection->send_message(resp);
439 case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
440 if (param->unreg_for_notify.status != ESP_GATT_OK) {
442 param->unreg_for_notify.status);
447 if (api_connection ==
nullptr)
451 resp.
handle = param->unreg_for_notify.handle;
452 api_connection->send_message(resp);
455 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
456 if (param->reg_for_notify.status != ESP_GATT_OK) {
458 param->reg_for_notify.status);
463 if (api_connection ==
nullptr)
467 resp.
handle = param->reg_for_notify.handle;
468 api_connection->send_message(resp);
471 case ESP_GATTC_NOTIFY_EVT: {
473 param->notify.handle);
475 if (api_connection ==
nullptr)
479 resp.
handle = param->notify.handle;
480 resp.
set_data(param->notify.value, param->notify.value_len);
481 api_connection->send_message(resp);