mirror of
https://github.com/esphome/esphome.git
synced 2026-08-27 00:18:32 +00:00
Merge branch 'esp32-gatt-backend' into neutral-ble-client
# Conflicts: # esphome/components/bluetooth_connection/bluetooth_connection_bluedroid.h # esphome/components/bluetooth_proxy/__init__.py
This commit is contained in:
@@ -163,8 +163,8 @@ _request_gatt_connection_slot = cg.slot_counter(GATT_CLIENT_COUNT_DEFINE)
|
||||
|
||||
def request_gatt_client() -> None:
|
||||
"""Compile in the neutral GATT client contract (ble_gatt_client.h) and
|
||||
claim one connection slot. Called by bluetooth_proxy once per connection
|
||||
it instantiates on a hub platform."""
|
||||
claim one connection slot. Called by bluetooth_connection.new_gatt_backend()
|
||||
once per backend instance."""
|
||||
cg.add_define("USE_BLE_GATT_CLIENT")
|
||||
_request_gatt_connection_slot()
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ static constexpr int GATT_ERR_NO_MEMORY = -2;
|
||||
/// delivers its disconnect completion.
|
||||
static constexpr uint32_t GATT_DISCONNECT_TIMEOUT_MS = 10000;
|
||||
|
||||
/// ATT MTU before negotiation completes (Bluetooth spec default).
|
||||
static constexpr uint16_t DEFAULT_ATT_MTU = 23;
|
||||
|
||||
// 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
|
||||
|
||||
@@ -17,8 +17,6 @@ from esphome.const import PLATFORM_ESP32, PLATFORM_RP2, PlatformFramework
|
||||
from esphome.core import CORE
|
||||
from esphome.types import ConfigType
|
||||
|
||||
DOMAIN = "bluetooth_connection"
|
||||
|
||||
|
||||
def AUTO_LOAD() -> list[str]:
|
||||
"""ble_device_base plus the platform BLE stack the build's backend
|
||||
@@ -40,10 +38,12 @@ bluetooth_connection_ns = cg.esphome_ns.namespace("bluetooth_connection")
|
||||
|
||||
# arduino-pico's prebuilt BTstack is compiled with MAX_NR_GATT_CLIENTS 1;
|
||||
# raising this needs an upstream change (the layer itself supports N).
|
||||
DOMAIN = "bluetooth_connection"
|
||||
|
||||
RP2_MAX_CONNECTIONS = 1
|
||||
|
||||
# Hub platforms with a GATT backend, mapped to their slot limit — the single
|
||||
# registry of which hub platforms run the connection-capable proxy.
|
||||
# Slot limits for the hub platforms running the connection-capable proxy;
|
||||
# the backend registry itself is _PLATFORM_BACKENDS below.
|
||||
HUB_MAX_CONNECTIONS: dict[str, int] = {PLATFORM_RP2: RP2_MAX_CONNECTIONS}
|
||||
|
||||
# The hub-platform wrapper and the backend codegen classes.
|
||||
@@ -73,9 +73,9 @@ def _rp2_schema_fragment() -> cv.Schema:
|
||||
async def _esp32_register(backend: cg.MockObj, config: ConfigType) -> None:
|
||||
from esphome.components import esp32_ble_tracker
|
||||
|
||||
# The tracker's promote loop owns connect timing; the backend's
|
||||
# tracker-facing shim registers as a raw client.
|
||||
await esp32_ble_tracker.register_raw_client(backend.tracker_client(), config)
|
||||
# The tracker's promote loop owns connect timing; the backend registers
|
||||
# as a raw client (it is the tracker's ESPBTClient).
|
||||
await esp32_ble_tracker.register_raw_client(backend, config)
|
||||
|
||||
|
||||
async def _rp2_register(backend: cg.MockObj, config: ConfigType) -> None:
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <esp_gatt_common_api.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace esphome::bluetooth_connection {
|
||||
@@ -35,21 +33,12 @@ using esp32_ble_tracker::ClientState;
|
||||
using esp32_ble_tracker::ConnectionType;
|
||||
|
||||
static constexpr uint16_t UNSET_CONN_ID = 0xFFFF;
|
||||
// Wire default before any MTU exchange (Bluetooth spec ATT_MTU minimum).
|
||||
static constexpr uint16_t DEFAULT_ATT_MTU = 23;
|
||||
// Bounds one characteristic's descriptor walk against a stack that never
|
||||
// reports end-of-range.
|
||||
static constexpr uint16_t MAX_DESCRIPTORS_PER_CHARACTERISTIC = 64;
|
||||
|
||||
// ---- tracker surface ----
|
||||
|
||||
bool BluedroidGattClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||
esp_ble_gattc_cb_param_t *param) {
|
||||
return this->handle_gattc_event_(event, gattc_if, param);
|
||||
}
|
||||
void BluedroidGattClient::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
||||
this->handle_gap_event_(event, param);
|
||||
}
|
||||
void BluedroidGattClient::connect() { this->tracker_connect_(); }
|
||||
void BluedroidGattClient::disconnect() { this->gatt_disconnect(); }
|
||||
|
||||
@@ -63,10 +52,10 @@ void BluedroidGattClient::setup() {
|
||||
void BluedroidGattClient::loop() {
|
||||
if (!esp32_ble::global_ble->is_active()) {
|
||||
// Stack down: re-register the app on the next enable.
|
||||
this->set_state_(ClientState::INIT);
|
||||
this->set_state(ClientState::INIT);
|
||||
return;
|
||||
}
|
||||
auto st = this->state_();
|
||||
auto st = this->state();
|
||||
if (st == ClientState::INIT) {
|
||||
auto ret = esp_ble_gattc_app_register(this->app_id);
|
||||
if (ret) {
|
||||
@@ -74,7 +63,7 @@ void BluedroidGattClient::loop() {
|
||||
this->mark_failed();
|
||||
}
|
||||
// Do not wait for REG_EVT; a dropped event must not wedge the slot.
|
||||
this->set_state_(ClientState::IDLE);
|
||||
this->set_state(ClientState::IDLE);
|
||||
} else if (st == ClientState::IDLE) {
|
||||
// The loop only drives the bootstrap and the disconnect safety timeout.
|
||||
this->disable_loop();
|
||||
@@ -85,7 +74,7 @@ void BluedroidGattClient::loop() {
|
||||
// lost CLOSE/DISCONNECT would otherwise leak the table and the cache.
|
||||
this->release_services();
|
||||
this->set_idle_();
|
||||
this->report_connection_state_(false, 0, ESP_GATT_CONN_TIMEOUT);
|
||||
this->listener_->on_connection_state(false, 0, ESP_GATT_CONN_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +90,7 @@ void BluedroidGattClient::dump_config() {
|
||||
int BluedroidGattClient::connect(uint64_t address, uint8_t addr_type) {
|
||||
// Only from idle: clobbering DISCONNECTING would open a new link the
|
||||
// stale CLOSE_EVT then tears down.
|
||||
if (this->state_() != ClientState::IDLE) {
|
||||
if (this->state() != ClientState::IDLE) {
|
||||
ESP_LOGW(TAG, "[%d] Connect rejected, slot busy", this->connection_index_);
|
||||
return ESP_GATT_BUSY;
|
||||
}
|
||||
@@ -109,12 +98,12 @@ int BluedroidGattClient::connect(uint64_t address, uint8_t addr_type) {
|
||||
this->remote_addr_type_ = addr_type;
|
||||
// Hand the request to the tracker's promote loop: it stops the scan, raises
|
||||
// coex, and calls tracker_connect_() - the tracker owns connect timing here.
|
||||
this->set_state_(ClientState::DISCOVERED);
|
||||
this->set_state(ClientState::DISCOVERED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BluedroidGattClient::tracker_connect_() {
|
||||
auto st = this->state_();
|
||||
auto st = this->state();
|
||||
if (st == ClientState::CONNECTING || st == ClientState::CONNECTED || st == ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%d] Connection already in progress", this->connection_index_);
|
||||
return;
|
||||
@@ -127,7 +116,7 @@ void BluedroidGattClient::tracker_connect_() {
|
||||
this->services_released_ = false;
|
||||
this->seen_mtu_ = false;
|
||||
this->enable_loop();
|
||||
this->set_state_(ClientState::CONNECTING);
|
||||
this->set_state(ClientState::CONNECTING);
|
||||
if (this->connection_type_ == ConnectionType::V3_WITHOUT_CACHE) {
|
||||
// Fast params for the discovery phase; stepped down at SEARCH_CMPL.
|
||||
esp_ble_gap_set_prefer_conn_params(this->remote_bda_, FAST_MIN_CONN_INTERVAL, FAST_MAX_CONN_INTERVAL, 0,
|
||||
@@ -141,13 +130,13 @@ void BluedroidGattClient::tracker_connect_() {
|
||||
if (ret) {
|
||||
this->log_gattc_warning_("esp_ble_gattc_open", ret);
|
||||
// CONNECT_EVT never fired, so conn_id_ is legitimately unset: plain IDLE.
|
||||
this->set_state_(ClientState::IDLE);
|
||||
this->report_connection_state_(false, 0, ret);
|
||||
this->set_state(ClientState::IDLE);
|
||||
this->listener_->on_connection_state(false, 0, ret);
|
||||
}
|
||||
}
|
||||
|
||||
int BluedroidGattClient::gatt_disconnect() {
|
||||
auto st = this->state_();
|
||||
auto st = this->state();
|
||||
if (st == ClientState::DISCONNECTING) {
|
||||
return 0;
|
||||
}
|
||||
@@ -158,7 +147,7 @@ int BluedroidGattClient::gatt_disconnect() {
|
||||
}
|
||||
if (st == ClientState::DISCOVERED) {
|
||||
// Parked for the tracker promote loop, never opened.
|
||||
this->set_state_(ClientState::IDLE);
|
||||
this->set_state(ClientState::IDLE);
|
||||
return ble_device_base::GATT_ERR_NOT_CONNECTED;
|
||||
}
|
||||
if (st == ClientState::CONNECTING || this->conn_id_ == UNSET_CONN_ID) {
|
||||
@@ -429,21 +418,17 @@ bool BluedroidGattClient::check_addr_(const esp_bd_addr_t &addr) const {
|
||||
}
|
||||
|
||||
void BluedroidGattClient::set_idle_() {
|
||||
this->set_state_(ClientState::IDLE);
|
||||
this->set_state(ClientState::IDLE);
|
||||
this->conn_id_ = UNSET_CONN_ID;
|
||||
}
|
||||
|
||||
void BluedroidGattClient::set_disconnecting_() {
|
||||
this->disconnecting_started_ = millis();
|
||||
this->set_state_(ClientState::DISCONNECTING);
|
||||
this->set_state(ClientState::DISCONNECTING);
|
||||
// The loop may be disabled while idle; the safety timeout needs it.
|
||||
this->enable_loop();
|
||||
}
|
||||
|
||||
void BluedroidGattClient::report_connection_state_(bool connected, uint16_t mtu, int error) {
|
||||
this->listener_->on_connection_state(connected, mtu, error);
|
||||
}
|
||||
|
||||
esp_err_t BluedroidGattClient::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency,
|
||||
uint16_t timeout, const char *param_type) {
|
||||
esp_ble_conn_update_params_t conn_params = {{0}};
|
||||
@@ -646,7 +631,7 @@ void BluedroidGattClient::stream_service_batch(BluetoothConnection &conn) {
|
||||
// ---- events ----
|
||||
|
||||
void BluedroidGattClient::handle_open_evt_(esp_ble_gattc_cb_param_t *param) {
|
||||
auto st = this->state_();
|
||||
auto st = this->state();
|
||||
if (st == ClientState::IDLE) {
|
||||
// IDF can deliver OPEN_EVT after esp_ble_gattc_open already returned an
|
||||
// error and the slot went IDLE; do not resurrect it.
|
||||
@@ -660,7 +645,7 @@ void BluedroidGattClient::handle_open_evt_(esp_ble_gattc_cb_param_t *param) {
|
||||
this->log_gattc_warning_("Connection open", param->open.status);
|
||||
// Never established, CLOSE_EVT may not follow.
|
||||
this->set_idle_();
|
||||
this->report_connection_state_(false, 0, param->open.status);
|
||||
this->listener_->on_connection_state(false, 0, param->open.status);
|
||||
return;
|
||||
}
|
||||
if (this->disconnect_pending()) {
|
||||
@@ -668,17 +653,17 @@ void BluedroidGattClient::handle_open_evt_(esp_ble_gattc_cb_param_t *param) {
|
||||
this->unconditional_disconnect_();
|
||||
return;
|
||||
}
|
||||
this->set_state_(ClientState::CONNECTED);
|
||||
this->set_state(ClientState::CONNECTED);
|
||||
ESP_LOGI(TAG, "[%d] Connection open", this->connection_index_);
|
||||
if (this->connection_type_ == ConnectionType::V3_WITH_CACHE) {
|
||||
this->set_state_(ClientState::ESTABLISHED);
|
||||
this->set_state(ClientState::ESTABLISHED);
|
||||
// No discovery phase: report immediately; the MTU report below is
|
||||
// suppressed by seen_mtu_ (HA tolerates a post-connect MTU of 23 here,
|
||||
// matching the previous esp32 behavior).
|
||||
this->seen_mtu_ = true;
|
||||
// Cached path never exchanged an MTU; HA has always seen the default.
|
||||
this->report_connection_state_(true, DEFAULT_ATT_MTU, 0);
|
||||
if (this->state_() != ClientState::DISCONNECTING) {
|
||||
this->listener_->on_connection_state(true, ble_device_base::DEFAULT_ATT_MTU, 0);
|
||||
if (this->state() != ClientState::DISCONNECTING) {
|
||||
// Settled; set_disconnecting_() re-enables the loop for the net.
|
||||
this->disable_loop();
|
||||
}
|
||||
@@ -686,12 +671,12 @@ void BluedroidGattClient::handle_open_evt_(esp_ble_gattc_cb_param_t *param) {
|
||||
}
|
||||
|
||||
void BluedroidGattClient::handle_disconnect_evt_(esp_ble_gattc_cb_param_t *param) {
|
||||
if (param->disconnect.reason == ESP_GATT_CONN_TERMINATE_PEER_USER && this->state_() == ClientState::CONNECTED) {
|
||||
if (param->disconnect.reason == ESP_GATT_CONN_TERMINATE_PEER_USER && this->state() == ClientState::CONNECTED) {
|
||||
ESP_LOGW(TAG, "[%d] Remote closed during discovery", this->connection_index_);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "[%d] DISCONNECT_EVT reason=0x%02x", this->connection_index_, param->disconnect.reason);
|
||||
}
|
||||
if (this->state_() == ClientState::IDLE) {
|
||||
if (this->state() == ClientState::IDLE) {
|
||||
// Active close delivers CLOSE_EVT first; never walk back to DISCONNECTING.
|
||||
return;
|
||||
}
|
||||
@@ -703,7 +688,7 @@ void BluedroidGattClient::handle_disconnect_evt_(esp_ble_gattc_cb_param_t *param
|
||||
this->set_disconnecting_();
|
||||
}
|
||||
|
||||
bool BluedroidGattClient::handle_gattc_event_(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if,
|
||||
bool BluedroidGattClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if,
|
||||
esp_ble_gattc_cb_param_t *param) {
|
||||
if (event == ESP_GATTC_REG_EVT && this->app_id != param->reg.app_id)
|
||||
return false;
|
||||
@@ -747,8 +732,8 @@ bool BluedroidGattClient::handle_gattc_event_(esp_gattc_cb_event_t event, esp_ga
|
||||
if (!this->seen_mtu_) {
|
||||
this->seen_mtu_ = true;
|
||||
// The connected report waited for the MTU; forwarded, not stored.
|
||||
this->report_connection_state_(true,
|
||||
param->cfg_mtu.status == ESP_GATT_OK ? param->cfg_mtu.mtu : DEFAULT_ATT_MTU, 0);
|
||||
this->listener_->on_connection_state(
|
||||
true, param->cfg_mtu.status == ESP_GATT_OK ? param->cfg_mtu.mtu : ble_device_base::DEFAULT_ATT_MTU, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -765,16 +750,16 @@ bool BluedroidGattClient::handle_gattc_event_(esp_gattc_cb_event_t event, esp_ga
|
||||
this->set_idle_();
|
||||
// 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, 0, param->close.reason);
|
||||
this->listener_->on_connection_state(false, 0, param->close.reason);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
||||
if (this->conn_id_ != param->search_cmpl.conn_id)
|
||||
return false;
|
||||
ESP_LOGI(TAG, "[%d] Service discovery complete", this->connection_index_);
|
||||
this->set_state_(ClientState::ESTABLISHED);
|
||||
this->set_state(ClientState::ESTABLISHED);
|
||||
this->handle_search_cmpl_();
|
||||
if (this->state_() != ClientState::DISCONNECTING) {
|
||||
if (this->state() != ClientState::DISCONNECTING) {
|
||||
// Settled; a failed count started a teardown that needs the loop.
|
||||
this->disable_loop();
|
||||
}
|
||||
@@ -821,7 +806,7 @@ bool BluedroidGattClient::handle_gattc_event_(esp_gattc_cb_event_t event, esp_ga
|
||||
return true;
|
||||
}
|
||||
|
||||
void BluedroidGattClient::handle_gap_event_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
||||
void BluedroidGattClient::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
||||
switch (event) {
|
||||
case ESP_GAP_BLE_SEC_REQ_EVT: {
|
||||
if (!this->check_addr_(param->ble_security.auth_cmpl.bd_addr))
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
// ble_device_base::BLEGattConnection alias for the hub BluetoothConnection
|
||||
// wrapper. Not a BLEClientBase: the tracker's promote loop owns
|
||||
// scan-stop/coex/one-connect-at-a-time, so the contract's connect() only
|
||||
// parks the address in DISCOVERED and the real esp_ble_gattc_open happens in
|
||||
// the tracker-invoked shim connect(). The shim exists because the tracker's
|
||||
// ESPBTClient::disconnect() returns void while the contract's returns int -
|
||||
// one class cannot carry both.
|
||||
// parks the address in DISCOVERED; the real esp_ble_gattc_open happens in
|
||||
// the tracker-invoked connect() override.
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -24,7 +22,6 @@
|
||||
|
||||
namespace esphome::bluetooth_connection {
|
||||
|
||||
class BluedroidGattClient;
|
||||
#ifdef BLUETOOTH_CONNECTION_SERVES_PROXY
|
||||
class BluetoothConnection;
|
||||
#endif
|
||||
@@ -43,7 +40,6 @@ class BluedroidGattClient final : public esp32_ble_tracker::ESPBTClient, public
|
||||
|
||||
// Wired by codegen before setup and invariant for the device lifetime.
|
||||
void set_listener(ble_device_base::GattClientListener *listener) { this->listener_ = listener; }
|
||||
esp32_ble_tracker::ESPBTClient *tracker_client() { return this; }
|
||||
|
||||
// ---- esp32_ble_tracker::ESPBTClient ----
|
||||
bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||
@@ -67,7 +63,8 @@ class BluedroidGattClient final : public esp32_ble_tracker::ESPBTClient, public
|
||||
int pair();
|
||||
int update_connection_params(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout);
|
||||
// On-demand table for direct consumers; the proxy streams instead, so the
|
||||
// materializer compiles only under USE_BLE_GATT_SERVICE_TABLE.
|
||||
// materializer compiles only under USE_BLE_GATT_SERVICE_TABLE (emitted by
|
||||
// direct-consumer codegen, never by the proxy).
|
||||
#ifdef USE_BLE_GATT_SERVICE_TABLE
|
||||
ble_device_base::GattServiceTable get_service_table();
|
||||
#else
|
||||
@@ -85,19 +82,14 @@ class BluedroidGattClient final : public esp32_ble_tracker::ESPBTClient, public
|
||||
void set_connection_type(ble_device_base::ConnectionType ct) { this->connection_type_ = ct; }
|
||||
|
||||
protected:
|
||||
esp32_ble_tracker::ClientState state_() const { return this->state(); }
|
||||
void set_state_(esp32_ble_tracker::ClientState st) { this->set_state(st); }
|
||||
bool check_addr_(const esp_bd_addr_t &addr) const;
|
||||
void tracker_connect_();
|
||||
bool handle_gattc_event_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
|
||||
void handle_gap_event_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
|
||||
void handle_open_evt_(esp_ble_gattc_cb_param_t *param);
|
||||
void handle_disconnect_evt_(esp_ble_gattc_cb_param_t *param);
|
||||
void handle_search_cmpl_();
|
||||
void unconditional_disconnect_();
|
||||
void set_idle_();
|
||||
void set_disconnecting_();
|
||||
void report_connection_state_(bool connected, uint16_t mtu, int error);
|
||||
esp_err_t update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout,
|
||||
const char *param_type);
|
||||
int check_and_log_error_(const char *operation, esp_err_t err);
|
||||
|
||||
@@ -148,8 +148,7 @@ void BluetoothConnection::on_connection_state(bool connected, uint16_t mtu, int
|
||||
return;
|
||||
}
|
||||
// V3_WITHOUT_CACHE: discover services first — the connected response is
|
||||
// sent when discovery completes, mirroring the esp32 flow (MTU + services
|
||||
// before the response).
|
||||
// sent when discovery completes (MTU + services before the response).
|
||||
this->state_ = ClientState::CONNECTED;
|
||||
int err = this->backend_->discover_services();
|
||||
if (err != 0) {
|
||||
@@ -337,8 +336,8 @@ void BluetoothConnection::send_service_for_discovery_() {
|
||||
}
|
||||
|
||||
// The subscriber vanished mid-stream: park the cursor at done WITHOUT
|
||||
// sending services-done (esp32 parity — a resubscribing client gets
|
||||
// silence and its 30 s timeout, never an authoritative partial list) and
|
||||
// sending services-done (a resubscribing client gets silence and its
|
||||
// 30 s timeout, never an authoritative partial list) and
|
||||
// free the table; the api-gone sweep tears the connection down anyway.
|
||||
auto *api_conn = this->proxy_->get_api_connection();
|
||||
if (api_conn == nullptr) {
|
||||
|
||||
@@ -43,7 +43,7 @@ class BluetoothConnection final : public ble_device_base::GattClientListener {
|
||||
|
||||
/// Start connecting: record the API address type (BLE_ADDR_TYPE_* code
|
||||
/// space) and open the connection through the backend. Failures report
|
||||
/// through the same reset path a failed open takes on esp32.
|
||||
/// through the same reset path a failed open takes.
|
||||
void initiate_connection(uint8_t address_type) {
|
||||
this->remote_addr_type_ = address_type;
|
||||
this->start_connect_();
|
||||
@@ -126,7 +126,7 @@ class BluetoothConnection final : public ble_device_base::GattClientListener {
|
||||
|
||||
// Group 2: 2-byte types
|
||||
int16_t send_service_{INIT_SENDING_SERVICES};
|
||||
uint16_t mtu_{23};
|
||||
uint16_t mtu_{ble_device_base::DEFAULT_ATT_MTU};
|
||||
|
||||
// Group 3: 8-byte and 4-byte types
|
||||
uint64_t address_{0};
|
||||
|
||||
@@ -92,8 +92,7 @@ class RP2GattClient final : public Component, public Parented<rp2040_ble::RP2040
|
||||
int pair();
|
||||
int update_connection_params(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout);
|
||||
ble_device_base::GattServiceTable get_service_table();
|
||||
// No deferred-disconnect state (disconnect is one call) and no
|
||||
// connection-type branching on this backend.
|
||||
// No connection-type branching on this backend.
|
||||
void set_connection_type(ble_device_base::ConnectionType ct) {}
|
||||
void release_services();
|
||||
|
||||
@@ -175,7 +174,7 @@ class RP2GattClient final : public Component, public Parented<rp2040_ble::RP2040
|
||||
// Group 4: 2-byte types (table counters written from the handler during
|
||||
// discovery, read from the main loop after the phase's QUERY_COMPLETE)
|
||||
hci_con_handle_t con_handle_{HCI_CON_HANDLE_INVALID};
|
||||
uint16_t mtu_{23};
|
||||
uint16_t mtu_{ble_device_base::DEFAULT_ATT_MTU};
|
||||
uint16_t op_handle_{0};
|
||||
uint16_t op_len_{0};
|
||||
uint16_t service_count_{0};
|
||||
|
||||
@@ -52,8 +52,9 @@ def AUTO_LOAD(config: ConfigType | None = None) -> list[str]:
|
||||
# Assistant) assumes an ESPHome proxy can scan actively, so a passive-only
|
||||
# proxy would be misdriven — bk72xx follows once the API carries a feature
|
||||
# flag clients can trust (FEATURE_ACTIVE_SCAN + a version flag, separate PRs).
|
||||
# Coupled to bluetooth_connection: platforms with a GATT backend are also
|
||||
# listed in its HUB_MAX_CONNECTIONS and its FILTER_SOURCE_FILES hub entry.
|
||||
# Coupled to bluetooth_connection: platforms here are also listed in its
|
||||
# _PLATFORM_BACKENDS registry, HUB_MAX_CONNECTIONS, and FILTER_SOURCE_FILES
|
||||
# hub entry.
|
||||
_HUB_PLATFORMS = (PLATFORM_LN882X, PLATFORM_RP2)
|
||||
|
||||
DEPENDENCIES = ["api"]
|
||||
@@ -203,7 +204,12 @@ def _rp2_config_schema() -> cv.All:
|
||||
async def _connections_to_code(var: cg.MockObj, config: ConfigType) -> None:
|
||||
"""One wrapper + backend pair per slot; the platform-specific backend
|
||||
registration lives in bluetooth_connection.new_gatt_backend()."""
|
||||
for connection_conf in config.get(CONF_CONNECTIONS, []):
|
||||
connections = config.get(CONF_CONNECTIONS, [])
|
||||
# The api component sizes BluetoothConnectionsFreeResponse.allocated with
|
||||
# this define whenever a proxy is present (zero on advertisement-only
|
||||
# hubs); sized here so it can never diverge from the loop below.
|
||||
cg.add_define("BLUETOOTH_PROXY_MAX_CONNECTIONS", len(connections))
|
||||
for connection_conf in connections:
|
||||
backend = await bluetooth_connection.new_gatt_backend(
|
||||
connection_conf, service_table=False
|
||||
)
|
||||
@@ -366,10 +372,6 @@ async def _to_code_esp32(config: ConfigType) -> None:
|
||||
# registration into the proxy; the other hubs are polled instead.
|
||||
cg.add_define("USE_BLE_SCANNER_STATE_CALLBACK")
|
||||
|
||||
# Define max connections for protobuf fixed array
|
||||
connection_count = len(config.get(CONF_CONNECTIONS, []))
|
||||
cg.add_define("BLUETOOTH_PROXY_MAX_CONNECTIONS", connection_count)
|
||||
|
||||
await _connections_to_code(var, config)
|
||||
|
||||
if config.get(CONF_CACHE_SERVICES):
|
||||
@@ -384,12 +386,6 @@ async def _to_code_ble_hub(config: ConfigType) -> None:
|
||||
hub = await cg.get_variable(config[ble_device_base.CONF_BLE_HUB_ID])
|
||||
cg.add(var.set_ble_hub(hub))
|
||||
|
||||
# The api component sizes BluetoothConnectionsFreeResponse.allocated with
|
||||
# this define whenever a proxy is present. Zero on advertisement-only hubs.
|
||||
# Sized from the instantiated connections so the define can never diverge
|
||||
# from the loop below (the define sizes fixed storage in the proxy).
|
||||
slots = len(config.get(CONF_CONNECTIONS, ()))
|
||||
cg.add_define("BLUETOOTH_PROXY_MAX_CONNECTIONS", slots)
|
||||
await _connections_to_code(var, config)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user