9#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
13#include <esp_hosted.h>
14#include <esp_hosted_misc.h>
15#include <esp_hosted_bluedroid.h>
18#include <esp_bt_device.h>
19#include <esp_bt_main.h>
20#include <esp_gap_ble_api.h>
21#include <freertos/FreeRTOS.h>
22#include <freertos/FreeRTOSConfig.h>
23#include <freertos/task.h>
27#include <esp32-hal-bt.h>
32static const char *
const TAG =
"esp32_ble";
35#define GAP_SCAN_COMPLETE_EVENTS \
36 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: \
37 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: \
38 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
40#define GAP_ADV_COMPLETE_EVENTS \
41 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: \
42 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: \
43 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: \
44 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: \
45 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
47#define GAP_SECURITY_EVENTS \
48 case ESP_GAP_BLE_AUTH_CMPL_EVT: \
49 case ESP_GAP_BLE_SEC_REQ_EVT: \
50 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: \
51 case ESP_GAP_BLE_PASSKEY_REQ_EVT: \
52 case ESP_GAP_BLE_NC_REQ_EVT
57 ESP_LOGE(TAG,
"BLE could not be prepared for configuration");
63 if (this->enable_on_boot_) {
84#ifdef USE_ESP32_BLE_ADVERTISING
89 this->advertising_->
start();
145 esp_err_t err = nvs_flash_init();
147 ESP_LOGE(TAG,
"nvs_flash_init failed: %d", err);
153#ifdef USE_ESP32_BLE_ADVERTISING
155 if (this->advertising_ !=
nullptr)
157 this->advertising_ =
new BLEAdvertising(this->advertising_cycle_time_);
167#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
170 ESP_LOGE(TAG,
"btStart failed: %d", esp_bt_controller_get_status());
174 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
176 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) {
177 esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
178 err = esp_bt_controller_init(&cfg);
180 ESP_LOGE(TAG,
"esp_bt_controller_init failed: %s", esp_err_to_name(err));
183 while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE)
186 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
187 err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
189 ESP_LOGE(TAG,
"esp_bt_controller_enable failed: %s", esp_err_to_name(err));
193 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
194 ESP_LOGE(TAG,
"esp bt controller enable failed");
200 esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
202 esp_hosted_connect_to_slave();
204 if (esp_hosted_bt_controller_init() != ESP_OK) {
205 ESP_LOGW(TAG,
"esp_hosted_bt_controller_init failed");
209 if (esp_hosted_bt_controller_enable() != ESP_OK) {
210 ESP_LOGW(TAG,
"esp_hosted_bt_controller_enable failed");
214 hosted_hci_bluedroid_open();
216 esp_bluedroid_hci_driver_operations_t operations = {
217 .send = hosted_hci_bluedroid_send,
218 .check_send_available = hosted_hci_bluedroid_check_send_available,
219 .register_host_callback = hosted_hci_bluedroid_register_host_callback,
221 esp_bluedroid_attach_hci_driver(&operations);
224 err = esp_bluedroid_init();
226 ESP_LOGE(TAG,
"esp_bluedroid_init failed: %d", err);
229 err = esp_bluedroid_enable();
231 ESP_LOGE(TAG,
"esp_bluedroid_enable failed: %d", err);
235#ifdef ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT
238 ESP_LOGE(TAG,
"esp_ble_gap_register_callback failed: %d", err);
243#if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT)
246 ESP_LOGE(TAG,
"esp_ble_gatts_register_callback failed: %d", err);
251#if defined(USE_ESP32_BLE_CLIENT) && defined(ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT)
254 ESP_LOGE(TAG,
"esp_ble_gattc_register_callback failed: %d", err);
261 name = this->name_.
value();
264 constexpr size_t mac_address_suffix_len = 6;
266 const char *mac_suffix_ptr = mac_addr.c_str() + mac_address_suffix_len;
271 if (name.length() > 20) {
274 name.erase(13, name.length() - 20);
281 err = esp_ble_gap_set_device_name(name.c_str());
283 ESP_LOGE(TAG,
"esp_ble_gap_set_device_name failed: %d", err);
287 err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_),
sizeof(uint8_t));
289 ESP_LOGE(TAG,
"esp_ble_gap_set_security_param failed: %d", err);
300 esp_err_t err = esp_bluedroid_disable();
302 ESP_LOGE(TAG,
"esp_bluedroid_disable failed: %d", err);
305 err = esp_bluedroid_deinit();
307 ESP_LOGE(TAG,
"esp_bluedroid_deinit failed: %d", err);
311#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
314 ESP_LOGE(TAG,
"btStop failed: %d", esp_bt_controller_get_status());
318 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
320 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED) {
321 err = esp_bt_controller_disable();
323 ESP_LOGE(TAG,
"esp_bt_controller_disable failed: %s", esp_err_to_name(err));
326 while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED)
329 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
330 err = esp_bt_controller_deinit();
332 ESP_LOGE(TAG,
"esp_bt_controller_deinit failed: %s", esp_err_to_name(err));
336 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
337 ESP_LOGE(TAG,
"esp bt controller disable failed");
343 if (esp_hosted_bt_controller_disable() != ESP_OK) {
344 ESP_LOGW(TAG,
"esp_hosted_bt_controller_disable failed");
348 if (esp_hosted_bt_controller_deinit(
false) != ESP_OK) {
349 ESP_LOGW(TAG,
"esp_hosted_bt_controller_deinit failed");
353 hosted_hci_bluedroid_close();
359 switch (this->state_) {
364 ESP_LOGD(TAG,
"Disabling");
366#ifdef ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT
367 for (
auto *ble_event_handler : this->ble_status_event_handlers_) {
368 ble_event_handler->ble_before_disabled_event_handler();
373 ESP_LOGE(TAG,
"Could not be dismantled");
381 ESP_LOGD(TAG,
"Enabling");
385 ESP_LOGE(TAG,
"Could not be set up");
397 BLEEvent *ble_event = this->ble_events_.pop();
398 while (ble_event !=
nullptr) {
399 switch (ble_event->
type_) {
400#if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT)
402 esp_gatts_cb_event_t
event = ble_event->
event_.
gatts.gatts_event;
403 esp_gatt_if_t gatts_if = ble_event->
event_.
gatts.gatts_if;
404 esp_ble_gatts_cb_param_t *param = &ble_event->
event_.
gatts.gatts_param;
405 ESP_LOGV(TAG,
"gatts_event [esp_gatt_if: %d] - %d", gatts_if, event);
406 for (
auto *gatts_handler : this->gatts_event_handlers_) {
407 gatts_handler->gatts_event_handler(event, gatts_if, param);
412#if defined(USE_ESP32_BLE_CLIENT) && defined(ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT)
414 esp_gattc_cb_event_t
event = ble_event->
event_.
gattc.gattc_event;
415 esp_gatt_if_t gattc_if = ble_event->
event_.
gattc.gattc_if;
416 esp_ble_gattc_cb_param_t *param = &ble_event->
event_.
gattc.gattc_param;
417 ESP_LOGV(TAG,
"gattc_event [esp_gatt_if: %d] - %d", gattc_if, event);
418 for (
auto *gattc_handler : this->gattc_event_handlers_) {
419 gattc_handler->gattc_event_handler(event, gattc_if, param);
425 esp_gap_ble_cb_event_t gap_event = ble_event->
event_.
gap.gap_event;
427 case ESP_GAP_BLE_SCAN_RESULT_EVT:
428#ifdef ESPHOME_ESP32_BLE_GAP_SCAN_EVENT_HANDLER_COUNT
430 for (
auto *scan_handler : this->gap_scan_event_handlers_) {
431 scan_handler->gap_scan_event_handler(ble_event->
scan_result());
437 GAP_SCAN_COMPLETE_EVENTS:
439 GAP_ADV_COMPLETE_EVENTS:
441 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
444 ESP_LOGV(TAG,
"gap_event_handler - %d", gap_event);
445#ifdef ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT
447 esp_ble_gap_cb_param_t *param;
454 GAP_SCAN_COMPLETE_EVENTS:
455 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.scan_complete);
459 GAP_ADV_COMPLETE_EVENTS:
460 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.adv_complete);
463 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
464 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.read_rssi_complete);
468 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.security);
476 for (
auto *gap_handler : this->gap_event_handlers_) {
477 gap_handler->gap_event_handler(gap_event, param);
485 ESP_LOGW(TAG,
"Unhandled GAP event type in loop: %d", gap_event);
494 this->ble_event_pool_.release(ble_event);
495 ble_event = this->ble_events_.pop();
497#ifdef USE_ESP32_BLE_ADVERTISING
498 if (this->advertising_ !=
nullptr) {
499 this->advertising_->
loop();
504 uint16_t dropped = this->ble_events_.get_and_reset_dropped_count();
506 ESP_LOGW(TAG,
"Dropped %u BLE events due to buffer overflow", dropped);
512 event->load_gap_event(e, p);
515#ifdef USE_ESP32_BLE_CLIENT
517 event->load_gattc_event(e, i, p);
521#ifdef USE_ESP32_BLE_SERVER
523 event->load_gatts_event(e, i, p);
530 if (event ==
nullptr) {
532 global_ble->ble_events_.increment_dropped_count();
546#ifdef USE_ESP32_BLE_SERVER
547template void enqueue_ble_event(esp_gatts_cb_event_t, esp_gatt_if_t, esp_ble_gatts_cb_param_t *);
549#ifdef USE_ESP32_BLE_CLIENT
550template void enqueue_ble_event(esp_gattc_cb_event_t, esp_gatt_if_t, esp_ble_gattc_cb_param_t *);
557 case ESP_GAP_BLE_SCAN_RESULT_EVT:
558 GAP_SCAN_COMPLETE_EVENTS:
560 GAP_ADV_COMPLETE_EVENTS:
562 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
571#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
577 case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
578 case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT:
579 case ESP_GAP_BLE_PHY_UPDATE_COMPLETE_EVT:
580 case ESP_GAP_BLE_CHANNEL_SELECT_ALGORITHM_EVT:
586 ESP_LOGW(TAG,
"Ignoring unexpected GAP event type: %d", event);
589#ifdef USE_ESP32_BLE_SERVER
591 esp_ble_gatts_cb_param_t *param) {
594#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
600#ifdef USE_ESP32_BLE_CLIENT
602 esp_ble_gattc_cb_param_t *param) {
605#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
614 const uint8_t *mac_address = esp_bt_dev_get_address();
616 const char *io_capability_s;
617 switch (this->io_cap_) {
619 io_capability_s =
"display_only";
622 io_capability_s =
"display_yes_no";
625 io_capability_s =
"keyboard_only";
627 case ESP_IO_CAP_NONE:
628 io_capability_s =
"none";
630 case ESP_IO_CAP_KBDISP:
631 io_capability_s =
"keyboard_display";
634 io_capability_s =
"invalid";
642 " IO Capability: %s",
643 mac_s, io_capability_s);
645 ESP_LOGCONFIG(TAG,
"Bluetooth stack is not enabled");
651 u |= uint64_t(
address[0] & 0xFF) << 40;
652 u |= uint64_t(
address[1] & 0xFF) << 32;
653 u |= uint64_t(
address[2] & 0xFF) << 24;
654 u |= uint64_t(
address[3] & 0xFF) << 16;
655 u |= uint64_t(
address[4] & 0xFF) << 8;
656 u |= uint64_t(
address[5] & 0xFF) << 0;
void wake_loop_threadsafe()
Wake the main event loop from a FreeRTOS task Thread-safe, can be called from task context to immedia...
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 add_service_uuid(ESPBTUUID uuid)
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 remove_service_uuid(ESPBTUUID uuid)
void register_raw_advertisement_callback(std::function< void(bool)> &&callback)
void set_appearance(uint16_t appearance)
union esphome::esp32_ble::BLEEvent::@78 event_
struct esphome::esp32_ble::BLEEvent::@78::gatts_event gatts
BLEScanResult scan_result
struct esphome::esp32_ble::BLEEvent::@78::gap_event gap
struct esphome::esp32_ble::BLEEvent::@78::gattc_event gattc
void advertising_set_manufacturer_data(const std::vector< uint8_t > &data)
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
friend void enqueue_ble_event(Args... args)
void advertising_register_raw_advertisement_callback(std::function< void(bool)> &&callback)
void advertising_set_service_data_and_name(std::span< const uint8_t > data, bool include_name)
void advertising_add_service_uuid(ESPBTUUID uuid)
void dump_config() override
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
void advertising_set_service_data(const std::vector< uint8_t > &data)
float get_setup_priority() const override
void advertising_remove_service_uuid(ESPBTUUID uuid)
value_type const & value() const
void load_ble_event(BLEEvent *event, esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p)
@ BLE_COMPONENT_STATE_DISABLE
BLE should be disabled on next loop.
@ BLE_COMPONENT_STATE_OFF
Nothing has been initialized yet.
@ BLE_COMPONENT_STATE_ENABLE
BLE should be enabled on next loop.
@ BLE_COMPONENT_STATE_DISABLED
BLE is disabled.
@ BLE_COMPONENT_STATE_ACTIVE
BLE is active.
uint64_t ble_addr_to_uint64(const esp_bd_addr_t address)
void enqueue_ble_event(Args... args)
void format_mac_addr_upper(const uint8_t *mac, char *output)
Format MAC address as XX:XX:XX:XX:XX:XX (uppercase)
std::string make_name_with_suffix(const std::string &name, char sep, const char *suffix_ptr, size_t suffix_len)
Concatenate a name with a separator and suffix using an efficient stack-based approach.
void IRAM_ATTR HOT delay(uint32_t ms)
std::string get_mac_address()
Get the device MAC address as a string, in lowercase hex notation.
Application App
Global storage of Application pointer - only one Application can exist.