45#if defined(CLANG_TIDY)
49#define BK72XX_BLE_NO_SDK
50#elif !__has_include("ble_api.h") || !__has_include("app_ble.h")
54#define BK72XX_BLE_NO_SDK
56 "bk72xx_ble requires a BLE 5.x Beken SDK (app_ble.h). Supported SoCs: BK7231N/BK7236 (BLE 5.1) and BK7238/BK7252N/BK7253 (BLE 5.2). BK7231T/BK7251/BK7271 (BLE 4.2) and BK7231Q (no BLE) are not supported."
59#ifndef BK72XX_BLE_NO_SDK
70#ifdef BK72XX_BLE_HAS_COMMON_BDADDR
71#include "common_bt_defines.h"
84static const char *
const TAG =
"bk72xx_ble";
86static constexpr uint32_t RECONCILE_RETRY_MS = 10;
87static constexpr uint32_t RECONCILE_REJECTED_RETRY_MS = 500;
88static constexpr uint32_t RECONCILE_PENDING_TIMEOUT_MS = 2000;
89static constexpr uint32_t SCAN_LIVENESS_CHECK_MS = 1000;
90static constexpr uint32_t TEARDOWN_STUCK_ERROR_MS = 30000;
94static BK72xxBLE *s_ble =
nullptr;
102static void ble_notice_callback(ble_notice_t notice,
void *param) {
103 if (s_ble ==
nullptr || param ==
nullptr)
105 if (notice != BLE_5_REPORT_ADV)
108 const recv_adv_t *info =
reinterpret_cast<const recv_adv_t *
>(param);
111 s_ble->
enqueue_scan_report(info->adv_addr,
static_cast<int8_t
>(info->rssi), info->adv_addr_type,
112 static_cast<uint8_t
>(info->evt_type), info->data, info->data_len);
116 const uint8_t *data, uint16_t data_len) {
118 if (report ==
nullptr) {
123 memcpy(report->
mac, mac, MAC_ADDRESS_SIZE);
128 (data_len <=
sizeof(report->
data)) ?
static_cast<uint8_t
>(data_len) :
static_cast<uint8_t
>(
sizeof(report->
data));
162 ble_set_notice_cb(ble_notice_callback);
171#ifdef BK72XX_BLE_HAS_COMMON_BDADDR
177 bool bdaddr_live =
false;
185 ESP_LOGW(TAG,
"Controller address still unset after init; BLE stack may not have started");
189 ESP_LOGD(TAG,
"BLE stack initialised");
204 ? RECONCILE_REJECTED_RETRY_MS
205 : RECONCILE_RETRY_MS;
214 ESP_LOGW(TAG,
"Controller dropped the scan; restarting");
220 if (report ==
nullptr)
223#ifdef BK72XX_BLE_SCAN_LISTENER_COUNT
225 listener->on_scan_report(*report);
232 uint16_t dropped = this->
report_queue_.get_and_reset_dropped_count();
234 ESP_LOGW(TAG,
"Dropped %u scan reports due to queue overflow", dropped);
238 for (
int i = 0; i < 6; i++)
247 " MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n"
258#ifdef BK72XX_BLE_HAS_COMMON_BDADDR
262 bool nonzero =
false;
282 uint8_t wifi_mac[MAC_ADDRESS_SIZE];
284 const uint8_t ble[MAC_ADDRESS_SIZE] = {wifi_mac[0], wifi_mac[1], wifi_mac[2],
285 wifi_mac[3], wifi_mac[4],
static_cast<uint8_t
>(wifi_mac[5] + 1)};
287 for (
int i = 0; i < 6; i++)
306 const ScanParams params{active, interval, window};
332 if (
millis() - start >= timeout_ms)
334 delay(RECONCILE_RETRY_MS);
354 ESP_LOGW(TAG,
"Scan activity release failed (err %d); retrying", this->
last_release_err_);
356 ESP_LOGW(TAG,
"Scan activity release rejected; retrying");
374 ESP_LOGE(TAG,
"Scan teardown cannot proceed; scanner is stuck (release err %d)", this->
last_release_err_);
377 ESP_LOGE(TAG,
"Scan teardown cannot proceed; scanner is stuck (controller busy)");
420 ESP_LOGE(TAG,
"Scan bring-up did not settle; giving up until the next start");
453 ESP_LOGD(TAG,
"Scan stop deferred (controller busy)");
478 ESP_LOGD(TAG,
"Scan start deferred (controller busy)");
struct bd_addr common_default_bdaddr
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
uint32_t teardown_stuck_log_ms_
ScanOpResult scan_start(uint16_t interval, uint16_t window, bool active)
Request a scan (interval/window in 0.625 ms BLE units); enables the stack first if needed.
void dump_config() override
uint8_t scan_activity_idx_
uint8_t ble_mac_[MAC_ADDRESS_SIZE]
void reset_teardown_episode_()
ScanOpResult last_result_
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_
void enable()
Bring up the BDK BLE stack (one-time; the BDK has no teardown path).
uint32_t pending_since_ms_
esphome::LockFreeQueue< BLEScanReport, MAX_SCAN_REPORT_QUEUE_SIZE > report_queue_
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_
uint32_t last_advance_ms_
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).
uint32_t teardown_since_ms_
void scan_stop()
Request the scanner stopped and the activity released; steps that cannot run yet are completed from l...
BdkOpResult bdk_scan_create(uint8_t activity_idx)
Create the scan activity (asynchronous); started once CREATED is observed.
BdkOpResult bdk_scan_release(uint8_t activity_idx, bool created, int *err_out)
Release the activity: delete when never started (a stop would be rejected), stop otherwise.
ScanOpResult
Outcome of one reconciliation step.
@ SETTLED
The request is reached: scan observed running, or stopped with the activity fully released.
@ FAILED
The controller rejected a step; retry later.
@ 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...
uint8_t bdk_scan_acquire_activity()
Claim an idle activity slot; INVALID_ACTIVITY_IDX when none is free.
BdkOpResult bdk_scan_start(uint8_t activity_idx, uint16_t interval, uint16_t window, bool active)
Start a created activity: the packed GAPM start, taking the scan mode the BDK's own start path hardco...
BdkOpResult
Outcome of a BDK scan operation request.
@ BUSY
Another controller operation is in flight; retry later.
@ OK
Accepted; completion is asynchronous.
BdkActivityState
Scan-relevant controller activity states, read live from the SDK.
@ OTHER
A non-scan or transitional state; settles on a later read.
@ CREATED
Created but not started.
@ IDLE
No activity (or one whose create failed).
BdkActivityState bdk_scan_state(uint8_t activity_idx)
Live state of the given activity; INVALID_ACTIVITY_IDX reads as IDLE.
bool bdk_scan_ready()
True when no controller operation is in flight (APP_BLE_READY).
constexpr float AFTER_WIFI
For components that should be initialized after WiFi is connected.
void get_mac_address_raw(uint8_t *mac)
Get the device MAC address as raw bytes, written into the provided byte array (6 bytes).
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
One advertisement report from the controller.
uint8_t mac[MAC_ADDRESS_SIZE]
One scan request: mode plus timing, in BLE units (0.625 ms).