66 auto &batch_buffer = get_batch_buffer();
69 size_t new_size = batch_buffer.size() + count;
70 if (batch_buffer.capacity() < new_size) {
71 batch_buffer.reserve(new_size);
75 for (
size_t i = 0; i < count; i++) {
76 auto &result = scan_results[i];
77 uint8_t
length = result.adv_data_len + result.scan_rsp_len;
79 batch_buffer.emplace_back();
80 auto &adv = batch_buffer.back();
82 adv.rssi = result.rssi;
83 adv.address_type = result.ble_addr_type;
84 adv.data.assign(&result.ble_adv[0], &result.ble_adv[
length]);
86 ESP_LOGV(TAG,
"Queuing raw packet from %02X:%02X:%02X:%02X:%02X:%02X, length %d. RSSI: %d dB", result.bda[0],
87 result.bda[1], result.bda[2], result.bda[3], result.bda[4], result.bda[5],
length, result.rssi);
92 if (batch_buffer.size() >= FLUSH_BATCH_SIZE) {
173 if (connection->get_address() != 0) {
174 connection->disconnect();
182 static uint32_t last_flush_time = 0;
186 if (now - last_flush_time >= 100) {
188 last_flush_time = now;
192 if (connection->send_service_ == connection->service_count_) {
193 connection->send_service_ = DONE_SENDING_SERVICES;
195 if (connection->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE ||
196 connection->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
197 connection->release_services();
199 }
else if (connection->send_service_ >= 0) {
200 esp_gattc_service_elem_t service_result;
201 uint16_t service_count = 1;
202 esp_gatt_status_t service_status =
203 esp_ble_gattc_get_service(connection->get_gattc_if(), connection->get_conn_id(),
nullptr, &service_result,
204 &service_count, connection->send_service_);
205 connection->send_service_++;
206 if (service_status != ESP_GATT_OK) {
207 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_service error at offset=%d, status=%d",
208 connection->get_connection_index(), connection->address_str().c_str(), connection->send_service_ - 1,
212 if (service_count == 0) {
213 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_service missing, service_count=%d",
214 connection->get_connection_index(), connection->address_str().c_str(), service_count);
218 resp.
address = connection->get_address();
222 service_resp.
handle = service_result.start_handle;
223 uint16_t char_offset = 0;
224 esp_gattc_char_elem_t char_result;
226 uint16_t total_char_count = 0;
227 esp_gatt_status_t char_count_status = esp_ble_gattc_get_attr_count(
228 connection->get_gattc_if(), connection->get_conn_id(), ESP_GATT_DB_CHARACTERISTIC,
229 service_result.start_handle, service_result.end_handle, 0, &total_char_count);
231 if (char_count_status == ESP_GATT_OK && total_char_count > 0) {
234 }
else if (char_count_status != ESP_GATT_OK) {
235 ESP_LOGW(TAG,
"[%d] [%s] Error getting characteristic count, status=%d", connection->get_connection_index(),
236 connection->address_str().c_str(), char_count_status);
241 uint16_t char_count = 1;
242 esp_gatt_status_t char_status = esp_ble_gattc_get_all_char(
243 connection->get_gattc_if(), connection->get_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) {
249 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", connection->get_connection_index(),
250 connection->address_str().c_str(), char_status);
253 if (char_count == 0) {
258 characteristic_resp.
handle = char_result.char_handle;
259 characteristic_resp.
properties = char_result.properties;
263 uint16_t total_desc_count = 0;
264 esp_gatt_status_t desc_count_status =
265 esp_ble_gattc_get_attr_count(connection->get_gattc_if(), connection->get_conn_id(), ESP_GATT_DB_DESCRIPTOR,
266 char_result.char_handle, service_result.end_handle, 0, &total_desc_count);
268 if (desc_count_status == ESP_GATT_OK && total_desc_count > 0) {
270 characteristic_resp.
descriptors.reserve(total_desc_count);
271 }
else if (desc_count_status != ESP_GATT_OK) {
272 ESP_LOGW(TAG,
"[%d] [%s] Error getting descriptor count for char handle %d, status=%d",
273 connection->get_connection_index(), connection->address_str().c_str(), char_result.char_handle,
278 uint16_t desc_offset = 0;
279 esp_gattc_descr_elem_t desc_result;
281 uint16_t desc_count = 1;
282 esp_gatt_status_t desc_status =
283 esp_ble_gattc_get_all_descr(connection->get_gattc_if(), connection->get_conn_id(),
284 char_result.char_handle, &desc_result, &desc_count, desc_offset);
285 if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
288 if (desc_status != ESP_GATT_OK) {
289 ESP_LOGE(TAG,
"[%d] [%s] esp_ble_gattc_get_all_descr error, status=%d", connection->get_connection_index(),
290 connection->address_str().c_str(), desc_status);
293 if (desc_count == 0) {
298 descriptor_resp.
handle = desc_result.handle;
299 characteristic_resp.
descriptors.push_back(std::move(descriptor_resp));
302 service_resp.
characteristics.push_back(std::move(characteristic_resp));
304 resp.
services.push_back(std::move(service_resp));
347 if (connection ==
nullptr) {
348 ESP_LOGW(TAG,
"No free connections available");
352 if (connection->state() == espbt::ClientState::CONNECTED ||
353 connection->state() == espbt::ClientState::ESTABLISHED) {
354 ESP_LOGW(TAG,
"[%d] [%s] Connection already established", connection->get_connection_index(),
355 connection->address_str().c_str());
359 }
else if (connection->state() == espbt::ClientState::SEARCHING) {
360 ESP_LOGW(TAG,
"[%d] [%s] Connection request ignored, already searching for device",
361 connection->get_connection_index(), connection->address_str().c_str());
363 }
else if (connection->state() == espbt::ClientState::DISCOVERED) {
364 ESP_LOGW(TAG,
"[%d] [%s] Connection request ignored, device already discovered",
365 connection->get_connection_index(), connection->address_str().c_str());
367 }
else if (connection->state() == espbt::ClientState::READY_TO_CONNECT) {
368 ESP_LOGW(TAG,
"[%d] [%s] Connection request ignored, waiting in line to connect",
369 connection->get_connection_index(), connection->address_str().c_str());
371 }
else if (connection->state() == espbt::ClientState::CONNECTING) {
372 if (connection->disconnect_pending()) {
373 ESP_LOGW(TAG,
"[%d] [%s] Connection request while pending disconnect, cancelling pending disconnect",
374 connection->get_connection_index(), connection->address_str().c_str());
375 connection->cancel_pending_disconnect();
378 ESP_LOGW(TAG,
"[%d] [%s] Connection request ignored, already connecting", connection->get_connection_index(),
379 connection->address_str().c_str());
381 }
else if (connection->state() == espbt::ClientState::DISCONNECTING) {
382 ESP_LOGW(TAG,
"[%d] [%s] Connection request ignored, device is disconnecting",
383 connection->get_connection_index(), connection->address_str().c_str());
385 }
else if (connection->state() != espbt::ClientState::INIT) {
386 ESP_LOGW(TAG,
"[%d] [%s] Connection already in progress", connection->get_connection_index(),
387 connection->address_str().c_str());
391 connection->set_connection_type(espbt::ConnectionType::V3_WITH_CACHE);
392 ESP_LOGI(TAG,
"[%d] [%s] Connecting v3 with cache", connection->get_connection_index(),
393 connection->address_str().c_str());
395 connection->set_connection_type(espbt::ConnectionType::V3_WITHOUT_CACHE);
396 ESP_LOGI(TAG,
"[%d] [%s] Connecting v3 without cache", connection->get_connection_index(),
397 connection->address_str().c_str());
399 connection->set_connection_type(espbt::ConnectionType::V1);
400 ESP_LOGI(TAG,
"[%d] [%s] Connecting v1", connection->get_connection_index(), connection->address_str().c_str());
404 connection->set_remote_addr_type(
static_cast<esp_ble_addr_type_t
>(msg.
address_type));
405 connection->set_state(espbt::ClientState::DISCOVERED);
407 connection->set_state(espbt::ClientState::SEARCHING);
414 if (connection ==
nullptr) {
419 if (connection->state() != espbt::ClientState::IDLE) {
420 connection->disconnect();
422 connection->set_address(0);
430 if (connection !=
nullptr) {
431 if (!connection->is_paired()) {
432 auto err = connection->pair();
445 esp_err_t ret = esp_ble_remove_bond_device(
address);
452 esp_err_t ret = esp_ble_gattc_cache_clean(
address);
455 call.success = ret == ESP_OK;