ESPHome 2025.10.0-dev
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 += "-" + get_mac_address().substr(6);
217 }
218 } else {
219 name = App.get_name();
220 if (name.length() > 20) {
222 name.erase(name.begin() + 13, name.end() - 7); // Remove characters between 13 and the mac address
223 } else {
224 name = name.substr(0, 20);
225 }
226 }
227 }
228
229 err = esp_ble_gap_set_device_name(name.c_str());
230 if (err != ESP_OK) {
231 ESP_LOGE(TAG, "esp_ble_gap_set_device_name failed: %d", err);
232 return false;
233 }
234
235 err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_), sizeof(uint8_t));
236 if (err != ESP_OK) {
237 ESP_LOGE(TAG, "esp_ble_gap_set_security_param failed: %d", err);
238 return false;
239 }
240
241 // BLE takes some time to be fully set up, 200ms should be more than enough
242 delay(200); // NOLINT
243
244 return true;
245}
246
248 esp_err_t err = esp_bluedroid_disable();
249 if (err != ESP_OK) {
250 ESP_LOGE(TAG, "esp_bluedroid_disable failed: %d", err);
251 return false;
252 }
253 err = esp_bluedroid_deinit();
254 if (err != ESP_OK) {
255 ESP_LOGE(TAG, "esp_bluedroid_deinit failed: %d", err);
256 return false;
257 }
258
259#ifdef USE_ARDUINO
260 if (!btStop()) {
261 ESP_LOGE(TAG, "btStop failed: %d", esp_bt_controller_get_status());
262 return false;
263 }
264#else
265 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
266 // stop bt controller
267 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED) {
268 err = esp_bt_controller_disable();
269 if (err != ESP_OK) {
270 ESP_LOGE(TAG, "esp_bt_controller_disable failed: %s", esp_err_to_name(err));
271 return false;
272 }
273 while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED)
274 ;
275 }
276 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
277 err = esp_bt_controller_deinit();
278 if (err != ESP_OK) {
279 ESP_LOGE(TAG, "esp_bt_controller_deinit failed: %s", esp_err_to_name(err));
280 return false;
281 }
282 }
283 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
284 ESP_LOGE(TAG, "esp bt controller disable failed");
285 return false;
286 }
287 }
288#endif
289 return true;
290}
291
293 switch (this->state_) {
296 return;
298 ESP_LOGD(TAG, "Disabling");
299
300 for (auto *ble_event_handler : this->ble_status_event_handlers_) {
301 ble_event_handler->ble_before_disabled_event_handler();
302 }
303
304 if (!ble_dismantle_()) {
305 ESP_LOGE(TAG, "Could not be dismantled");
306 this->mark_failed();
307 return;
308 }
309 this->state_ = BLE_COMPONENT_STATE_DISABLED;
310 return;
311 }
313 ESP_LOGD(TAG, "Enabling");
314 this->state_ = BLE_COMPONENT_STATE_OFF;
315
316 if (!ble_setup_()) {
317 ESP_LOGE(TAG, "Could not be set up");
318 this->mark_failed();
319 return;
320 }
321
322 this->state_ = BLE_COMPONENT_STATE_ACTIVE;
323 return;
324 }
326 break;
327 }
328
329 BLEEvent *ble_event = this->ble_events_.pop();
330 while (ble_event != nullptr) {
331 switch (ble_event->type_) {
332#ifdef USE_ESP32_BLE_SERVER
333 case BLEEvent::GATTS: {
334 esp_gatts_cb_event_t event = ble_event->event_.gatts.gatts_event;
335 esp_gatt_if_t gatts_if = ble_event->event_.gatts.gatts_if;
336 esp_ble_gatts_cb_param_t *param = &ble_event->event_.gatts.gatts_param;
337 ESP_LOGV(TAG, "gatts_event [esp_gatt_if: %d] - %d", gatts_if, event);
338 for (auto *gatts_handler : this->gatts_event_handlers_) {
339 gatts_handler->gatts_event_handler(event, gatts_if, param);
340 }
341 break;
342 }
343#endif
344#ifdef USE_ESP32_BLE_CLIENT
345 case BLEEvent::GATTC: {
346 esp_gattc_cb_event_t event = ble_event->event_.gattc.gattc_event;
347 esp_gatt_if_t gattc_if = ble_event->event_.gattc.gattc_if;
348 esp_ble_gattc_cb_param_t *param = &ble_event->event_.gattc.gattc_param;
349 ESP_LOGV(TAG, "gattc_event [esp_gatt_if: %d] - %d", gattc_if, event);
350 for (auto *gattc_handler : this->gattc_event_handlers_) {
351 gattc_handler->gattc_event_handler(event, gattc_if, param);
352 }
353 break;
354 }
355#endif
356 case BLEEvent::GAP: {
357 esp_gap_ble_cb_event_t gap_event = ble_event->event_.gap.gap_event;
358 switch (gap_event) {
359 case ESP_GAP_BLE_SCAN_RESULT_EVT:
360 // Use the new scan event handler - no memcpy!
361 for (auto *scan_handler : this->gap_scan_event_handlers_) {
362 scan_handler->gap_scan_event_handler(ble_event->scan_result());
363 }
364 break;
365
366 // Scan complete events
367 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
368 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
369 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
370 // All three scan complete events have the same structure with just status
371 // The scan_complete struct matches ESP-IDF's layout exactly, so this reinterpret_cast is safe
372 // This is verified at compile-time by static_assert checks in ble_event.h
373 // The struct already contains our copy of the status (copied in BLEEvent constructor)
374 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
375 for (auto *gap_handler : this->gap_event_handlers_) {
376 gap_handler->gap_event_handler(
377 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.scan_complete));
378 }
379 break;
380
381 // Advertising complete events
382 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
383 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
384 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
385 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
386 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
387 // All advertising complete events have the same structure with just status
388 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
389 for (auto *gap_handler : this->gap_event_handlers_) {
390 gap_handler->gap_event_handler(
391 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.adv_complete));
392 }
393 break;
394
395 // RSSI complete event
396 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
397 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
398 for (auto *gap_handler : this->gap_event_handlers_) {
399 gap_handler->gap_event_handler(
400 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.read_rssi_complete));
401 }
402 break;
403
404 // Security events
405 case ESP_GAP_BLE_AUTH_CMPL_EVT:
406 case ESP_GAP_BLE_SEC_REQ_EVT:
407 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:
408 case ESP_GAP_BLE_PASSKEY_REQ_EVT:
409 case ESP_GAP_BLE_NC_REQ_EVT:
410 ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
411 for (auto *gap_handler : this->gap_event_handlers_) {
412 gap_handler->gap_event_handler(
413 gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.security));
414 }
415 break;
416
417 default:
418 // Unknown/unhandled event
419 ESP_LOGW(TAG, "Unhandled GAP event type in loop: %d", gap_event);
420 break;
421 }
422 break;
423 }
424 default:
425 break;
426 }
427 // Return the event to the pool
428 this->ble_event_pool_.release(ble_event);
429 ble_event = this->ble_events_.pop();
430 }
431#ifdef USE_ESP32_BLE_ADVERTISING
432 if (this->advertising_ != nullptr) {
433 this->advertising_->loop();
434 }
435#endif
436
437 // Log dropped events periodically
438 uint16_t dropped = this->ble_events_.get_and_reset_dropped_count();
439 if (dropped > 0) {
440 ESP_LOGW(TAG, "Dropped %u BLE events due to buffer overflow", dropped);
441 }
442}
443
444// Helper function to load new event data based on type
445void load_ble_event(BLEEvent *event, esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
446 event->load_gap_event(e, p);
447}
448
449#ifdef USE_ESP32_BLE_CLIENT
450void load_ble_event(BLEEvent *event, esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
451 event->load_gattc_event(e, i, p);
452}
453#endif
454
455#ifdef USE_ESP32_BLE_SERVER
456void load_ble_event(BLEEvent *event, esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
457 event->load_gatts_event(e, i, p);
458}
459#endif
460
461template<typename... Args> void enqueue_ble_event(Args... args) {
462 // Allocate an event from the pool
463 BLEEvent *event = global_ble->ble_event_pool_.allocate();
464 if (event == nullptr) {
465 // No events available - queue is full or we're out of memory
466 global_ble->ble_events_.increment_dropped_count();
467 return;
468 }
469
470 // Load new event data (replaces previous event)
471 load_ble_event(event, args...);
472
473 // Push the event to the queue
474 global_ble->ble_events_.push(event);
475 // Push always succeeds because we're the only producer and the pool ensures we never exceed queue size
476}
477
478// Explicit template instantiations for the friend function
479template void enqueue_ble_event(esp_gap_ble_cb_event_t, esp_ble_gap_cb_param_t *);
480#ifdef USE_ESP32_BLE_SERVER
481template void enqueue_ble_event(esp_gatts_cb_event_t, esp_gatt_if_t, esp_ble_gatts_cb_param_t *);
482#endif
483#ifdef USE_ESP32_BLE_CLIENT
484template void enqueue_ble_event(esp_gattc_cb_event_t, esp_gatt_if_t, esp_ble_gattc_cb_param_t *);
485#endif
486
487void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
488 switch (event) {
489 // Queue GAP events that components need to handle
490 // Scanning events - used by esp32_ble_tracker
491 case ESP_GAP_BLE_SCAN_RESULT_EVT:
492 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
493 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
494 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
495 // Advertising events - used by esp32_ble_beacon and esp32_ble server
496 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
497 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
498 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
499 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
500 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
501 // Connection events - used by ble_client
502 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
503 // Security events - used by ble_client and bluetooth_proxy
504 case ESP_GAP_BLE_AUTH_CMPL_EVT:
505 case ESP_GAP_BLE_SEC_REQ_EVT:
506 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:
507 case ESP_GAP_BLE_PASSKEY_REQ_EVT:
508 case ESP_GAP_BLE_NC_REQ_EVT:
509 enqueue_ble_event(event, param);
510 return;
511
512 // Ignore these GAP events as they are not relevant for our use case
513 case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
514 case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT:
515 case ESP_GAP_BLE_PHY_UPDATE_COMPLETE_EVT: // BLE 5.0 PHY update complete
516 case ESP_GAP_BLE_CHANNEL_SELECT_ALGORITHM_EVT: // BLE 5.0 channel selection algorithm
517 return;
518
519 default:
520 break;
521 }
522 ESP_LOGW(TAG, "Ignoring unexpected GAP event type: %d", event);
523}
524
525#ifdef USE_ESP32_BLE_SERVER
526void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
527 esp_ble_gatts_cb_param_t *param) {
528 enqueue_ble_event(event, gatts_if, param);
529}
530#endif
531
532#ifdef USE_ESP32_BLE_CLIENT
533void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
534 esp_ble_gattc_cb_param_t *param) {
535 enqueue_ble_event(event, gattc_if, param);
536}
537#endif
538
540
542 const uint8_t *mac_address = esp_bt_dev_get_address();
543 if (mac_address) {
544 const char *io_capability_s;
545 switch (this->io_cap_) {
546 case ESP_IO_CAP_OUT:
547 io_capability_s = "display_only";
548 break;
549 case ESP_IO_CAP_IO:
550 io_capability_s = "display_yes_no";
551 break;
552 case ESP_IO_CAP_IN:
553 io_capability_s = "keyboard_only";
554 break;
555 case ESP_IO_CAP_NONE:
556 io_capability_s = "none";
557 break;
558 case ESP_IO_CAP_KBDISP:
559 io_capability_s = "keyboard_display";
560 break;
561 default:
562 io_capability_s = "invalid";
563 break;
564 }
565 ESP_LOGCONFIG(TAG,
566 "BLE:\n"
567 " MAC address: %s\n"
568 " IO Capability: %s",
569 format_mac_address_pretty(mac_address).c_str(), io_capability_s);
570 } else {
571 ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled");
572 }
573}
574
575uint64_t ble_addr_to_uint64(const esp_bd_addr_t address) {
576 uint64_t u = 0;
577 u |= uint64_t(address[0] & 0xFF) << 40;
578 u |= uint64_t(address[1] & 0xFF) << 32;
579 u |= uint64_t(address[2] & 0xFF) << 24;
580 u |= uint64_t(address[3] & 0xFF) << 16;
581 u |= uint64_t(address[4] & 0xFF) << 8;
582 u |= uint64_t(address[5] & 0xFF) << 0;
583 return u;
584}
585
586ESP32BLE *global_ble = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
587
588} // namespace esphome::esp32_ble
589
590#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:487
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:533
friend void enqueue_ble_event(Args... args)
Definition ble.cpp:461
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:541
void loop() override
Definition ble.cpp:292
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:526
void advertising_set_service_data(const std::vector< uint8_t > &data)
Definition ble.cpp:64
float get_setup_priority() const override
Definition ble.cpp:539
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:586
void load_ble_event(BLEEvent *event, esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p)
Definition ble.cpp:445
@ 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:575
void enqueue_ble_event(Args... args)
Definition ble.cpp:461
std::string format_mac_address_pretty(const uint8_t *mac)
Definition helpers.cpp:257
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:29
std::string get_mac_address()
Get the device MAC address as a string, in lowercase hex notation.
Definition helpers.cpp:590
Application App
Global storage of Application pointer - only one Application can exist.