mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[bk72xx_ble] Codegen-sized StaticVector for scan listeners (#18055)
This commit is contained in:
@@ -24,6 +24,7 @@ from esphome.components import libretiny
|
||||
from esphome.components.libretiny.const import FAMILY_BK7231N, FAMILY_BK7238
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ID
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.types import ConfigType
|
||||
|
||||
DEPENDENCIES = ["bk72xx"]
|
||||
@@ -45,6 +46,23 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
KEY_SCAN_LISTENER_COUNT = "bk72xx_ble_scan_listener_count"
|
||||
|
||||
|
||||
def request_scan_listener_slot() -> None:
|
||||
"""Called from a consumer's codegen once per registered scan listener; sizes
|
||||
the controller's StaticVector listener storage (heap-free, mirrors the
|
||||
tracker's ble_device_base listener storage)."""
|
||||
CORE.data[KEY_SCAN_LISTENER_COUNT] = CORE.data.get(KEY_SCAN_LISTENER_COUNT, 0) + 1
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _add_listener_count() -> None:
|
||||
# FINAL: every consumer's to_code has requested its slot by now.
|
||||
if count := CORE.data.get(KEY_SCAN_LISTENER_COUNT, 0):
|
||||
cg.add_define("BK72XX_BLE_SCAN_LISTENER_COUNT", count)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
@@ -92,3 +110,5 @@ async def to_code(config: ConfigType) -> None:
|
||||
)
|
||||
|
||||
cg.add_define("USE_BK72XX_BLE")
|
||||
|
||||
CORE.add_job(_add_listener_count)
|
||||
|
||||
@@ -179,8 +179,10 @@ void BK72xxBLE::loop() {
|
||||
if (report == nullptr)
|
||||
return;
|
||||
do {
|
||||
#ifdef BK72XX_BLE_SCAN_LISTENER_COUNT
|
||||
for (auto *listener : this->scan_listeners_)
|
||||
listener->on_scan_report(*report);
|
||||
#endif
|
||||
this->report_pool_.release(report);
|
||||
} while ((report = this->report_queue_.pop()) != nullptr);
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/event_pool.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/lock_free_queue.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace esphome::bk72xx_ble {
|
||||
|
||||
@@ -62,8 +62,12 @@ class BK72xxBLE final : public Component {
|
||||
/// Controller BLE address, least-significant octet first (BLE convention).
|
||||
void get_mac_lsb_first(uint8_t out[6]) const;
|
||||
|
||||
#ifdef BK72XX_BLE_SCAN_LISTENER_COUNT
|
||||
/// Register a consumer for scan reports (delivered on the main task via loop()).
|
||||
/// Storage is codegen-sized: the consumer's codegen requests a slot via
|
||||
/// request_scan_listener_slot(), which emits BK72XX_BLE_SCAN_LISTENER_COUNT.
|
||||
void register_scan_listener(BLEScanListener *listener) { this->scan_listeners_.push_back(listener); }
|
||||
#endif
|
||||
|
||||
/// Start the controller scan. Interval/window are in BLE units (0.625 ms).
|
||||
/// Enables the stack first if needed. Returns false on controller failure.
|
||||
@@ -78,7 +82,11 @@ class BK72xxBLE final : public Component {
|
||||
protected:
|
||||
void resolve_mac_();
|
||||
|
||||
std::vector<BLEScanListener *> scan_listeners_;
|
||||
#ifdef BK72XX_BLE_SCAN_LISTENER_COUNT
|
||||
// Codegen-sized: no heap allocation, no std::vector template instantiation —
|
||||
// the same StaticVector pattern as the tracker's ble_device_base listeners.
|
||||
StaticVector<BLEScanListener *, BK72XX_BLE_SCAN_LISTENER_COUNT> scan_listeners_;
|
||||
#endif
|
||||
// Report ring: the BDK notice callback (BLE task) allocates a report from the
|
||||
// pool, fills it and pushes the pointer; loop() pops, dispatches and releases.
|
||||
// Lock-free SPSC, zero allocation at steady state — the esp32_ble pattern.
|
||||
|
||||
@@ -69,6 +69,9 @@ async def to_code(config: ConfigType) -> None:
|
||||
|
||||
parent = await cg.get_variable(config[CONF_BK72XX_BLE_ID])
|
||||
cg.add(var.set_parent(parent))
|
||||
# The tracker registers itself as a controller scan listener in setup();
|
||||
# request the codegen-sized StaticVector slot for it.
|
||||
bk72xx_ble.request_scan_listener_slot()
|
||||
|
||||
# Get notified when an OTA update starts, to pause scanning (esp32_ble_tracker parity)
|
||||
ota.request_ota_state_listeners()
|
||||
|
||||
@@ -454,6 +454,7 @@
|
||||
|
||||
#ifdef USE_LIBRETINY
|
||||
#define USE_BK72XX_BLE
|
||||
#define BK72XX_BLE_SCAN_LISTENER_COUNT 1
|
||||
#define USE_LN882H_BLE
|
||||
#define LN882H_BLE_SCAN_LISTENER_COUNT 1
|
||||
#define USE_CAPTIVE_PORTAL
|
||||
|
||||
Reference in New Issue
Block a user