mirror of
https://github.com/esphome/esphome.git
synced 2025-10-05 11:23:47 +01:00
wip
This commit is contained in:
@@ -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();
|
||||||
|
@@ -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;
|
||||||
|
@@ -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(¶m, 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, ¶m);
|
||||||
|
} 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
|
||||||
|
@@ -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_;
|
||||||
|
@@ -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
|
||||||
|
@@ -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_;
|
||||||
|
@@ -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))
|
||||||
|
@@ -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,10 +401,65 @@ 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(¶m, 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, ¶m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param ¶m) {
|
void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param ¶m) {
|
||||||
ESP_LOGV(TAG, "gap_scan_set_param_complete - status %d", param.status);
|
ESP_LOGV(TAG, "gap_scan_set_param_complete - status %d", param.status);
|
||||||
@@ -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 ¶m) {
|
// 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) {
|
||||||
|
@@ -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};
|
||||||
|
Reference in New Issue
Block a user