1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-04 19:03:47 +01:00

[esp32_ble_server] Optimize notification and action managers for typical use cases (#10897)

This commit is contained in:
J. Nick Koston
2025-09-28 17:32:16 -05:00
committed by GitHub
parent ef73ae2116
commit ab79e596b5
4 changed files with 88 additions and 22 deletions

View File

@@ -51,11 +51,11 @@ void BLECharacteristic::notify() {
for (auto &client : this->service_->get_server()->get_clients()) {
size_t length = this->value_.size();
// If the client is not in the list of clients to notify, skip it
if (this->clients_to_notify_.count(client) == 0)
// Find the client in the list of clients to notify
auto *entry = this->find_client_in_notify_list_(client);
if (entry == nullptr)
continue;
// If the client is in the list of clients to notify, check if it requires an ack (i.e. INDICATE)
bool require_ack = this->clients_to_notify_[client];
bool require_ack = entry->indicate;
// TODO: Remove this block when INDICATE acknowledgment is supported
if (require_ack) {
ESP_LOGW(TAG, "INDICATE acknowledgment is not yet supported (i.e. it works as a NOTIFY)");
@@ -79,10 +79,11 @@ void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) {
uint16_t cccd = encode_uint16(value[1], value[0]);
bool notify = (cccd & 1) != 0;
bool indicate = (cccd & 2) != 0;
// Remove existing entry if present
this->remove_client_from_notify_list_(conn_id);
// Add new entry if needed
if (notify || indicate) {
this->clients_to_notify_[conn_id] = indicate;
} else {
this->clients_to_notify_.erase(conn_id);
this->clients_to_notify_.push_back({conn_id, indicate});
}
});
}
@@ -307,6 +308,28 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
}
}
void BLECharacteristic::remove_client_from_notify_list_(uint16_t conn_id) {
// Since we typically have very few clients (often just 1), we can optimize
// for the common case by swapping with the last element and popping
for (size_t i = 0; i < this->clients_to_notify_.size(); i++) {
if (this->clients_to_notify_[i].conn_id == conn_id) {
// Swap with last element and pop (safe even when i is the last element)
this->clients_to_notify_[i] = this->clients_to_notify_.back();
this->clients_to_notify_.pop_back();
return;
}
}
}
BLECharacteristic::ClientNotificationEntry *BLECharacteristic::find_client_in_notify_list_(uint16_t conn_id) {
for (auto &entry : this->clients_to_notify_) {
if (entry.conn_id == conn_id) {
return &entry;
}
}
return nullptr;
}
} // namespace esp32_ble_server
} // namespace esphome