mirror of
https://github.com/esphome/esphome.git
synced 2026-09-27 15:00:24 +00:00
Report teardown once at CLOSE_EVT and refuse connects on a busy slot
This commit is contained in:
@@ -111,6 +111,11 @@ concept BLEGattConnectionContract = requires(T conn, Sink *sink, const uint8_t *
|
||||
{ conn.update_connection_params(uint16_t{}, uint16_t{}, uint16_t{}, uint16_t{}) } -> std::same_as<int>;
|
||||
{ conn.get_service_table() } -> std::same_as<GattServiceTable>;
|
||||
{ conn.release_services() } -> std::same_as<void>;
|
||||
// Deferred-disconnect visibility and the connection-type hint; backends
|
||||
// without the underlying state carry inline no-ops.
|
||||
{ conn.disconnect_pending() } -> std::same_as<bool>;
|
||||
{ conn.cancel_pending_disconnect() } -> std::same_as<void>;
|
||||
{ conn.set_connection_type(ConnectionType{}) } -> std::same_as<void>;
|
||||
};
|
||||
|
||||
// The event sink the backend calls directly (the hub BluetoothConnection
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
|
||||
#include <esp_bt.h>
|
||||
#endif
|
||||
#include <esp_gatt_common_api.h>
|
||||
|
||||
#include <cstring>
|
||||
@@ -92,6 +89,13 @@ void BluedroidGattClient::dump_config() {
|
||||
// ---- contract ops ----
|
||||
|
||||
int BluedroidGattClient::connect(uint64_t address, uint8_t addr_type) {
|
||||
// Refuse anything but a fully idle slot. Clobbering DISCONNECTING with
|
||||
// DISCOVERED would let the tracker open a new link while the old one is
|
||||
// still closing - the stale CLOSE_EVT then tears the new attempt down.
|
||||
if (this->state_() != ClientState::IDLE) {
|
||||
ESP_LOGW(TAG, "[%d] Connect rejected, slot busy", this->connection_index_);
|
||||
return ESP_GATT_BUSY;
|
||||
}
|
||||
ble_device_base::uint64_to_mac_msb_first(address, this->remote_bda_);
|
||||
this->remote_addr_type_ = addr_type;
|
||||
// Hand the request to the tracker's promote loop: it stops the scan, raises
|
||||
@@ -488,11 +492,12 @@ void BluedroidGattClient::handle_disconnect_evt_(esp_ble_gattc_cb_param_t *param
|
||||
// Active close delivers CLOSE_EVT first; never walk back to DISCONNECTING.
|
||||
return;
|
||||
}
|
||||
// Passive disconnect: report now, but wait for CLOSE_EVT before going IDLE -
|
||||
// reconnecting earlier makes the controller reject with 133 or assert.
|
||||
// Passive disconnect: wait for CLOSE_EVT before going IDLE (reconnecting
|
||||
// earlier makes the controller reject with 133 or assert) and before
|
||||
// reporting - the wrapper frees the slot on the report, and a freed slot
|
||||
// invites a reconnect into the still-closing link.
|
||||
this->release_services();
|
||||
this->set_disconnecting_();
|
||||
this->report_connection_state_(false, param->disconnect.reason);
|
||||
}
|
||||
|
||||
bool BluedroidGattClient::handle_gattc_event_(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if,
|
||||
@@ -556,9 +561,8 @@ bool BluedroidGattClient::handle_gattc_event_(esp_gattc_cb_event_t event, esp_ga
|
||||
return false;
|
||||
this->release_services();
|
||||
this->set_idle_();
|
||||
// The wrapper frees the slot on this final report; after a passive
|
||||
// disconnect this is the second connected=false, matching the previous
|
||||
// esp32 behavior (report at DISCONNECT, slot free at CLOSE).
|
||||
// The one connected=false report: the wrapper frees the slot on it,
|
||||
// so it must not fire before the controller finished closing.
|
||||
this->report_connection_state_(false, param->close.reason);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ conn_err_t unpair_device(uint64_t address) {
|
||||
conn_err_t clear_gatt_cache(uint64_t address) {
|
||||
esp_bd_addr_t bda;
|
||||
ble_device_base::uint64_to_mac_msb_first(address, bda);
|
||||
esp_ble_gattc_cache_clean(bda);
|
||||
return CONN_OK;
|
||||
return esp_ble_gattc_cache_clean(bda);
|
||||
}
|
||||
|
||||
} // namespace esphome::bluetooth_connection
|
||||
|
||||
@@ -130,7 +130,10 @@ void BluetoothConnection::on_connection_state(bool connected, uint16_t mtu, int
|
||||
if (this->connection_type_ == ConnectionType::V3_WITH_CACHE) {
|
||||
// The API client has the services cached; never discover them. No
|
||||
// discovery phase needs the fast interval, so settle straight into the
|
||||
// shared steady-state parameters (same lifecycle place as esp32).
|
||||
// shared steady-state parameters. On esp32 the backend already set the
|
||||
// same values as prefer-params before opening, so this request is
|
||||
// usually redundant there - kept because rp2 has no prefer-params and
|
||||
// the explicit update is its only path to the steady-state interval.
|
||||
this->state_ = ClientState::ESTABLISHED;
|
||||
int param_err = this->backend_->update_connection_params(ble_device_base::MEDIUM_MIN_CONN_INTERVAL,
|
||||
ble_device_base::MEDIUM_MAX_CONN_INTERVAL, 0,
|
||||
|
||||
@@ -51,6 +51,9 @@ class MinimalConnection {
|
||||
}
|
||||
GattServiceTable get_service_table() { return {}; }
|
||||
void release_services() {}
|
||||
bool disconnect_pending() const { return false; }
|
||||
void cancel_pending_disconnect() {}
|
||||
void set_connection_type(ConnectionType ct) {}
|
||||
|
||||
protected:
|
||||
RecordingSink *listener_{nullptr};
|
||||
|
||||
Reference in New Issue
Block a user