mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 10:47:10 +00:00
Fix ESPHome Bluetooth diagnostics (#106151)
This commit is contained in:
parent
ced4123d4c
commit
e2314565bb
@ -32,12 +32,13 @@ async def async_get_config_entry_diagnostics(
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
config_entry.unique_id
|
config_entry.unique_id
|
||||||
and (scanner := async_scanner_by_source(hass, config_entry.unique_id))
|
and (scanner := async_scanner_by_source(hass, config_entry.unique_id.upper()))
|
||||||
and (bluetooth_device := entry_data.bluetooth_device)
|
and (bluetooth_device := entry_data.bluetooth_device)
|
||||||
):
|
):
|
||||||
diag["bluetooth"] = {
|
diag["bluetooth"] = {
|
||||||
"connections_free": bluetooth_device.ble_connections_free,
|
"connections_free": bluetooth_device.ble_connections_free,
|
||||||
"connections_limit": bluetooth_device.ble_connections_limit,
|
"connections_limit": bluetooth_device.ble_connections_limit,
|
||||||
|
"available": bluetooth_device.available,
|
||||||
"scanner": await scanner.async_diagnostics(),
|
"scanner": await scanner.async_diagnostics(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ def mock_config_entry(hass) -> MockConfigEntry:
|
|||||||
CONF_NOISE_PSK: "12345678123456781234567812345678",
|
CONF_NOISE_PSK: "12345678123456781234567812345678",
|
||||||
CONF_DEVICE_NAME: "test",
|
CONF_DEVICE_NAME: "test",
|
||||||
},
|
},
|
||||||
|
# ESPHome unique ids are lower case
|
||||||
unique_id="11:22:33:44:55:aa",
|
unique_id="11:22:33:44:55:aa",
|
||||||
)
|
)
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
@ -96,7 +97,8 @@ def mock_device_info() -> DeviceInfo:
|
|||||||
uses_password=False,
|
uses_password=False,
|
||||||
name="test",
|
name="test",
|
||||||
legacy_bluetooth_proxy_version=0,
|
legacy_bluetooth_proxy_version=0,
|
||||||
mac_address="11:22:33:44:55:aa",
|
# ESPHome mac addresses are UPPER case
|
||||||
|
mac_address="11:22:33:44:55:AA",
|
||||||
esphome_version="1.0.0",
|
esphome_version="1.0.0",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -230,7 +232,7 @@ async def _mock_generic_device_entry(
|
|||||||
"name": "test",
|
"name": "test",
|
||||||
"friendly_name": "Test",
|
"friendly_name": "Test",
|
||||||
"esphome_version": "1.0.0",
|
"esphome_version": "1.0.0",
|
||||||
"mac_address": "11:22:33:44:55:aa",
|
"mac_address": "11:22:33:44:55:AA",
|
||||||
}
|
}
|
||||||
device_info = DeviceInfo(**(default_device_info | mock_device_info))
|
device_info = DeviceInfo(**(default_device_info | mock_device_info))
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ async def test_bluetooth_connect_with_raw_adv(
|
|||||||
hass: HomeAssistant, mock_bluetooth_entry_with_raw_adv: MockESPHomeDevice
|
hass: HomeAssistant, mock_bluetooth_entry_with_raw_adv: MockESPHomeDevice
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test bluetooth connect with raw advertisements."""
|
"""Test bluetooth connect with raw advertisements."""
|
||||||
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:aa")
|
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:AA")
|
||||||
assert scanner is not None
|
assert scanner is not None
|
||||||
assert scanner.connectable is True
|
assert scanner.connectable is True
|
||||||
assert scanner.scanning is True
|
assert scanner.scanning is True
|
||||||
@ -18,11 +18,11 @@ async def test_bluetooth_connect_with_raw_adv(
|
|||||||
await mock_bluetooth_entry_with_raw_adv.mock_disconnect(True)
|
await mock_bluetooth_entry_with_raw_adv.mock_disconnect(True)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:aa")
|
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:AA")
|
||||||
assert scanner is None
|
assert scanner is None
|
||||||
await mock_bluetooth_entry_with_raw_adv.mock_connect()
|
await mock_bluetooth_entry_with_raw_adv.mock_connect()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:aa")
|
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:AA")
|
||||||
assert scanner.scanning is True
|
assert scanner.scanning is True
|
||||||
|
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ async def test_bluetooth_connect_with_legacy_adv(
|
|||||||
hass: HomeAssistant, mock_bluetooth_entry_with_legacy_adv: MockESPHomeDevice
|
hass: HomeAssistant, mock_bluetooth_entry_with_legacy_adv: MockESPHomeDevice
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test bluetooth connect with legacy advertisements."""
|
"""Test bluetooth connect with legacy advertisements."""
|
||||||
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:aa")
|
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:AA")
|
||||||
assert scanner is not None
|
assert scanner is not None
|
||||||
assert scanner.connectable is True
|
assert scanner.connectable is True
|
||||||
assert scanner.scanning is True
|
assert scanner.scanning is True
|
||||||
@ -38,9 +38,9 @@ async def test_bluetooth_connect_with_legacy_adv(
|
|||||||
await mock_bluetooth_entry_with_legacy_adv.mock_disconnect(True)
|
await mock_bluetooth_entry_with_legacy_adv.mock_disconnect(True)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:aa")
|
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:AA")
|
||||||
assert scanner is None
|
assert scanner is None
|
||||||
await mock_bluetooth_entry_with_legacy_adv.mock_connect()
|
await mock_bluetooth_entry_with_legacy_adv.mock_connect()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:aa")
|
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:AA")
|
||||||
assert scanner.scanning is True
|
assert scanner.scanning is True
|
||||||
|
@ -432,7 +432,7 @@ async def test_user_discovers_name_and_gets_key_from_dashboard_fails(
|
|||||||
DeviceInfo(
|
DeviceInfo(
|
||||||
uses_password=False,
|
uses_password=False,
|
||||||
name="test",
|
name="test",
|
||||||
mac_address="11:22:33:44:55:aa",
|
mac_address="11:22:33:44:55:AA",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
"""Tests for the diagnostics data provided by the ESPHome integration."""
|
"""Tests for the diagnostics data provided by the ESPHome integration."""
|
||||||
|
from unittest.mock import ANY
|
||||||
|
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components import bluetooth
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .conftest import MockESPHomeDevice
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||||
from tests.typing import ClientSessionGenerator
|
from tests.typing import ClientSessionGenerator
|
||||||
@ -20,3 +25,77 @@ async def test_diagnostics(
|
|||||||
result = await get_diagnostics_for_config_entry(hass, hass_client, init_integration)
|
result = await get_diagnostics_for_config_entry(hass, hass_client, init_integration)
|
||||||
|
|
||||||
assert result == snapshot
|
assert result == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
async def test_diagnostics_with_bluetooth(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_client: ClientSessionGenerator,
|
||||||
|
mock_bluetooth_entry_with_raw_adv: MockESPHomeDevice,
|
||||||
|
) -> None:
|
||||||
|
"""Test diagnostics for config entry with Bluetooth."""
|
||||||
|
scanner = bluetooth.async_scanner_by_source(hass, "11:22:33:44:55:AA")
|
||||||
|
assert scanner is not None
|
||||||
|
assert scanner.connectable is True
|
||||||
|
entry = mock_bluetooth_entry_with_raw_adv.entry
|
||||||
|
result = await get_diagnostics_for_config_entry(hass, hass_client, entry)
|
||||||
|
assert result == {
|
||||||
|
"bluetooth": {
|
||||||
|
"available": True,
|
||||||
|
"connections_free": 0,
|
||||||
|
"connections_limit": 0,
|
||||||
|
"scanner": {
|
||||||
|
"connectable": True,
|
||||||
|
"discovered_device_timestamps": {},
|
||||||
|
"discovered_devices_and_advertisement_data": [],
|
||||||
|
"last_detection": ANY,
|
||||||
|
"monotonic_time": ANY,
|
||||||
|
"name": "test (11:22:33:44:55:AA)",
|
||||||
|
"scanning": True,
|
||||||
|
"source": "11:22:33:44:55:AA",
|
||||||
|
"start_time": ANY,
|
||||||
|
"time_since_last_device_detection": {},
|
||||||
|
"type": "ESPHomeScanner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"data": {
|
||||||
|
"device_name": "test",
|
||||||
|
"host": "test.local",
|
||||||
|
"password": "",
|
||||||
|
"port": 6053,
|
||||||
|
},
|
||||||
|
"disabled_by": None,
|
||||||
|
"domain": "esphome",
|
||||||
|
"entry_id": ANY,
|
||||||
|
"minor_version": 1,
|
||||||
|
"options": {"allow_service_calls": False},
|
||||||
|
"pref_disable_new_entities": False,
|
||||||
|
"pref_disable_polling": False,
|
||||||
|
"source": "user",
|
||||||
|
"title": "Mock Title",
|
||||||
|
"unique_id": "11:22:33:44:55:aa",
|
||||||
|
"version": 1,
|
||||||
|
},
|
||||||
|
"storage_data": {
|
||||||
|
"api_version": {"major": 99, "minor": 99},
|
||||||
|
"device_info": {
|
||||||
|
"bluetooth_proxy_feature_flags": 63,
|
||||||
|
"compilation_time": "",
|
||||||
|
"esphome_version": "1.0.0",
|
||||||
|
"friendly_name": "Test",
|
||||||
|
"has_deep_sleep": False,
|
||||||
|
"legacy_bluetooth_proxy_version": 0,
|
||||||
|
"mac_address": "**REDACTED**",
|
||||||
|
"manufacturer": "",
|
||||||
|
"model": "",
|
||||||
|
"name": "test",
|
||||||
|
"project_name": "",
|
||||||
|
"project_version": "",
|
||||||
|
"suggested_area": "",
|
||||||
|
"uses_password": False,
|
||||||
|
"voice_assistant_version": 0,
|
||||||
|
"webserver_port": 0,
|
||||||
|
},
|
||||||
|
"services": [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -51,7 +51,7 @@ async def test_migrate_entity_unique_id(
|
|||||||
assert entity_registry.async_get_entity_id("sensor", "esphome", "my_sensor") is None
|
assert entity_registry.async_get_entity_id("sensor", "esphome", "my_sensor") is None
|
||||||
# Note that ESPHome includes the EntityInfo type in the unique id
|
# Note that ESPHome includes the EntityInfo type in the unique id
|
||||||
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
||||||
assert entry.unique_id == "11:22:33:44:55:aa-sensor-mysensor"
|
assert entry.unique_id == "11:22:33:44:55:AA-sensor-mysensor"
|
||||||
|
|
||||||
|
|
||||||
async def test_migrate_entity_unique_id_downgrade_upgrade(
|
async def test_migrate_entity_unique_id_downgrade_upgrade(
|
||||||
@ -71,7 +71,7 @@ async def test_migrate_entity_unique_id_downgrade_upgrade(
|
|||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
"sensor",
|
"sensor",
|
||||||
"esphome",
|
"esphome",
|
||||||
"11:22:33:44:55:aa-sensor-mysensor",
|
"11:22:33:44:55:AA-sensor-mysensor",
|
||||||
suggested_object_id="new_sensor",
|
suggested_object_id="new_sensor",
|
||||||
disabled_by=None,
|
disabled_by=None,
|
||||||
)
|
)
|
||||||
@ -108,4 +108,4 @@ async def test_migrate_entity_unique_id_downgrade_upgrade(
|
|||||||
)
|
)
|
||||||
# Note that ESPHome includes the EntityInfo type in the unique id
|
# Note that ESPHome includes the EntityInfo type in the unique id
|
||||||
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
||||||
assert entry.unique_id == "11:22:33:44:55:aa-sensor-mysensor"
|
assert entry.unique_id == "11:22:33:44:55:AA-sensor-mysensor"
|
||||||
|
@ -45,7 +45,7 @@ async def test_esphome_device_with_old_bluetooth(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
issue_registry = ir.async_get(hass)
|
issue_registry = ir.async_get(hass)
|
||||||
issue = issue_registry.async_get_issue(
|
issue = issue_registry.async_get_issue(
|
||||||
"esphome", "ble_firmware_outdated-11:22:33:44:55:aa"
|
"esphome", "ble_firmware_outdated-11:22:33:44:55:AA"
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
issue.learn_more_url
|
issue.learn_more_url
|
||||||
@ -87,7 +87,10 @@ async def test_esphome_device_with_password(
|
|||||||
issue_registry = ir.async_get(hass)
|
issue_registry = ir.async_get(hass)
|
||||||
assert (
|
assert (
|
||||||
issue_registry.async_get_issue(
|
issue_registry.async_get_issue(
|
||||||
"esphome", "api_password_deprecated-11:22:33:44:55:aa"
|
# This issue uses the ESPHome mac address which
|
||||||
|
# is always UPPER case
|
||||||
|
"esphome",
|
||||||
|
"api_password_deprecated-11:22:33:44:55:AA",
|
||||||
)
|
)
|
||||||
is not None
|
is not None
|
||||||
)
|
)
|
||||||
@ -118,8 +121,10 @@ async def test_esphome_device_with_current_bluetooth(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
issue_registry = ir.async_get(hass)
|
issue_registry = ir.async_get(hass)
|
||||||
assert (
|
assert (
|
||||||
|
# This issue uses the ESPHome device info mac address which
|
||||||
|
# is always UPPER case
|
||||||
issue_registry.async_get_issue(
|
issue_registry.async_get_issue(
|
||||||
"esphome", "ble_firmware_outdated-11:22:33:44:55:aa"
|
"esphome", "ble_firmware_outdated-11:22:33:44:55:AA"
|
||||||
)
|
)
|
||||||
is None
|
is None
|
||||||
)
|
)
|
||||||
|
@ -118,7 +118,7 @@ async def test_generic_numeric_sensor_with_entity_category_and_icon(
|
|||||||
assert entry is not None
|
assert entry is not None
|
||||||
# Note that ESPHome includes the EntityInfo type in the unique id
|
# Note that ESPHome includes the EntityInfo type in the unique id
|
||||||
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
||||||
assert entry.unique_id == "11:22:33:44:55:aa-sensor-mysensor"
|
assert entry.unique_id == "11:22:33:44:55:AA-sensor-mysensor"
|
||||||
assert entry.entity_category is EntityCategory.DIAGNOSTIC
|
assert entry.entity_category is EntityCategory.DIAGNOSTIC
|
||||||
|
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ async def test_generic_numeric_sensor_state_class_measurement(
|
|||||||
assert entry is not None
|
assert entry is not None
|
||||||
# Note that ESPHome includes the EntityInfo type in the unique id
|
# Note that ESPHome includes the EntityInfo type in the unique id
|
||||||
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
# as this is not a 1:1 mapping to the entity platform (ie. text_sensor)
|
||||||
assert entry.unique_id == "11:22:33:44:55:aa-sensor-mysensor"
|
assert entry.unique_id == "11:22:33:44:55:AA-sensor-mysensor"
|
||||||
assert entry.entity_category is None
|
assert entry.entity_category is None
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user