ESPHome 2026.8.0b4
Loading...
Searching...
No Matches
bk72xx_ble.h
Go to the documentation of this file.
1#pragma once
2
4
5#ifdef USE_BK72XX_BLE
6
11
12#include <cstdint>
13
14#include "bdk_scan.h"
15
16namespace esphome::bk72xx_ble {
17
18enum class BLEComponentState : uint8_t {
19 STATE_OFF = 0,
21 ACTIVE,
22};
23
25enum class ScanOpResult : uint8_t {
26 SETTLED,
28 PENDING,
30 FAILED,
31};
32
34struct ScanParams {
35 bool active;
36 uint16_t interval;
37 uint16_t window;
38 bool operator==(const ScanParams &) const = default;
39};
40
43 uint8_t mac[MAC_ADDRESS_SIZE]; // LSB-first, as the controller delivers it
44 int8_t rssi; // signed dBm
45 uint8_t addr_type;
46 // GAPM report info byte (recv_adv_t.evt_type): bits 0-2 report type
47 // (1 = legacy adv, 3 = legacy scan response), bit 5 scannable — lets the
48 // tracker's merger tell the two frames apart.
49 uint8_t evt_type;
50 uint8_t data_len; // bytes valid in data[]
51 uint8_t data[62]; // legacy advertisement (31) + scan response (31)
52
53 // EventPool contract: nothing is heap-allocated inside a report.
54 void release() {}
55};
56
62 public:
63 virtual void on_scan_report(const BLEScanReport &report) = 0;
64
65 protected:
66 ~BLEScanListener() = default; // deletion via this interface is not part of the contract
67};
68
69// Maximum reports buffered between the BLE task and loop().
70static constexpr uint8_t MAX_SCAN_REPORT_QUEUE_SIZE = 64;
71
72class BK72xxBLE final : public Component {
73 public:
74 void setup() override;
75 void loop() override;
76 void dump_config() override;
77 float get_setup_priority() const override;
78
80 void enable();
81 bool is_active() const { return this->state_ == BLEComponentState::ACTIVE; }
82
83 void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
84
86 void get_mac_lsb_first(uint8_t out[MAC_ADDRESS_SIZE]) const;
87
88#ifdef BK72XX_BLE_SCAN_LISTENER_COUNT
92 void register_scan_listener(BLEScanListener *listener) { this->scan_listeners_.push_back(listener); }
93#endif
94
98 ScanOpResult scan_start(uint16_t interval, uint16_t window, bool active);
101 void scan_stop();
104 bool flush_pending_stop(uint32_t timeout_ms);
108
111 void enqueue_scan_report(const uint8_t *mac, int8_t rssi, uint8_t addr_type, uint8_t evt_type, const uint8_t *data,
112 uint16_t data_len);
113
114 protected:
115 void resolve_mac_();
119 bool teardown_stuck_(uint32_t now);
122
123#ifdef BK72XX_BLE_SCAN_LISTENER_COUNT
124 // Codegen-sized: no heap allocation, no std::vector template instantiation —
125 // the same StaticVector pattern as the tracker's ble_device_base listeners.
127#endif
128 // Report ring: the BDK notice callback (BLE task) allocates a report from the
129 // pool, fills it and pushes the pointer; loop() pops, dispatches and releases.
130 // Lock-free SPSC, zero allocation at steady state — the esp32_ble pattern.
132 // Pool sized to queue capacity (SIZE-1): the ring reserves one slot, so
133 // allocate() returns nullptr before push() can fail. This prevents leaking a
134 // pool slot on a failed push and keeps release() off the producer path.
135 esphome::EventPool<BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE - 1> report_pool_;
136 // Largest-to-smallest: padding only at the tail, absorbed by future byte fields.
138 uint32_t pending_since_ms_{0}; // bring-up budget anchor; refilled on request change
139 uint32_t teardown_since_ms_{0}; // unfinished teardown episode start; 0 = none
140 uint32_t teardown_stuck_log_ms_{0}; // last stuck-teardown ERROR; re-logged each TEARDOWN_STUCK_ERROR_MS
141 int last_release_err_{0}; // SDK code of the episode's last failed release; 0 = none
142 ScanParams requested_{}; // latched by scan_start()
143 ScanParams applied_{}; // last params we commanded; mismatch with requested_ restarts
144 uint8_t ble_mac_[MAC_ADDRESS_SIZE]{0}; // LSB-first (BLE convention)
146 bool scan_wanted_{false}; // the latched request is to scan (vs stopped)
147 bool release_warned_{false}; // gates the release WARN; widens the pump gate
148 bool restarting_{false}; // mode-change release in flight; teardown deadline governs until released
149 bool enable_on_boot_{false};
150 // PENDING means advance_() has more to do; loop() drives it, paced and
151 // (for a bring-up) bounded.
154};
155
156} // namespace esphome::bk72xx_ble
157
158#endif // USE_BK72XX_BLE
Minimal static vector - saves memory by avoiding std::vector overhead.
Definition helpers.h:227
ScanOpResult last_scan_result() const
Last reconciliation outcome; on FAILED the consumer's retry policy owns recovery.
Definition bk72xx_ble.h:107
void register_scan_listener(BLEScanListener *listener)
Register a consumer for scan reports (delivered on the main task via loop()).
Definition bk72xx_ble.h:92
uint8_t ble_mac_[MAC_ADDRESS_SIZE]
Definition bk72xx_ble.h:144
float get_setup_priority() const override
ScanOpResult advance_stop_(BdkActivityState state, bool ready)
void release_activity_(BdkActivityState state)
StaticVector< BLEScanListener *, BK72XX_BLE_SCAN_LISTENER_COUNT > scan_listeners_
Definition bk72xx_ble.h:126
void enable()
Bring up the BDK BLE stack (one-time; the BDK has no teardown path).
esphome::LockFreeQueue< BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE > report_queue_
Definition bk72xx_ble.h:131
void enqueue_scan_report(const uint8_t *mac, int8_t rssi, uint8_t addr_type, uint8_t evt_type, const uint8_t *data, uint16_t data_len)
Internal: buffer one controller report (BDK notice callback, BLE task context — bounded copy under th...
void get_mac_lsb_first(uint8_t out[MAC_ADDRESS_SIZE]) const
Controller BLE address, least-significant octet first (BLE convention).
ScanOpResult advance_start_(BdkActivityState state, bool ready)
esphome::EventPool< BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE - 1 > report_pool_
Definition bk72xx_ble.h:135
void set_enable_on_boot(bool enable_on_boot)
Definition bk72xx_ble.h:83
bool teardown_stuck_(uint32_t now)
bool flush_pending_stop(uint32_t timeout_ms)
Drive a requested stop until the radio is observed idle, bounded by timeout_ms (for OTA).
void scan_stop()
Request the scanner stopped and the activity released; steps that cannot run yet are completed from l...
Consumer interface for controller scan reports.
Definition bk72xx_ble.h:61
virtual void on_scan_report(const BLEScanReport &report)=0
bool state
Definition fan.h:2
ScanOpResult
Outcome of one reconciliation step.
Definition bk72xx_ble.h:25
@ SETTLED
The request is reached: scan observed running, or stopped with the activity fully released.
@ PENDING
A step is in flight; loop() keeps advancing — call scan_start() again to learn the outcome.
constexpr uint8_t INVALID_ACTIVITY_IDX
Activity index value marking "no scan activity", the BDK's own convention (asserted against its symbo...
Definition bdk_scan.h:13
BdkActivityState
Scan-relevant controller activity states, read live from the SDK.
Definition bdk_scan.h:16
uint32_t * scan_start
static void uint32_t
One advertisement report from the controller.
Definition bk72xx_ble.h:42
uint8_t mac[MAC_ADDRESS_SIZE]
Definition bk72xx_ble.h:43
One scan request: mode plus timing, in BLE units (0.625 ms).
Definition bk72xx_ble.h:34
bool operator==(const ScanParams &) const =default