ESPHome 2025.10.2
Loading...
Searching...
No Matches
ble.cpp
Go to the documentation of this file.
1#include "ble.h"
2
3#ifdef USE_ESP32
4
7#include "esphome/core/log.h"
8
9#include <esp_bt.h>
10#include <esp_bt_device.h>
11#include <esp_bt_main.h>
12#include <esp_gap_ble_api.h>
13#include <freertos/FreeRTOS.h>
14#include <freertos/FreeRTOSConfig.h>
15#include <freertos/task.h>
16#include <nvs_flash.h>
17
18#ifdef USE_ARDUINO
19#include <esp32-hal-bt.h>
20#endif
21
23
24static const char *const TAG = "esp32_ble";
25
27 global_ble = this;
28 if (!ble_pre_setup_()) {
29 ESP_LOGE(TAG, "BLE could not be prepared for configuration");
30 this->mark_failed();
31 return;
32 }
33
34 this->state_ = BLE_COMPONENT_STATE_DISABLED;
35 if (this->enable_on_boot_) {
36 this->enable();
37 }
38}
39
41 if (this->state_ != BLE_COMPONENT_STATE_DISABLED)
42 return;
43
44 this->state_ = BLE_COMPONENT_STATE_ENABLE;
45}
46
48 if (this->state_ == BLE_COMPONENT_STATE_DISABLED)
49 return;
50
51 this->state_ = BLE_COMPONENT_STATE_DISABLE;
52}
53
54bool ESP32BLE::is_active() { return this->state_ == BLE_COMPONENT_STATE_ACTIVE; }
55
56#ifdef USE_ESP32_BLE_ADVERTISING
58 this->advertising_init_();
59 if (!this->is_active())
60 return;
61 this->advertising_->start();
62}
63
64void ESP32BLE::advertising_set_service_data(const std::vector<uint8_t> &data) {
65 this->advertising_init_();
66 this->advertising_->set_service_data(data);
67 this->advertising_start();
68}
69
70void ESP32BLE::advertising_set_manufacturer_data(const std::vector<uint8_t> &data) {
71 this->advertising_init_();
72 this->advertising_->set_manufacturer_data(data);
73 this->advertising_start();
74}
75
76void ESP32BLE::advertising_set_service_data_and_name(std::span<const uint8_t> data, bool include_name) {
77 // This method atomically updates both service data and device name inclusion in BLE advertising.
78 // When include_name is true, the device name is included in the advertising packet making it
79 // visible to passive BLE scanners. When false, the name is only visible in scan response
80 // (requires active scanning). This atomic operation ensures we only restart advertising once
81 // when changing both properties, avoiding the brief gap that would occur with separate calls.
82
83 this->advertising_init_();
84
85 if (include_name) {
86 // When including name, clear service data first to avoid packet overflow
87 this->advertising_->set_service_data(std::span<const uint8_t>{});
88 this->advertising_->set_include_name(true);
89 } else {
90 // When including service data, clear name first to avoid packet overflow
91 this->advertising_->set_include_name(false);
92 this->advertising_->set_service_data(data);
93 }
94
95 this->advertising_start();
96}
97
98void ESP32BLE::advertising_register_raw_advertisement_callback(std::function<void(bool)> &&callback) {
99 this->advertising_init_();
100 this->advertising_->register_raw_advertisement_callback(std::move(callback));
101}
102
104 this->advertising_init_();
105 this->advertising_->add_service_uuid(uuid);
106 this->advertising_start();
107}
108
110 this->advertising_init_();
111 this->advertising_->remove_service_uuid(uuid);
112 this->advertising_start();
113}
114#endif
115
117 esp_err_t err = nvs_flash_init();
118 if (err != ESP_OK) {
119 ESP_LOGE(TAG, "nvs_flash_init failed: %d", err);
120 return false;
121 }
122 return true;
123}
124
125#ifdef USE_ESP32_BLE_ADVERTISING
127 if (this->advertising_ != nullptr)
128 return;
129 this->advertising_ = new BLEAdvertising(this->advertising_cycle_time_); // NOLINT(cppcoreguidelines-owning-memory)
130
131 this->advertising_->set_scan_response(true);
132 this->advertising_->set_min_preferred_interval(0x06);
133 this->advertising_->set_appearance(this->appearance_);
134}
135#endif
136
138 esp_err_t err;
139#ifdef USE_ARDUINO
140 if (!btStart()) {
141 ESP_LOGE(TAG, "btStart failed: %d", esp_bt_controller_get_status());
142 return false;
143 }
144#else
145 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
146 // start bt controller
147 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) {
148 esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
149 err = esp_bt_controller_init(&cfg);
150 if (err != ESP_OK) {
151 ESP_LOGE(TAG, "esp_bt_controller_init failed: %s", esp_err_to_name(err));
152 return false;
153 }
154 while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE)
155 ;
156 }
157 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
158 err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
159 if (err != ESP_OK) {
160 ESP_LOGE(TAG, "esp_bt_controller_enable failed: %s", esp_err_to_name(err));
161 return false;
162 }
163 }
164 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
165 ESP_LOGE(TAG, "esp bt controller enable failed");
166 return false;
167 }
168 }
169#endif
170
171 esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
172
173 err = esp_bluedroid_init();
174 if (err != ESP_OK) {
175 ESP_LOGE(TAG, "esp_bluedroid_init failed: %d", err);
176 return false;
177 }
178 err = esp_bluedroid_enable();
179 if (err != ESP_OK) {
180 ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", err);
181 return false;
182 }
183
184 if (!this->gap_event_handlers_.empty()) {
185 err = esp_ble_gap_register_callback(ESP32BLE::gap_event_handler);
186 if (err != ESP_OK) {
187 ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", err);
188 return false;
189 }
190 }
191
192#ifdef USE_ESP32_BLE_SERVER
193 if (!this->gatts_event_handlers_.empty()) {
194 err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler);
195 if (err != ESP_OK) {
196 ESP_LOGE(TAG, "esp_ble_gatts_register_callback failed: %d", err);
197 return false;
198 }
199 }
200#endif
201
202#ifdef USE_ESP32_BLE_CLIENT
203 if (!this->gattc_event_handlers_.empty()) {
204 err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler);
205 if (err != ESP_OK) {
206 ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err);
207 return false;
208 }
209 }
210#endif
211
212 std::string name;
213 if (this->name_.has_value()) {
214 name = this->name_.value();
216 name += "-";
217 name += get_mac_address().substr(6);
218 }
219 } else {
220 name = App.get_name();
221 if (name.length() > 20) {
223 // Keep first 13 chars and last 7 chars (MAC suffix), remove middle
224 name.erase(13, name.length() - 20);
225 } else {
226 name.resize(20);
227 }
228 }
229 }
230
231 err = esp_ble_gap_set_device_name(name.c_str());
232 if (err != ESP_OK) {
233 ESP_LOGE(TAG, "esp_ble_gap_set_device_name failed: %d", err);
234 return false;
235 }
236
237 err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_), sizeof(uint8_t));
238 if (err != ESP_OK) {
239 ESP_LOGE(TAG, "esp_ble_gap_set_security_param failed: %d", err);
240 return false;
241 }
242
243 // BLE takes some time to be fully set up, 200ms should be more than enough
244 delay(200); // NOLINT
245
246 return true;
247}
248
250 esp_err_t err = esp_bluedroid_disable();
251 if (err != ESP_OK) {
252 ESP_LOGE(TAG, "esp_bluedroid_disable failed: %d", err);
253 return false;
254 }
255 err = esp_bluedroid_deinit();
256 if (err != ESP_OK) {
257 ESP_LOGE(TAG, "esp_bluedroid_deinit failed: %d", err);
258 return false;
259 }
260
261#ifdef USE_ARDUINO
262 if (!btStop()) {
263 ESP_LOGE(TAG, "btStop failed: %d", esp_bt_controller_get_status());
264 return false;
265 }
266#else
267 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
268 // stop bt controller
269 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED) {
270 err = esp_bt_controller_disable();
271 if (err != ESP_OK) {
272 ESP_LOGE(TAG, "esp_bt_controller_disable failed: %s", esp_err_to_name(err));
273 return false;
274 }
275 while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED)
276 ;
277 }
278 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
279 err = esp_bt_controller_deinit();
280 if (err != ESP_OK) {
281 ESP_LOGE(TAG, "esp_bt_controller_deinit failed: %s", esp_err_to_name(err));
282 return false;
283 }
284 }
285 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
286 ESP_LOGE(TAG, "esp bt controller disable failed");
287 return false;
288 }
289 }
290#endif
291 return true;
292}
293
295 switch (this->state_) {
298 return;
300 ESP_LOGD(TAG, "Disabling");
301
302 for (auto *ble_event_handler : this->ble_status_event_handlers_) {
303 ble_event_handler->ble_before_disabled_event_handler();
304 }
305
306 if (!ble_dismantle_()) {
307 ESP_LOGE(TAG, "Could not be dismantled");
308 this->mark_failed();
309 return;
310 }
311 this->state_ = BLE_COMPONENT_STATE_DISABLED;
312 return;
313 }
315 ESP_LOGD(TAG, "Enabling");
316 this->state_ = BLE_COMPONENT_STATE_OFF;
317
318 if (!ble_setup_()) {
319 ESP_LOGE(TAG, "Could not be set up");
320 this->mark_failed();
321 return;
322 }
323
324 this->state_ = BLE_COMPONENT_STATE_ACTIVE;
325 return;
326 }
328 break;
329 }
330
331 BLEEvent *ble_event = this->ble_events_.pop();
332 while (ble_event != nullptr) {
333 switch (ble_event->type_) {
334#ifdef USE_ESP32_BLE_SERVER
335 case BLEEvent::GATTS: {
336 esp_gatts_cb_event_t event = ble_event->event_.gatts.gatts_event;
337 esp_gatt_if_t gatts_if = ble_event->event_.gatts.gatts_if;
338 esp_ble_gatts_cb_param_t *param = &ble_event->event_.gatts.gatts_param;
339 ESP_LOGV(TAG, "gatts_event [esp_gatt_if: %d] - %d", gatts_if, event);
340 for (auto *gatts_handler : this->gatts_event_handlers_) {
341 gatts_handler->gatts_event_handler(event, gatts_if, param);
342 }
343 break;
344 }
345#endif
346#ifdef USE_ESP32_BLE_CLIENT
347 case BLEEvent::GATTC: {
348 esp_gattc_cb_event_t event = ble_event->event_.gattc.gattc_event;
349 esp_gatt_if_t gattc_if = ble_event->event_.gattc.gattc_if;
350 esp_ble_gattc_cb_param_t *param = &ble_event->event_.gattc.gattc_param;
351 ESP_LOGV(TAG, "gattc_event [esp_gatt_if: %d] - %d", gattc_if, event);
352 for (auto *gattc_handler : this->gattc_event_handlers_) {
353 gattc_handler->gattc_event_handler(event, gattc_if, param);
354 }
355 break;
356 }
357#endif
358 case BLEEvent::GAP: {
359 esp_gap_ble_cb_event_t gap_event = ble_event->event_.gap.gap_event;
360 switch (gap_event) {
361 case ESP_GAP_BLE_SCAN_RESULT_EVT:
362 // Use the new scan event handler - no memcpy!
363 for (auto *scan_handler : this->gap_scan_event_handlers_) {
364 scan_handler->gap_scan_event_handler(ble_event->scan_result());
365 }
366 break;
367
368 // Scan complete events
369 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
370 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
371 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
372 // All three scan complete events have the same structure with just status
373 // The scan_complete struct matches ESP-IDF's layout exactly, so this reinterpret_cast is safe
374 // This is verified at compile-time by static_assert checks in ble_event.h
375 // The struct already contains our copy of the status (copied in BLEEvent constructor)
376 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
377 for (auto *gap_handler : this->gap_event_handlers_) {
378 gap_handler->gap_event_handler(
379 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.scan_complete));
380 }
381 break;
382
383 // Advertising complete events
384 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
385 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
386 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
387 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
388 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
389 // All advertising complete events have the same structure with just status
390 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
391 for (auto *gap_handler : this->gap_event_handlers_) {
392 gap_handler->gap_event_handler(
393 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.adv_complete));
394 }
395 break;
396
397 // RSSI complete event
398 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
399 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
400 for (auto *gap_handler : this->gap_event_handlers_) {
401 gap_handler->gap_event_handler(
402 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.read_rssi_complete));
403 }
404 break;
405
406 // Security events
407 case ESP_GAP_BLE_AUTH_CMPL_EVT:
408 case ESP_GAP_BLE_SEC_REQ_EVT:
409 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:
410 case ESP_GAP_BLE_PASSKEY_REQ_EVT:
411 case ESP_GAP_BLE_NC_REQ_EVT:
412 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
413 for (auto *gap_handler : this->gap_event_handlers_) {
414 gap_handler->gap_event_handler(
415 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.security));
416 }
417 break;
418
419 default:
420 // Unknown/unhandled event
421 ESP_LOGW(TAG, "Unhandled GAP event type in loop: %d", gap_event);
422 break;
423 }
424 break;
425 }
426 default:
427 break;
428 }
429 // Return the event to the pool
430 this->ble_event_pool_.release(ble_event);
431 ble_event = this->ble_events_.pop();
432 }
433#ifdef USE_ESP32_BLE_ADVERTISING
434 if (this->advertising_ != nullptr) {
435 this->advertising_->loop();
436 }
437#endif
438
439 // Log dropped events periodically
440 uint16_t dropped = this->ble_events_.get_and_reset_dropped_count();
441 if (dropped > 0) {
442 ESP_LOGW(TAG, "Dropped %u BLE events due to buffer overflow", dropped);
443 }
444}
445
446// Helper function to load new event data based on type
447void load_ble_event(BLEEvent *event, esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
448 event->load_gap_event(e, p);
449}
450
451#ifdef USE_ESP32_BLE_CLIENT
452void load_ble_event(BLEEvent *event, esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
453 event->load_gattc_event(e, i, p);
454}
455#endif
456
457#ifdef USE_ESP32_BLE_SERVER
458void load_ble_event(BLEEvent *event, esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
459 event->load_gatts_event(e, i, p);
460}
461#endif
462
463template<typename... Args> void enqueue_ble_event(Args... args) {
464 // Allocate an event from the pool
465 BLEEvent *event = global_ble->ble_event_pool_.allocate();
466 if (event == nullptr) {
467 // No events available - queue is full or we're out of memory
468 global_ble->ble_events_.increment_dropped_count();
469 return;
470 }
471
472 // Load new event data (replaces previous event)
473 load_ble_event(event, args...);
474
475 // Push the event to the queue
476 global_ble->ble_events_.push(event);
477 // Push always succeeds because we're the only producer and the pool ensures we never exceed queue size
478}
479
480// Explicit template instantiations for the friend function
481template void enqueue_ble_event(esp_gap_ble_cb_event_t, esp_ble_gap_cb_param_t *);
482#ifdef USE_ESP32_BLE_SERVER
483template void enqueue_ble_event(esp_gatts_cb_event_t, esp_gatt_if_t, esp_ble_gatts_cb_param_t *);
484#endif
485#ifdef USE_ESP32_BLE_CLIENT
486template void enqueue_ble_event(esp_gattc_cb_event_t, esp_gatt_if_t, esp_ble_gattc_cb_param_t *);
487#endif
488
489void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
490 switch (event) {
491 // Queue GAP events that components need to handle
492 // Scanning events - used by esp32_ble_tracker
493 case ESP_GAP_BLE_SCAN_RESULT_EVT:
494 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
495 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
496 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
497 // Advertising events - used by esp32_ble_beacon and esp32_ble server
498 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
499 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
500 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
501 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
502 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
503 // Connection events - used by ble_client
504 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
505 // Security events - used by ble_client and bluetooth_proxy
506 case ESP_GAP_BLE_AUTH_CMPL_EVT:
507 case ESP_GAP_BLE_SEC_REQ_EVT:
508 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:
509 case ESP_GAP_BLE_PASSKEY_REQ_EVT:
510 case ESP_GAP_BLE_NC_REQ_EVT:
511 enqueue_ble_event(event, param);
512 return;
513
514 // Ignore these GAP events as they are not relevant for our use case
515 case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
516 case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT:
517 case ESP_GAP_BLE_PHY_UPDATE_COMPLETE_EVT: // BLE 5.0 PHY update complete
518 case ESP_GAP_BLE_CHANNEL_SELECT_ALGORITHM_EVT: // BLE 5.0 channel selection algorithm
519 return;
520
521 default:
522 break;
523 }
524 ESP_LOGW(TAG, "Ignoring unexpected GAP event type: %d", event);
525}
526
527#ifdef USE_ESP32_BLE_SERVER
528void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
529 esp_ble_gatts_cb_param_t *param) {
530 enqueue_ble_event(event, gatts_if, param);
531}
532#endif
533
534#ifdef USE_ESP32_BLE_CLIENT
535void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
536 esp_ble_gattc_cb_param_t *param) {
537 enqueue_ble_event(event, gattc_if, param);
538}
539#endif
540
542
544 const uint8_t *mac_address = esp_bt_dev_get_address();
545 if (mac_address) {
546 const char *io_capability_s;
547 switch (this->io_cap_) {
548 case ESP_IO_CAP_OUT:
549 io_capability_s = "display_only";
550 break;
551 case ESP_IO_CAP_IO:
552 io_capability_s = "display_yes_no";
553 break;
554 case ESP_IO_CAP_IN:
555 io_capability_s = "keyboard_only";
556 break;
557 case ESP_IO_CAP_NONE:
558 io_capability_s = "none";
559 break;
560 case ESP_IO_CAP_KBDISP:
561 io_capability_s = "keyboard_display";
562 break;
563 default:
564 io_capability_s = "invalid";
565 break;
566 }
567 ESP_LOGCONFIG(TAG,
568 "BLE:\n"
569 " MAC address: %s\n"
570 " IO Capability: %s",
571 format_mac_address_pretty(mac_address).c_str(), io_capability_s);
572 } else {
573 ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled");
574 }
575}
576
577uint64_t ble_addr_to_uint64(const esp_bd_addr_t address) {
578 uint64_t u = 0;
579 u |= uint64_t(address[0] & 0xFF) << 40;
580 u |= uint64_t(address[1] & 0xFF) << 32;
581 u |= uint64_t(address[2] & 0xFF) << 24;
582 u |= uint64_t(address[3] & 0xFF) << 16;
583 u |= uint64_t(address[4] & 0xFF) << 8;
584 u |= uint64_t(address[5] & 0xFF) << 0;
585 return u;
586}
587
588ESP32BLE *global_ble = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
589
590} // namespace esphome::esp32_ble
591
592#endif
uint8_t address
Definition bl0906.h:4
bool is_name_add_mac_suffix_enabled() const
const std::string & get_name() const
Get the name of this Application set by pre_setup().
virtual void mark_failed()
Mark this component as failed.
void set_manufacturer_data(const std::vector< uint8_t > &data)
void set_scan_response(bool scan_response)
void set_include_name(bool include_name)
void set_min_preferred_interval(uint16_t interval)
void set_service_data(const std::vector< uint8_t > &data)
void register_raw_advertisement_callback(std::function< void(bool)> &&callback)
void set_appearance(uint16_t appearance)
struct esphome::esp32_ble::BLEEvent::@73::gatts_event gatts
union esphome::esp32_ble::BLEEvent::@73 event_
struct esphome::esp32_ble::BLEEvent::@73::gattc_event gattc
struct esphome::esp32_ble::BLEEvent::@73::gap_event gap
void advertising_set_manufacturer_data(const std::vector< uint8_t > &data)
Definition ble.cpp:70
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
Definition ble.cpp:489
static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
Definition ble.cpp:535
friend void enqueue_ble_event(Args... args)
Definition ble.cpp:463
void advertising_register_raw_advertisement_callback(std::function< void(bool)> &&callback)
Definition ble.cpp:98
void advertising_set_service_data_and_name(std::span< const uint8_t > data, bool include_name)
Definition ble.cpp:76
void advertising_add_service_uuid(ESPBTUUID uuid)
Definition ble.cpp:103
void dump_config() override
Definition ble.cpp:543
void loop() override
Definition ble.cpp:294
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
Definition ble.cpp:528
void advertising_set_service_data(const std::vector< uint8_t > &data)
Definition ble.cpp:64
float get_setup_priority() const override
Definition ble.cpp:541
void setup() override
Definition ble.cpp:26
void advertising_remove_service_uuid(ESPBTUUID uuid)
Definition ble.cpp:109
bool has_value() const
Definition optional.h:92
value_type const & value() const
Definition optional.h:94
ESP32BLE * global_ble
Definition ble.cpp:588
void load_ble_event(BLEEvent *event, esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p)
Definition ble.cpp:447
@ BLE_COMPONENT_STATE_DISABLE
BLE should be disabled on next loop.
Definition ble.h:59
@ BLE_COMPONENT_STATE_OFF
Nothing has been initialized yet.
Definition ble.h:57
@ BLE_COMPONENT_STATE_ENABLE
BLE should be enabled on next loop.
Definition ble.h:63
@ BLE_COMPONENT_STATE_DISABLED
BLE is disabled.
Definition ble.h:61
@ BLE_COMPONENT_STATE_ACTIVE
BLE is active.
Definition ble.h:65
uint64_t ble_addr_to_uint64(const esp_bd_addr_t address)
Definition ble.cpp:577
void enqueue_ble_event(Args... args)
Definition ble.cpp:463
std::string format_mac_address_pretty(const uint8_t *mac)
Definition helpers.cpp:258
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:30
std::string get_mac_address()
Get the device MAC address as a string, in lowercase hex notation.
Definition helpers.cpp:608
Application App
Global storage of Application pointer - only one Application can exist.