diff --git a/esphome/components/ble_device_base/__init__.py b/esphome/components/ble_device_base/__init__.py index bc97c973ea..161fb22d27 100644 --- a/esphome/components/ble_device_base/__init__.py +++ b/esphome/components/ble_device_base/__init__.py @@ -51,8 +51,7 @@ ble_device_base_ns = cg.esphome_ns.namespace("ble_device_base") # The neutral tracker contract. Every tracker's codegen class declares this as # a parent, which is what lets cv.use_id(BLEHub) resolve any of them. Python -# only: the C++ name is a per-platform alias for the build's tracker class -# (ble_hub_impl.h), so generated code never names ble_device_base::BLEHub. +# only: C++-side the name is a per-platform alias (ble_hub_impl.h). BLEHub = ble_device_base_ns.class_("BLEHub") # The neutral listener base (C++: ble_device_base::ESPBTDeviceListener). diff --git a/esphome/components/ble_device_base/automation.h b/esphome/components/ble_device_base/automation.h index cb933dd690..ba3128c0ee 100644 --- a/esphome/components/ble_device_base/automation.h +++ b/esphome/components/ble_device_base/automation.h @@ -1,9 +1,8 @@ // Platform-neutral BLE advertisement triggers: ESPBTDeviceListener subclasses // registered on a BLEHub, exposed by each tracker under its own automation // names. parse_device()'s return feeds the "Found device" suppression. -// The constructors are templated on the hub type instead of naming BLEHub: -// the contract is duck-typed and this header must also build with no tracker -// present (host unit tests). +// Constructors are templated on the hub type so this header also builds with +// no tracker present (host unit tests). #pragma once diff --git a/esphome/components/ble_device_base/ble_hub.h b/esphome/components/ble_device_base/ble_hub.h index 7069093110..a7ed976520 100644 --- a/esphome/components/ble_device_base/ble_hub.h +++ b/esphome/components/ble_device_base/ble_hub.h @@ -1,17 +1,10 @@ // ble_hub.h // -// The platform-neutral BLE tracker contract: the types every tracker and -// consumer share, plus (below) the method surface every tracker provides. -// -// Exactly one tracker component exists per build (one chip, one controller), -// so BLEHub is not an abstract interface: ble_hub_impl.h binds the name to -// the build's tracker with a `using` alias, and every hub call is a direct, -// inlinable member call — no vtable, no virtual dispatch. Trackers include -// this header and implement the documented surface; consumers include -// ble_hub_impl.h and bind in YAML via `cv.use_id(BLEHub)` (the Python-side -// class, which resolves whichever tracker the config declares). Adding a new -// BLE chip requires only a new tracker component that provides the surface -// and an alias arm in ble_hub_impl.h. +// The platform-neutral BLE tracker contract: shared types plus the method +// surface every tracker provides (documented below). Exactly one tracker +// exists per build, so BLEHub is a compile-time alias (ble_hub_impl.h), not +// an abstract interface — no vtable, every hub call inlinable. Consumers +// include ble_hub_impl.h and bind in YAML via cv.use_id(BLEHub). // // Chip differences are expressed as data (HubCapabilities), never as // platform conditionals in consumers. @@ -65,9 +58,8 @@ enum class ScannerState : uint8_t { }; /// Subscriber slot for scanner-state transitions; same shape as -/// RawAdvertisementCallback, delivered on the ESPHome main loop. Hubs that -/// cannot push drop the registration and the consumer falls back to polling -/// scan_running(). +/// RawAdvertisementCallback, delivered on the ESPHome main loop. Only hubs +/// that push provide the setter; consumers of the rest poll scan_running(). struct ScannerStateCallback { void *instance{nullptr}; void (*fn)(void *instance, ScannerState state){nullptr}; @@ -103,11 +95,8 @@ struct HubCapabilities { // /// Wire the raw-advertisement stream (bluetooth_proxy). One consumer at a time. // void set_raw_advertisement_callback(RawAdvertisementCallback callback); // -// /// Push subscriber for scanner-state transitions, invoked where the hub's -// /// state changes. Provided only by hubs that push (today: esp32), gated on -// /// USE_BLE_SCANNER_STATE_CALLBACK (bluetooth_proxy emits the define), so -// /// subscriber-less builds carry no storage. Consumers of a hub without it -// /// fall back to polling scan_running(). +// /// Push hubs only (today: esp32), gated on USE_BLE_SCANNER_STATE_CALLBACK +// /// (emitted by the subscriber's codegen) so other builds carry no storage. // void set_scanner_state_callback(ScannerStateCallback callback); // // static constexpr HubCapabilities get_capabilities(); diff --git a/esphome/components/ble_device_base/ble_hub_impl.h b/esphome/components/ble_device_base/ble_hub_impl.h index 29cec01f58..e5062d2f25 100644 --- a/esphome/components/ble_device_base/ble_hub_impl.h +++ b/esphome/components/ble_device_base/ble_hub_impl.h @@ -1,11 +1,8 @@ // ble_hub_impl.h // -// Binds ble_device_base::BLEHub to the build's tracker. Exactly one tracker -// component exists per build, so the hub is a compile-time alias rather than -// an abstract interface: every hub call is a direct, inlinable member call -// and trackers carry no vtable for the contract. Consumers include this -// header; trackers include ble_hub.h (the contract types and the documented -// method surface). Each tracker's codegen emits its USE_*_BLE_TRACKER define. +// Binds ble_device_base::BLEHub to the build's one tracker; each tracker's +// codegen emits its USE_*_BLE_TRACKER define. Consumers include this header, +// trackers include ble_hub.h (the contract). #pragma once diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index 0b76e450cb..2a0d62c69b 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -76,8 +76,7 @@ void BluetoothProxy::setup() { static_cast(self)->on_raw_advertisement_(adv); }}); #ifdef USE_BLE_SCANNER_STATE_CALLBACK - // Only hubs that push scanner-state transitions compile the slot (today: - // esp32); elsewhere loop() polls scan_running() instead. + // Only push hubs compile the slot; elsewhere loop() polls scan_running(). this->hub_->set_scanner_state_callback({this, [](void *self, ble_device_base::ScannerState state) { static_cast(self)->send_bluetooth_scanner_state_(state); }}); diff --git a/tests/components/ble_device_base/test_raw_callback.cpp b/tests/components/ble_device_base/test_raw_callback.cpp index 6ee9e38852..62a9aebb81 100644 --- a/tests/components/ble_device_base/test_raw_callback.cpp +++ b/tests/components/ble_device_base/test_raw_callback.cpp @@ -13,9 +13,7 @@ namespace esphome::ble_device_base::testing { // // The in-tree emit site (BK72xxBLETracker::on_scan_report) compiles against // the Beken SDK and cannot run host-side, so the guard-and-fire semantics are -// pinned here through a minimal host hub instead. The contract is duck-typed -// (BLEHub is a per-platform alias, not a base class), so the fake carries -// only the slot surface under test. +// pinned here through a minimal host hub carrying only the slot under test. namespace { class FakeHub { diff --git a/tests/components/ble_device_base/test_scan_mode_request.cpp b/tests/components/ble_device_base/test_scan_mode_request.cpp index 3948532f41..6d3ce6c382 100644 --- a/tests/components/ble_device_base/test_scan_mode_request.cpp +++ b/tests/components/ble_device_base/test_scan_mode_request.cpp @@ -7,11 +7,8 @@ namespace esphome::ble_device_base::testing { // Pins the request_scan_mode() contract documented in ble_hub.h: a hub -// without a mode switch refuses without changing any state (so callers report -// the real state back), while a switching hub both honors the request and -// applies it. The contract is duck-typed (BLEHub is a per-platform alias), -// so the shapes are pinned through minimal host hubs mirroring the in-tree -// tracker stubs. +// without a mode switch refuses without changing any state, a switching hub +// honors and applies. Minimal host hubs mirror the in-tree tracker stubs. namespace { class RefusingHub {