1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-05 11:23:47 +01:00
This commit is contained in:
J. Nick Koston
2025-06-11 09:56:02 -05:00
parent f467c79a20
commit 1eec1239ec
9 changed files with 235 additions and 61 deletions

View File

@@ -58,7 +58,7 @@ static std::vector<api::BluetoothLERawAdvertisement> &get_batch_buffer() {
return batch_buffer; return batch_buffer;
} }
bool BluetoothProxy::parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count) { bool BluetoothProxy::parse_devices(const esp32_ble::BLEScanResult *scan_results, size_t count) {
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr || !this->raw_advertisements_) if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr || !this->raw_advertisements_)
return false; return false;
@@ -73,7 +73,7 @@ bool BluetoothProxy::parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_p
// Add new advertisements to the batch buffer // Add new advertisements to the batch buffer
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
auto &result = advertisements[i]; auto &result = scan_results[i];
uint8_t length = result.adv_data_len + result.scan_rsp_len; uint8_t length = result.adv_data_len + result.scan_rsp_len;
batch_buffer.emplace_back(); batch_buffer.emplace_back();

View File

@@ -52,7 +52,7 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com
public: public:
BluetoothProxy(); BluetoothProxy();
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override; bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
bool parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count) override; bool parse_devices(const esp32_ble::BLEScanResult *scan_results, size_t count) override;
void dump_config() override; void dump_config() override;
void setup() override; void setup() override;
void loop() override; void loop() override;

View File

@@ -312,9 +312,36 @@ void ESP32BLE::loop() {
this->real_gattc_event_handler_(ble_event->event_.gattc.gattc_event, ble_event->event_.gattc.gattc_if, this->real_gattc_event_handler_(ble_event->event_.gattc.gattc_event, ble_event->event_.gattc.gattc_if,
&ble_event->event_.gattc.gattc_param); &ble_event->event_.gattc.gattc_param);
break; break;
case BLEEvent::GAP: case BLEEvent::GAP: {
this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param); esp_gap_ble_cb_event_t gap_event = ble_event->event_.gap.gap_event;
if (gap_event == ESP_GAP_BLE_SCAN_RESULT_EVT) {
// Use the new scan event handler - no memcpy!
for (auto *scan_handler : this->gap_scan_event_handlers_) {
scan_handler->gap_scan_event_handler(ble_event->scan_result());
}
} else if (gap_event == ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT ||
gap_event == ESP_GAP_BLE_SCAN_START_COMPLETE_EVT ||
gap_event == ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT) {
// Create temporary param for scan complete events
esp_ble_gap_cb_param_t param;
memset(&param, 0, sizeof(param));
// Set the appropriate status field based on event type
if (gap_event == ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT) {
param.scan_param_cmpl.status = ble_event->event_.gap.scan_complete.status;
} else if (gap_event == ESP_GAP_BLE_SCAN_START_COMPLETE_EVT) {
param.scan_start_cmpl.status = ble_event->event_.gap.scan_complete.status;
} else if (gap_event == ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT) {
param.scan_stop_cmpl.status = ble_event->event_.gap.scan_complete.status;
}
this->real_gap_event_handler_(gap_event, &param);
} else {
// Fallback for unexpected events (uses full param copy)
this->real_gap_event_handler_(gap_event, &ble_event->event_.gap.gap_param);
}
break; break;
}
default: default:
break; break;
} }
@@ -328,6 +355,13 @@ void ESP32BLE::loop() {
} }
void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
static constexpr size_t MAX_BLE_QUEUE_SIZE = SCAN_RESULT_BUFFER_SIZE * 2;
if (global_ble->ble_events_.size() >= MAX_BLE_QUEUE_SIZE) {
ESP_LOGW(TAG, "BLE event queue full (%d), dropping GAP event %d", MAX_BLE_QUEUE_SIZE, event);
return;
}
BLEEvent *new_event = EVENT_ALLOCATOR.allocate(1); BLEEvent *new_event = EVENT_ALLOCATOR.allocate(1);
if (new_event == nullptr) { if (new_event == nullptr) {
// Memory too fragmented to allocate new event. Can only drop it until memory comes back // Memory too fragmented to allocate new event. Can only drop it until memory comes back
@@ -346,6 +380,13 @@ void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap
void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t *param) { esp_ble_gatts_cb_param_t *param) {
static constexpr size_t MAX_BLE_QUEUE_SIZE = SCAN_RESULT_BUFFER_SIZE * 2;
if (global_ble->ble_events_.size() >= MAX_BLE_QUEUE_SIZE) {
ESP_LOGW(TAG, "BLE event queue full (%d), dropping GATTS event %d", MAX_BLE_QUEUE_SIZE, event);
return;
}
BLEEvent *new_event = EVENT_ALLOCATOR.allocate(1); BLEEvent *new_event = EVENT_ALLOCATOR.allocate(1);
if (new_event == nullptr) { if (new_event == nullptr) {
// Memory too fragmented to allocate new event. Can only drop it until memory comes back // Memory too fragmented to allocate new event. Can only drop it until memory comes back
@@ -365,6 +406,13 @@ void ESP32BLE::real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if
void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) { esp_ble_gattc_cb_param_t *param) {
static constexpr size_t MAX_BLE_QUEUE_SIZE = SCAN_RESULT_BUFFER_SIZE * 2;
if (global_ble->ble_events_.size() >= MAX_BLE_QUEUE_SIZE) {
ESP_LOGW(TAG, "BLE event queue full (%d), dropping GATTC event %d", MAX_BLE_QUEUE_SIZE, event);
return;
}
BLEEvent *new_event = EVENT_ALLOCATOR.allocate(1); BLEEvent *new_event = EVENT_ALLOCATOR.allocate(1);
if (new_event == nullptr) { if (new_event == nullptr) {
// Memory too fragmented to allocate new event. Can only drop it until memory comes back // Memory too fragmented to allocate new event. Can only drop it until memory comes back

View File

@@ -22,6 +22,13 @@
namespace esphome { namespace esphome {
namespace esp32_ble { namespace esp32_ble {
// Maximum number of BLE scan results to buffer
#ifdef USE_PSRAM
static constexpr uint8_t SCAN_RESULT_BUFFER_SIZE = 32;
#else
static constexpr uint8_t SCAN_RESULT_BUFFER_SIZE = 20;
#endif
uint64_t ble_addr_to_uint64(const esp_bd_addr_t address); uint64_t ble_addr_to_uint64(const esp_bd_addr_t address);
// NOLINTNEXTLINE(modernize-use-using) // NOLINTNEXTLINE(modernize-use-using)
@@ -57,6 +64,23 @@ class GAPEventHandler {
virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0; virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0;
}; };
// Structure for BLE scan results - only fields we actually use
struct BLEScanResult {
esp_bd_addr_t bda;
uint8_t ble_addr_type;
int8_t rssi;
uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX];
uint8_t adv_data_len;
uint8_t scan_rsp_len;
uint8_t search_evt;
}; // ~73 bytes vs ~400 bytes for full esp_ble_gap_cb_param_t
class GAPScanEventHandler {
public:
// Receives scan results directly without memcpy
virtual void gap_scan_event_handler(const BLEScanResult &scan_result) = 0;
};
class GATTcEventHandler { class GATTcEventHandler {
public: public:
virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
@@ -101,6 +125,9 @@ class ESP32BLE : public Component {
void advertising_register_raw_advertisement_callback(std::function<void(bool)> &&callback); void advertising_register_raw_advertisement_callback(std::function<void(bool)> &&callback);
void register_gap_event_handler(GAPEventHandler *handler) { this->gap_event_handlers_.push_back(handler); } void register_gap_event_handler(GAPEventHandler *handler) { this->gap_event_handlers_.push_back(handler); }
void register_gap_scan_event_handler(GAPScanEventHandler *handler) {
this->gap_scan_event_handlers_.push_back(handler);
}
void register_gattc_event_handler(GATTcEventHandler *handler) { this->gattc_event_handlers_.push_back(handler); } void register_gattc_event_handler(GATTcEventHandler *handler) { this->gattc_event_handlers_.push_back(handler); }
void register_gatts_event_handler(GATTsEventHandler *handler) { this->gatts_event_handlers_.push_back(handler); } void register_gatts_event_handler(GATTsEventHandler *handler) { this->gatts_event_handlers_.push_back(handler); }
void register_ble_status_event_handler(BLEStatusEventHandler *handler) { void register_ble_status_event_handler(BLEStatusEventHandler *handler) {
@@ -123,6 +150,7 @@ class ESP32BLE : public Component {
void advertising_init_(); void advertising_init_();
std::vector<GAPEventHandler *> gap_event_handlers_; std::vector<GAPEventHandler *> gap_event_handlers_;
std::vector<GAPScanEventHandler *> gap_scan_event_handlers_;
std::vector<GATTcEventHandler *> gattc_event_handlers_; std::vector<GATTcEventHandler *> gattc_event_handlers_;
std::vector<GATTsEventHandler *> gatts_event_handlers_; std::vector<GATTsEventHandler *> gatts_event_handlers_;
std::vector<BLEStatusEventHandler *> ble_status_event_handlers_; std::vector<BLEStatusEventHandler *> ble_status_event_handlers_;

View File

@@ -10,21 +10,56 @@
namespace esphome { namespace esphome {
namespace esp32_ble { namespace esp32_ble {
// Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop(). // Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop().
// This class stores each event in a single type. // This class stores each event with minimal memory usage by only copying the data we actually need.
class BLEEvent { class BLEEvent {
public: public:
BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) { BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
this->event_.gap.gap_event = e;
memcpy(&this->event_.gap.gap_param, p, sizeof(esp_ble_gap_cb_param_t));
this->type_ = GAP; this->type_ = GAP;
this->event_.gap.gap_event = e;
// Only copy the data we actually use for each GAP event type
switch (e) {
case ESP_GAP_BLE_SCAN_RESULT_EVT:
// Copy only the fields we use from scan results (~72 bytes)
memcpy(this->event_.gap.scan_result.bda, p->scan_rst.bda, sizeof(esp_bd_addr_t));
this->event_.gap.scan_result.ble_addr_type = p->scan_rst.ble_addr_type;
this->event_.gap.scan_result.rssi = p->scan_rst.rssi;
this->event_.gap.scan_result.adv_data_len = p->scan_rst.adv_data_len;
this->event_.gap.scan_result.scan_rsp_len = p->scan_rst.scan_rsp_len;
this->event_.gap.scan_result.search_evt = p->scan_rst.search_evt;
memcpy(this->event_.gap.scan_result.ble_adv, p->scan_rst.ble_adv,
ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX);
break;
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
this->event_.gap.scan_complete.status = p->scan_param_cmpl.status;
break;
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
this->event_.gap.scan_complete.status = p->scan_start_cmpl.status;
break;
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
this->event_.gap.scan_complete.status = p->scan_stop_cmpl.status;
break;
default:
// For any other GAP events, copy the full param
// This is a safety fallback but shouldn't happen in normal operation
memcpy(&this->event_.gap.gap_param, p, sizeof(esp_ble_gap_cb_param_t));
break;
}
}; };
BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) { BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
this->type_ = GATTC;
this->event_.gattc.gattc_event = e; this->event_.gattc.gattc_event = e;
this->event_.gattc.gattc_if = i; this->event_.gattc.gattc_if = i;
memcpy(&this->event_.gattc.gattc_param, p, sizeof(esp_ble_gattc_cb_param_t)); memcpy(&this->event_.gattc.gattc_param, p, sizeof(esp_ble_gattc_cb_param_t));
// Need to also make a copy of relevant event data.
// Copy data for events that need it
switch (e) { switch (e) {
case ESP_GATTC_NOTIFY_EVT: case ESP_GATTC_NOTIFY_EVT:
this->data.assign(p->notify.value, p->notify.value + p->notify.value_len); this->data.assign(p->notify.value, p->notify.value + p->notify.value_len);
@@ -38,14 +73,15 @@ class BLEEvent {
default: default:
break; break;
} }
this->type_ = GATTC;
}; };
BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) { BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
this->type_ = GATTS;
this->event_.gatts.gatts_event = e; this->event_.gatts.gatts_event = e;
this->event_.gatts.gatts_if = i; this->event_.gatts.gatts_if = i;
memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t)); memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t));
// Need to also make a copy of relevant event data.
// Copy data for events that need it
switch (e) { switch (e) {
case ESP_GATTS_WRITE_EVT: case ESP_GATTS_WRITE_EVT:
this->data.assign(p->write.value, p->write.value + p->write.len); this->data.assign(p->write.value, p->write.value + p->write.len);
@@ -54,39 +90,55 @@ class BLEEvent {
default: default:
break; break;
} }
this->type_ = GATTS;
}; };
union { union {
// NOLINTNEXTLINE(readability-identifier-naming) // NOLINTNEXTLINE(readability-identifier-naming)
struct gap_event { struct gap_event {
esp_gap_ble_cb_event_t gap_event; esp_gap_ble_cb_event_t gap_event;
union {
BLEScanResult scan_result; // ~73 bytes
// Minimal storage for scan complete events
struct {
esp_bt_status_t status;
} scan_complete; // 1 byte
// Fallback for unexpected events (shouldn't be used)
esp_ble_gap_cb_param_t gap_param; esp_ble_gap_cb_param_t gap_param;
} gap; };
} gap; // ~80 bytes instead of 400+
// NOLINTNEXTLINE(readability-identifier-naming) // NOLINTNEXTLINE(readability-identifier-naming)
struct gattc_event { struct gattc_event {
esp_gattc_cb_event_t gattc_event; esp_gattc_cb_event_t gattc_event;
esp_gatt_if_t gattc_if; esp_gatt_if_t gattc_if;
esp_ble_gattc_cb_param_t gattc_param; esp_ble_gattc_cb_param_t gattc_param;
} gattc; } gattc; // ~68 bytes
// NOLINTNEXTLINE(readability-identifier-naming) // NOLINTNEXTLINE(readability-identifier-naming)
struct gatts_event { struct gatts_event {
esp_gatts_cb_event_t gatts_event; esp_gatts_cb_event_t gatts_event;
esp_gatt_if_t gatts_if; esp_gatt_if_t gatts_if;
esp_ble_gatts_cb_param_t gatts_param; esp_ble_gatts_cb_param_t gatts_param;
} gatts; } gatts; // ~68 bytes
} event_; } event_; // Union size is now ~80 bytes (largest member)
std::vector<uint8_t> data{}; // For GATTC/GATTS data
std::vector<uint8_t> data{};
// NOLINTNEXTLINE(readability-identifier-naming) // NOLINTNEXTLINE(readability-identifier-naming)
enum ble_event_t : uint8_t { enum ble_event_t : uint8_t {
GAP, GAP,
GATTC, GATTC,
GATTS, GATTS,
} type_; } type_;
// Helper methods to access event data
esp_gap_ble_cb_event_t gap_event_type() const { return event_.gap.gap_event; }
const BLEScanResult &scan_result() const { return event_.gap.scan_result; }
esp_bt_status_t scan_complete_status() const { return event_.gap.scan_complete.status; }
}; };
// Total size: ~110 bytes instead of 440 bytes!
} // namespace esp32_ble } // namespace esp32_ble
} // namespace esphome } // namespace esphome

View File

@@ -45,6 +45,10 @@ template<class T> class Queue {
return element; return element;
} }
size_t size() const {
return q_.size(); // Atomic read, no lock needed
}
protected: protected:
std::queue<T *> q_; std::queue<T *> q_;
SemaphoreHandle_t m_; SemaphoreHandle_t m_;

View File

@@ -268,6 +268,7 @@ async def to_code(config):
parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID]) parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID])
cg.add(parent.register_gap_event_handler(var)) cg.add(parent.register_gap_event_handler(var))
cg.add(parent.register_gap_scan_event_handler(var))
cg.add(parent.register_gattc_event_handler(var)) cg.add(parent.register_gattc_event_handler(var))
cg.add(parent.register_ble_status_event_handler(var)) cg.add(parent.register_ble_status_event_handler(var))
cg.add(var.set_parent(parent)) cg.add(var.set_parent(parent))

View File

@@ -50,9 +50,8 @@ void ESP32BLETracker::setup() {
ESP_LOGE(TAG, "BLE Tracker was marked failed by ESP32BLE"); ESP_LOGE(TAG, "BLE Tracker was marked failed by ESP32BLE");
return; return;
} }
ExternalRAMAllocator<esp_ble_gap_cb_param_t::ble_scan_result_evt_param> allocator( ExternalRAMAllocator<BLEScanResult> allocator(ExternalRAMAllocator<BLEScanResult>::ALLOW_FAILURE);
ExternalRAMAllocator<esp_ble_gap_cb_param_t::ble_scan_result_evt_param>::ALLOW_FAILURE); this->scan_result_buffer_ = allocator.allocate(SCAN_RESULT_BUFFER_SIZE);
this->scan_result_buffer_ = allocator.allocate(ESP32BLETracker::SCAN_RESULT_BUFFER_SIZE);
if (this->scan_result_buffer_ == nullptr) { if (this->scan_result_buffer_ == nullptr) {
ESP_LOGE(TAG, "Could not allocate buffer for BLE Tracker!"); ESP_LOGE(TAG, "Could not allocate buffer for BLE Tracker!");
@@ -140,7 +139,24 @@ void ESP32BLETracker::loop() {
if (this->parse_advertisements_) { if (this->parse_advertisements_) {
for (size_t i = 0; i < index; i++) { for (size_t i = 0; i < index; i++) {
ESPBTDevice device; ESPBTDevice device;
device.parse_scan_rst(this->scan_result_buffer_[i]); // Convert BLEScanResult to ESP-IDF format for parse_scan_rst
esp_ble_gap_cb_param_t::ble_scan_result_evt_param param;
memcpy(param.bda, this->scan_result_buffer_[i].bda, sizeof(esp_bd_addr_t));
param.ble_addr_type = this->scan_result_buffer_[i].ble_addr_type;
param.rssi = this->scan_result_buffer_[i].rssi;
param.adv_data_len = this->scan_result_buffer_[i].adv_data_len;
param.scan_rsp_len = this->scan_result_buffer_[i].scan_rsp_len;
param.search_evt = this->scan_result_buffer_[i].search_evt;
memcpy(param.ble_adv, this->scan_result_buffer_[i].ble_adv,
ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX);
// Fill in fields we don't store
param.dev_type = 0;
param.ble_evt_type = 0;
param.flag = 0;
param.num_resps = 1;
param.num_dis = 0;
device.parse_scan_rst(param);
bool found = false; bool found = false;
for (auto *listener : this->listeners_) { for (auto *listener : this->listeners_) {
@@ -371,7 +387,7 @@ void ESP32BLETracker::recalculate_advertisement_parser_types() {
void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
switch (event) { switch (event) {
case ESP_GAP_BLE_SCAN_RESULT_EVT: case ESP_GAP_BLE_SCAN_RESULT_EVT:
this->gap_scan_result_(param->scan_rst); // This will be handled by gap_scan_event_handler instead
break; break;
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
this->gap_scan_set_param_complete_(param->scan_param_cmpl); this->gap_scan_set_param_complete_(param->scan_param_cmpl);
@@ -385,9 +401,64 @@ void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_ga
default: default:
break; break;
} }
// Still forward non-scan events to clients
if (event != ESP_GAP_BLE_SCAN_RESULT_EVT) {
for (auto *client : this->clients_) { for (auto *client : this->clients_) {
client->gap_event_handler(event, param); client->gap_event_handler(event, param);
} }
}
}
void ESP32BLETracker::gap_scan_event_handler(const BLEScanResult &scan_result) {
ESP_LOGV(TAG, "gap_scan_result - event %d", scan_result.search_evt);
if (scan_result.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) {
if (xSemaphoreTake(this->scan_result_lock_, 0)) {
if (this->scan_result_index_ < SCAN_RESULT_BUFFER_SIZE) {
// Store BLEScanResult directly in our buffer
this->scan_result_buffer_[this->scan_result_index_++] = scan_result;
}
xSemaphoreGive(this->scan_result_lock_);
}
} else if (scan_result.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) {
// Scan finished on its own
if (this->scanner_state_ != ScannerState::RUNNING) {
if (this->scanner_state_ == ScannerState::STOPPING) {
ESP_LOGE(TAG, "Scan was not running when scan completed.");
} else if (this->scanner_state_ == ScannerState::STARTING) {
ESP_LOGE(TAG, "Scan was not started when scan completed.");
} else if (this->scanner_state_ == ScannerState::FAILED) {
ESP_LOGE(TAG, "Scan was in failed state when scan completed.");
} else if (this->scanner_state_ == ScannerState::IDLE) {
ESP_LOGE(TAG, "Scan was idle when scan completed.");
} else if (this->scanner_state_ == ScannerState::STOPPED) {
ESP_LOGE(TAG, "Scan was stopped when scan completed.");
}
}
this->set_scanner_state_(ScannerState::STOPPED);
}
// Forward scan results to clients - they still expect the old format
if (scan_result.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) {
esp_ble_gap_cb_param_t param;
memset(&param, 0, sizeof(param));
memcpy(param.scan_rst.bda, scan_result.bda, sizeof(esp_bd_addr_t));
param.scan_rst.ble_addr_type = scan_result.ble_addr_type;
param.scan_rst.rssi = scan_result.rssi;
param.scan_rst.adv_data_len = scan_result.adv_data_len;
param.scan_rst.scan_rsp_len = scan_result.scan_rsp_len;
param.scan_rst.search_evt = scan_result.search_evt;
memcpy(param.scan_rst.ble_adv, scan_result.ble_adv, ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX);
param.scan_rst.dev_type = 0;
param.scan_rst.ble_evt_type = 0;
param.scan_rst.flag = 0;
param.scan_rst.num_resps = 1;
param.scan_rst.num_dis = 0;
for (auto *client : this->clients_) {
client->gap_event_handler(ESP_GAP_BLE_SCAN_RESULT_EVT, &param);
}
}
} }
void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param &param) { void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param &param) {
@@ -444,33 +515,7 @@ void ESP32BLETracker::gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_
this->set_scanner_state_(ScannerState::STOPPED); this->set_scanner_state_(ScannerState::STOPPED);
} }
void ESP32BLETracker::gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param) { // Removed - functionality moved to gap_scan_event_handler
ESP_LOGV(TAG, "gap_scan_result - event %d", param.search_evt);
if (param.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) {
if (xSemaphoreTake(this->scan_result_lock_, 0)) {
if (this->scan_result_index_ < ESP32BLETracker::SCAN_RESULT_BUFFER_SIZE) {
this->scan_result_buffer_[this->scan_result_index_++] = param;
}
xSemaphoreGive(this->scan_result_lock_);
}
} else if (param.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) {
// Scan finished on its own
if (this->scanner_state_ != ScannerState::RUNNING) {
if (this->scanner_state_ == ScannerState::STOPPING) {
ESP_LOGE(TAG, "Scan was not running when scan completed.");
} else if (this->scanner_state_ == ScannerState::STARTING) {
ESP_LOGE(TAG, "Scan was not started when scan completed.");
} else if (this->scanner_state_ == ScannerState::FAILED) {
ESP_LOGE(TAG, "Scan was in failed state when scan completed.");
} else if (this->scanner_state_ == ScannerState::IDLE) {
ESP_LOGE(TAG, "Scan was idle when scan completed.");
} else if (this->scanner_state_ == ScannerState::STOPPED) {
ESP_LOGE(TAG, "Scan was stopped when scan completed.");
}
}
this->set_scanner_state_(ScannerState::STOPPED);
}
}
void ESP32BLETracker::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, void ESP32BLETracker::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) { esp_ble_gattc_cb_param_t *param) {

View File

@@ -121,9 +121,7 @@ class ESPBTDeviceListener {
public: public:
virtual void on_scan_end() {} virtual void on_scan_end() {}
virtual bool parse_device(const ESPBTDevice &device) = 0; virtual bool parse_device(const ESPBTDevice &device) = 0;
virtual bool parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count) { virtual bool parse_devices(const BLEScanResult *scan_results, size_t count) { return false; };
return false;
};
virtual AdvertisementParserType get_advertisement_parser_type() { virtual AdvertisementParserType get_advertisement_parser_type() {
return AdvertisementParserType::PARSED_ADVERTISEMENTS; return AdvertisementParserType::PARSED_ADVERTISEMENTS;
}; };
@@ -210,6 +208,7 @@ class ESPBTClient : public ESPBTDeviceListener {
class ESP32BLETracker : public Component, class ESP32BLETracker : public Component,
public GAPEventHandler, public GAPEventHandler,
public GAPScanEventHandler,
public GATTcEventHandler, public GATTcEventHandler,
public BLEStatusEventHandler, public BLEStatusEventHandler,
public Parented<ESP32BLE> { public Parented<ESP32BLE> {
@@ -240,6 +239,7 @@ class ESP32BLETracker : public Component,
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) override; esp_ble_gattc_cb_param_t *param) override;
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
void gap_scan_event_handler(const BLEScanResult &scan_result) override;
void ble_before_disabled_event_handler() override; void ble_before_disabled_event_handler() override;
void add_scanner_state_callback(std::function<void(ScannerState)> &&callback) { void add_scanner_state_callback(std::function<void(ScannerState)> &&callback) {
@@ -287,12 +287,8 @@ class ESP32BLETracker : public Component,
bool parse_advertisements_{false}; bool parse_advertisements_{false};
SemaphoreHandle_t scan_result_lock_; SemaphoreHandle_t scan_result_lock_;
size_t scan_result_index_{0}; size_t scan_result_index_{0};
#ifdef USE_PSRAM // SCAN_RESULT_BUFFER_SIZE is now defined in esp32_ble/ble.h
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 32; BLEScanResult *scan_result_buffer_;
#else
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 20;
#endif // USE_PSRAM
esp_ble_gap_cb_param_t::ble_scan_result_evt_param *scan_result_buffer_;
esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS}; esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS}; esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
int connecting_{0}; int connecting_{0};