ESPHome 2025.8.2
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 don't have heap allocations
159 break;
160 case GATTC:
161 // Param is now stored inline, only delete heap data if it was heap-allocated
162 if (!this->event_.gattc.is_inline && this->event_.gattc.data.heap_data != nullptr) {
163 delete[] this->event_.gattc.data.heap_data;
164 }
165 // Clear critical fields to prevent issues if type changes
166 this->event_.gattc.is_inline = false;
167 this->event_.gattc.data.heap_data = nullptr;
168 break;
169 case GATTS:
170 // Param is now stored inline, only delete heap data if it was heap-allocated
171 if (!this->event_.gatts.is_inline && this->event_.gatts.data.heap_data != nullptr) {
172 delete[] this->event_.gatts.data.heap_data;
173 }
174 // Clear critical fields to prevent issues if type changes
175 this->event_.gatts.is_inline = false;
176 this->event_.gatts.data.heap_data = nullptr;
177 break;
178 }
179 }
180
181 // Load new event data for reuse (replaces previous event data)
182 void load_gap_event(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
183 this->release();
184 this->type_ = GAP;
185 this->init_gap_data_(e, p);
186 }
187
188 void load_gattc_event(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
189 this->release();
190 this->type_ = GATTC;
191 this->init_gattc_data_(e, i, p);
192 }
193
194 void load_gatts_event(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
195 this->release();
196 this->type_ = GATTS;
197 this->init_gatts_data_(e, i, p);
198 }
199
200 // Disable copy to prevent double-delete
201 BLEEvent(const BLEEvent &) = delete;
202 BLEEvent &operator=(const BLEEvent &) = delete;
203
204 union {
205 // NOLINTNEXTLINE(readability-identifier-naming)
206 struct gap_event {
207 esp_gap_ble_cb_event_t gap_event;
208 union {
209 BLEScanResult scan_result; // 73 bytes - Used by: esp32_ble_tracker
210 // This matches ESP-IDF's scan complete event structures
211 // All three (scan_param_cmpl, scan_start_cmpl, scan_stop_cmpl) have identical layout
212 // Used by: esp32_ble_tracker
214 // Advertising complete events all have same structure
215 // Used by: esp32_ble_beacon, esp32_ble server components
216 // ADV_DATA_SET, SCAN_RSP_DATA_SET, ADV_DATA_RAW_SET, ADV_START, ADV_STOP
218 // RSSI complete event
219 // Used by: ble_client (ble_rssi_sensor component)
221 // Security events - we store the full security union
222 // Used by: ble_client (automation), bluetooth_proxy, esp32_ble_client
223 esp_ble_sec_t security; // Variable size, but fits within scan_result size
224 };
225 } gap; // 80 bytes total
226
227 // NOLINTNEXTLINE(readability-identifier-naming)
228 struct gattc_event {
229 esp_ble_gattc_cb_param_t gattc_param; // Stored inline (28 bytes)
230 esp_gattc_cb_event_t gattc_event; // 4 bytes
231 union {
232 uint8_t *heap_data; // 4 bytes when heap-allocated
233 uint8_t inline_data[GATTC_INLINE_DATA_SIZE]; // 44 bytes when stored inline
234 } data; // 44 bytes total
235 uint16_t data_len; // 2 bytes
236 esp_gatt_if_t gattc_if; // 1 byte
237 bool is_inline; // 1 byte - true when data is stored inline
238 } gattc; // Total: 80 bytes
239
240 // NOLINTNEXTLINE(readability-identifier-naming)
241 struct gatts_event {
242 esp_ble_gatts_cb_param_t gatts_param; // Stored inline (32 bytes)
243 esp_gatts_cb_event_t gatts_event; // 4 bytes
244 union {
245 uint8_t *heap_data; // 4 bytes when heap-allocated
246 uint8_t inline_data[GATTS_INLINE_DATA_SIZE]; // 40 bytes when stored inline
247 } data; // 40 bytes total
248 uint16_t data_len; // 2 bytes
249 esp_gatt_if_t gatts_if; // 1 byte
250 bool is_inline; // 1 byte - true when data is stored inline
251 } gatts; // Total: 80 bytes
252 } event_; // 80 bytes
253
255
256 // Helper methods to access event data
257 ble_event_t type() const { return type_; }
258 esp_gap_ble_cb_event_t gap_event_type() const { return event_.gap.gap_event; }
259 const BLEScanResult &scan_result() const { return event_.gap.scan_result; }
260 esp_bt_status_t scan_complete_status() const { return event_.gap.scan_complete.status; }
261 esp_bt_status_t adv_complete_status() const { return event_.gap.adv_complete.status; }
262 const RSSICompleteData &read_rssi_complete() const { return event_.gap.read_rssi_complete; }
263 const esp_ble_sec_t &security() const { return event_.gap.security; }
264
265 private:
266 // Helper to copy data with inline storage optimization
267 template<typename EventStruct, size_t InlineSize>
268 void copy_data_with_inline_storage_(EventStruct &event, const uint8_t *src_data, uint16_t len,
269 uint8_t **param_value_ptr) {
270 event.data_len = len;
271 if (len > 0) {
272 if (len <= InlineSize) {
273 event.is_inline = true;
274 memcpy(event.data.inline_data, src_data, len);
275 *param_value_ptr = event.data.inline_data;
276 } else {
277 event.is_inline = false;
278 event.data.heap_data = new uint8_t[len];
279 memcpy(event.data.heap_data, src_data, len);
280 *param_value_ptr = event.data.heap_data;
281 }
282 } else {
283 event.is_inline = false;
284 event.data.heap_data = nullptr;
285 *param_value_ptr = nullptr;
286 }
287 }
288
289 // Initialize GAP event data
290 void init_gap_data_(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
291 this->event_.gap.gap_event = e;
292
293 if (p == nullptr) {
294 return; // Invalid event, but we can't log in header file
295 }
296
297 // Copy data based on event type
298 switch (e) {
299 case ESP_GAP_BLE_SCAN_RESULT_EVT:
300 memcpy(this->event_.gap.scan_result.bda, p->scan_rst.bda, sizeof(esp_bd_addr_t));
301 this->event_.gap.scan_result.ble_addr_type = p->scan_rst.ble_addr_type;
302 this->event_.gap.scan_result.rssi = p->scan_rst.rssi;
303 this->event_.gap.scan_result.adv_data_len = p->scan_rst.adv_data_len;
304 this->event_.gap.scan_result.scan_rsp_len = p->scan_rst.scan_rsp_len;
305 this->event_.gap.scan_result.search_evt = p->scan_rst.search_evt;
306 memcpy(this->event_.gap.scan_result.ble_adv, p->scan_rst.ble_adv,
307 ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX);
308 break;
309
310 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
311 this->event_.gap.scan_complete.status = p->scan_param_cmpl.status;
312 break;
313
314 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
315 this->event_.gap.scan_complete.status = p->scan_start_cmpl.status;
316 break;
317
318 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
319 this->event_.gap.scan_complete.status = p->scan_stop_cmpl.status;
320 break;
321
322 // Advertising complete events - all have same structure with just status
323 // Used by: esp32_ble_beacon, esp32_ble server components
324 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
325 this->event_.gap.adv_complete.status = p->adv_data_cmpl.status;
326 break;
327 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
328 this->event_.gap.adv_complete.status = p->scan_rsp_data_cmpl.status;
329 break;
330 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: // Used by: esp32_ble_beacon
331 this->event_.gap.adv_complete.status = p->adv_data_raw_cmpl.status;
332 break;
333 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: // Used by: esp32_ble_beacon
334 this->event_.gap.adv_complete.status = p->adv_start_cmpl.status;
335 break;
336 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: // Used by: esp32_ble_beacon
337 this->event_.gap.adv_complete.status = p->adv_stop_cmpl.status;
338 break;
339
340 // RSSI complete event
341 // Used by: ble_client (ble_rssi_sensor)
342 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
343 this->event_.gap.read_rssi_complete.status = p->read_rssi_cmpl.status;
344 this->event_.gap.read_rssi_complete.rssi = p->read_rssi_cmpl.rssi;
345 memcpy(this->event_.gap.read_rssi_complete.remote_addr, p->read_rssi_cmpl.remote_addr, sizeof(esp_bd_addr_t));
346 break;
347
348 // Security events - copy the entire security union
349 // Used by: ble_client, bluetooth_proxy, esp32_ble_client
350 case ESP_GAP_BLE_AUTH_CMPL_EVT: // Used by: bluetooth_proxy, esp32_ble_client
351 case ESP_GAP_BLE_SEC_REQ_EVT: // Used by: esp32_ble_client
352 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: // Used by: ble_client automation
353 case ESP_GAP_BLE_PASSKEY_REQ_EVT: // Used by: ble_client automation
354 case ESP_GAP_BLE_NC_REQ_EVT: // Used by: ble_client automation
355 memcpy(&this->event_.gap.security, &p->ble_security, sizeof(esp_ble_sec_t));
356 break;
357
358 default:
359 // We only store data for GAP events that components currently use
360 // Unknown events still get queued and logged in ble.cpp:375 as
361 // "Unhandled GAP event type in loop" - this helps identify new events
362 // that components might need in the future
363 break;
364 }
365 }
366
367 // Initialize GATTC event data
368 void init_gattc_data_(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
369 this->event_.gattc.gattc_event = e;
370 this->event_.gattc.gattc_if = i;
371
372 if (p == nullptr) {
373 // Zero out the param struct when null
374 memset(&this->event_.gattc.gattc_param, 0, sizeof(this->event_.gattc.gattc_param));
375 this->event_.gattc.is_inline = false;
376 this->event_.gattc.data.heap_data = nullptr;
377 this->event_.gattc.data_len = 0;
378 return; // Invalid event, but we can't log in header file
379 }
380
381 // Copy param struct inline (no heap allocation!)
382 // GATTC/GATTS events are rare (<1% of events) but we can still store them inline
383 // along with small data payloads, eliminating all heap allocations for typical BLE operations
384 // CRITICAL: This copy is REQUIRED for memory safety - the ESP-IDF param pointer
385 // is only valid during the callback and will be reused/freed after we return
386 this->event_.gattc.gattc_param = *p;
387
388 // Copy data for events that need it
389 // The param struct contains pointers (e.g., notify.value) that point to temporary buffers.
390 // We must copy this data to ensure it remains valid when the event is processed later.
391 switch (e) {
392 case ESP_GATTC_NOTIFY_EVT:
393 copy_data_with_inline_storage_<decltype(this->event_.gattc), GATTC_INLINE_DATA_SIZE>(
394 this->event_.gattc, p->notify.value, p->notify.value_len, &this->event_.gattc.gattc_param.notify.value);
395 break;
396 case ESP_GATTC_READ_CHAR_EVT:
397 case ESP_GATTC_READ_DESCR_EVT:
398 copy_data_with_inline_storage_<decltype(this->event_.gattc), GATTC_INLINE_DATA_SIZE>(
399 this->event_.gattc, p->read.value, p->read.value_len, &this->event_.gattc.gattc_param.read.value);
400 break;
401 default:
402 this->event_.gattc.is_inline = false;
403 this->event_.gattc.data.heap_data = nullptr;
404 this->event_.gattc.data_len = 0;
405 break;
406 }
407 }
408
409 // Initialize GATTS event data
410 void init_gatts_data_(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
411 this->event_.gatts.gatts_event = e;
412 this->event_.gatts.gatts_if = i;
413
414 if (p == nullptr) {
415 // Zero out the param struct when null
416 memset(&this->event_.gatts.gatts_param, 0, sizeof(this->event_.gatts.gatts_param));
417 this->event_.gatts.is_inline = false;
418 this->event_.gatts.data.heap_data = nullptr;
419 this->event_.gatts.data_len = 0;
420 return; // Invalid event, but we can't log in header file
421 }
422
423 // Copy param struct inline (no heap allocation!)
424 // GATTC/GATTS events are rare (<1% of events) but we can still store them inline
425 // along with small data payloads, eliminating all heap allocations for typical BLE operations
426 // CRITICAL: This copy is REQUIRED for memory safety - the ESP-IDF param pointer
427 // is only valid during the callback and will be reused/freed after we return
428 this->event_.gatts.gatts_param = *p;
429
430 // Copy data for events that need it
431 // The param struct contains pointers (e.g., write.value) that point to temporary buffers.
432 // We must copy this data to ensure it remains valid when the event is processed later.
433 switch (e) {
434 case ESP_GATTS_WRITE_EVT:
435 copy_data_with_inline_storage_<decltype(this->event_.gatts), GATTS_INLINE_DATA_SIZE>(
436 this->event_.gatts, p->write.value, p->write.len, &this->event_.gatts.gatts_param.write.value);
437 break;
438 default:
439 this->event_.gatts.is_inline = false;
440 this->event_.gatts.data.heap_data = nullptr;
441 this->event_.gatts.data_len = 0;
442 break;
443 }
444 }
445};
446
447// Verify the gap_event struct hasn't grown beyond expected size
448// The gap member in the union should be 80 bytes (including the gap_event enum)
449static_assert(sizeof(decltype(((BLEEvent *) nullptr)->event_.gap)) <= 80, "gap_event struct has grown beyond 80 bytes");
450
451// Verify GATTC and GATTS structs don't exceed GAP struct size
452// This ensures the union size is determined by GAP (the most common event type)
453static_assert(sizeof(decltype(((BLEEvent *) nullptr)->event_.gattc)) <=
454 sizeof(decltype(((BLEEvent *) nullptr)->event_.gap)),
455 "gattc_event struct exceeds gap_event size - union size would increase");
456static_assert(sizeof(decltype(((BLEEvent *) nullptr)->event_.gatts)) <=
457 sizeof(decltype(((BLEEvent *) nullptr)->event_.gap)),
458 "gatts_event struct exceeds gap_event size - union size would increase");
459
460// Verify esp_ble_sec_t fits within our union
461static_assert(sizeof(esp_ble_sec_t) <= 73, "esp_ble_sec_t is larger than BLEScanResult");
462
463// BLEEvent total size: 84 bytes (80 byte union + 1 byte type + 3 bytes padding)
464
465} // namespace esphome::esp32_ble
466
467#endif
union esphome::esp32_ble::BLEEvent::@77::gattc_event::@80 data
struct esphome::esp32_ble::BLEEvent::@77::gattc_event gattc
BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p)
Definition ble_event.h:133
BLEEvent(const BLEEvent &)=delete
struct esphome::esp32_ble::BLEEvent::@77::gap_event gap
esp_bt_status_t adv_complete_status() const
Definition ble_event.h:261
StatusOnlyData scan_complete
Definition ble_event.h:213
const esp_ble_sec_t & security() const
Definition ble_event.h:263
void load_gap_event(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p)
Definition ble_event.h:182
esp_bt_status_t scan_complete_status() const
Definition ble_event.h:260
ble_event_t type() const
Definition ble_event.h:257
BLEEvent & operator=(const BLEEvent &)=delete
esp_gatts_cb_event_t gatts_event
Definition ble_event.h:243
esp_ble_gattc_cb_param_t gattc_param
Definition ble_event.h:229
struct esphome::esp32_ble::BLEEvent::@77::gatts_event gatts
esp_gap_ble_cb_event_t gap_event
Definition ble_event.h:207
esp_gattc_cb_event_t gattc_event
Definition ble_event.h:230
esp_ble_gatts_cb_param_t gatts_param
Definition ble_event.h:242
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:233
union esphome::esp32_ble::BLEEvent::@77 event_
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:258
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:194
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:188
StatusOnlyData adv_complete
Definition ble_event.h:217
RSSICompleteData read_rssi_complete
Definition ble_event.h:220
const RSSICompleteData & read_rssi_complete() const
Definition ble_event.h:262
const BLEScanResult & scan_result() const
Definition ble_event.h:259
std::string size_t len
Definition helpers.h:279