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.init(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();
256 fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
257 characteristic_resp.handle = char_result.char_handle;
258 characteristic_resp.properties = char_result.properties;
262 uint16_t total_desc_count = 0;
263 esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
264 this->
gattc_if_, this->
conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
266 if (desc_count_status != ESP_GATT_OK) {
271 if (total_desc_count == 0) {
276 characteristic_resp.descriptors.init(total_desc_count);
277 uint16_t desc_offset = 0;
278 esp_gattc_descr_elem_t desc_result;
280 uint16_t desc_count = 1;
281 esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
282 this->
gattc_if_, this->
conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
283 if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
286 if (desc_status != ESP_GATT_OK) {
291 if (desc_count == 0) {
295 characteristic_resp.descriptors.emplace_back();
296 auto &descriptor_resp = characteristic_resp.descriptors.back();
297 fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
298 descriptor_resp.handle = desc_result.handle;
306 service_resp.calculate_size(service_sizer);
307 size_t service_size = service_sizer.
get_size() + 1;
310 if (current_size + service_size > MAX_PACKET_SIZE) {
314 ESP_LOGD(TAG,
"[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
320 ESP_LOGV(TAG,
"[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->
connection_index_,
330 current_size += service_size;
367 esp_ble_gattc_cb_param_t *param) {
372 case ESP_GATTC_DISCONNECT_EVT: {
376 param->disconnect.reason);
381 case ESP_GATTC_CLOSE_EVT: {
383 param->close.reason);
389 case ESP_GATTC_OPEN_EVT: {
390 if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
392 }
else if (this->
connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
399 case ESP_GATTC_CFG_MTU_EVT:
400 case ESP_GATTC_SEARCH_CMPL_EVT: {
412 case ESP_GATTC_READ_DESCR_EVT:
413 case ESP_GATTC_READ_CHAR_EVT: {
414 if (param->read.status != ESP_GATT_OK) {
421 resp.
handle = param->read.handle;
422 resp.
set_data(param->read.value, param->read.value_len);
426 case ESP_GATTC_WRITE_CHAR_EVT:
427 case ESP_GATTC_WRITE_DESCR_EVT: {
428 if (param->write.status != ESP_GATT_OK) {
435 resp.
handle = param->write.handle;
439 case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
440 if (param->unreg_for_notify.status != ESP_GATT_OK) {
442 param->unreg_for_notify.status);
448 resp.
handle = param->unreg_for_notify.handle;
452 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
453 if (param->reg_for_notify.status != ESP_GATT_OK) {
455 param->reg_for_notify.status);
461 resp.
handle = param->reg_for_notify.handle;
465 case ESP_GATTC_NOTIFY_EVT: {
467 param->notify.handle);
470 resp.
handle = param->notify.handle;
471 resp.
set_data(param->notify.value, param->notify.value_len);