19static const char *
const TAG =
"bk72xx_ble_tracker";
27static constexpr uint32_t SCAN_START_RETRY_MS = 1000;
28static constexpr uint8_t SCAN_START_RETRY_MAX_DOUBLINGS = 6;
31static constexpr uint32_t SCAN_STABLE_RESET_MS = 30000;
34static constexpr uint32_t OTA_STOP_FLUSH_MS = 100;
50#ifdef USE_OTA_STATE_LISTENER
63#ifdef USE_OTA_STATE_LISTENER
73 ESP_LOGE(TAG,
"Scan still stopping at OTA start; the radio may contend with the update");
108 ESP_LOGW(TAG,
"Controller scan lost; retrying");
194 ESP_LOGW(TAG,
"Scan start keeps failing; retrying every %" PRIu32
" s",
195 (SCAN_START_RETRY_MS << SCAN_START_RETRY_MAX_DOUBLINGS) / 1000);
202 "BK72xx BLE Tracker:\n"
203 " Scan Duration: %" PRIu32
" s\n"
204 " Scan Interval: %" PRIu32
" ms (%" PRIu32
" BLE units)\n"
205 " Scan Window: %" PRIu32
" ms (%" PRIu32
" BLE units)\n"
206 " Scan Type: %s (configured %s)\n"
207 " Continuous Scanning: %s",
222static constexpr uint8_t GAPM_REPORT_TYPE_MASK = 0x07;
223static constexpr uint8_t GAPM_REPORT_TYPE_SCAN_RSP_EXT = 2;
224static constexpr uint8_t GAPM_REPORT_TYPE_SCAN_RSP_LEG = 3;
225static constexpr uint8_t GAPM_REPORT_INFO_SCAN_ADV_BIT = 1 << 5;
231 const uint8_t rtype = report.
evt_type & GAPM_REPORT_TYPE_MASK;
232 if (rtype == GAPM_REPORT_TYPE_SCAN_RSP_LEG || rtype == GAPM_REPORT_TYPE_SCAN_RSP_EXT) {
245 false, this->scan_continuous_ ?
nullptr : TAG);
319 ESP_LOGD(TAG,
"Scan started (%s, window=%" PRIu32
"ms, interval=%" PRIu32
"ms)",
338 ESP_LOGD(TAG,
"Scan stopped");
368 ESP_LOGV(TAG,
"Scan mode %s", active ?
"active" :
"passive");
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.
void enable_loop()
Enable this component's loop.
void disable_loop()
Disable this component's loop.
bk72xx_ble::BK72xxBLE * parent_
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.
ScanOpResult last_scan_result() const
Last reconciliation outcome; on FAILED the consumer's retry policy owns recovery.
void register_scan_listener(BLEScanListener *listener)
Register a consumer for scan reports (delivered on the main task via loop()).
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...
void on_ota_global_state(ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) override
bool try_start_with_backoff_(uint32_t now, bool force=false)
Rate-limited (re)start; true when the scan is running (the caller must not reuse a now older than the...
bool scan_continuous_before_ota_
uint8_t failed_start_count_
void on_scan_report(const bk72xx_ble::BLEScanReport &report) override
ble_device_base::AdvDispatcher dispatcher_
void restart_scan_duration()
Re-anchor the one-shot duration clock of a running scan to now — used when an action changes the scan...
bool request_scan_mode(bool active)
void mark_scan_ended_(uint32_t now)
uint32_t scan_period_start_
ble_device_base::ScanResponseMerger merger_
bk72xx_ble::ScanOpResult controller_scan_start_()
Stamp-and-start for every controller scan attempt, so the retry rate limit covers all callers.
bool scan_requested_before_ota_
void dump_config() override
uint32_t last_scan_start_attempt_
void count_failed_start_()
uint32_t scan_start_time_
bool scan_active_configured_
void on_scan_end()
Fire listeners' on_scan_end and reset the per-scan discovered-log dedup.
void dispatch(const uint8_t *mac, int8_t rssi, uint8_t addr_type, const uint8_t *data, uint8_t data_len, bool raw_only, const char *log_unclaimed_tag)
Dispatch one (possibly merged) advertisement: the raw callback, and — unless raw_only — parsing for l...
void stash_adv(const uint8_t *mac, int8_t rssi, uint8_t addr_type, const uint8_t *data, uint8_t data_len, uint32_t now)
Hold a scannable advertisement, waiting for its scan response.
void sweep(uint32_t now)
Timeout flush (call from loop() with the stash_adv() clock): deliver held advertisements whose scan r...
void flush()
Deliver every held advertisement now (scan period/scan is ending, before on_scan_end fires): unmerged...
void submit_scan_rsp(const uint8_t *mac, int8_t rssi, uint8_t addr_type, const uint8_t *data, uint8_t data_len)
A scan response arrived: append it to the held advertisement from the same device and deliver the pai...
bool empty() const
Lets loop() skip the cross-TU sweep() call in the common case (empty: passive scan,...
void bind(AdvDispatcher *dispatcher, const bool *scan_continuous, const char *log_tag)
Wire the merger's output; call once in the tracker's setup().
void add_global_state_listener(OTAGlobalStateListener *listener)
constexpr uint32_t ble_units_to_ms(uint32_t units)
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.
OTAGlobalCallback * get_global_ota_callback()
Application App
Global storage of Application pointer - only one Application can exist.
One advertisement report from the controller.
uint8_t mac[MAC_ADDRESS_SIZE]