mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
Merge branch 'gatt-consumer-support' into radon-eye-neutral-gatt
This commit is contained in:
@@ -117,31 +117,31 @@ _PLATFORM_BACKENDS: dict[str, _PlatformBackend] = {
|
|||||||
GATT_CLIENT_PLATFORMS = list(_PLATFORM_BACKENDS)
|
GATT_CLIENT_PLATFORMS = list(_PLATFORM_BACKENDS)
|
||||||
|
|
||||||
|
|
||||||
def _backend_entry() -> _PlatformBackend:
|
def _backend_entry(platform: str | None = None) -> _PlatformBackend:
|
||||||
if (entry := _PLATFORM_BACKENDS.get(CORE.target_platform)) is None:
|
key = platform if platform is not None else CORE.target_platform
|
||||||
raise cv.Invalid(
|
if (entry := _PLATFORM_BACKENDS.get(key)) is None:
|
||||||
f"no GATT client backend is registered for {CORE.target_platform}"
|
raise cv.Invalid(f"no GATT client backend is registered for {key}")
|
||||||
)
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
|
|
||||||
def gatt_client_schema() -> cv.Schema:
|
def gatt_client_schema(platform: str | None = None) -> cv.Schema:
|
||||||
"""Schema fragment for one GATT backend instance: its generated id plus
|
"""Schema fragment for one GATT backend instance: its generated id plus
|
||||||
the platform-stack reference new_gatt_backend() resolves. Platform
|
the platform-stack reference new_gatt_backend() resolves.
|
||||||
dispatch happens at call time, so call this from inside a validator or a
|
|
||||||
per-platform schema builder, never at module import.
|
Defaults to the platform being validated; pass `platform` explicitly when
|
||||||
|
building a schema outside validation (the language-schema dumper calls
|
||||||
|
per-platform builders under arbitrary CORE platforms).
|
||||||
"""
|
"""
|
||||||
entry = _backend_entry()
|
entry = _backend_entry(platform)
|
||||||
return entry.schema_fragment().extend(
|
return entry.schema_fragment().extend(
|
||||||
{cv.GenerateID(CONF_BACKEND_ID): cv.declare_id(entry.backend_class)}
|
{cv.GenerateID(CONF_BACKEND_ID): cv.declare_id(entry.backend_class)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def hub_connection_schema() -> cv.Schema:
|
def hub_connection_schema(platform: str | None = None) -> cv.Schema:
|
||||||
"""Per-slot schema for the proxy's connection wrappers: the wrapper id on
|
"""Per-slot schema for the proxy's connection wrappers: the wrapper id on
|
||||||
top of the backend fragment. Same call-time constraint as
|
top of the backend fragment. Same platform rules as gatt_client_schema()."""
|
||||||
gatt_client_schema()."""
|
return gatt_client_schema(platform).extend(
|
||||||
return gatt_client_schema().extend(
|
|
||||||
{cv.GenerateID(): cv.declare_id(HubBluetoothConnection)}
|
{cv.GenerateID(): cv.declare_id(HubBluetoothConnection)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,13 @@ import logging
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.components import ble_device_base, bluetooth_connection
|
from esphome.components import ble_device_base, bluetooth_connection
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ACTIVE, CONF_ID, PLATFORM_LN882X, PLATFORM_RP2
|
from esphome.const import (
|
||||||
|
CONF_ACTIVE,
|
||||||
|
CONF_ID,
|
||||||
|
PLATFORM_ESP32,
|
||||||
|
PLATFORM_LN882X,
|
||||||
|
PLATFORM_RP2,
|
||||||
|
)
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
||||||
from esphome.types import ConfigType
|
from esphome.types import ConfigType
|
||||||
@@ -84,7 +90,7 @@ def _esp32_config_schema() -> cv.All:
|
|||||||
f"update _IDF_MAX_CONNECTIONS in bluetooth_proxy/__init__.py"
|
f"update _IDF_MAX_CONNECTIONS in bluetooth_proxy/__init__.py"
|
||||||
)
|
)
|
||||||
|
|
||||||
CONNECTION_SCHEMA = bluetooth_connection.hub_connection_schema()
|
CONNECTION_SCHEMA = bluetooth_connection.hub_connection_schema(PLATFORM_ESP32)
|
||||||
|
|
||||||
def validate_connections(config):
|
def validate_connections(config):
|
||||||
if CONF_CONNECTIONS in config:
|
if CONF_CONNECTIONS in config:
|
||||||
@@ -147,7 +153,7 @@ def _rp2_config_schema() -> cv.All:
|
|||||||
"""Full proxy on the rp2 BLE hub: active connections through the BTstack
|
"""Full proxy on the rp2 BLE hub: active connections through the BTstack
|
||||||
GATT client backend in bluetooth_connection. The slot limit comes from the
|
GATT client backend in bluetooth_connection. The slot limit comes from the
|
||||||
prebuilt BTstack library (one connection today); the code is built for N."""
|
prebuilt BTstack library (one connection today); the code is built for N."""
|
||||||
connection_schema = bluetooth_connection.hub_connection_schema()
|
connection_schema = bluetooth_connection.hub_connection_schema(PLATFORM_RP2)
|
||||||
|
|
||||||
def populate_connections(config: ConfigType) -> ConfigType:
|
def populate_connections(config: ConfigType) -> ConfigType:
|
||||||
# One wrapper + backend pair per slot, declared during validation so
|
# One wrapper + backend pair per slot, declared during validation so
|
||||||
|
|||||||
@@ -14,15 +14,11 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from esphome import config_validation as cv
|
from esphome import config_validation as cv
|
||||||
from esphome.components.bluetooth_proxy import CONFIG_SCHEMA, _esp32_config_schema
|
from esphome.components.bluetooth_proxy import CONFIG_SCHEMA, _esp32_config_schema
|
||||||
from esphome.const import KEY_CORE, KEY_TARGET_PLATFORM, PLATFORM_ESP32
|
|
||||||
from esphome.core import CORE
|
|
||||||
|
|
||||||
|
|
||||||
def _esp32_schema_keys() -> dict[str, object]:
|
def _esp32_schema_keys() -> dict[str, object]:
|
||||||
# The builder resolves the backend schema through the platform-dispatched
|
# The builder names its platform explicitly, so no CORE state is needed
|
||||||
# bluetooth_connection.gatt_client_schema(), so the platform must be set
|
# (this also mirrors how the language-schema dumper calls it).
|
||||||
# (conftest's autouse reset restores CORE after each test).
|
|
||||||
CORE.data.setdefault(KEY_CORE, {})[KEY_TARGET_PLATFORM] = PLATFORM_ESP32
|
|
||||||
return _keys(_schema_of(_esp32_config_schema()))
|
return _keys(_schema_of(_esp32_config_schema()))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user