mirror of
https://github.com/esphome/esphome.git
synced 2026-08-23 06:36:23 +00:00
Address review: explicit connections claim slots, re-enable clears backoff
- Explicit `connections:` entries now charge the slot ledger like the generated ones (dev let them evade the controller budget); pinned by a test - set_enabled(true) clears the connect backoff - a re-enable is an explicit try-again - The neutral engine's source filter uses the shared frameworks_for_platforms helper; ledger tests use the conftest fixture
This commit is contained in:
@@ -12,7 +12,10 @@ from esphome.components.ble_device_base import (
|
||||
as_reversed_hex_array,
|
||||
bt_uuid,
|
||||
)
|
||||
from esphome.config_helpers import filter_source_files_from_platform
|
||||
from esphome.config_helpers import (
|
||||
filter_source_files_from_platform,
|
||||
frameworks_for_platforms,
|
||||
)
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_CHARACTERISTIC_UUID,
|
||||
@@ -59,12 +62,9 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
||||
},
|
||||
# Every framework of every non-esp32 registry platform: a platform
|
||||
# that validates the neutral arm must also compile the neutral engine.
|
||||
"ble_client_gatt.cpp": {
|
||||
pf
|
||||
for pf in PlatformFramework
|
||||
if pf.value[0] in bluetooth_connection.GATT_CLIENT_PLATFORMS
|
||||
and pf.value[0] != PLATFORM_ESP32
|
||||
},
|
||||
"ble_client_gatt.cpp": frameworks_for_platforms(
|
||||
set(bluetooth_connection.GATT_CLIENT_PLATFORMS) - {PLATFORM_ESP32}
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -28,8 +28,13 @@ void BLEClient::set_enabled(bool enabled) {
|
||||
this->enabled = enabled;
|
||||
if (!enabled) {
|
||||
this->disconnect();
|
||||
return;
|
||||
}
|
||||
// Enabling does not connect: the next sighting does (legacy parity).
|
||||
// A re-enable is an explicit "try again": clear the backoff so the next
|
||||
// sighting connects promptly. Enabling does not itself connect (legacy
|
||||
// parity).
|
||||
this->consecutive_failures_ = 0;
|
||||
this->hold_off_ms_ = 0;
|
||||
}
|
||||
|
||||
bool BLEClient::parse_device(const ble_device_base::ESPBTDevice &device) {
|
||||
|
||||
@@ -99,6 +99,12 @@ def _esp32_config_schema() -> cv.All:
|
||||
raise cv.Invalid(
|
||||
"Connections can only be used if the proxy is set to active"
|
||||
)
|
||||
# Explicit entries claim slots like the generated ones; dev
|
||||
# historically skipped this, letting an explicit-connections
|
||||
# config evade the controller budget.
|
||||
bluetooth_connection.consume_gatt_slot(
|
||||
"bluetooth_proxy", len(config[CONF_CONNECTIONS])
|
||||
)(config)
|
||||
elif config[CONF_ACTIVE]:
|
||||
connection_slots: int = config[CONF_CONNECTION_SLOTS]
|
||||
bluetooth_connection.consume_gatt_slot("bluetooth_proxy", connection_slots)(
|
||||
|
||||
@@ -9,31 +9,29 @@ from esphome.components import (
|
||||
bluetooth_connection,
|
||||
bluetooth_proxy,
|
||||
)
|
||||
from esphome.const import (
|
||||
CONF_MAC_ADDRESS,
|
||||
KEY_CORE,
|
||||
KEY_TARGET_PLATFORM,
|
||||
PLATFORM_RP2,
|
||||
PlatformFramework,
|
||||
)
|
||||
from esphome.const import CONF_MAC_ADDRESS, PlatformFramework
|
||||
from esphome.core import CORE
|
||||
|
||||
from ..types import SetCoreConfigCallable
|
||||
|
||||
|
||||
def test_gatt_slot_ledger_rejects_overcommit_on_rp2() -> None:
|
||||
def test_gatt_slot_ledger_rejects_overcommit_on_rp2(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
# The cap logic in isolation: two hand charges must trip it.
|
||||
CORE.data.setdefault(KEY_CORE, {})[KEY_TARGET_PLATFORM] = PLATFORM_RP2
|
||||
set_core_config(PlatformFramework.RP2_ARDUINO)
|
||||
bluetooth_connection.consume_gatt_slot("bluetooth_proxy")({})
|
||||
bluetooth_connection.consume_gatt_slot("ble_client")({})
|
||||
with pytest.raises(cv.Invalid, match="supports at most 1 GATT client"):
|
||||
bluetooth_connection.FINAL_VALIDATE_SCHEMA({})
|
||||
|
||||
|
||||
def test_gatt_slot_ledger_skipped_in_testing_mode() -> None:
|
||||
def test_gatt_slot_ledger_skipped_in_testing_mode(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
# Grouped component builds merge fixtures past the cap; the check defers
|
||||
# to testing mode like esp32_ble.validate_connection_slots.
|
||||
CORE.data.setdefault(KEY_CORE, {})[KEY_TARGET_PLATFORM] = PLATFORM_RP2
|
||||
set_core_config(PlatformFramework.RP2_ARDUINO)
|
||||
bluetooth_connection.consume_gatt_slot("bluetooth_proxy")({})
|
||||
bluetooth_connection.consume_gatt_slot("ble_client")({})
|
||||
CORE.testing_mode = True
|
||||
|
||||
@@ -179,6 +179,16 @@ def test_rp2_rejects_esp32_only_keys_by_name(
|
||||
bluetooth_proxy.CONFIG_SCHEMA({"connections": [{}]})
|
||||
|
||||
|
||||
def test_esp32_explicit_connections_claim_gatt_slots(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
# Explicit `connections:` entries must charge the slot ledger like the
|
||||
# generated ones; dev historically let them evade the budget.
|
||||
set_core_config(PlatformFramework.ESP32_IDF)
|
||||
bluetooth_proxy.CONFIG_SCHEMA({"active": True, "connections": [{}, {}]})
|
||||
assert "bluetooth_proxy" in bluetooth_connection._ledger().consumers
|
||||
|
||||
|
||||
def test_hub_source_filter_covers_every_hub_platform() -> None:
|
||||
# bluetooth_connection cannot import this module to derive the hub.cpp
|
||||
# framework set, so pin it here: a platform admitted to the proxy but
|
||||
|
||||
Reference in New Issue
Block a user