diff --git a/esphome/components/bluetooth_connection/bluetooth_connection_esp32.cpp b/esphome/components/bluetooth_connection/bluetooth_connection_esp32.cpp index be6fa4c6c52..f5c59ca43a5 100644 --- a/esphome/components/bluetooth_connection/bluetooth_connection_esp32.cpp +++ b/esphome/components/bluetooth_connection/bluetooth_connection_esp32.cpp @@ -479,12 +479,6 @@ esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enabl return this->check_and_log_error_("esp_ble_gattc_unregister_for_notify", err); } -esp32_ble_tracker::AdvertisementParserType BluetoothConnection::get_advertisement_parser_type() { - // RAW keeps the tracker from building parsed ESPBTDevice objects for the - // proxy's connections (the proxy itself consumes the hub raw callback). - return esp32_ble_tracker::AdvertisementParserType::RAW_ADVERTISEMENTS; -} - } // namespace esphome::bluetooth_connection #endif // USE_ESP32 diff --git a/esphome/components/bluetooth_connection/bluetooth_connection_esp32.h b/esphome/components/bluetooth_connection/bluetooth_connection_esp32.h index 531ff311a79..fb60d93e9c0 100644 --- a/esphome/components/bluetooth_connection/bluetooth_connection_esp32.h +++ b/esphome/components/bluetooth_connection/bluetooth_connection_esp32.h @@ -21,7 +21,8 @@ class BluetoothConnection final : public esp32_ble_client::BLEClientBase { bool 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; - esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override; + // The proxy's connections never consume parsed ESPBTDevice objects. + bool wants_parsed_advertisements() override { return false; } esp_err_t read_characteristic(uint16_t handle); esp_err_t write_characteristic(uint16_t handle, const uint8_t *data, size_t length, bool response); diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index 86d45c144a1..9fc975680ea 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -20,10 +20,6 @@ #include "esphome/components/bluetooth_connection/bluetooth_connection_esp32.h" -#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID -#include -#endif -#include #else #include "esphome/components/ble_device_base/ble_hub.h" #ifdef USE_BLE_GATT_CLIENT @@ -179,28 +175,15 @@ class BluetoothProxy final : public Component { } void get_bluetooth_mac_address_pretty(std::span output) { -#ifdef USE_ESP32 - const uint8_t *mac = esp_bt_dev_get_address(); - if (mac != nullptr) { - format_mac_addr_upper(mac, output.data()); - } else { - output[0] = '\0'; - } -#else uint8_t mac[6] = {}; this->hub_->get_adapter_mac(mac); - // Mirror the esp32 arm's unavailable -> empty-string fallback: some hubs - // (rp2040's BTstack) only learn the address once the link layer is up, and - // report all-zero until then. - bool nonzero = false; - for (uint8_t b : mac) - nonzero |= b != 0; - if (nonzero) { + // Unavailable -> empty string: some hubs (rp2040's BTstack) only learn + // the address once the link layer is up, and report all-zero until then. + if (mac_address_is_valid(mac)) { format_mac_addr_upper(mac, output.data()); } else { output[0] = '\0'; } -#endif } protected: diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index fb75e8837f2..d11683ab353 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -674,11 +674,23 @@ void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gat } #endif +void ESP32BLE::get_mac_msb_first(uint8_t out[6]) const { + // The running stack owns the address (on hosted controllers it lives in + // the remote chip's efuse); null before init becomes all-zero. + const uint8_t *mac = esp_bt_dev_get_address(); + if (mac != nullptr) { + memcpy(out, mac, 6); + } else { + memset(out, 0, 6); + } +} + float ESP32BLE::get_setup_priority() const { return setup_priority::BLUETOOTH; } void ESP32BLE::dump_config() { - const uint8_t *mac_address = esp_bt_dev_get_address(); - if (mac_address) { + uint8_t mac_address[6]; + this->get_mac_msb_first(mac_address); + if (mac_address_is_valid(mac_address)) { const char *io_capability_s; switch (this->io_cap_) { case ESP_IO_CAP_OUT: diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index c85ddfc983f..45cfd8ee714 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -108,6 +108,8 @@ class ESP32BLE final : public Component { void setup() override; void loop() override; void dump_config() override; + /// Adapter MAC in printable (MSB-first) order; all-zero until the stack is up. + void get_mac_msb_first(uint8_t out[6]) const; float get_setup_priority() const override; void set_name(const char *name) { this->name_ = name; } diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index e51b293bfed..0950bfeb701 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -271,7 +271,9 @@ void ESP32BLETracker::register_client(ESPBTClient *client) { // Safe because ESP32BLETracker (singleton) outlives all registered clients. client->set_tracker_state_version(&this->state_version_); this->clients_.push_back(client); - this->recalculate_advertisement_parser_types(); + // Registration is add-only, so the flag is a monotonic OR. + if (client->wants_parsed_advertisements()) + this->parse_advertisements_ = true; #endif } @@ -283,48 +285,11 @@ void ESP32BLETracker::register_listener(ble_device_base::ESPBTDeviceListener *li #endif } -void ESP32BLETracker::get_adapter_mac(uint8_t out[6]) { - get_mac_address_raw(out); // WiFi base MAC, MSB-first - // BT MAC = base MAC + 2 on the last octet only, wrapping without carry — - // exactly ESP-IDF's esp_read_mac(ESP_MAC_BT): mac[5] += MAC_ADDR_UNIVERSE_BT_OFFSET. - out[5] += 2; -} - void ESP32BLETracker::register_listener(ESPBTDeviceListener *listener) { #ifdef ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT listener->set_parent(this); this->listeners_.push_back(listener); - this->recalculate_advertisement_parser_types(); -#endif -} - -void ESP32BLETracker::recalculate_advertisement_parser_types() { - this->raw_advertisements_ = false; - this->parse_advertisements_ = false; -#ifdef ESPHOME_BLE_DEVICE_BASE_LISTENER_COUNT - // Neutral (BLEHub) listeners are parsed-advertisement consumers and are not in - // listeners_; without this, any later esp32-path registration (e.g. the proxy's - // GATT clients) would recompute the flags and silently drop parsed dispatch. - if (!this->neutral_listeners_.empty()) - this->parse_advertisements_ = true; -#endif -#ifdef ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT - for (auto *listener : this->listeners_) { - if (listener->get_advertisement_parser_type() == AdvertisementParserType::PARSED_ADVERTISEMENTS) { - this->parse_advertisements_ = true; - } else { - this->raw_advertisements_ = true; - } - } -#endif -#ifdef ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT - for (auto *client : this->clients_) { - if (client->get_advertisement_parser_type() == AdvertisementParserType::PARSED_ADVERTISEMENTS) { - this->parse_advertisements_ = true; - } else { - this->raw_advertisements_ = true; - } - } + this->parse_advertisements_ = true; #endif } @@ -478,20 +443,6 @@ void ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) { this->raw_advertisement_callback_.invoke(adv); } - // Process raw advertisements - if (this->raw_advertisements_) { -#ifdef ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT - for (auto *listener : this->listeners_) { - listener->parse_devices(&scan_result, 1); - } -#endif -#ifdef ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT - for (auto *client : this->clients_) { - client->parse_devices(&scan_result, 1); - } -#endif - } - // Process parsed advertisements if (this->parse_advertisements_) { #ifdef USE_ESP32_BLE_DEVICE diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index c570c281220..ee1b1429c08 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -35,11 +35,6 @@ using namespace esp32_ble; using adv_data_t = ble_device_base::adv_data_t; -enum AdvertisementParserType { - PARSED_ADVERTISEMENTS, - RAW_ADVERTISEMENTS, -}; - #ifdef USE_ESP32_BLE_UUID using ServiceData = ble_device_base::ServiceData; #endif @@ -63,10 +58,6 @@ class ESPBTDeviceListener : public ble_device_base::ESPBTDeviceListener { // Raw-only build: no parsed-device support is compiled in. bool parse_device(const ble_device_base::ESPBTDevice &device) override { return false; } #endif - virtual bool parse_devices(const BLEScanResult *scan_results, size_t count) { return false; }; - virtual AdvertisementParserType get_advertisement_parser_type() { - return AdvertisementParserType::PARSED_ADVERTISEMENTS; - }; void set_parent(ESP32BLETracker *parent) { parent_ = parent; } protected: @@ -123,6 +114,10 @@ class BLEScannerStateListener { /// The pointer may be null if the client is not registered with a tracker. class ESPBTClient : public ESPBTDeviceListener { public: + /// False keeps the tracker from building parsed ESPBTDevice objects on + /// this client's account (raw consumers use the hub callback). + virtual bool wants_parsed_advertisements() { return true; } + virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) = 0; virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0; @@ -199,7 +194,6 @@ class ESP32BLETracker final : public Component, // esp32-flavored path (unmigrated esp32 sensors; sets the tracker back-pointer). void register_listener(ESPBTDeviceListener *listener); void register_client(ESPBTClient *client); - void recalculate_advertisement_parser_types(); // ---- ble_device_base::BLEHub (the platform-neutral tracker contract) ---- void register_listener(ble_device_base::ESPBTDeviceListener *listener) override; @@ -212,7 +206,7 @@ class ESP32BLETracker final : public Component, return {/* active_scan = */ true, /* merges_scan_response = */ true, /* gatt = */ true, /* scan_mode_switch = */ false}; } - void get_adapter_mac(uint8_t out[6]) override; + void get_adapter_mac(uint8_t out[6]) override { this->parent_->get_mac_msb_first(out); } bool scan_running() override { return this->scanner_state_ == ScannerState::RUNNING; } bool scan_active() override { return this->scan_active_; } @@ -355,7 +349,6 @@ class ESP32BLETracker final : public Component, bool scan_continuous_before_ota_{false}; #endif bool ble_was_disabled_{true}; - bool raw_advertisements_{false}; bool parse_advertisements_{false}; #ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE bool coex_prefer_ble_{false};