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:
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user