Skip to content

Conversation

@bdraco
Copy link
Member

@bdraco bdraco commented Oct 12, 2025

Proposed change

Fixes Bluetooth device discovery for devices that alternate advertisement names to work within the 31-byte BLE advertisement size limit.

This PR fixes a bug where Bluetooth devices that alternate their advertised name would not trigger re-discovery. This critically affects devices that must alternate between short names (with sensor data) and full names (with minimal data) due to the 31-byte BLE advertisement constraint.

User impact: Many integrations discover devices by matching local_name patterns (e.g., Govee*, SensorPush*, Inkbird*, Ruuvi *, etc.). Bluetooth LE advertisements are limited to 31 bytes, so devices often alternate between different advertisement packets - some with a short name and sensor data, others with a full name but less data. When the matcher only sees the short name advertisement first, re-discovery does not fire when the full name advertisement is later received, so these devices are never discovered at all if the short name doesn't match the pattern.

Example: A SensorPush device alternates advertisements:

  • Advertisement 1: name=s + temperature/humidity data (fits in 31 bytes)
  • Advertisement 2: name=SensorPush HT.w 12345 + minimal data (fits in 31 bytes)

Without this fix, if the matcher sees advertisement 1 first, the sensorpush integration (which matches local_name: "SensorPush*") never discovers the device because re-discovery doesn't fire when advertisement 2 with the full name arrives.

This is standard BLE behavior where devices alternate advertisement content to work within the 31-byte limit.

Root cause: The IntegrationMatchHistory class tracked which advertisement fields (manufacturer_data, service_data, service_uuids) had been seen for each device to optimize matcher performance. However, it did not track the device name. When a device's name changed but other fields remained the same, seen_all_fields() would incorrectly return True, causing an early return with an empty match set instead of re-evaluating the device against matchers.

Fix: Added name field to IntegrationMatchHistory and updated seen_all_fields() to check if the name has changed. When the name changes, the device is now re-evaluated against all matchers, triggering a second discovery that allows integrations to update the device information.

Example scenario:

SensorPush device alternating advertisements:

  1. Advertisement 1: name=s + sensor data → no match (doesn't match SensorPush* pattern)
  2. Advertisement 2: name=SensorPush HT.w 12345 + minimal data → previously returned empty match, device never discovered
  3. With this fix → matches sensorpush by name pattern, device is discovered

This same issue affects many other integrations that match by local_name pattern including Govee, Inkbird, Ruuvi, and dozens of others listed in bluetooth.py.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request: N/A
  • Link to developer documentation pull request: N/A
  • Link to frontend pull request: N/A

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.

To help with the load of incoming pull requests:

@bdraco bdraco changed the title Fix Bluetooth discovery when device name changes Fix Bluetooth discovery for devices with alternating advertisement names Oct 13, 2025
@bdraco bdraco added this to the 2025.10.3 milestone Oct 13, 2025
@bdraco bdraco marked this pull request as ready for review October 13, 2025 00:10
Copilot AI review requested due to automatic review settings October 13, 2025 00:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a Bluetooth discovery bug where devices that alternate their advertisement names to work within BLE's 31-byte limit would not be re-discovered when their name changed. The issue prevented many integrations from discovering devices that match by name patterns (e.g., SensorPush*, Govee*) when the device's first advertisement used a short name that didn't match the pattern.

  • Adds name tracking to the IntegrationMatchHistory class to detect when device names change
  • Updates the seen_all_fields() function to trigger re-evaluation when names change
  • Includes comprehensive test coverage for the name change scenario

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
homeassistant/components/bluetooth/match.py Added name field to IntegrationMatchHistory and updated matching logic to re-evaluate devices when names change
tests/components/bluetooth/test_init.py Added test case verifying discovery works when device name changes from MAC address to real name

@balloob balloob merged commit 94d015e into home-assistant:dev Oct 13, 2025
48 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Oct 14, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants