diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index c6bb296cdc..3dc4af1058 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -6,13 +6,19 @@ from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant DEPENDENCIES = ["esp32"] CODEOWNERS = ["@jesserockz"] -CONFLICTS_WITH = ["esp32_ble_tracker", "esp32_ble_beacon"] +CONFLICTS_WITH = ["esp32_ble_beacon"] + +CONF_BLE_ID = "ble_id" NO_BLUTOOTH_VARIANTS = [const.VARIANT_ESP32S2] esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble") ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component) +GAPEventHandler = esp32_ble_ns.class_("GAPEventHandler") +GATTcEventHandler = esp32_ble_ns.class_("GATTcEventHandler") +GATTsEventHandler = esp32_ble_ns.class_("GATTsEventHandler") + CONFIG_SCHEMA = cv.Schema( { diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index ecd591d169..456332b748 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -4,13 +4,13 @@ #include "esphome/core/application.h" #include "esphome/core/log.h" -#include -#include -#include #include -#include -#include +#include #include +#include +#include +#include +#include #ifdef USE_ARDUINO #include @@ -40,15 +40,6 @@ void ESP32BLE::setup() { ESP_LOGD(TAG, "BLE setup complete"); } -void ESP32BLE::mark_failed() { - Component::mark_failed(); -#ifdef USE_ESP32_BLE_SERVER - if (this->server_ != nullptr) { - this->server_->mark_failed(); - } -#endif -} - bool ESP32BLE::ble_setup_() { esp_err_t err = nvs_flash_init(); if (err != ESP_OK) { @@ -100,13 +91,16 @@ bool ESP32BLE::ble_setup_() { ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", err); return false; } - err = esp_ble_gap_register_callback(ESP32BLE::gap_event_handler); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", err); - return false; + + if (!this->gap_event_handlers_.empty()) { + err = esp_ble_gap_register_callback(ESP32BLE::gap_event_handler); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", err); + return false; + } } - if (this->has_server()) { + if (!this->gatts_event_handlers_.empty()) { err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gatts_register_callback failed: %d", err); @@ -114,7 +108,7 @@ bool ESP32BLE::ble_setup_() { } } - if (this->has_client()) { + if (!this->gattc_event_handlers_.empty()) { err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err); @@ -158,6 +152,10 @@ void ESP32BLE::loop() { this->real_gatts_event_handler_(ble_event->event_.gatts.gatts_event, ble_event->event_.gatts.gatts_if, &ble_event->event_.gatts.gatts_param); break; + case BLEEvent::GATTC: + this->real_gattc_event_handler_(ble_event->event_.gattc.gattc_event, ble_event->event_.gattc.gattc_if, + &ble_event->event_.gattc.gattc_param); + break; case BLEEvent::GAP: this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param); break; @@ -176,9 +174,8 @@ void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { ESP_LOGV(TAG, "(BLE) gap_event_handler - %d", event); - switch (event) { - default: - break; + for (auto *gap_handler : this->gap_event_handlers_) { + gap_handler->gap_event_handler(event, param); } } @@ -191,14 +188,23 @@ void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gat void ESP32BLE::real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { ESP_LOGV(TAG, "(BLE) gatts_event [esp_gatt_if: %d] - %d", gatts_if, event); -#ifdef USE_ESP32_BLE_SERVER - this->server_->gatts_event_handler(event, gatts_if, param); -#endif + for (auto *gatts_handler : this->gatts_event_handlers_) { + gatts_handler->gatts_event_handler(event, gatts_if, param); + } } +void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) { + BLEEvent *new_event = new BLEEvent(event, gattc_if, param); // NOLINT(cppcoreguidelines-owning-memory) + global_ble->ble_events_.push(new_event); +} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + void ESP32BLE::real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { - // this->client_->gattc_event_handler(event, gattc_if, param); + ESP_LOGV(TAG, "(BLE) gattc_event [esp_gatt_if: %d] - %d", gattc_if, event); + for (auto *gattc_handler : this->gattc_event_handlers_) { + gattc_handler->gattc_event_handler(event, gattc_if, param); + } } float ESP32BLE::get_setup_priority() const { return setup_priority::BLUETOOTH; } diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 0477dee070..5970b43688 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -5,17 +5,16 @@ #include "esphome/core/component.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" -#include "queue.h" -#ifdef USE_ESP32_BLE_SERVER -#include "esphome/components/esp32_ble_server/ble_server.h" -#endif +#include "queue.h" +#include "ble_event.h" #ifdef USE_ESP32 #include #include #include + namespace esphome { namespace esp32_ble { @@ -26,28 +25,36 @@ typedef struct { uint16_t mtu; } conn_status_t; +class GAPEventHandler { + public: + virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0; +}; + +class GATTcEventHandler { + public: + virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) = 0; +}; + +class GATTsEventHandler { + public: + virtual void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) = 0; +}; + class ESP32BLE : public Component { public: void setup() override; void loop() override; void dump_config() override; float get_setup_priority() const override; - void mark_failed() override; - - bool has_server() { -#ifdef USE_ESP32_BLE_SERVER - return this->server_ != nullptr; -#else - return false; -#endif - } - bool has_client() { return false; } BLEAdvertising *get_advertising() { return this->advertising_; } -#ifdef USE_ESP32_BLE_SERVER - void set_server(esp32_ble_server::BLEServer *server) { this->server_ = server; } -#endif + void register_gap_event_handler(GAPEventHandler *handler) { this->gap_event_handlers_.push_back(handler); } + void register_gattc_event_handler(GATTcEventHandler *handler) { this->gattc_event_handlers_.push_back(handler); } + void register_gatts_event_handler(GATTsEventHandler *handler) { this->gatts_event_handlers_.push_back(handler); } + protected: static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_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); @@ -59,9 +66,10 @@ class ESP32BLE : public Component { bool ble_setup_(); -#ifdef USE_ESP32_BLE_SERVER - esp32_ble_server::BLEServer *server_{nullptr}; -#endif + std::vector gap_event_handlers_; + std::vector gattc_event_handlers_; + std::vector gatts_event_handlers_; + Queue ble_events_; BLEAdvertising *advertising_; }; diff --git a/esphome/components/esp32_ble_tracker/queue.h b/esphome/components/esp32_ble/ble_event.h similarity index 50% rename from esphome/components/esp32_ble_tracker/queue.h rename to esphome/components/esp32_ble/ble_event.h index f1dcc337e8..1cf63b2fab 100644 --- a/esphome/components/esp32_ble_tracker/queue.h +++ b/esphome/components/esp32_ble/ble_event.h @@ -1,69 +1,23 @@ #pragma once #ifdef USE_ESP32 -#include "esphome/core/component.h" -#include "esphome/core/helpers.h" -#include -#include -#include #include #include #include -#include -#include - -/* - * BLE events come in from a separate Task (thread) in the ESP32 stack. Rather - * than trying to deal with various locking strategies, all incoming GAP and GATT - * events will simply be placed on a semaphore guarded queue. The next time the - * component runs loop(), these events are popped off the queue and handed at - * this safer time. - */ +#include namespace esphome { -namespace esp32_ble_tracker { - -template class Queue { - public: - Queue() { m_ = xSemaphoreCreateMutex(); } - - void push(T *element) { - if (element == nullptr) - return; - if (xSemaphoreTake(m_, 5L / portTICK_PERIOD_MS)) { - q_.push(element); - xSemaphoreGive(m_); - } - } - - T *pop() { - T *element = nullptr; - - if (xSemaphoreTake(m_, 5L / portTICK_PERIOD_MS)) { - if (!q_.empty()) { - element = q_.front(); - q_.pop(); - } - xSemaphoreGive(m_); - } - return element; - } - - protected: - std::queue q_; - SemaphoreHandle_t m_; -}; - -// Received GAP and GATTC events are only queued, and get processed in the main loop(). +namespace esp32_ble { +// Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop(). // This class stores each event in a single type. class BLEEvent { public: BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) { this->event_.gap.gap_event = e; memcpy(&this->event_.gap.gap_param, p, sizeof(esp_ble_gap_cb_param_t)); - this->type_ = 0; + this->type_ = GAP; }; BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) { @@ -84,26 +38,57 @@ class BLEEvent { default: break; } - this->type_ = 1; + this->type_ = GATTC; + }; + + BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) { + this->event_.gatts.gatts_event = e; + this->event_.gatts.gatts_if = i; + memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t)); + // Need to also make a copy of relevant event data. + switch (e) { + case ESP_GATTS_WRITE_EVT: + this->data.assign(p->write.value, p->write.value + p->write.len); + this->event_.gatts.gatts_param.write.value = this->data.data(); + break; + default: + break; + } + this->type_ = GATTS; }; union { - struct gap_event { // NOLINT(readability-identifier-naming) + // NOLINTNEXTLINE(readability-identifier-naming) + struct gap_event { esp_gap_ble_cb_event_t gap_event; esp_ble_gap_cb_param_t gap_param; } gap; - struct gattc_event { // NOLINT(readability-identifier-naming) + // NOLINTNEXTLINE(readability-identifier-naming) + struct gattc_event { esp_gattc_cb_event_t gattc_event; esp_gatt_if_t gattc_if; esp_ble_gattc_cb_param_t gattc_param; } gattc; + + // NOLINTNEXTLINE(readability-identifier-naming) + struct gatts_event { + esp_gatts_cb_event_t gatts_event; + esp_gatt_if_t gatts_if; + esp_ble_gatts_cb_param_t gatts_param; + } gatts; } event_; + std::vector data{}; - uint8_t type_; // 0=gap 1=gattc + // NOLINTNEXTLINE(readability-identifier-naming) + enum ble_event_t : uint8_t { + GAP, + GATTC, + GATTS, + } type_; }; -} // namespace esp32_ble_tracker +} // namespace esp32_ble } // namespace esphome #endif diff --git a/esphome/components/esp32_ble/ble_uuid.cpp b/esphome/components/esp32_ble/ble_uuid.cpp index 8556aa87df..a50d3dbd42 100644 --- a/esphome/components/esp32_ble/ble_uuid.cpp +++ b/esphome/components/esp32_ble/ble_uuid.cpp @@ -27,8 +27,7 @@ ESPBTUUID ESPBTUUID::from_uint32(uint32_t uuid) { ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) { ESPBTUUID ret; ret.uuid_.len = ESP_UUID_LEN_128; - for (size_t i = 0; i < ESP_UUID_LEN_128; i++) - ret.uuid_.uuid.uuid128[i] = data[i]; + memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128); return ret; } ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { @@ -91,10 +90,13 @@ ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { ESPBTUUID ESPBTUUID::from_uuid(esp_bt_uuid_t uuid) { ESPBTUUID ret; ret.uuid_.len = uuid.len; - ret.uuid_.uuid.uuid16 = uuid.uuid.uuid16; - ret.uuid_.uuid.uuid32 = uuid.uuid.uuid32; - for (size_t i = 0; i < ESP_UUID_LEN_128; i++) - ret.uuid_.uuid.uuid128[i] = uuid.uuid.uuid128[i]; + if (uuid.len == ESP_UUID_LEN_16) { + ret.uuid_.uuid.uuid16 = uuid.uuid.uuid16; + } else if (uuid.len == ESP_UUID_LEN_32) { + ret.uuid_.uuid.uuid32 = uuid.uuid.uuid32; + } else if (uuid.len == ESP_UUID_LEN_128) { + memcpy(ret.uuid_.uuid.uuid128, uuid.uuid.uuid128, ESP_UUID_LEN_128); + } return ret; } ESPBTUUID ESPBTUUID::as_128bit() const { @@ -158,30 +160,26 @@ bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const { } return false; } -esp_bt_uuid_t ESPBTUUID::get_uuid() { return this->uuid_; } -std::string ESPBTUUID::to_string() { - char sbuf[64]; +esp_bt_uuid_t ESPBTUUID::get_uuid() const { return this->uuid_; } +std::string ESPBTUUID::to_string() const { switch (this->uuid_.len) { case ESP_UUID_LEN_16: - sprintf(sbuf, "0x%02X%02X", this->uuid_.uuid.uuid16 >> 8, this->uuid_.uuid.uuid16 & 0xff); - break; + return str_snprintf("0x%02X%02X", 6, this->uuid_.uuid.uuid16 >> 8, this->uuid_.uuid.uuid16 & 0xff); case ESP_UUID_LEN_32: - sprintf(sbuf, "0x%02X%02X%02X%02X", this->uuid_.uuid.uuid32 >> 24, (this->uuid_.uuid.uuid32 >> 16 & 0xff), - (this->uuid_.uuid.uuid32 >> 8 & 0xff), this->uuid_.uuid.uuid32 & 0xff); - break; + return str_snprintf("0x%02X%02X%02X%02X", 10, this->uuid_.uuid.uuid32 >> 24, + (this->uuid_.uuid.uuid32 >> 16 & 0xff), (this->uuid_.uuid.uuid32 >> 8 & 0xff), + this->uuid_.uuid.uuid32 & 0xff); default: case ESP_UUID_LEN_128: - char *bpos = sbuf; + std::string buf; for (int8_t i = 15; i >= 0; i--) { - sprintf(bpos, "%02X", this->uuid_.uuid.uuid128[i]); - bpos += 2; + buf += str_snprintf("%02X", 2, this->uuid_.uuid.uuid128[i]); if (i == 6 || i == 8 || i == 10 || i == 12) - sprintf(bpos++, "-"); + buf += "-"; } - sbuf[47] = '\0'; - break; + return buf; } - return sbuf; + return ""; } } // namespace esp32_ble diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index f953f9fede..790a57c59d 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -32,9 +32,9 @@ class ESPBTUUID { bool operator==(const ESPBTUUID &uuid) const; bool operator!=(const ESPBTUUID &uuid) const { return !(*this == uuid); } - esp_bt_uuid_t get_uuid(); + esp_bt_uuid_t get_uuid() const; - std::string to_string(); + std::string to_string() const; protected: esp_bt_uuid_t uuid_; diff --git a/esphome/components/esp32_ble/queue.h b/esphome/components/esp32_ble/queue.h index 8d05eca058..5b31b97ae2 100644 --- a/esphome/components/esp32_ble/queue.h +++ b/esphome/components/esp32_ble/queue.h @@ -2,16 +2,9 @@ #ifdef USE_ESP32 -#include "esphome/core/component.h" -#include "esphome/core/helpers.h" - -#include #include -#include +#include -#include -#include -#include #include #include @@ -57,84 +50,6 @@ template class Queue { SemaphoreHandle_t m_; }; -// Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop(). -// This class stores each event in a single type. -class BLEEvent { - public: - BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) { - this->event_.gap.gap_event = e; - memcpy(&this->event_.gap.gap_param, p, sizeof(esp_ble_gap_cb_param_t)); - this->type_ = GAP; - }; - - BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) { - this->event_.gattc.gattc_event = e; - this->event_.gattc.gattc_if = i; - memcpy(&this->event_.gattc.gattc_param, p, sizeof(esp_ble_gattc_cb_param_t)); - // Need to also make a copy of notify event data. - switch (e) { - case ESP_GATTC_NOTIFY_EVT: - memcpy(this->event_.gattc.data, p->notify.value, p->notify.value_len); - this->event_.gattc.gattc_param.notify.value = this->event_.gattc.data; - break; - case ESP_GATTC_READ_CHAR_EVT: - case ESP_GATTC_READ_DESCR_EVT: - memcpy(this->event_.gattc.data, p->read.value, p->read.value_len); - this->event_.gattc.gattc_param.read.value = this->event_.gattc.data; - break; - default: - break; - } - this->type_ = GATTC; - }; - - BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) { - this->event_.gatts.gatts_event = e; - this->event_.gatts.gatts_if = i; - memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t)); - // Need to also make a copy of write data. - switch (e) { - case ESP_GATTS_WRITE_EVT: - memcpy(this->event_.gatts.data, p->write.value, p->write.len); - this->event_.gatts.gatts_param.write.value = this->event_.gatts.data; - break; - default: - break; - } - this->type_ = GATTS; - }; - - union { - // NOLINTNEXTLINE(readability-identifier-naming) - struct gap_event { - esp_gap_ble_cb_event_t gap_event; - esp_ble_gap_cb_param_t gap_param; - } gap; - - // NOLINTNEXTLINE(readability-identifier-naming) - struct gattc_event { - esp_gattc_cb_event_t gattc_event; - esp_gatt_if_t gattc_if; - esp_ble_gattc_cb_param_t gattc_param; - uint8_t data[64]; - } gattc; - - // NOLINTNEXTLINE(readability-identifier-naming) - struct gatts_event { - esp_gatts_cb_event_t gatts_event; - esp_gatt_if_t gatts_if; - esp_ble_gatts_cb_param_t gatts_param; - uint8_t data[64]; - } gatts; - } event_; - // NOLINTNEXTLINE(readability-identifier-naming) - enum ble_event_t : uint8_t { - GAP, - GATTC, - GATTS, - } type_; -}; - } // namespace esp32_ble } // namespace esphome diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index 2fcc5c7743..0ddfa62c1b 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -7,21 +7,25 @@ from esphome.components.esp32 import add_idf_sdkconfig_option AUTO_LOAD = ["esp32_ble"] CODEOWNERS = ["@jesserockz"] -CONFLICTS_WITH = ["esp32_ble_tracker", "esp32_ble_beacon"] +CONFLICTS_WITH = ["esp32_ble_beacon"] DEPENDENCIES = ["esp32"] CONF_MANUFACTURER = "manufacturer" -CONF_BLE_ID = "ble_id" esp32_ble_server_ns = cg.esphome_ns.namespace("esp32_ble_server") -BLEServer = esp32_ble_server_ns.class_("BLEServer", cg.Component) +BLEServer = esp32_ble_server_ns.class_( + "BLEServer", + cg.Component, + esp32_ble.GATTsEventHandler, + cg.Parented.template(esp32_ble.ESP32BLE), +) BLEServiceComponent = esp32_ble_server_ns.class_("BLEServiceComponent") CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(BLEServer), - cv.GenerateID(CONF_BLE_ID): cv.use_id(esp32_ble.ESP32BLE), + cv.GenerateID(esp32_ble.CONF_BLE_ID): cv.use_id(esp32_ble.ESP32BLE), cv.Optional(CONF_MANUFACTURER, default="ESPHome"): cv.string, cv.Optional(CONF_MODEL): cv.string, } @@ -29,16 +33,18 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): - parent = await cg.get_variable(config[CONF_BLE_ID]) var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID]) + cg.add(parent.register_gatts_event_handler(var)) + cg.add(var.set_parent(parent)) + cg.add(var.set_manufacturer(config[CONF_MANUFACTURER])) if CONF_MODEL in config: cg.add(var.set_model(config[CONF_MODEL])) cg.add_define("USE_ESP32_BLE_SERVER") - cg.add(parent.set_server(var)) - if CORE.using_esp_idf: add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) diff --git a/esphome/components/esp32_ble_server/ble_server.cpp b/esphome/components/esp32_ble_server/ble_server.cpp index 15bea07021..7cbf40c076 100644 --- a/esphome/components/esp32_ble_server/ble_server.cpp +++ b/esphome/components/esp32_ble_server/ble_server.cpp @@ -25,7 +25,8 @@ static const uint16_t VERSION_UUID = 0x2A26; static const uint16_t MANUFACTURER_UUID = 0x2A29; void BLEServer::setup() { - if (this->is_failed()) { + if (this->parent_->is_failed()) { + this->mark_failed(); ESP_LOGE(TAG, "BLE Server was marked failed by ESP32BLE"); return; } diff --git a/esphome/components/esp32_ble_server/ble_server.h b/esphome/components/esp32_ble_server/ble_server.h index f82e854090..ac759f2dcd 100644 --- a/esphome/components/esp32_ble_server/ble_server.h +++ b/esphome/components/esp32_ble_server/ble_server.h @@ -3,6 +3,7 @@ #include "ble_service.h" #include "ble_characteristic.h" +#include "esphome/components/esp32_ble/ble.h" #include "esphome/components/esp32_ble/ble_advertising.h" #include "esphome/components/esp32_ble/ble_uuid.h" #include "esphome/components/esp32_ble/queue.h" @@ -32,7 +33,7 @@ class BLEServiceComponent { virtual void stop(); }; -class BLEServer : public Component { +class BLEServer : public Component, public GATTsEventHandler, public Parented { public: void setup() override; void loop() override; @@ -55,7 +56,8 @@ class BLEServer : public Component { uint32_t get_connected_client_count() { return this->connected_clients_; } const std::map &get_clients() { return this->clients_; } - void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); + void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) override; void register_service_component(BLEServiceComponent *component) { this->service_components_.push_back(component); } diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index c20491e701..23f109b5ac 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -15,10 +15,11 @@ from esphome.const import ( CONF_ON_BLE_SERVICE_DATA_ADVERTISE, CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE, ) +from esphome.components import esp32_ble from esphome.core import CORE from esphome.components.esp32 import add_idf_sdkconfig_option -from esphome.components import esp32_ble +AUTO_LOAD = ["esp32_ble"] DEPENDENCIES = ["esp32"] CONF_ESP32_BLE_ID = "esp32_ble_id" @@ -27,7 +28,13 @@ CONF_WINDOW = "window" CONF_CONTINUOUS = "continuous" CONF_ON_SCAN_END = "on_scan_end" esp32_ble_tracker_ns = cg.esphome_ns.namespace("esp32_ble_tracker") -ESP32BLETracker = esp32_ble_tracker_ns.class_("ESP32BLETracker", cg.Component) +ESP32BLETracker = esp32_ble_tracker_ns.class_( + "ESP32BLETracker", + cg.Component, + esp32_ble.GAPEventHandler, + esp32_ble.GATTcEventHandler, + cg.Parented.template(esp32_ble.ESP32BLE), +) ESPBTClient = esp32_ble_tracker_ns.class_("ESPBTClient") ESPBTDeviceListener = esp32_ble_tracker_ns.class_("ESPBTDeviceListener") ESPBTDevice = esp32_ble_tracker_ns.class_("ESPBTDevice") @@ -138,6 +145,7 @@ def as_reversed_hex_array(value): CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(ESP32BLETracker), + cv.GenerateID(esp32_ble.CONF_BLE_ID): cv.use_id(esp32_ble.ESP32BLE), cv.Optional(CONF_SCAN_PARAMETERS, default={}): cv.All( cv.Schema( { @@ -200,6 +208,12 @@ ESP_BLE_DEVICE_SCHEMA = cv.Schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) + + parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID]) + cg.add(parent.register_gap_event_handler(var)) + cg.add(parent.register_gattc_event_handler(var)) + cg.add(var.set_parent(parent)) + params = config[CONF_SCAN_PARAMETERS] cg.add(var.set_scan_duration(params[CONF_DURATION])) cg.add(var.set_scan_interval(int(params[CONF_INTERVAL].total_milliseconds / 0.625))) @@ -248,6 +262,7 @@ async def to_code(config): add_idf_sdkconfig_option("CONFIG_BTU_TASK_STACK_SIZE", 8192) cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts + cg.add_define("USE_ESP32_BLE_CLIENT") ESP32_BLE_START_SCAN_ACTION_SCHEMA = cv.Schema( diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 45509c489c..ea911d21e5 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -7,14 +7,14 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include -#include -#include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #ifdef USE_OTA #include "esphome/components/ota/ota_component.h" @@ -48,14 +48,16 @@ uint64_t ble_addr_to_uint64(const esp_bd_addr_t address) { float ESP32BLETracker::get_setup_priority() const { return setup_priority::BLUETOOTH; } void ESP32BLETracker::setup() { + if (this->parent_->is_failed()) { + this->mark_failed(); + ESP_LOGE(TAG, "BLE Tracker was marked failed by ESP32BLE"); + return; + } + global_esp32_ble_tracker = this; this->scan_result_lock_ = xSemaphoreCreateMutex(); this->scan_end_lock_ = xSemaphoreCreateMutex(); this->scanner_idle_ = true; - if (!ESP32BLETracker::ble_setup()) { - this->mark_failed(); - return; - } #ifdef USE_OTA ota::global_ota_component->add_on_state_callback([this](ota::OTAState state, float progress, uint8_t error) { @@ -75,18 +77,6 @@ void ESP32BLETracker::setup() { } void ESP32BLETracker::loop() { - BLEEvent *ble_event = this->ble_events_.pop(); - while (ble_event != nullptr) { - if (ble_event->type_) { - this->real_gattc_event_handler_(ble_event->event_.gattc.gattc_event, ble_event->event_.gattc.gattc_if, - &ble_event->event_.gattc.gattc_param); - } else { - this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param); - } - delete ble_event; // NOLINT(cppcoreguidelines-owning-memory) - ble_event = this->ble_events_.pop(); - } - int connecting = 0; int discovered = 0; int searching = 0; @@ -238,85 +228,6 @@ void ESP32BLETracker::stop_scan() { this->cancel_timeout("scan"); } -bool ESP32BLETracker::ble_setup() { - // Initialize non-volatile storage for the bluetooth controller - esp_err_t err = nvs_flash_init(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "nvs_flash_init failed: %d", err); - return false; - } - -#ifdef USE_ARDUINO - if (!btStart()) { - ESP_LOGE(TAG, "btStart failed: %d", esp_bt_controller_get_status()); - return false; - } -#else - if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { - // start bt controller - if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) { - esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - err = esp_bt_controller_init(&cfg); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bt_controller_init failed: %s", esp_err_to_name(err)); - return false; - } - while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) - ; - } - if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) { - err = esp_bt_controller_enable(ESP_BT_MODE_BLE); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bt_controller_enable failed: %s", esp_err_to_name(err)); - return false; - } - } - if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { - ESP_LOGE(TAG, "esp bt controller enable failed"); - return false; - } - } -#endif - - esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); - - err = esp_bluedroid_init(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bluedroid_init failed: %d", err); - return false; - } - err = esp_bluedroid_enable(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", err); - return false; - } - err = esp_ble_gap_register_callback(ESP32BLETracker::gap_event_handler); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_register_callback failed: %d", err); - return false; - } - err = esp_ble_gattc_register_callback(ESP32BLETracker::gattc_event_handler); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err); - return false; - } - - // Empty name - esp_ble_gap_set_device_name(""); - - esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; - err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_set_security_param failed: %d", err); - return false; - } - - // BLE takes some time to be fully set up, 200ms should be more than enough - delay(200); // NOLINT - - return true; -} - void ESP32BLETracker::start_scan_(bool first) { // The lock must be held when calling this function. if (xSemaphoreTake(this->scan_end_lock_, 0L)) { @@ -369,11 +280,6 @@ void ESP32BLETracker::register_client(ESPBTClient *client) { } void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { - BLEEvent *gap_event = new BLEEvent(event, param); // NOLINT(cppcoreguidelines-owning-memory) - global_esp32_ble_tracker->ble_events_.push(gap_event); -} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - -void ESP32BLETracker::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { switch (event) { case ESP_GAP_BLE_SCAN_RESULT_EVT: this->gap_scan_result_(param->scan_rst); @@ -428,204 +334,11 @@ void ESP32BLETracker::gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_re void ESP32BLETracker::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { - BLEEvent *gattc_event = new BLEEvent(event, gattc_if, param); // NOLINT(cppcoreguidelines-owning-memory) - global_esp32_ble_tracker->ble_events_.push(gattc_event); -} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - -void ESP32BLETracker::real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t *param) { for (auto *client : this->clients_) { client->gattc_event_handler(event, gattc_if, param); } } -ESPBTUUID::ESPBTUUID() : uuid_() {} -ESPBTUUID ESPBTUUID::from_uint16(uint16_t uuid) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_16; - ret.uuid_.uuid.uuid16 = uuid; - return ret; -} -ESPBTUUID ESPBTUUID::from_uint32(uint32_t uuid) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_32; - ret.uuid_.uuid.uuid32 = uuid; - return ret; -} -ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) { - ESPBTUUID ret; - ret.uuid_.len = ESP_UUID_LEN_128; - for (size_t i = 0; i < ESP_UUID_LEN_128; i++) - ret.uuid_.uuid.uuid128[i] = data[i]; - return ret; -} -ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { - ESPBTUUID ret; - if (data.length() == 4) { - ret.uuid_.len = ESP_UUID_LEN_16; - ret.uuid_.uuid.uuid16 = 0; - for (int i = 0; i < data.length();) { - uint8_t msb = data.c_str()[i]; - uint8_t lsb = data.c_str()[i + 1]; - - if (msb > '9') - msb -= 7; - if (lsb > '9') - lsb -= 7; - ret.uuid_.uuid.uuid16 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << (2 - i) * 4; - i += 2; - } - } else if (data.length() == 8) { - ret.uuid_.len = ESP_UUID_LEN_32; - ret.uuid_.uuid.uuid32 = 0; - for (int i = 0; i < data.length();) { - uint8_t msb = data.c_str()[i]; - uint8_t lsb = data.c_str()[i + 1]; - - if (msb > '9') - msb -= 7; - if (lsb > '9') - lsb -= 7; - ret.uuid_.uuid.uuid32 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << (6 - i) * 4; - i += 2; - } - } else if (data.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be - // investigated (lack of time) - ret.uuid_.len = ESP_UUID_LEN_128; - memcpy(ret.uuid_.uuid.uuid128, (uint8_t *) data.data(), 16); - } else if (data.length() == 36) { - // If the length of the string is 36 bytes then we will assume it is a long hex string in - // UUID format. - ret.uuid_.len = ESP_UUID_LEN_128; - int n = 0; - for (int i = 0; i < data.length();) { - if (data.c_str()[i] == '-') - i++; - uint8_t msb = data.c_str()[i]; - uint8_t lsb = data.c_str()[i + 1]; - - if (msb > '9') - msb -= 7; - if (lsb > '9') - lsb -= 7; - ret.uuid_.uuid.uuid128[15 - n++] = ((msb & 0x0F) << 4) | (lsb & 0x0F); - i += 2; - } - } else { - ESP_LOGE(TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes - %s", data.c_str()); - } - return ret; -} -ESPBTUUID ESPBTUUID::from_uuid(esp_bt_uuid_t uuid) { - ESPBTUUID ret; - ret.uuid_.len = uuid.len; - if (uuid.len == ESP_UUID_LEN_16) { - ret.uuid_.uuid.uuid16 = uuid.uuid.uuid16; - } else if (uuid.len == ESP_UUID_LEN_32) { - ret.uuid_.uuid.uuid32 = uuid.uuid.uuid32; - } else if (uuid.len == ESP_UUID_LEN_128) { - memcpy(ret.uuid_.uuid.uuid128, uuid.uuid.uuid128, ESP_UUID_LEN_128); - } - return ret; -} -ESPBTUUID ESPBTUUID::as_128bit() const { - if (this->uuid_.len == ESP_UUID_LEN_128) { - return *this; - } - uint8_t data[] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint32_t uuid32; - if (this->uuid_.len == ESP_UUID_LEN_32) { - uuid32 = this->uuid_.uuid.uuid32; - } else { - uuid32 = this->uuid_.uuid.uuid16; - } - for (uint8_t i = 0; i < this->uuid_.len; i++) { - data[12 + i] = ((uuid32 >> i * 8) & 0xFF); - } - return ESPBTUUID::from_raw(data); -} -bool ESPBTUUID::contains(uint8_t data1, uint8_t data2) const { - if (this->uuid_.len == ESP_UUID_LEN_16) { - return (this->uuid_.uuid.uuid16 >> 8) == data2 && (this->uuid_.uuid.uuid16 & 0xFF) == data1; - } else if (this->uuid_.len == ESP_UUID_LEN_32) { - for (uint8_t i = 0; i < 3; i++) { - bool a = ((this->uuid_.uuid.uuid32 >> i * 8) & 0xFF) == data1; - bool b = ((this->uuid_.uuid.uuid32 >> (i + 1) * 8) & 0xFF) == data2; - if (a && b) - return true; - } - } else { - for (uint8_t i = 0; i < 15; i++) { - if (this->uuid_.uuid.uuid128[i] == data1 && this->uuid_.uuid.uuid128[i + 1] == data2) - return true; - } - } - return false; -} -bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const { - if (this->uuid_.len == uuid.uuid_.len) { - switch (this->uuid_.len) { - case ESP_UUID_LEN_16: - if (uuid.uuid_.uuid.uuid16 == this->uuid_.uuid.uuid16) { - return true; - } - break; - case ESP_UUID_LEN_32: - if (uuid.uuid_.uuid.uuid32 == this->uuid_.uuid.uuid32) { - return true; - } - break; - case ESP_UUID_LEN_128: - for (int i = 0; i < ESP_UUID_LEN_128; i++) { - if (uuid.uuid_.uuid.uuid128[i] != this->uuid_.uuid.uuid128[i]) { - return false; - } - } - return true; - break; - } - } else { - return this->as_128bit() == uuid.as_128bit(); - } - return false; -} -esp_bt_uuid_t ESPBTUUID::get_uuid() const { return this->uuid_; } -std::string ESPBTUUID::to_string() const { - switch (this->uuid_.len) { - case ESP_UUID_LEN_16: - return str_snprintf("0x%02X%02X", 6, this->uuid_.uuid.uuid16 >> 8, this->uuid_.uuid.uuid16 & 0xff); - case ESP_UUID_LEN_32: - return str_snprintf("0x%02X%02X%02X%02X", 10, this->uuid_.uuid.uuid32 >> 24, - (this->uuid_.uuid.uuid32 >> 16 & 0xff), (this->uuid_.uuid.uuid32 >> 8 & 0xff), - this->uuid_.uuid.uuid32 & 0xff); - default: - case ESP_UUID_LEN_128: - std::string buf; - for (uint8_t i = 0; i < 16; i++) { - buf += str_snprintf("%02X", 2, this->uuid_.uuid.uuid128[i]); - if (i == 3 || i == 5 || i == 7 || i == 9) - buf += "-"; - } - return buf; - } - return ""; -} - -uint64_t ESPBTUUID::get_128bit_high() const { - esp_bt_uuid_t uuid = this->as_128bit().get_uuid(); - return ((uint64_t) uuid.uuid.uuid128[15] << 56) | ((uint64_t) uuid.uuid.uuid128[14] << 48) | - ((uint64_t) uuid.uuid.uuid128[13] << 40) | ((uint64_t) uuid.uuid.uuid128[12] << 32) | - ((uint64_t) uuid.uuid.uuid128[11] << 24) | ((uint64_t) uuid.uuid.uuid128[10] << 16) | - ((uint64_t) uuid.uuid.uuid128[9] << 8) | ((uint64_t) uuid.uuid.uuid128[8]); -} -uint64_t ESPBTUUID::get_128bit_low() const { - esp_bt_uuid_t uuid = this->as_128bit().get_uuid(); - return ((uint64_t) uuid.uuid.uuid128[7] << 56) | ((uint64_t) uuid.uuid.uuid128[6] << 48) | - ((uint64_t) uuid.uuid.uuid128[5] << 40) | ((uint64_t) uuid.uuid.uuid128[4] << 32) | - ((uint64_t) uuid.uuid.uuid128[3] << 24) | ((uint64_t) uuid.uuid.uuid128[2] << 16) | - ((uint64_t) uuid.uuid.uuid128[1] << 8) | ((uint64_t) uuid.uuid.uuid128[0]); -} - ESPBLEiBeacon::ESPBLEiBeacon(const uint8_t *data) { memcpy(&this->beacon_data_, data, sizeof(beacon_data_)); } optional ESPBLEiBeacon::from_manufacturer_data(const ServiceData &data) { if (!data.uuid.contains(0x4C, 0x00)) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index e6f7829353..d1f72cf78d 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -1,9 +1,8 @@ #pragma once -#include "esphome/core/component.h" #include "esphome/core/automation.h" +#include "esphome/core/component.h" #include "esphome/core/helpers.h" -#include "queue.h" #include #include @@ -15,40 +14,16 @@ #include #include +#include +#include + +#include "esphome/components/esp32_ble/ble.h" +#include "esphome/components/esp32_ble/ble_uuid.h" + namespace esphome { namespace esp32_ble_tracker { -class ESPBTUUID { - public: - ESPBTUUID(); - - static ESPBTUUID from_uint16(uint16_t uuid); - - static ESPBTUUID from_uint32(uint32_t uuid); - - static ESPBTUUID from_raw(const uint8_t *data); - - static ESPBTUUID from_raw(const std::string &data); - - static ESPBTUUID from_uuid(esp_bt_uuid_t uuid); - - ESPBTUUID as_128bit() const; - - bool contains(uint8_t data1, uint8_t data2) const; - - bool operator==(const ESPBTUUID &uuid) const; - bool operator!=(const ESPBTUUID &uuid) const { return !(*this == uuid); } - - esp_bt_uuid_t get_uuid() const; - - std::string to_string() const; - - uint64_t get_128bit_high() const; - uint64_t get_128bit_low() const; - - protected: - esp_bt_uuid_t uuid_; -}; +using namespace esp32_ble; using adv_data_t = std::vector; @@ -191,7 +166,7 @@ class ESPBTClient : public ESPBTDeviceListener { ClientState state_; }; -class ESP32BLETracker : public Component { +class ESP32BLETracker : public Component, public GAPEventHandler, public GATTcEventHandler, public Parented { public: void set_scan_duration(uint32_t scan_duration) { scan_duration_ = scan_duration; } void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; } @@ -218,16 +193,15 @@ class ESP32BLETracker : public Component { void start_scan(); void stop_scan(); + void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) override; + void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; + protected: - /// The FreeRTOS task managing the bluetooth interface. - static bool ble_setup(); /// Start a single scan by setting up the parameters and doing some esp-idf calls. void start_scan_(bool first); /// Called when a scan ends void end_of_scan_(); - /// Callback that will handle all GAP events and redistribute them to other callbacks. - static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); - void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); /// Called when a `ESP_GAP_BLE_SCAN_RESULT_EVT` event is received. void gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m); /// Called when a `ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT` event is received. @@ -238,9 +212,6 @@ class ESP32BLETracker : public Component { void gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param ¶m); int app_id_; - /// Callback that will handle all GATTC events and redistribute them to other callbacks. - static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); - void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); /// Vector of addresses that have already been printed in print_bt_device_info std::vector already_discovered_; @@ -263,8 +234,6 @@ class ESP32BLETracker : public Component { esp_ble_gap_cb_param_t::ble_scan_result_evt_param scan_result_buffer_[16]; esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS}; esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS}; - - Queue ble_events_; }; // NOLINTNEXTLINE diff --git a/esphome/components/esp32_improv/__init__.py b/esphome/components/esp32_improv/__init__.py index 1e50418e01..7170a6dabf 100644 --- a/esphome/components/esp32_improv/__init__.py +++ b/esphome/components/esp32_improv/__init__.py @@ -6,7 +6,7 @@ from esphome.const import CONF_ID AUTO_LOAD = ["binary_sensor", "output", "esp32_ble_server"] CODEOWNERS = ["@jesserockz"] -CONFLICTS_WITH = ["esp32_ble_tracker", "esp32_ble_beacon"] +CONFLICTS_WITH = ["esp32_ble_beacon"] DEPENDENCIES = ["wifi", "esp32"] CONF_AUTHORIZED_DURATION = "authorized_duration"