169 if (api_conn ==
nullptr) {
183 static constexpr size_t MAX_PACKET_SIZE = 1360;
186 size_t current_size = 0;
192 esp_gattc_service_elem_t service_result;
193 uint16_t service_count = 1;
194 esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->
gattc_if_, this->
conn_id_,
nullptr,
197 if (service_status != ESP_GATT_OK || service_count == 0) {
198 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
200 service_status != ESP_GATT_OK ?
"error" :
"missing", service_status, service_count, this->
send_service_);
206 uint16_t total_char_count = 0;
207 esp_gatt_status_t char_count_status =
208 esp_ble_gattc_get_attr_count(this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_CHARACTERISTIC,
209 service_result.start_handle, service_result.end_handle, 0, &total_char_count);
211 if (char_count_status != ESP_GATT_OK) {
218 size_t estimated_size = estimate_service_size(total_char_count, use_efficient_uuids);
219 if (!resp.
services.empty() && (current_size + estimated_size > MAX_PACKET_SIZE)) {
226 auto &service_resp = resp.
services.back();
228 fill_gatt_uuid(service_resp.uuid, service_resp.short_uuid, service_result.uuid, use_efficient_uuids);
230 service_resp.handle = service_result.start_handle;
232 if (total_char_count > 0) {
234 service_resp.characteristics.reserve(total_char_count);
235 uint16_t char_offset = 0;
236 esp_gattc_char_elem_t char_result;
238 uint16_t char_count = 1;
239 esp_gatt_status_t char_status =
240 esp_ble_gattc_get_all_char(this->
gattc_if_, this->
conn_id_, service_result.start_handle,
241 service_result.end_handle, &char_result, &char_count, char_offset);
242 if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
245 if (char_status != ESP_GATT_OK) {
250 if (char_count == 0) {
254 service_resp.characteristics.emplace_back();
255 auto &characteristic_resp = service_resp.characteristics.back();
257 fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
259 characteristic_resp.handle = char_result.char_handle;
260 characteristic_resp.properties = char_result.properties;
264 uint16_t total_desc_count = 0;
265 esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
266 this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
268 if (desc_count_status != ESP_GATT_OK) {
273 if (total_desc_count == 0) {
279 characteristic_resp.descriptors.reserve(total_desc_count);
280 uint16_t desc_offset = 0;
281 esp_gattc_descr_elem_t desc_result;
283 uint16_t desc_count = 1;
284 esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
285 this->
gattc_if_, this->
conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
286 if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
289 if (desc_status != ESP_GATT_OK) {
294 if (desc_count == 0) {
298 characteristic_resp.descriptors.emplace_back();
299 auto &descriptor_resp = characteristic_resp.descriptors.back();
301 fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
303 descriptor_resp.handle = desc_result.handle;
311 service_resp.calculate_size(service_sizer);
312 size_t service_size = service_sizer.
get_size() + 1;
315 if (current_size + service_size > MAX_PACKET_SIZE) {
319 ESP_LOGD(TAG,
"[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
325 ESP_LOGV(TAG,
"[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->
connection_index_,
335 current_size += service_size;
372 esp_ble_gattc_cb_param_t *param) {
377 case ESP_GATTC_DISCONNECT_EVT: {
381 param->disconnect.reason);
386 case ESP_GATTC_CLOSE_EVT: {
388 param->close.reason);
394 case ESP_GATTC_OPEN_EVT: {
395 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
397 }
else if (this->
connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
404 case ESP_GATTC_CFG_MTU_EVT:
405 case ESP_GATTC_SEARCH_CMPL_EVT: {
417 case ESP_GATTC_READ_DESCR_EVT:
418 case ESP_GATTC_READ_CHAR_EVT: {
419 if (param->read.status != ESP_GATT_OK) {
426 resp.
handle = param->read.handle;
427 resp.
set_data(param->read.value, param->read.value_len);
431 case ESP_GATTC_WRITE_CHAR_EVT:
432 case ESP_GATTC_WRITE_DESCR_EVT: {
433 if (param->write.status != ESP_GATT_OK) {
440 resp.
handle = param->write.handle;
444 case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
445 if (param->unreg_for_notify.status != ESP_GATT_OK) {
447 param->unreg_for_notify.status);
453 resp.
handle = param->unreg_for_notify.handle;
457 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
458 if (param->reg_for_notify.status != ESP_GATT_OK) {
460 param->reg_for_notify.status);
466 resp.
handle = param->reg_for_notify.handle;
470 case ESP_GATTC_NOTIFY_EVT: {
472 param->notify.handle);
475 resp.
handle = param->notify.handle;
476 resp.
set_data(param->notify.value, param->notify.value_len);