its too much

This commit is contained in:
J. Nick Koston
2025-05-13 03:00:38 -05:00
parent 83db3eddd9
commit d95bbfc6c4
4 changed files with 60 additions and 9 deletions

View File

@@ -51,14 +51,19 @@ bool BluetoothProxy::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
return true;
}
// Static buffer to store advertisements between batches
static constexpr size_t MAX_BATCH_SIZE = 64; // Larger batch size for more efficient transfers
static std::vector<api::BluetoothLERawAdvertisement> batch_buffer;
bool BluetoothProxy::parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_param *advertisements, size_t count) {
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr || !this->raw_advertisements_)
return false;
api::BluetoothLERawAdvertisementsResponse resp;
// Pre-allocate the advertisements vector to avoid reallocations
resp.advertisements.reserve(count);
if (batch_buffer.capacity() < MAX_BATCH_SIZE) {
batch_buffer.reserve(MAX_BATCH_SIZE);
}
// Add new advertisements to the batch buffer
for (size_t i = 0; i < count; i++) {
auto &result = advertisements[i];
api::BluetoothLERawAdvertisement adv;
@@ -71,15 +76,36 @@ bool BluetoothProxy::parse_devices(esp_ble_gap_cb_param_t::ble_scan_result_evt_p
// Use a bulk insert instead of individual push_backs
adv.data.insert(adv.data.end(), &result.ble_adv[0], &result.ble_adv[length]);
resp.advertisements.push_back(std::move(adv));
batch_buffer.push_back(std::move(adv));
ESP_LOGV(TAG, "Proxying raw packet from %02X:%02X:%02X:%02X:%02X:%02X, length %d. RSSI: %d dB", result.bda[0],
ESP_LOGV(TAG, "Queuing raw packet from %02X:%02X:%02X:%02X:%02X:%02X, length %d. RSSI: %d dB", result.bda[0],
result.bda[1], result.bda[2], result.bda[3], result.bda[4], result.bda[5], length, result.rssi);
}
ESP_LOGV(TAG, "Proxying %d packets", count);
this->api_connection_->send_bluetooth_le_raw_advertisements_response(resp);
// Only send if we've accumulated a good batch size to maximize batching efficiency
if (batch_buffer.size() >= MAX_BATCH_SIZE) {
this->flush_pending_advertisements();
}
return true;
}
void BluetoothProxy::flush_pending_advertisements() {
if (batch_buffer.empty() || !api::global_api_server->is_connected() || this->api_connection_ == nullptr)
return;
api::BluetoothLERawAdvertisementsResponse resp;
resp.advertisements.reserve(batch_buffer.size());
// Move all advertisements from the buffer to the response
for (auto &adv : batch_buffer) {
resp.advertisements.push_back(std::move(adv));
}
ESP_LOGV(TAG, "Proxying batch of %d packets", resp.advertisements.size());
this->api_connection_->send_bluetooth_le_raw_advertisements_response(resp);
batch_buffer.clear();
}
void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &device) {
api::BluetoothLEAdvertisementResponse resp;
resp.address = device.address_uint64();
@@ -148,6 +174,18 @@ void BluetoothProxy::loop() {
}
return;
}
// Flush any pending BLE advertisements that have been accumulated but not yet sent
if (this->raw_advertisements_) {
static uint32_t last_flush_time = 0;
uint32_t now = millis();
// Flush accumulated advertisements every 100ms
if (now - last_flush_time >= 100) {
this->flush_pending_advertisements();
last_flush_time = now;
}
}
for (auto *connection : this->connections_) {
if (connection->send_service_ == connection->service_count_) {
connection->send_service_ = DONE_SENDING_SERVICES;
@@ -526,6 +564,12 @@ void BluetoothProxy::unsubscribe_api_connection(api::APIConnection *api_connecti
ESP_LOGV(TAG, "API connection is not subscribed");
return;
}
// Flush any pending advertisements before unsubscribing
if (this->raw_advertisements_) {
this->flush_pending_advertisements();
}
this->api_connection_ = nullptr;
this->raw_advertisements_ = false;
this->parent_->recalculate_advertisement_parser_types();

View File

@@ -56,6 +56,7 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com
void dump_config() override;
void setup() override;
void loop() override;
void flush_pending_advertisements();
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override;
void register_connection(BluetoothConnection *connection) {

View File

@@ -120,9 +120,15 @@ void ESP32BLETracker::loop() {
}
bool promote_to_connecting = discovered && !searching && !connecting;
static uint32_t last_process_time = 0;
uint32_t now = millis();
// Process scan results less frequently to allow more batching - process every 50ms
if (this->scanner_state_ == ScannerState::RUNNING &&
this->scan_result_index_ && // if it looks like we have a scan result we will take the lock
(now - last_process_time >= 50 || this->scan_result_index_ >= ESP32BLETracker::SCAN_RESULT_BUFFER_SIZE / 2) &&
xSemaphoreTake(this->scan_result_lock_, 5L / portTICK_PERIOD_MS)) {
last_process_time = now;
uint32_t index = this->scan_result_index_;
if (index >= ESP32BLETracker::SCAN_RESULT_BUFFER_SIZE) {
ESP_LOGW(TAG, "Too many BLE events to process. Some devices may not show up.");

View File

@@ -288,9 +288,9 @@ class ESP32BLETracker : public Component,
SemaphoreHandle_t scan_result_lock_;
size_t scan_result_index_{0};
#ifdef USE_PSRAM
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 32;
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 128;
#else
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 16;
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 64;
#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};