ESPHome 2026.3.0
Loading...
Searching...
No Matches
ble_event.h
Go to the documentation of this file.
1#pragma once
2
3#ifdef USE_ESP32
4
5#include <cstddef> // for offsetof
6#include <cstring> // for memcpy
7#include <esp_gap_ble_api.h>
8#include <esp_gattc_api.h>
9#include <esp_gatts_api.h>
10
11#include "ble_scan_result.h"
12
13namespace esphome::esp32_ble {
14
15// Compile-time verification that ESP-IDF scan complete events only contain a status field
16// This ensures our reinterpret_cast in ble.cpp is safe
17static_assert(sizeof(esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param) == sizeof(esp_bt_status_t),
18 "ESP-IDF scan_param_cmpl structure has unexpected size");
19static_assert(sizeof(esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param) == sizeof(esp_bt_status_t),
20 "ESP-IDF scan_start_cmpl structure has unexpected size");
21static_assert(sizeof(esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param) == sizeof(esp_bt_status_t),
22 "ESP-IDF scan_stop_cmpl structure has unexpected size");
23
24// Verify the status field is at offset 0 (first member)
25static_assert(offsetof(esp_ble_gap_cb_param_t, scan_param_cmpl.status) == 0,
26 "status must be first member of scan_param_cmpl");
27static_assert(offsetof(esp_ble_gap_cb_param_t, scan_start_cmpl.status) == 0,
28 "status must be first member of scan_start_cmpl");
29static_assert(offsetof(esp_ble_gap_cb_param_t, scan_stop_cmpl.status) == 0,
30 "status must be first member of scan_stop_cmpl");
31
32// Compile-time verification for advertising complete events
33static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_data_cmpl_evt_param) == sizeof(esp_bt_status_t),
34 "ESP-IDF adv_data_cmpl structure has unexpected size");
35static_assert(sizeof(esp_ble_gap_cb_param_t::ble_scan_rsp_data_cmpl_evt_param) == sizeof(esp_bt_status_t),
36 "ESP-IDF scan_rsp_data_cmpl structure has unexpected size");
37static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_data_raw_cmpl_evt_param) == sizeof(esp_bt_status_t),
38 "ESP-IDF adv_data_raw_cmpl structure has unexpected size");
39static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_start_cmpl_evt_param) == sizeof(esp_bt_status_t),
40 "ESP-IDF adv_start_cmpl structure has unexpected size");
41static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_stop_cmpl_evt_param) == sizeof(esp_bt_status_t),
42 "ESP-IDF adv_stop_cmpl structure has unexpected size");
43
44// Verify the status field is at offset 0 for advertising events
45static_assert(offsetof(esp_ble_gap_cb_param_t, adv_data_cmpl.status) == 0,
46 "status must be first member of adv_data_cmpl");
47static_assert(offsetof(esp_ble_gap_cb_param_t, scan_rsp_data_cmpl.status) == 0,
48 "status must be first member of scan_rsp_data_cmpl");
49static_assert(offsetof(esp_ble_gap_cb_param_t, adv_data_raw_cmpl.status) == 0,
50 "status must be first member of adv_data_raw_cmpl");
51static_assert(offsetof(esp_ble_gap_cb_param_t, adv_start_cmpl.status) == 0,
52 "status must be first member of adv_start_cmpl");
53static_assert(offsetof(esp_ble_gap_cb_param_t, adv_stop_cmpl.status) == 0,
54 "status must be first member of adv_stop_cmpl");
55
56// Compile-time verification for RSSI complete event structure
57static_assert(offsetof(esp_ble_gap_cb_param_t, read_rssi_cmpl.status) == 0,
58 "status must be first member of read_rssi_cmpl");
59static_assert(offsetof(esp_ble_gap_cb_param_t, read_rssi_cmpl.rssi) == sizeof(esp_bt_status_t),
60 "rssi must immediately follow status in read_rssi_cmpl");
61static_assert(offsetof(esp_ble_gap_cb_param_t, read_rssi_cmpl.remote_addr) == sizeof(esp_bt_status_t) + sizeof(int8_t),
62 "remote_addr must follow rssi in read_rssi_cmpl");
63
64// Param struct sizes on ESP32
65static constexpr size_t GATTC_PARAM_SIZE = 28;
66static constexpr size_t GATTS_PARAM_SIZE = 32;
67
68// Maximum size for inline storage of data
69// GATTC: 80 - 28 (param) - 8 (other fields) = 44 bytes for data
70// GATTS: 80 - 32 (param) - 8 (other fields) = 40 bytes for data
71static constexpr size_t GATTC_INLINE_DATA_SIZE = 44;
72static constexpr size_t GATTS_INLINE_DATA_SIZE = 40;
73
74// Verify param struct sizes
75static_assert(sizeof(esp_ble_gattc_cb_param_t) == GATTC_PARAM_SIZE, "GATTC param size unexpected");
76static_assert(sizeof(esp_ble_gatts_cb_param_t) == GATTS_PARAM_SIZE, "GATTS param size unexpected");
77
78// Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop().
79// This class stores each event with minimal memory usage.
80// GAP events (99% of traffic) don't have the heap allocation overhead.
81// GATTC/GATTS events use heap allocation for their param and inline storage for small data.
82//
83// Event flow:
84// 1. ESP-IDF BLE stack calls our static handlers in the BLE task context
85// 2. The handlers create a BLEEvent instance, copying only the data we need
86// 3. The event is pushed to a thread-safe queue
87// 4. In the main loop(), events are popped from the queue and processed
88// 5. The event destructor cleans up any external allocations
89//
90// Thread safety:
91// - GAP events: We copy only the fields we need directly into the union
92// - GATTC/GATTS events: We heap-allocate and copy the entire param struct, ensuring
93// the data remains valid even after the BLE callback returns. The original
94// param pointer from ESP-IDF is only valid during the callback.
95//
96// CRITICAL DESIGN NOTE:
97// The heap allocations for GATTC/GATTS events are REQUIRED for memory safety.
98// DO NOT attempt to optimize by removing these allocations or storing pointers
99// to the original ESP-IDF data. The ESP-IDF callback data has a different lifetime
100// than our event processing, and accessing it after the callback returns would
101// result in use-after-free bugs and crashes.
102class BLEEvent {
103 public:
104 // NOLINTNEXTLINE(readability-identifier-naming)
105 enum ble_event_t : uint8_t {
109 };
110
111 // Type definitions for cleaner method signatures
113 esp_bt_status_t status;
114 };
115
117 esp_bt_status_t status;
118 int8_t rssi;
119 esp_bd_addr_t remote_addr;
120 };
121
122 // Constructor for GAP events - no external allocations needed
123 BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
124 this->type_ = GAP;
125 this->init_gap_data_(e, p);
126 }
127
128 // Constructor for GATTC events - param stored inline, data may use heap
129 // IMPORTANT: We MUST copy the param struct because the pointer from ESP-IDF
130 // is only valid during the callback execution. Since BLE events are processed
131 // asynchronously in the main loop, we store our own copy inline to ensure
132 // the data remains valid until the event is processed.
133 BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
134 this->type_ = GATTC;
135 this->init_gattc_data_(e, i, p);
136 }
137
138 // Constructor for GATTS events - param stored inline, data may use heap
139 // IMPORTANT: We MUST copy the param struct because the pointer from ESP-IDF
140 // is only valid during the callback execution. Since BLE events are processed
141 // asynchronously in the main loop, we store our own copy inline to ensure
142 // the data remains valid until the event is processed.
143 BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
144 this->type_ = GATTS;
145 this->init_gatts_data_(e, i, p);
146 }
147
148 // Destructor to clean up heap allocations
149 ~BLEEvent() { this->release(); }
150
151 // Default constructor for pre-allocation in pool
153
154 // Invoked on return to EventPool - clean up any heap-allocated data
155 void release() {
156 switch (this->type_) {
157 case GAP:
158 // GAP events never have heap allocations
159 break;
160 case GATTC:
161 if (!this->event_.gattc.is_inline && this->event_.gattc.data.heap_data != nullptr) {
162 delete[] this->event_.gattc.data.heap_data;
163 this->event_.gattc.data.heap_data = nullptr;
164 }
165 break;
166 case GATTS:
167 if (!this->event_.gatts.is_inline && this->event_.gatts.data.heap_data != nullptr) {
168 delete[] this->event_.gatts.data.heap_data;
169 this->event_.gatts.data.heap_data = nullptr;
170 }
171 break;
172 }
173 }
174
175 // Load new event data for reuse (replaces previous event data)
176 // Note: release() is NOT called here because EventPool::release() already
177 // calls event->release() before returning to the free list. Every event
178 // from allocate() is already in a clean state.
179 void load_gap_event(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
180 this->type_ = GAP;
181 this->init_gap_data_(e, p);
182 }
183
184 void load_gattc_event(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
185 this->type_ = GATTC;
186 this->init_gattc_data_(e, i, p);
187 }
188
189 void load_gatts_event(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
190 this->type_ = GATTS;
191 this->init_gatts_data_(e, i, p);
192 }
193
194 // Disable copy to prevent double-delete
195 BLEEvent(const BLEEvent &) = delete;
196 BLEEvent &operator=(const BLEEvent &) = delete;
197
198 union {
199 // NOLINTNEXTLINE(readability-identifier-naming)
200 struct gap_event {
201 esp_gap_ble_cb_event_t gap_event;
202 union {
203 BLEScanResult scan_result; // 73 bytes - Used by: esp32_ble_tracker
204 // This matches ESP-IDF's scan complete event structures
205 // All three (scan_param_cmpl, scan_start_cmpl, scan_stop_cmpl) have identical layout
206 // Used by: esp32_ble_tracker
208 // Advertising complete events all have same structure
209 // Used by: esp32_ble_beacon, esp32_ble server components
210 // ADV_DATA_SET, SCAN_RSP_DATA_SET, ADV_DATA_RAW_SET, ADV_START, ADV_STOP
212 // RSSI complete event
213 // Used by: ble_client (ble_rssi_sensor component)
215 // Security events - we store the full security union
216 // Used by: ble_client (automation), bluetooth_proxy, esp32_ble_client
217 esp_ble_sec_t security; // Variable size, but fits within scan_result size
218 };
219 } gap; // 80 bytes total
220
221 // NOLINTNEXTLINE(readability-identifier-naming)
222 struct gattc_event {
223 esp_ble_gattc_cb_param_t gattc_param; // Stored inline (28 bytes)
224 esp_gattc_cb_event_t gattc_event; // 4 bytes
225 union {
226 uint8_t *heap_data; // 4 bytes when heap-allocated
227 uint8_t inline_data[GATTC_INLINE_DATA_SIZE]; // 44 bytes when stored inline
228 } data; // 44 bytes total
229 uint16_t data_len; // 2 bytes
230 esp_gatt_if_t gattc_if; // 1 byte
231 bool is_inline; // 1 byte - true when data is stored inline
232 } gattc; // Total: 80 bytes
233
234 // NOLINTNEXTLINE(readability-identifier-naming)
235 struct gatts_event {
236 esp_ble_gatts_cb_param_t gatts_param; // Stored inline (32 bytes)
237 esp_gatts_cb_event_t gatts_event; // 4 bytes
238 union {
239 uint8_t *heap_data; // 4 bytes when heap-allocated
240 uint8_t inline_data[GATTS_INLINE_DATA_SIZE]; // 40 bytes when stored inline
241 } data; // 40 bytes total
242 uint16_t data_len; // 2 bytes
243 esp_gatt_if_t gatts_if; // 1 byte
244 bool is_inline; // 1 byte - true when data is stored inline
245 } gatts; // Total: 80 bytes
246 } event_; // 80 bytes
247
249
250 // Helper methods to access event data
251 ble_event_t type() const { return type_; }
252 esp_gap_ble_cb_event_t gap_event_type() const { return event_.gap.gap_event; }
253 const BLEScanResult &scan_result() const { return event_.gap.scan_result; }
254 esp_bt_status_t scan_complete_status() const { return event_.gap.scan_complete.status; }
255 esp_bt_status_t adv_complete_status() const { return event_.gap.adv_complete.status; }
256 const RSSICompleteData &read_rssi_complete() const { return event_.gap.read_rssi_complete; }
257 const esp_ble_sec_t &security() const { return event_.gap.security; }
258
259 private:
260 // Helper to copy data with inline storage optimization
261 template<typename EventStruct, size_t InlineSize>
262 void copy_data_with_inline_storage_(EventStruct &event, const uint8_t *src_data, uint16_t len,
263 uint8_t **param_value_ptr) {
264 event.data_len = len;
265 if (len > 0) {
266 if (len <= InlineSize) {
267 event.is_inline = true;
268 memcpy(event.data.inline_data, src_data, len);
269 *param_value_ptr = event.data.inline_data;
270 } else {
271 event.is_inline = false;
272 event.data.heap_data = new uint8_t[len];
273 memcpy(event.data.heap_data, src_data, len);
274 *param_value_ptr = event.data.heap_data;
275 }
276 } else {
277 event.is_inline = false;
278 event.data.heap_data = nullptr;
279 *param_value_ptr = nullptr;
280 }
281 }
282
283 // Initialize GAP event data
284 void init_gap_data_(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
285 this->event_.gap.gap_event = e;
286
287 if (p == nullptr) {
288 return; // Invalid event, but we can't log in header file
289 }
290
291 // Copy data based on event type
292 switch (e) {
293 case ESP_GAP_BLE_SCAN_RESULT_EVT:
294 memcpy(this->event_.gap.scan_result.bda, p->scan_rst.bda, sizeof(esp_bd_addr_t));
295 this->event_.gap.scan_result.ble_addr_type = p->scan_rst.ble_addr_type;
296 this->event_.gap.scan_result.rssi = p->scan_rst.rssi;
297 this->event_.gap.scan_result.adv_data_len = p->scan_rst.adv_data_len;
298 this->event_.gap.scan_result.scan_rsp_len = p->scan_rst.scan_rsp_len;
299 this->event_.gap.scan_result.search_evt = p->scan_rst.search_evt;
300 memcpy(this->event_.gap.scan_result.ble_adv, p->scan_rst.ble_adv,
301 ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX);
302 break;
303
304 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
305 this->event_.gap.scan_complete.status = p->scan_param_cmpl.status;
306 break;
307
308 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
309 this->event_.gap.scan_complete.status = p->scan_start_cmpl.status;
310 break;
311
312 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
313 this->event_.gap.scan_complete.status = p->scan_stop_cmpl.status;
314 break;
315
316 // Advertising complete events - all have same structure with just status
317 // Used by: esp32_ble_beacon, esp32_ble server components
318 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
319 this->event_.gap.adv_complete.status = p->adv_data_cmpl.status;
320 break;
321 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
322 this->event_.gap.adv_complete.status = p->scan_rsp_data_cmpl.status;
323 break;
324 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: // Used by: esp32_ble_beacon
325 this->event_.gap.adv_complete.status = p->adv_data_raw_cmpl.status;
326 break;
327 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: // Used by: esp32_ble_beacon
328 this->event_.gap.adv_complete.status = p->adv_start_cmpl.status;
329 break;
330 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: // Used by: esp32_ble_beacon
331 this->event_.gap.adv_complete.status = p->adv_stop_cmpl.status;
332 break;
333
334 // RSSI complete event
335 // Used by: ble_client (ble_rssi_sensor)
336 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
337 this->event_.gap.read_rssi_complete.status = p->read_rssi_cmpl.status;
338 this->event_.gap.read_rssi_complete.rssi = p->read_rssi_cmpl.rssi;
339 memcpy(this->event_.gap.read_rssi_complete.remote_addr, p->read_rssi_cmpl.remote_addr, sizeof(esp_bd_addr_t));
340 break;
341
342 // Security events - copy the entire security union
343 // Used by: ble_client, bluetooth_proxy, esp32_ble_client
344 case ESP_GAP_BLE_AUTH_CMPL_EVT: // Used by: bluetooth_proxy, esp32_ble_client
345 case ESP_GAP_BLE_SEC_REQ_EVT: // Used by: esp32_ble_client
346 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: // Used by: ble_client automation
347 case ESP_GAP_BLE_PASSKEY_REQ_EVT: // Used by: ble_client automation
348 case ESP_GAP_BLE_NC_REQ_EVT: // Used by: ble_client automation
349 memcpy(&this->event_.gap.security, &p->ble_security, sizeof(esp_ble_sec_t));
350 break;
351
352 default:
353 // We only store data for GAP events that components currently use
354 // Unknown events still get queued and logged in ble.cpp:375 as
355 // "Unhandled GAP event type in loop" - this helps identify new events
356 // that components might need in the future
357 break;
358 }
359 }
360
361 // Initialize GATTC event data
362 void init_gattc_data_(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
363 this->event_.gattc.gattc_event = e;
364 this->event_.gattc.gattc_if = i;
365
366 if (p == nullptr) {
367 // Zero out the param struct when null
368 memset(&this->event_.gattc.gattc_param, 0, sizeof(this->event_.gattc.gattc_param));
369 this->event_.gattc.is_inline = false;
370 this->event_.gattc.data.heap_data = nullptr;
371 this->event_.gattc.data_len = 0;
372 return; // Invalid event, but we can't log in header file
373 }
374
375 // Copy param struct inline (no heap allocation!)
376 // GATTC/GATTS events are rare (<1% of events) but we can still store them inline
377 // along with small data payloads, eliminating all heap allocations for typical BLE operations
378 // CRITICAL: This copy is REQUIRED for memory safety - the ESP-IDF param pointer
379 // is only valid during the callback and will be reused/freed after we return
380 this->event_.gattc.gattc_param = *p;
381
382 // Copy data for events that need it
383 // The param struct contains pointers (e.g., notify.value) that point to temporary buffers.
384 // We must copy this data to ensure it remains valid when the event is processed later.
385 switch (e) {
386 case ESP_GATTC_NOTIFY_EVT:
387 copy_data_with_inline_storage_<decltype(this->event_.gattc), GATTC_INLINE_DATA_SIZE>(
388 this->event_.gattc, p->notify.value, p->notify.value_len, &this->event_.gattc.gattc_param.notify.value);
389 break;
390 case ESP_GATTC_READ_CHAR_EVT:
391 case ESP_GATTC_READ_DESCR_EVT:
392 copy_data_with_inline_storage_<decltype(this->event_.gattc), GATTC_INLINE_DATA_SIZE>(
393 this->event_.gattc, p->read.value, p->read.value_len, &this->event_.gattc.gattc_param.read.value);
394 break;
395 default:
396 this->event_.gattc.is_inline = false;
397 this->event_.gattc.data.heap_data = nullptr;
398 this->event_.gattc.data_len = 0;
399 break;
400 }
401 }
402
403 // Initialize GATTS event data
404 void init_gatts_data_(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
405 this->event_.gatts.gatts_event = e;
406 this->event_.gatts.gatts_if = i;
407
408 if (p == nullptr) {
409 // Zero out the param struct when null
410 memset(&this->event_.gatts.gatts_param, 0, sizeof(this->event_.gatts.gatts_param));
411 this->event_.gatts.is_inline = false;
412 this->event_.gatts.data.heap_data = nullptr;
413 this->event_.gatts.data_len = 0;
414 return; // Invalid event, but we can't log in header file
415 }
416
417 // Copy param struct inline (no heap allocation!)
418 // GATTC/GATTS events are rare (<1% of events) but we can still store them inline
419 // along with small data payloads, eliminating all heap allocations for typical BLE operations
420 // CRITICAL: This copy is REQUIRED for memory safety - the ESP-IDF param pointer
421 // is only valid during the callback and will be reused/freed after we return
422 this->event_.gatts.gatts_param = *p;
423
424 // Copy data for events that need it
425 // The param struct contains pointers (e.g., write.value) that point to temporary buffers.
426 // We must copy this data to ensure it remains valid when the event is processed later.
427 switch (e) {
428 case ESP_GATTS_WRITE_EVT:
429 copy_data_with_inline_storage_<decltype(this->event_.gatts), GATTS_INLINE_DATA_SIZE>(
430 this->event_.gatts, p->write.value, p->write.len, &this->event_.gatts.gatts_param.write.value);
431 break;
432 default:
433 this->event_.gatts.is_inline = false;
434 this->event_.gatts.data.heap_data = nullptr;
435 this->event_.gatts.data_len = 0;
436 break;
437 }
438 }
439};
440
441// Verify the gap_event struct hasn't grown beyond expected size
442// The gap member in the union should be 80 bytes (including the gap_event enum)
443static_assert(sizeof(decltype(((BLEEvent *) nullptr)->event_.gap)) <= 80, "gap_event struct has grown beyond 80 bytes");
444
445// Verify GATTC and GATTS structs don't exceed GAP struct size
446// This ensures the union size is determined by GAP (the most common event type)
447static_assert(sizeof(decltype(((BLEEvent *) nullptr)->event_.gattc)) <=
448 sizeof(decltype(((BLEEvent *) nullptr)->event_.gap)),
449 "gattc_event struct exceeds gap_event size - union size would increase");
450static_assert(sizeof(decltype(((BLEEvent *) nullptr)->event_.gatts)) <=
451 sizeof(decltype(((BLEEvent *) nullptr)->event_.gap)),
452 "gatts_event struct exceeds gap_event size - union size would increase");
453
454// Verify esp_ble_sec_t fits within our union
455static_assert(sizeof(esp_ble_sec_t) <= 73, "esp_ble_sec_t is larger than BLEScanResult");
456
457// BLEEvent total size: 84 bytes (80 byte union + 1 byte type + 3 bytes padding)
458
459} // namespace esphome::esp32_ble
460
461#endif
union esphome::esp32_ble::BLEEvent::@78 event_
BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p)
Definition ble_event.h:133
struct esphome::esp32_ble::BLEEvent::@78::gatts_event gatts
BLEEvent(const BLEEvent &)=delete
esp_bt_status_t adv_complete_status() const
Definition ble_event.h:255
StatusOnlyData scan_complete
Definition ble_event.h:207
const esp_ble_sec_t & security() const
Definition ble_event.h:257
struct esphome::esp32_ble::BLEEvent::@78::gap_event gap
struct esphome::esp32_ble::BLEEvent::@78::gattc_event gattc
void load_gap_event(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p)
Definition ble_event.h:179
esp_bt_status_t scan_complete_status() const
Definition ble_event.h:254
ble_event_t type() const
Definition ble_event.h:251
BLEEvent & operator=(const BLEEvent &)=delete
esp_gatts_cb_event_t gatts_event
Definition ble_event.h:237
esp_ble_gattc_cb_param_t gattc_param
Definition ble_event.h:223
esp_gap_ble_cb_event_t gap_event
Definition ble_event.h:201
esp_gattc_cb_event_t gattc_event
Definition ble_event.h:224
esp_ble_gatts_cb_param_t gatts_param
Definition ble_event.h:236
BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p)
Definition ble_event.h:123
uint8_t inline_data[GATTC_INLINE_DATA_SIZE]
Definition ble_event.h:227
BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p)
Definition ble_event.h:143
esp_gap_ble_cb_event_t gap_event_type() const
Definition ble_event.h:252
void load_gatts_event(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p)
Definition ble_event.h:189
void load_gattc_event(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p)
Definition ble_event.h:184
StatusOnlyData adv_complete
Definition ble_event.h:211
RSSICompleteData read_rssi_complete
Definition ble_event.h:214
const RSSICompleteData & read_rssi_complete() const
Definition ble_event.h:256
const BLEScanResult & scan_result() const
Definition ble_event.h:253
union esphome::esp32_ble::BLEEvent::@78::gattc_event::@81 data
std::string size_t len
Definition helpers.h:892