diff --git a/.github/workflows/auto-label-pr.yml b/.github/workflows/auto-label-pr.yml index 748235df30..c42b5330d2 100644 --- a/.github/workflows/auto-label-pr.yml +++ b/.github/workflows/auto-label-pr.yml @@ -382,7 +382,7 @@ jobs: const labels = new Set(); // Check for missing tests - if ((allLabels.has('new-component') || allLabels.has('new-platform')) && !allLabels.has('has-tests')) { + if ((allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) && !allLabels.has('has-tests')) { labels.add('needs-tests'); } diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index ba5f994e9a..2672ea1edb 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -321,6 +321,7 @@ HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA = cv.maybe_simple_value( HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA, ) async def homeassistant_tag_scanned_to_code(config, action_id, template_arg, args): + cg.add_define("USE_API_HOMEASSISTANT_SERVICES") serv = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, serv, True) cg.add(var.set_service("esphome.tag_scanned")) diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index 723466a5ff..80b7fbe960 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -183,6 +183,12 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest this->send_device_connection(msg.address, false); return; } + if (!msg.has_address_type) { + ESP_LOGE(TAG, "[%d] [%s] Missing address type in connect request", connection->get_connection_index(), + connection->address_str().c_str()); + this->send_device_connection(msg.address, false); + return; + } if (connection->state() == espbt::ClientState::CONNECTED || connection->state() == espbt::ClientState::ESTABLISHED) { this->log_connection_request_ignored_(connection, connection->state()); @@ -209,13 +215,9 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest connection->set_connection_type(espbt::ConnectionType::V3_WITHOUT_CACHE); this->log_connection_info_(connection, "v3 without cache"); } - if (msg.has_address_type) { - uint64_to_bd_addr(msg.address, connection->remote_bda_); - connection->set_remote_addr_type(static_cast(msg.address_type)); - connection->set_state(espbt::ClientState::DISCOVERED); - } else { - connection->set_state(espbt::ClientState::SEARCHING); - } + uint64_to_bd_addr(msg.address, connection->remote_bda_); + connection->set_remote_addr_type(static_cast(msg.address_type)); + connection->set_state(espbt::ClientState::DISCOVERED); this->send_connections_free(); break; } diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index e23be2e0c1..30e1866f9f 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -92,7 +92,7 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) { return false; if (this->address_ == 0 || device.address_uint64() != this->address_) return false; - if (this->state_ != espbt::ClientState::IDLE && this->state_ != espbt::ClientState::SEARCHING) + if (this->state_ != espbt::ClientState::IDLE) return false; this->log_event_("Found device"); @@ -190,8 +190,7 @@ void BLEClientBase::unconditional_disconnect() { this->log_gattc_warning_("esp_ble_gattc_close", err); } - if (this->state_ == espbt::ClientState::SEARCHING || this->state_ == espbt::ClientState::READY_TO_CONNECT || - this->state_ == espbt::ClientState::DISCOVERED) { + if (this->state_ == espbt::ClientState::READY_TO_CONNECT || this->state_ == espbt::ClientState::DISCOVERED) { this->set_address(0); this->set_state(espbt::ClientState::IDLE); } else { diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 0455d136df..0edde169eb 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -49,8 +49,6 @@ const char *client_state_to_string(ClientState state) { return "DISCONNECTING"; case ClientState::IDLE: return "IDLE"; - case ClientState::SEARCHING: - return "SEARCHING"; case ClientState::DISCOVERED: return "DISCOVERED"; case ClientState::READY_TO_CONNECT: @@ -136,9 +134,8 @@ void ESP32BLETracker::loop() { ClientStateCounts counts = this->count_client_states_(); if (counts != this->client_state_counts_) { this->client_state_counts_ = counts; - ESP_LOGD(TAG, "connecting: %d, discovered: %d, searching: %d, disconnecting: %d", - this->client_state_counts_.connecting, this->client_state_counts_.discovered, - this->client_state_counts_.searching, this->client_state_counts_.disconnecting); + ESP_LOGD(TAG, "connecting: %d, discovered: %d, disconnecting: %d", this->client_state_counts_.connecting, + this->client_state_counts_.discovered, this->client_state_counts_.disconnecting); } if (this->scanner_state_ == ScannerState::FAILED || @@ -158,10 +155,8 @@ void ESP32BLETracker::loop() { https://github.com/espressif/esp-idf/issues/6688 */ - bool promote_to_connecting = counts.discovered && !counts.searching && !counts.connecting; - if (this->scanner_state_ == ScannerState::IDLE && !counts.connecting && !counts.disconnecting && - !promote_to_connecting) { + if (this->scanner_state_ == ScannerState::IDLE && !counts.connecting && !counts.disconnecting && !counts.discovered) { #ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE this->update_coex_preference_(false); #endif @@ -170,12 +165,11 @@ void ESP32BLETracker::loop() { } } // If there is a discovered client and no connecting - // clients and no clients using the scanner to search for - // devices, then promote the discovered client to ready to connect. + // clients, then promote the discovered client to ready to connect. // We check both RUNNING and IDLE states because: // - RUNNING: gap_scan_event_handler initiates stop_scan_() but promotion can happen immediately // - IDLE: Scanner has already stopped (naturally or by gap_scan_event_handler) - if (promote_to_connecting && + if (counts.discovered && !counts.connecting && (this->scanner_state_ == ScannerState::RUNNING || this->scanner_state_ == ScannerState::IDLE)) { this->try_promote_discovered_clients_(); } @@ -307,14 +301,7 @@ void ESP32BLETracker::gap_scan_event_handler(const BLEScanResult &scan_result) { if (scan_result.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { // Process the scan result immediately - bool found_discovered_client = this->process_scan_result_(scan_result); - - // If we found a discovered client that needs promotion, stop scanning - // This replaces the promote_to_connecting logic from loop() - if (found_discovered_client && this->scanner_state_ == ScannerState::RUNNING) { - ESP_LOGD(TAG, "Found discovered client, stopping scan for connection"); - this->stop_scan_(); - } + this->process_scan_result_(scan_result); } else if (scan_result.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) { // Scan finished on its own if (this->scanner_state_ != ScannerState::RUNNING) { @@ -640,9 +627,8 @@ void ESP32BLETracker::dump_config() { this->scan_duration_, this->scan_interval_ * 0.625f, this->scan_window_ * 0.625f, this->scan_active_ ? "ACTIVE" : "PASSIVE", YESNO(this->scan_continuous_)); ESP_LOGCONFIG(TAG, " Scanner State: %s", this->scanner_state_to_string_(this->scanner_state_)); - ESP_LOGCONFIG(TAG, " Connecting: %d, discovered: %d, searching: %d, disconnecting: %d", - this->client_state_counts_.connecting, this->client_state_counts_.discovered, - this->client_state_counts_.searching, this->client_state_counts_.disconnecting); + ESP_LOGCONFIG(TAG, " Connecting: %d, discovered: %d, disconnecting: %d", this->client_state_counts_.connecting, + this->client_state_counts_.discovered, this->client_state_counts_.disconnecting); if (this->scan_start_fail_count_) { ESP_LOGCONFIG(TAG, " Scan Start Fail Count: %d", this->scan_start_fail_count_); } @@ -720,20 +706,9 @@ bool ESPBTDevice::resolve_irk(const uint8_t *irk) const { ecb_ciphertext[13] == ((addr64 >> 16) & 0xff); } -bool ESP32BLETracker::has_connecting_clients_() const { - for (auto *client : this->clients_) { - auto state = client->state(); - if (state == ClientState::CONNECTING || state == ClientState::READY_TO_CONNECT) { - return true; - } - } - return false; -} #endif // USE_ESP32_BLE_DEVICE -bool ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) { - bool found_discovered_client = false; - +void ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) { // Process raw advertisements if (this->raw_advertisements_) { for (auto *listener : this->listeners_) { @@ -759,14 +734,6 @@ bool ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) { for (auto *client : this->clients_) { if (client->parse_device(device)) { found = true; - // Check if this client is discovered and needs promotion - if (client->state() == ClientState::DISCOVERED) { - // Only check for connecting clients if we found a discovered client - // This matches the original logic: !connecting && client->state() == DISCOVERED - if (!this->has_connecting_clients_()) { - found_discovered_client = true; - } - } } } @@ -775,8 +742,6 @@ bool ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) { } #endif // USE_ESP32_BLE_DEVICE } - - return found_discovered_client; } void ESP32BLETracker::cleanup_scan_state_(bool is_stop_complete) { diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 3022eb25d2..c369608d18 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -141,12 +141,10 @@ class ESPBTDeviceListener { struct ClientStateCounts { uint8_t connecting = 0; uint8_t discovered = 0; - uint8_t searching = 0; uint8_t disconnecting = 0; bool operator==(const ClientStateCounts &other) const { - return connecting == other.connecting && discovered == other.discovered && searching == other.searching && - disconnecting == other.disconnecting; + return connecting == other.connecting && discovered == other.discovered && disconnecting == other.disconnecting; } bool operator!=(const ClientStateCounts &other) const { return !(*this == other); } @@ -159,8 +157,6 @@ enum class ClientState : uint8_t { DISCONNECTING, // Connection is idle, no device detected. IDLE, - // Searching for device. - SEARCHING, // Device advertisement found. DISCOVERED, // Device is discovered and the scanner is stopped @@ -321,9 +317,6 @@ class ESP32BLETracker : public Component, case ClientState::DISCOVERED: counts.discovered++; break; - case ClientState::SEARCHING: - counts.searching++; - break; case ClientState::CONNECTING: case ClientState::READY_TO_CONNECT: counts.connecting++;