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>
34static const char *
const TAG =
"esp32_ble";
37#define GAP_SCAN_COMPLETE_EVENTS \
38 case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: \
39 case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: \
40 case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
42#define GAP_ADV_COMPLETE_EVENTS \
43 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: \
44 case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: \
45 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: \
46 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: \
47 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
49#define GAP_SECURITY_EVENTS \
50 case ESP_GAP_BLE_AUTH_CMPL_EVT: \
51 case ESP_GAP_BLE_SEC_REQ_EVT: \
52 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: \
53 case ESP_GAP_BLE_PASSKEY_REQ_EVT: \
54 case ESP_GAP_BLE_NC_REQ_EVT
59 ESP_LOGE(TAG,
"BLE could not be prepared for configuration");
65 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
168 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
170 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) {
171 esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
172 err = esp_bt_controller_init(&cfg);
174 ESP_LOGE(TAG,
"esp_bt_controller_init failed: %s", esp_err_to_name(err));
177 while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE)
180 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
181 err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
183 ESP_LOGE(TAG,
"esp_bt_controller_enable failed: %s", esp_err_to_name(err));
187 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
188 ESP_LOGE(TAG,
"esp bt controller enable failed");
193 esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
195 esp_hosted_connect_to_slave();
197 if (esp_hosted_bt_controller_init() != ESP_OK) {
198 ESP_LOGW(TAG,
"esp_hosted_bt_controller_init failed");
202 if (esp_hosted_bt_controller_enable() != ESP_OK) {
203 ESP_LOGW(TAG,
"esp_hosted_bt_controller_enable failed");
207 hosted_hci_bluedroid_open();
209 esp_bluedroid_hci_driver_operations_t operations = {
210 .send = hosted_hci_bluedroid_send,
211 .check_send_available = hosted_hci_bluedroid_check_send_available,
212 .register_host_callback = hosted_hci_bluedroid_register_host_callback,
214 esp_bluedroid_attach_hci_driver(&operations);
217 err = esp_bluedroid_init();
219 ESP_LOGE(TAG,
"esp_bluedroid_init failed: %d", err);
222 err = esp_bluedroid_enable();
224 ESP_LOGE(TAG,
"esp_bluedroid_enable failed: %d", err);
228#ifdef ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT
231 ESP_LOGE(TAG,
"esp_ble_gap_register_callback failed: %d", err);
236#if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT)
239 ESP_LOGE(TAG,
"esp_ble_gatts_register_callback failed: %d", err);
244#if defined(USE_ESP32_BLE_CLIENT) && defined(ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT)
247 ESP_LOGE(TAG,
"esp_ble_gattc_register_callback failed: %d", err);
254 constexpr size_t ble_name_max_len = 21;
255 char name_buffer[ble_name_max_len];
256 const char *device_name;
258 if (this->name_ !=
nullptr) {
261 constexpr size_t mac_address_suffix_len = 6;
262 char mac_addr[MAC_ADDRESS_BUFFER_SIZE];
264 const char *mac_suffix_ptr = mac_addr + mac_address_suffix_len;
266 mac_address_suffix_len);
267 device_name = name_buffer;
269 device_name = this->name_;
273 size_t name_len = app_name.
length();
277 memcpy(name_buffer, app_name.c_str(), 13);
278 memcpy(name_buffer + 13, app_name.c_str() + name_len - 7, 7);
280 memcpy(name_buffer, app_name.c_str(), 20);
282 name_buffer[20] =
'\0';
284 memcpy(name_buffer, app_name.c_str(), name_len + 1);
286 device_name = name_buffer;
289 err = esp_ble_gap_set_device_name(device_name);
291 ESP_LOGE(TAG,
"esp_ble_gap_set_device_name failed: %d", err);
295 err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_),
sizeof(esp_ble_io_cap_t));
297 ESP_LOGE(TAG,
"esp_ble_gap_set_security_param iocap_mode failed: %d", err);
301#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS
302 if (this->max_key_size_) {
303 err = esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &(this->max_key_size_),
sizeof(uint8_t));
305 ESP_LOGE(TAG,
"esp_ble_gap_set_security_param max_key_size failed: %d", err);
310 if (this->min_key_size_) {
311 err = esp_ble_gap_set_security_param(ESP_BLE_SM_MIN_KEY_SIZE, &(this->min_key_size_),
sizeof(uint8_t));
313 ESP_LOGE(TAG,
"esp_ble_gap_set_security_param min_key_size failed: %d", err);
318 if (this->auth_req_mode_) {
319 err = esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &(this->auth_req_mode_.value()),
320 sizeof(esp_ble_auth_req_t));
322 ESP_LOGE(TAG,
"esp_ble_gap_set_security_param authen_req_mode failed: %d", err);
335 esp_err_t err = esp_bluedroid_disable();
338 if (err != ESP_ERR_INVALID_STATE) {
339 ESP_LOGE(TAG,
"esp_bluedroid_disable failed: %d", err);
342 ESP_LOGD(TAG,
"Already disabled");
344 err = esp_bluedroid_deinit();
347 if (err != ESP_ERR_INVALID_STATE) {
348 ESP_LOGE(TAG,
"esp_bluedroid_deinit failed: %d", err);
351 ESP_LOGD(TAG,
"Already deinitialized");
354#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
355 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
357 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED) {
358 err = esp_bt_controller_disable();
360 ESP_LOGE(TAG,
"esp_bt_controller_disable failed: %s", esp_err_to_name(err));
363 while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED)
366 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) {
367 err = esp_bt_controller_deinit();
369 ESP_LOGE(TAG,
"esp_bt_controller_deinit failed: %s", esp_err_to_name(err));
373 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
374 ESP_LOGE(TAG,
"esp bt controller disable failed");
379 if (esp_hosted_bt_controller_disable() != ESP_OK) {
380 ESP_LOGW(TAG,
"esp_hosted_bt_controller_disable failed");
384 if (esp_hosted_bt_controller_deinit(
false) != ESP_OK) {
385 ESP_LOGW(TAG,
"esp_hosted_bt_controller_deinit failed");
389 hosted_hci_bluedroid_close();
396 this->loop_handle_state_transition_not_active_();
400#ifdef USE_ESP32_BLE_ADVERTISING
401 if (this->advertising_ !=
nullptr) {
402 this->advertising_->
loop();
406 BLEEvent *ble_event = this->ble_events_.pop();
407 if (ble_event ==
nullptr)
411 switch (ble_event->
type_) {
412#if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT)
414 esp_gatts_cb_event_t
event = ble_event->
event_.
gatts.gatts_event;
415 esp_gatt_if_t gatts_if = ble_event->
event_.
gatts.gatts_if;
416 esp_ble_gatts_cb_param_t *param = &ble_event->
event_.
gatts.gatts_param;
417 ESP_LOGV(TAG,
"gatts_event [esp_gatt_if: %d] - %d", gatts_if, event);
418 this->gatts_event_callbacks_.call(event, gatts_if, param);
422#if defined(USE_ESP32_BLE_CLIENT) && defined(ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT)
424 esp_gattc_cb_event_t
event = ble_event->
event_.
gattc.gattc_event;
425 esp_gatt_if_t gattc_if = ble_event->
event_.
gattc.gattc_if;
426 esp_ble_gattc_cb_param_t *param = &ble_event->
event_.
gattc.gattc_param;
427 ESP_LOGV(TAG,
"gattc_event [esp_gatt_if: %d] - %d", gattc_if, event);
428 this->gattc_event_callbacks_.call(event, gattc_if, param);
433 esp_gap_ble_cb_event_t gap_event = ble_event->
event_.
gap.gap_event;
435 case ESP_GAP_BLE_SCAN_RESULT_EVT:
436#ifdef ESPHOME_ESP32_BLE_GAP_SCAN_EVENT_HANDLER_COUNT
437 this->gap_scan_event_callbacks_.call(ble_event->
scan_result());
442 GAP_SCAN_COMPLETE_EVENTS:
444 GAP_ADV_COMPLETE_EVENTS:
446 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
449 ESP_LOGV(TAG,
"gap_event_handler - %d", gap_event);
450#ifdef ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT
452 esp_ble_gap_cb_param_t *param = NULL;
459 GAP_SCAN_COMPLETE_EVENTS:
460 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.scan_complete);
464 GAP_ADV_COMPLETE_EVENTS:
465 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.adv_complete);
468 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
469 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.read_rssi_complete);
473 param =
reinterpret_cast<esp_ble_gap_cb_param_t *
>(&ble_event->
event_.
gap.security);
481 this->gap_event_callbacks_.call(gap_event, param);
488 ESP_LOGW(TAG,
"Unhandled GAP event type in loop: %d", gap_event);
497 this->ble_event_pool_.release(ble_event);
498 }
while ((ble_event = this->ble_events_.pop()) !=
nullptr);
503 uint16_t dropped = this->ble_events_.get_and_reset_dropped_count();
505 ESP_LOGW(TAG,
"Dropped %u BLE events due to buffer overflow", dropped);
509void ESP32BLE::loop_handle_state_transition_not_active_() {
512 ESP_LOGD(TAG,
"Disabling");
514#ifdef ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT
515 this->ble_status_event_callbacks_.call();
519 ESP_LOGE(TAG,
"Could not be dismantled");
525 ESP_LOGD(TAG,
"Enabling");
529 ESP_LOGE(TAG,
"Could not be set up");
540 event->load_gap_event(e, p);
543#ifdef USE_ESP32_BLE_CLIENT
545 event->load_gattc_event(e, i, p);
549#ifdef USE_ESP32_BLE_SERVER
551 event->load_gatts_event(e, i, p);
558 if (event ==
nullptr) {
560 global_ble->ble_events_.increment_dropped_count();
575#ifdef USE_ESP32_BLE_SERVER
576template void enqueue_ble_event(esp_gatts_cb_event_t, esp_gatt_if_t, esp_ble_gatts_cb_param_t *);
578#ifdef USE_ESP32_BLE_CLIENT
579template void enqueue_ble_event(esp_gattc_cb_event_t, esp_gatt_if_t, esp_ble_gattc_cb_param_t *);
586 case ESP_GAP_BLE_SCAN_RESULT_EVT:
587 GAP_SCAN_COMPLETE_EVENTS:
589 GAP_ADV_COMPLETE_EVENTS:
591 case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
604 case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
605 case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT:
606 case ESP_GAP_BLE_PHY_UPDATE_COMPLETE_EVT:
607 case ESP_GAP_BLE_CHANNEL_SELECT_ALGORITHM_EVT:
613 ESP_LOGW(TAG,
"Ignoring unexpected GAP event type: %d", event);
616#ifdef USE_ESP32_BLE_SERVER
618 esp_ble_gatts_cb_param_t *param) {
625#ifdef USE_ESP32_BLE_CLIENT
627 esp_ble_gattc_cb_param_t *param) {
637 const uint8_t *mac_address = esp_bt_dev_get_address();
639 const char *io_capability_s;
640 switch (this->io_cap_) {
642 io_capability_s =
"display_only";
645 io_capability_s =
"display_yes_no";
648 io_capability_s =
"keyboard_only";
650 case ESP_IO_CAP_NONE:
651 io_capability_s =
"none";
653 case ESP_IO_CAP_KBDISP:
654 io_capability_s =
"keyboard_display";
657 io_capability_s =
"invalid";
666 " IO Capability: %s",
667 mac_s, io_capability_s);
668#ifdef USE_ESP32_BLE_PSRAM
669 ESP_LOGCONFIG(TAG,
" PSRAM BLE allocation: enabled");
672#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS
673 const char *auth_req_mode_s =
"<default>";
674 if (this->auth_req_mode_) {
675 switch (this->auth_req_mode_.value()) {
677 auth_req_mode_s =
"no_bond";
680 auth_req_mode_s =
"bond";
683 auth_req_mode_s =
"mitm";
686 auth_req_mode_s =
"bond_mitm";
689 auth_req_mode_s =
"sc_only";
692 auth_req_mode_s =
"sc_bond";
695 auth_req_mode_s =
"sc_mitm";
698 auth_req_mode_s =
"sc_mitm_bond";
703 ESP_LOGCONFIG(TAG,
" Auth Req Mode: %s", auth_req_mode_s);
704 if (this->max_key_size_ && this->min_key_size_) {
705 ESP_LOGCONFIG(TAG,
" Key Size: %u - %u", this->min_key_size_, this->max_key_size_);
706 }
else if (this->max_key_size_) {
707 ESP_LOGCONFIG(TAG,
" Key Size: <default> - %u", this->max_key_size_);
708 }
else if (this->min_key_size_) {
709 ESP_LOGCONFIG(TAG,
" Key Size: %u - <default>", this->min_key_size_);
714 ESP_LOGCONFIG(TAG,
"Bluetooth stack is not enabled");
const StringRef & get_name() const
Get the name of this Application set by pre_setup().
void wake_loop_threadsafe()
Wake the main event loop from another thread or callback.
bool is_name_add_mac_suffix_enabled() const
void mark_failed()
Mark this component as failed.
constexpr size_type length() const
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)
ESPHOME_ALWAYS_INLINE bool is_active()
float get_setup_priority() const override
void advertising_remove_service_uuid(ESPBTUUID uuid)
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.
void enqueue_ble_event(Args... args)
constexpr float BLUETOOTH
size_t make_name_with_suffix_to(char *buffer, size_t buffer_size, const char *name, size_t name_len, char sep, const char *suffix_ptr, size_t suffix_len)
Zero-allocation version: format name + separator + suffix directly into buffer.
const char int const __FlashStringHelper va_list args
void get_mac_address_into_buffer(std::span< char, MAC_ADDRESS_BUFFER_SIZE > buf)
Get the device MAC address into the given buffer, in lowercase hex notation.
void HOT delay(uint32_t ms)
Application App
Global storage of Application pointer - only one Application can exist.
char * format_mac_addr_upper(const uint8_t *mac, char *output)
Format MAC address as XX:XX:XX:XX:XX:XX (uppercase, colon separators)