mirror of
https://github.com/esphome/esphome.git
synced 2026-08-25 15:46:20 +00:00
Merge branch 'esp32-gatt-backend' into esp32-proxy-flip
This commit is contained in:
@@ -15,13 +15,13 @@ namespace esphome::ble_device_base {
|
||||
/// ATT code range so they cannot be mistaken for spec errors. -1 is
|
||||
/// understood by API clients as "not connected". Shared by every GATT
|
||||
/// client backend.
|
||||
static constexpr int GATT_ERR_NOT_CONNECTED = -1;
|
||||
static constexpr int GATT_ERR_NO_MEMORY = -2;
|
||||
|
||||
/// Safety net shared by every GATT backend: force IDLE when the stack never
|
||||
/// delivers its disconnect completion.
|
||||
static constexpr uint32_t GATT_DISCONNECT_TIMEOUT_MS = 10000;
|
||||
|
||||
static constexpr int GATT_ERR_NOT_CONNECTED = -1;
|
||||
static constexpr int GATT_ERR_NO_MEMORY = -2;
|
||||
|
||||
// Preferred connection parameters shared by every platform's GATT client so
|
||||
// the backends cannot drift (units: interval 1.25 ms, timeout 10 ms; latency
|
||||
// 0). FAST covers connection setup and service discovery; MEDIUM is the
|
||||
|
||||
@@ -135,13 +135,18 @@ void BluedroidGattClient::tracker_connect_() {
|
||||
|
||||
int BluedroidGattClient::disconnect() {
|
||||
auto st = this->state_();
|
||||
if (st == ClientState::IDLE || st == ClientState::DISCONNECTING) {
|
||||
if (st == ClientState::DISCONNECTING) {
|
||||
return 0;
|
||||
}
|
||||
// Nothing was opened, so no completion event will follow: report
|
||||
// not-connected and the hub frees the slot at once (rp2 convention).
|
||||
if (st == ClientState::IDLE) {
|
||||
return ble_device_base::GATT_ERR_NOT_CONNECTED;
|
||||
}
|
||||
if (st == ClientState::DISCOVERED) {
|
||||
// Never opened: nothing to close.
|
||||
// Parked for the tracker promote loop, never opened.
|
||||
this->set_state_(ClientState::IDLE);
|
||||
return 0;
|
||||
return ble_device_base::GATT_ERR_NOT_CONNECTED;
|
||||
}
|
||||
if (st == ClientState::CONNECTING || this->conn_id_ == UNSET_CONN_ID) {
|
||||
ESP_LOGD(TAG, "[%d] Disconnect scheduled", this->connection_index_);
|
||||
@@ -279,10 +284,20 @@ void BluedroidGattClient::handle_search_cmpl_() {
|
||||
this->update_conn_params_(MEDIUM_MIN_CONN_INTERVAL, MEDIUM_MAX_CONN_INTERVAL, 0, MEDIUM_CONN_TIMEOUT, "medium");
|
||||
uint16_t primary = 0;
|
||||
uint16_t secondary = 0;
|
||||
esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_PRIMARY_SERVICE, 0x0001, 0xFFFF, 0,
|
||||
&primary);
|
||||
esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_SECONDARY_SERVICE, 0x0001, 0xFFFF, 0,
|
||||
&secondary);
|
||||
auto primary_status = esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_PRIMARY_SERVICE,
|
||||
0x0001, 0xFFFF, 0, &primary);
|
||||
auto secondary_status = esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_SECONDARY_SERVICE,
|
||||
0x0001, 0xFFFF, 0, &secondary);
|
||||
if (primary_status != ESP_GATT_OK || secondary_status != ESP_GATT_OK) {
|
||||
// A failed count must not become an authoritative empty database - V3
|
||||
// clients cache the streamed result permanently.
|
||||
auto status = primary_status != ESP_GATT_OK ? primary_status : secondary_status;
|
||||
this->log_gattc_warning_("esp_ble_gattc_get_attr_count", status);
|
||||
if (this->listener_ != nullptr) {
|
||||
this->listener_->on_service_discovery_done(status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this->service_total_ = primary + secondary;
|
||||
this->listener_->on_service_discovery_done(0);
|
||||
}
|
||||
@@ -358,6 +373,7 @@ void BluedroidGattClient::stream_service_batch(BluetoothConnection &conn) {
|
||||
}
|
||||
if (char_status != ESP_GATT_OK || cc == 0) {
|
||||
if (char_status != ESP_GATT_OK) {
|
||||
this->log_gattc_warning_("esp_ble_gattc_get_all_char", char_status);
|
||||
conn.send_service_ = DONE_SENDING_SERVICES;
|
||||
return;
|
||||
}
|
||||
@@ -371,8 +387,15 @@ void BluedroidGattClient::stream_service_batch(BluetoothConnection &conn) {
|
||||
characteristic_resp.properties = char_result.properties;
|
||||
|
||||
uint16_t total_desc_count = 0;
|
||||
esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0,
|
||||
char_result.char_handle, &total_desc_count);
|
||||
auto desc_count_status = esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR,
|
||||
0, 0, char_result.char_handle, &total_desc_count);
|
||||
if (desc_count_status != ESP_GATT_OK) {
|
||||
// Abort rather than stream the characteristic descriptor-less: a
|
||||
// missing CCCD in a cached database breaks notifications for good.
|
||||
this->log_gattc_warning_("esp_ble_gattc_get_attr_count", desc_count_status);
|
||||
conn.send_service_ = DONE_SENDING_SERVICES;
|
||||
return;
|
||||
}
|
||||
if (total_desc_count > 0) {
|
||||
characteristic_resp.descriptors.init(total_desc_count);
|
||||
uint16_t desc_offset = 0;
|
||||
@@ -386,6 +409,7 @@ void BluedroidGattClient::stream_service_batch(BluetoothConnection &conn) {
|
||||
}
|
||||
if (desc_status != ESP_GATT_OK || dc == 0) {
|
||||
if (desc_status != ESP_GATT_OK) {
|
||||
this->log_gattc_warning_("esp_ble_gattc_get_all_descr", desc_status);
|
||||
conn.send_service_ = DONE_SENDING_SERVICES;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#if defined(USE_RP2040_BLE)
|
||||
#include "bluetooth_connection_rp2.h"
|
||||
#define ESPHOME_BLE_GATT_CONNECTION_TYPE bluetooth_connection::RP2GattClient
|
||||
#elif defined(USE_ESP32)
|
||||
#elif defined(USE_ESP32_BLE)
|
||||
#include "bluetooth_connection_bluedroid.h"
|
||||
#define ESPHOME_BLE_GATT_CONNECTION_TYPE bluetooth_connection::BluedroidGattClient
|
||||
#elif defined(USE_BLE_GATT_CLIENT_STUB_BACKEND)
|
||||
|
||||
@@ -67,8 +67,8 @@ void BluetoothConnection::disconnect() {
|
||||
void BluetoothConnection::check_disconnect_timeout_() {
|
||||
// Safety net mirroring the esp32 base class: if the backend's disconnect
|
||||
// completion is lost, force the slot free instead of leaking it.
|
||||
static constexpr uint32_t DISCONNECT_TIMEOUT_MS = 10000;
|
||||
if (this->state_ == ClientState::DISCONNECTING && millis() - this->disconnecting_started_ > DISCONNECT_TIMEOUT_MS) {
|
||||
if (this->state_ == ClientState::DISCONNECTING &&
|
||||
millis() - this->disconnecting_started_ > ble_device_base::GATT_DISCONNECT_TIMEOUT_MS) {
|
||||
ESP_LOGW(TAG, "[%d] [%s] Disconnect timeout, freeing slot", this->connection_index_, this->address_str_);
|
||||
this->reset_connection_(GATT_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user