mirror of
https://github.com/esphome/esphome.git
synced 2025-10-06 11:53:45 +01:00
merge
This commit is contained in:
@@ -116,7 +116,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
)
|
)
|
||||||
.extend(cv.COMPONENT_SCHEMA)
|
.extend(cv.COMPONENT_SCHEMA)
|
||||||
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA),
|
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA),
|
||||||
esp32_ble_tracker.consume_connection_slots(1, "ble_client"),
|
esp32_ble.consume_connection_slots(1, "ble_client"),
|
||||||
)
|
)
|
||||||
|
|
||||||
CONF_BLE_CLIENT_ID = "ble_client_id"
|
CONF_BLE_CLIENT_ID = "ble_client_id"
|
||||||
|
@@ -42,9 +42,7 @@ def validate_connections(config):
|
|||||||
)
|
)
|
||||||
elif config[CONF_ACTIVE]:
|
elif config[CONF_ACTIVE]:
|
||||||
connection_slots: int = config[CONF_CONNECTION_SLOTS]
|
connection_slots: int = config[CONF_CONNECTION_SLOTS]
|
||||||
esp32_ble_tracker.consume_connection_slots(connection_slots, "bluetooth_proxy")(
|
esp32_ble.consume_connection_slots(connection_slots, "bluetooth_proxy")(config)
|
||||||
config
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
**config,
|
**config,
|
||||||
@@ -65,11 +63,11 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
default=DEFAULT_CONNECTION_SLOTS,
|
default=DEFAULT_CONNECTION_SLOTS,
|
||||||
): cv.All(
|
): cv.All(
|
||||||
cv.positive_int,
|
cv.positive_int,
|
||||||
cv.Range(min=1, max=esp32_ble_tracker.IDF_MAX_CONNECTIONS),
|
cv.Range(min=1, max=esp32_ble.IDF_MAX_CONNECTIONS),
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_CONNECTIONS): cv.All(
|
cv.Optional(CONF_CONNECTIONS): cv.All(
|
||||||
cv.ensure_list(CONNECTION_SCHEMA),
|
cv.ensure_list(CONNECTION_SCHEMA),
|
||||||
cv.Length(min=1, max=esp32_ble_tracker.IDF_MAX_CONNECTIONS),
|
cv.Length(min=1, max=esp32_ble.IDF_MAX_CONNECTIONS),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
|
from collections.abc import Callable, MutableMapping
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
@@ -9,16 +12,19 @@ from esphome.const import (
|
|||||||
CONF_ENABLE_ON_BOOT,
|
CONF_ENABLE_ON_BOOT,
|
||||||
CONF_ESPHOME,
|
CONF_ESPHOME,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
|
CONF_MAX_CONNECTIONS,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_NAME_ADD_MAC_SUFFIX,
|
CONF_NAME_ADD_MAC_SUFFIX,
|
||||||
)
|
)
|
||||||
from esphome.core import TimePeriod
|
from esphome.core import CORE, TimePeriod
|
||||||
import esphome.final_validate as fv
|
import esphome.final_validate as fv
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
CODEOWNERS = ["@jesserockz", "@Rapsssito", "@bdraco"]
|
CODEOWNERS = ["@jesserockz", "@Rapsssito", "@bdraco"]
|
||||||
DOMAIN = "esp32_ble"
|
DOMAIN = "esp32_ble"
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BTLoggers(Enum):
|
class BTLoggers(Enum):
|
||||||
"""Bluetooth logger categories available in ESP-IDF.
|
"""Bluetooth logger categories available in ESP-IDF.
|
||||||
@@ -127,6 +133,28 @@ CONF_DISABLE_BT_LOGS = "disable_bt_logs"
|
|||||||
CONF_CONNECTION_TIMEOUT = "connection_timeout"
|
CONF_CONNECTION_TIMEOUT = "connection_timeout"
|
||||||
CONF_MAX_NOTIFICATIONS = "max_notifications"
|
CONF_MAX_NOTIFICATIONS = "max_notifications"
|
||||||
|
|
||||||
|
# BLE connection limits
|
||||||
|
# ESP-IDF CONFIG_BT_ACL_CONNECTIONS has range 1-9, default 4
|
||||||
|
# Total instances: 10 (ADV + SCAN + connections)
|
||||||
|
# - ADV only: up to 9 connections
|
||||||
|
# - SCAN only: up to 9 connections
|
||||||
|
# - ADV + SCAN: up to 8 connections
|
||||||
|
DEFAULT_MAX_CONNECTIONS = 3
|
||||||
|
IDF_MAX_CONNECTIONS = 9
|
||||||
|
|
||||||
|
# Connection slot tracking keys
|
||||||
|
KEY_ESP32_BLE = "esp32_ble"
|
||||||
|
KEY_USED_CONNECTION_SLOTS = "used_connection_slots"
|
||||||
|
|
||||||
|
# Export for use by other components (bluetooth_proxy, etc.)
|
||||||
|
__all__ = [
|
||||||
|
"DEFAULT_MAX_CONNECTIONS",
|
||||||
|
"IDF_MAX_CONNECTIONS",
|
||||||
|
"KEY_ESP32_BLE",
|
||||||
|
"KEY_USED_CONNECTION_SLOTS",
|
||||||
|
"consume_connection_slots",
|
||||||
|
]
|
||||||
|
|
||||||
NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2]
|
NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2]
|
||||||
|
|
||||||
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
|
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
|
||||||
@@ -183,6 +211,9 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
cv.positive_int,
|
cv.positive_int,
|
||||||
cv.Range(min=1, max=64),
|
cv.Range(min=1, max=64),
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_MAX_CONNECTIONS, default=DEFAULT_MAX_CONNECTIONS): cv.All(
|
||||||
|
cv.positive_int, cv.Range(min=1, max=IDF_MAX_CONNECTIONS)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
@@ -230,6 +261,56 @@ def validate_variant(_):
|
|||||||
raise cv.Invalid(f"{variant} does not support Bluetooth")
|
raise cv.Invalid(f"{variant} does not support Bluetooth")
|
||||||
|
|
||||||
|
|
||||||
|
def consume_connection_slots(
|
||||||
|
value: int, consumer: str
|
||||||
|
) -> Callable[[MutableMapping], MutableMapping]:
|
||||||
|
"""Reserve BLE connection slots for a component.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: Number of connection slots to reserve
|
||||||
|
consumer: Name of the component consuming the slots
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A validator function that records the slot usage
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _consume_connection_slots(config: MutableMapping) -> MutableMapping:
|
||||||
|
data: dict[str, Any] = CORE.data.setdefault(KEY_ESP32_BLE, {})
|
||||||
|
slots: list[str] = data.setdefault(KEY_USED_CONNECTION_SLOTS, [])
|
||||||
|
slots.extend([consumer] * value)
|
||||||
|
return config
|
||||||
|
|
||||||
|
return _consume_connection_slots
|
||||||
|
|
||||||
|
|
||||||
|
def validate_connection_slots(max_connections: int) -> None:
|
||||||
|
"""Validate that BLE connection slots don't exceed the configured maximum."""
|
||||||
|
ble_data = CORE.data.get(KEY_ESP32_BLE, {})
|
||||||
|
used_slots = ble_data.get(KEY_USED_CONNECTION_SLOTS, [])
|
||||||
|
num_used = len(used_slots)
|
||||||
|
|
||||||
|
if num_used <= max_connections:
|
||||||
|
return
|
||||||
|
|
||||||
|
slot_users = ", ".join(used_slots)
|
||||||
|
|
||||||
|
if num_used > IDF_MAX_CONNECTIONS:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"BLE components require {num_used} connection slots but maximum is {IDF_MAX_CONNECTIONS}. "
|
||||||
|
f"Reduce the number of BLE clients. Components: {slot_users}"
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER.warning(
|
||||||
|
"BLE components require %d connection slot(s) but only %d configured. "
|
||||||
|
"Please set 'max_connections: %d' in the 'esp32_ble' component. "
|
||||||
|
"Components: %s",
|
||||||
|
num_used,
|
||||||
|
max_connections,
|
||||||
|
num_used,
|
||||||
|
slot_users,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def final_validation(config):
|
def final_validation(config):
|
||||||
validate_variant(config)
|
validate_variant(config)
|
||||||
if (name := config.get(CONF_NAME)) is not None:
|
if (name := config.get(CONF_NAME)) is not None:
|
||||||
@@ -245,6 +326,10 @@ def final_validation(config):
|
|||||||
# Set GATT Client/Server sdkconfig options based on which components are loaded
|
# Set GATT Client/Server sdkconfig options based on which components are loaded
|
||||||
full_config = fv.full_config.get()
|
full_config = fv.full_config.get()
|
||||||
|
|
||||||
|
# Validate connection slots usage
|
||||||
|
max_connections = config.get(CONF_MAX_CONNECTIONS, DEFAULT_MAX_CONNECTIONS)
|
||||||
|
validate_connection_slots(max_connections)
|
||||||
|
|
||||||
# Check if BLE Server is needed
|
# Check if BLE Server is needed
|
||||||
has_ble_server = "esp32_ble_server" in full_config
|
has_ble_server = "esp32_ble_server" in full_config
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", has_ble_server)
|
add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", has_ble_server)
|
||||||
@@ -255,6 +340,26 @@ def final_validation(config):
|
|||||||
)
|
)
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_GATTC_ENABLE", has_ble_client)
|
add_idf_sdkconfig_option("CONFIG_BT_GATTC_ENABLE", has_ble_client)
|
||||||
|
|
||||||
|
# Handle max_connections: check for deprecated location in esp32_ble_tracker
|
||||||
|
max_connections = config.get(CONF_MAX_CONNECTIONS, DEFAULT_MAX_CONNECTIONS)
|
||||||
|
|
||||||
|
# Use value from tracker if esp32_ble doesn't have it explicitly set (backward compat)
|
||||||
|
if "esp32_ble_tracker" in full_config:
|
||||||
|
tracker_config = full_config["esp32_ble_tracker"]
|
||||||
|
if "max_connections" in tracker_config and CONF_MAX_CONNECTIONS not in config:
|
||||||
|
max_connections = tracker_config["max_connections"]
|
||||||
|
|
||||||
|
# Set CONFIG_BT_ACL_CONNECTIONS to the maximum connections needed + 1 for ADV/SCAN
|
||||||
|
# This is the Bluedroid host stack total instance limit (range 1-9, default 4)
|
||||||
|
# Total instances = ADV/SCAN (1) + connection slots (max_connections)
|
||||||
|
# Shared between client (tracker/ble_client) and server
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", max_connections + 1)
|
||||||
|
|
||||||
|
# Set controller-specific max connections for ESP32 (classic)
|
||||||
|
# CONFIG_BTDM_CTRL_BLE_MAX_CONN is ESP32-specific controller limit (just connections, not ADV/SCAN)
|
||||||
|
# For newer chips (C3/S3/etc), different configs are used automatically
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BTDM_CTRL_BLE_MAX_CONN", max_connections)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
@@ -270,6 +375,10 @@ async def to_code(config):
|
|||||||
cg.add(var.set_name(name))
|
cg.add(var.set_name(name))
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
# Define max connections for use in C++ code (e.g., ble_server.h)
|
||||||
|
max_connections = config.get(CONF_MAX_CONNECTIONS, DEFAULT_MAX_CONNECTIONS)
|
||||||
|
cg.add_define("USE_ESP32_BLE_MAX_CONNECTIONS", max_connections)
|
||||||
|
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
|
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
|
||||||
|
|
||||||
|
@@ -49,7 +49,11 @@ void BLECharacteristic::notify() {
|
|||||||
this->service_->get_server()->get_connected_client_count() == 0)
|
this->service_->get_server()->get_connected_client_count() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto &client : this->service_->get_server()->get_clients()) {
|
const uint16_t *clients = this->service_->get_server()->get_clients();
|
||||||
|
uint8_t client_count = this->service_->get_server()->get_client_count();
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < client_count; i++) {
|
||||||
|
uint16_t client = clients[i];
|
||||||
size_t length = this->value_.size();
|
size_t length = this->value_.size();
|
||||||
// Find the client in the list of clients to notify
|
// Find the client in the list of clients to notify
|
||||||
auto *entry = this->find_client_in_notify_list_(client);
|
auto *entry = this->find_client_in_notify_list_(client);
|
||||||
|
@@ -185,9 +185,35 @@ void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t ga
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t BLEServer::find_client_index_(uint16_t conn_id) const {
|
||||||
|
for (uint8_t i = 0; i < this->client_count_; i++) {
|
||||||
|
if (this->clients_[i] == conn_id)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEServer::add_client_(uint16_t conn_id) {
|
||||||
|
// Check if already in list
|
||||||
|
if (this->find_client_index_(conn_id) >= 0)
|
||||||
|
return;
|
||||||
|
// Add if there's space
|
||||||
|
if (this->client_count_ < USE_ESP32_BLE_MAX_CONNECTIONS) {
|
||||||
|
this->clients_[this->client_count_++] = conn_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEServer::remove_client_(uint16_t conn_id) {
|
||||||
|
int8_t index = this->find_client_index_(conn_id);
|
||||||
|
if (index >= 0) {
|
||||||
|
// Replace with last element and decrement count
|
||||||
|
this->clients_[index] = this->clients_[--this->client_count_];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BLEServer::ble_before_disabled_event_handler() {
|
void BLEServer::ble_before_disabled_event_handler() {
|
||||||
// Delete all clients
|
// Delete all clients
|
||||||
this->clients_.clear();
|
this->client_count_ = 0;
|
||||||
// Delete all services
|
// Delete all services
|
||||||
for (auto &entry : this->services_) {
|
for (auto &entry : this->services_) {
|
||||||
entry.service->do_delete();
|
entry.service->do_delete();
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
@@ -47,8 +46,9 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
|
|||||||
void set_device_information_service(BLEService *service) { this->device_information_service_ = service; }
|
void set_device_information_service(BLEService *service) { this->device_information_service_ = service; }
|
||||||
|
|
||||||
esp_gatt_if_t get_gatts_if() { return this->gatts_if_; }
|
esp_gatt_if_t get_gatts_if() { return this->gatts_if_; }
|
||||||
uint32_t get_connected_client_count() { return this->clients_.size(); }
|
uint32_t get_connected_client_count() { return this->client_count_; }
|
||||||
const std::unordered_set<uint16_t> &get_clients() { return this->clients_; }
|
const uint16_t *get_clients() const { return this->clients_; }
|
||||||
|
uint8_t get_client_count() const { return this->client_count_; }
|
||||||
|
|
||||||
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
|
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
|
||||||
esp_ble_gatts_cb_param_t *param) override;
|
esp_ble_gatts_cb_param_t *param) override;
|
||||||
@@ -82,8 +82,9 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
|
|||||||
|
|
||||||
void restart_advertising_();
|
void restart_advertising_();
|
||||||
|
|
||||||
void add_client_(uint16_t conn_id) { this->clients_.insert(conn_id); }
|
int8_t find_client_index_(uint16_t conn_id) const;
|
||||||
void remove_client_(uint16_t conn_id) { this->clients_.erase(conn_id); }
|
void add_client_(uint16_t conn_id);
|
||||||
|
void remove_client_(uint16_t conn_id);
|
||||||
void dispatch_callbacks_(CallbackType type, uint16_t conn_id);
|
void dispatch_callbacks_(CallbackType type, uint16_t conn_id);
|
||||||
|
|
||||||
std::vector<CallbackEntry> callbacks_;
|
std::vector<CallbackEntry> callbacks_;
|
||||||
@@ -92,7 +93,8 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
|
|||||||
esp_gatt_if_t gatts_if_{0};
|
esp_gatt_if_t gatts_if_{0};
|
||||||
bool registered_{false};
|
bool registered_{false};
|
||||||
|
|
||||||
std::unordered_set<uint16_t> clients_;
|
uint16_t clients_[USE_ESP32_BLE_MAX_CONNECTIONS]{};
|
||||||
|
uint8_t client_count_{0};
|
||||||
std::vector<ServiceEntry> services_{};
|
std::vector<ServiceEntry> services_{};
|
||||||
std::vector<BLEService *> services_to_start_{};
|
std::vector<BLEService *> services_to_start_{};
|
||||||
BLEService *device_information_service_{};
|
BLEService *device_information_service_{};
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable, MutableMapping
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.components import esp32_ble
|
from esphome.components import esp32_ble
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
from esphome.components.esp32_ble import (
|
from esphome.components.esp32_ble import (
|
||||||
|
DEFAULT_MAX_CONNECTIONS,
|
||||||
|
IDF_MAX_CONNECTIONS,
|
||||||
BTLoggers,
|
BTLoggers,
|
||||||
bt_uuid,
|
bt_uuid,
|
||||||
bt_uuid16_format,
|
bt_uuid16_format,
|
||||||
@@ -39,18 +39,12 @@ AUTO_LOAD = ["esp32_ble"]
|
|||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
CODEOWNERS = ["@bdraco"]
|
CODEOWNERS = ["@bdraco"]
|
||||||
|
|
||||||
KEY_ESP32_BLE_TRACKER = "esp32_ble_tracker"
|
|
||||||
KEY_USED_CONNECTION_SLOTS = "used_connection_slots"
|
|
||||||
|
|
||||||
CONF_ESP32_BLE_ID = "esp32_ble_id"
|
CONF_ESP32_BLE_ID = "esp32_ble_id"
|
||||||
CONF_SCAN_PARAMETERS = "scan_parameters"
|
CONF_SCAN_PARAMETERS = "scan_parameters"
|
||||||
CONF_WINDOW = "window"
|
CONF_WINDOW = "window"
|
||||||
CONF_ON_SCAN_END = "on_scan_end"
|
CONF_ON_SCAN_END = "on_scan_end"
|
||||||
CONF_SOFTWARE_COEXISTENCE = "software_coexistence"
|
CONF_SOFTWARE_COEXISTENCE = "software_coexistence"
|
||||||
|
|
||||||
DEFAULT_MAX_CONNECTIONS = 3
|
|
||||||
IDF_MAX_CONNECTIONS = 9
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -128,6 +122,15 @@ def validate_scan_parameters(config):
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def validate_max_connections_deprecated(config: ConfigType) -> ConfigType:
|
||||||
|
if CONF_MAX_CONNECTIONS in config:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"The 'max_connections' option in 'esp32_ble_tracker' is deprecated. "
|
||||||
|
"Please move it to the 'esp32_ble' component instead."
|
||||||
|
)
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def as_hex(value):
|
def as_hex(value):
|
||||||
return cg.RawExpression(f"0x{value}ULL")
|
return cg.RawExpression(f"0x{value}ULL")
|
||||||
|
|
||||||
@@ -150,18 +153,6 @@ def as_reversed_hex_array(value):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def consume_connection_slots(
|
|
||||||
value: int, consumer: str
|
|
||||||
) -> Callable[[MutableMapping], MutableMapping]:
|
|
||||||
def _consume_connection_slots(config: MutableMapping) -> MutableMapping:
|
|
||||||
data: dict[str, Any] = CORE.data.setdefault(KEY_ESP32_BLE_TRACKER, {})
|
|
||||||
slots: list[str] = data.setdefault(KEY_USED_CONNECTION_SLOTS, [])
|
|
||||||
slots.extend([consumer] * value)
|
|
||||||
return config
|
|
||||||
|
|
||||||
return _consume_connection_slots
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
CONFIG_SCHEMA = cv.All(
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
@@ -224,48 +215,11 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.OnlyWith(CONF_SOFTWARE_COEXISTENCE, "wifi", default=True): bool,
|
cv.OnlyWith(CONF_SOFTWARE_COEXISTENCE, "wifi", default=True): bool,
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA),
|
).extend(cv.COMPONENT_SCHEMA),
|
||||||
|
validate_max_connections_deprecated,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def validate_remaining_connections(config):
|
FINAL_VALIDATE_SCHEMA = esp32_ble.validate_variant
|
||||||
data: dict[str, Any] = CORE.data.get(KEY_ESP32_BLE_TRACKER, {})
|
|
||||||
slots: list[str] = data.get(KEY_USED_CONNECTION_SLOTS, [])
|
|
||||||
used_slots = len(slots)
|
|
||||||
if used_slots <= config[CONF_MAX_CONNECTIONS]:
|
|
||||||
return config
|
|
||||||
slot_users = ", ".join(slots)
|
|
||||||
|
|
||||||
if used_slots < IDF_MAX_CONNECTIONS:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"esp32_ble_tracker exceeded `%s`: components attempted to consume %d "
|
|
||||||
"connection slot(s) out of available configured maximum %d connection "
|
|
||||||
"slot(s); The system automatically increased `%s` to %d to match the "
|
|
||||||
"number of used connection slot(s) by components: %s.",
|
|
||||||
CONF_MAX_CONNECTIONS,
|
|
||||||
used_slots,
|
|
||||||
config[CONF_MAX_CONNECTIONS],
|
|
||||||
CONF_MAX_CONNECTIONS,
|
|
||||||
used_slots,
|
|
||||||
slot_users,
|
|
||||||
)
|
|
||||||
config[CONF_MAX_CONNECTIONS] = used_slots
|
|
||||||
return config
|
|
||||||
|
|
||||||
msg = (
|
|
||||||
f"esp32_ble_tracker exceeded `{CONF_MAX_CONNECTIONS}`: "
|
|
||||||
f"components attempted to consume {used_slots} connection slot(s) "
|
|
||||||
f"out of available configured maximum {config[CONF_MAX_CONNECTIONS]} "
|
|
||||||
f"connection slot(s); Decrease the number of BLE clients ({slot_users})"
|
|
||||||
)
|
|
||||||
if config[CONF_MAX_CONNECTIONS] < IDF_MAX_CONNECTIONS:
|
|
||||||
msg += f" or increase {CONF_MAX_CONNECTIONS}` to {used_slots}"
|
|
||||||
msg += f" to stay under the {IDF_MAX_CONNECTIONS} connection slot(s) limit."
|
|
||||||
raise cv.Invalid(msg)
|
|
||||||
|
|
||||||
|
|
||||||
FINAL_VALIDATE_SCHEMA = cv.All(
|
|
||||||
validate_remaining_connections, esp32_ble.validate_variant
|
|
||||||
)
|
|
||||||
|
|
||||||
ESP_BLE_DEVICE_SCHEMA = cv.Schema(
|
ESP_BLE_DEVICE_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
@@ -345,10 +299,8 @@ async def to_code(config):
|
|||||||
# Match arduino CONFIG_BTU_TASK_STACK_SIZE
|
# Match arduino CONFIG_BTU_TASK_STACK_SIZE
|
||||||
# https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866
|
# https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192)
|
add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192)
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9)
|
# Note: CONFIG_BT_ACL_CONNECTIONS and CONFIG_BTDM_CTRL_BLE_MAX_CONN are now
|
||||||
add_idf_sdkconfig_option(
|
# configured in esp32_ble component based on max_connections setting
|
||||||
"CONFIG_BTDM_CTRL_BLE_MAX_CONN", config[CONF_MAX_CONNECTIONS]
|
|
||||||
)
|
|
||||||
|
|
||||||
cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts
|
cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts
|
||||||
cg.add_define("USE_ESP32_BLE_CLIENT")
|
cg.add_define("USE_ESP32_BLE_CLIENT")
|
||||||
|
@@ -159,6 +159,7 @@
|
|||||||
#define BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE 16
|
#define BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE 16
|
||||||
#define USE_CAPTIVE_PORTAL
|
#define USE_CAPTIVE_PORTAL
|
||||||
#define USE_ESP32_BLE
|
#define USE_ESP32_BLE
|
||||||
|
#define USE_ESP32_BLE_MAX_CONNECTIONS 3
|
||||||
#define USE_ESP32_BLE_CLIENT
|
#define USE_ESP32_BLE_CLIENT
|
||||||
#define USE_ESP32_BLE_DEVICE
|
#define USE_ESP32_BLE_DEVICE
|
||||||
#define USE_ESP32_BLE_SERVER
|
#define USE_ESP32_BLE_SERVER
|
||||||
|
Reference in New Issue
Block a user