mirror of
https://github.com/esphome/esphome.git
synced 2025-09-02 11:22:24 +01:00
[esp32_ble] Optimize BLE event memory usage by eliminating std::vector overhead (#10247)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -3,8 +3,7 @@
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include <cstddef> // for offsetof
|
#include <cstddef> // for offsetof
|
||||||
#include <vector>
|
#include <cstring> // for memcpy
|
||||||
|
|
||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
#include <esp_gattc_api.h>
|
#include <esp_gattc_api.h>
|
||||||
#include <esp_gatts_api.h>
|
#include <esp_gatts_api.h>
|
||||||
@@ -64,7 +63,7 @@ static_assert(offsetof(esp_ble_gap_cb_param_t, read_rssi_cmpl.remote_addr) == si
|
|||||||
|
|
||||||
// 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 with minimal memory usage.
|
// This class stores each event with minimal memory usage.
|
||||||
// GAP events (99% of traffic) don't have the vector overhead.
|
// GAP events (99% of traffic) don't have the heap allocation overhead.
|
||||||
// GATTC/GATTS events use heap allocation for their param and data.
|
// GATTC/GATTS events use heap allocation for their param and data.
|
||||||
//
|
//
|
||||||
// Event flow:
|
// Event flow:
|
||||||
@@ -145,16 +144,18 @@ class BLEEvent {
|
|||||||
}
|
}
|
||||||
if (this->type_ == GATTC) {
|
if (this->type_ == GATTC) {
|
||||||
delete this->event_.gattc.gattc_param;
|
delete this->event_.gattc.gattc_param;
|
||||||
delete this->event_.gattc.data;
|
delete[] this->event_.gattc.data;
|
||||||
this->event_.gattc.gattc_param = nullptr;
|
this->event_.gattc.gattc_param = nullptr;
|
||||||
this->event_.gattc.data = nullptr;
|
this->event_.gattc.data = nullptr;
|
||||||
|
this->event_.gattc.data_len = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this->type_ == GATTS) {
|
if (this->type_ == GATTS) {
|
||||||
delete this->event_.gatts.gatts_param;
|
delete this->event_.gatts.gatts_param;
|
||||||
delete this->event_.gatts.data;
|
delete[] this->event_.gatts.data;
|
||||||
this->event_.gatts.gatts_param = nullptr;
|
this->event_.gatts.gatts_param = nullptr;
|
||||||
this->event_.gatts.data = nullptr;
|
this->event_.gatts.data = nullptr;
|
||||||
|
this->event_.gatts.data_len = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,16 +210,18 @@ class BLEEvent {
|
|||||||
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; // Heap-allocated
|
esp_ble_gattc_cb_param_t *gattc_param; // Heap-allocated
|
||||||
std::vector<uint8_t> *data; // Heap-allocated
|
uint8_t *data; // Heap-allocated raw buffer (manually managed)
|
||||||
} gattc; // 16 bytes (pointers only)
|
uint16_t data_len; // Track size separately
|
||||||
|
} gattc;
|
||||||
|
|
||||||
// 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; // Heap-allocated
|
esp_ble_gatts_cb_param_t *gatts_param; // Heap-allocated
|
||||||
std::vector<uint8_t> *data; // Heap-allocated
|
uint8_t *data; // Heap-allocated raw buffer (manually managed)
|
||||||
} gatts; // 16 bytes (pointers only)
|
uint16_t data_len; // Track size separately
|
||||||
|
} gatts;
|
||||||
} event_; // 80 bytes
|
} event_; // 80 bytes
|
||||||
|
|
||||||
ble_event_t type_;
|
ble_event_t type_;
|
||||||
@@ -319,6 +322,7 @@ class BLEEvent {
|
|||||||
if (p == nullptr) {
|
if (p == nullptr) {
|
||||||
this->event_.gattc.gattc_param = nullptr;
|
this->event_.gattc.gattc_param = nullptr;
|
||||||
this->event_.gattc.data = nullptr;
|
this->event_.gattc.data = nullptr;
|
||||||
|
this->event_.gattc.data_len = 0;
|
||||||
return; // Invalid event, but we can't log in header file
|
return; // Invalid event, but we can't log in header file
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,16 +340,29 @@ class BLEEvent {
|
|||||||
// We must copy this data to ensure it remains valid when the event is processed later.
|
// We must copy this data to ensure it remains valid when the event is processed later.
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case ESP_GATTC_NOTIFY_EVT:
|
case ESP_GATTC_NOTIFY_EVT:
|
||||||
this->event_.gattc.data = new std::vector<uint8_t>(p->notify.value, p->notify.value + p->notify.value_len);
|
this->event_.gattc.data_len = p->notify.value_len;
|
||||||
this->event_.gattc.gattc_param->notify.value = this->event_.gattc.data->data();
|
if (p->notify.value_len > 0) {
|
||||||
|
this->event_.gattc.data = new uint8_t[p->notify.value_len];
|
||||||
|
memcpy(this->event_.gattc.data, p->notify.value, p->notify.value_len);
|
||||||
|
} else {
|
||||||
|
this->event_.gattc.data = nullptr;
|
||||||
|
}
|
||||||
|
this->event_.gattc.gattc_param->notify.value = this->event_.gattc.data;
|
||||||
break;
|
break;
|
||||||
case ESP_GATTC_READ_CHAR_EVT:
|
case ESP_GATTC_READ_CHAR_EVT:
|
||||||
case ESP_GATTC_READ_DESCR_EVT:
|
case ESP_GATTC_READ_DESCR_EVT:
|
||||||
this->event_.gattc.data = new std::vector<uint8_t>(p->read.value, p->read.value + p->read.value_len);
|
this->event_.gattc.data_len = p->read.value_len;
|
||||||
this->event_.gattc.gattc_param->read.value = this->event_.gattc.data->data();
|
if (p->read.value_len > 0) {
|
||||||
|
this->event_.gattc.data = new uint8_t[p->read.value_len];
|
||||||
|
memcpy(this->event_.gattc.data, p->read.value, p->read.value_len);
|
||||||
|
} else {
|
||||||
|
this->event_.gattc.data = nullptr;
|
||||||
|
}
|
||||||
|
this->event_.gattc.gattc_param->read.value = this->event_.gattc.data;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this->event_.gattc.data = nullptr;
|
this->event_.gattc.data = nullptr;
|
||||||
|
this->event_.gattc.data_len = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,6 +375,7 @@ class BLEEvent {
|
|||||||
if (p == nullptr) {
|
if (p == nullptr) {
|
||||||
this->event_.gatts.gatts_param = nullptr;
|
this->event_.gatts.gatts_param = nullptr;
|
||||||
this->event_.gatts.data = nullptr;
|
this->event_.gatts.data = nullptr;
|
||||||
|
this->event_.gatts.data_len = 0;
|
||||||
return; // Invalid event, but we can't log in header file
|
return; // Invalid event, but we can't log in header file
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,11 +393,18 @@ class BLEEvent {
|
|||||||
// We must copy this data to ensure it remains valid when the event is processed later.
|
// We must copy this data to ensure it remains valid when the event is processed later.
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case ESP_GATTS_WRITE_EVT:
|
case ESP_GATTS_WRITE_EVT:
|
||||||
this->event_.gatts.data = new std::vector<uint8_t>(p->write.value, p->write.value + p->write.len);
|
this->event_.gatts.data_len = p->write.len;
|
||||||
this->event_.gatts.gatts_param->write.value = this->event_.gatts.data->data();
|
if (p->write.len > 0) {
|
||||||
|
this->event_.gatts.data = new uint8_t[p->write.len];
|
||||||
|
memcpy(this->event_.gatts.data, p->write.value, p->write.len);
|
||||||
|
} else {
|
||||||
|
this->event_.gatts.data = nullptr;
|
||||||
|
}
|
||||||
|
this->event_.gatts.gatts_param->write.value = this->event_.gatts.data;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this->event_.gatts.data = nullptr;
|
this->event_.gatts.data = nullptr;
|
||||||
|
this->event_.gatts.data_len = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user