Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Paulus Schoutsen
98cff0bd74 Add integration back 2024-11-02 18:58:03 +00:00
Paulus Schoutsen
b3a32b5f59 Update format 2024-11-02 18:58:03 +00:00
Paulus Schoutsen
d7d2b7ad76 Add method to generate devices analytics payload 2024-11-02 18:58:01 +00:00
2 changed files with 176 additions and 2 deletions

View file

@ -27,8 +27,8 @@ from homeassistant.config_entries import SOURCE_IGNORE
from homeassistant.const import ATTR_DOMAIN, __version__ as HA_VERSION
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.entity_registry as er
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.storage import Store
from homeassistant.helpers.system_info import async_get_system_info
@ -370,3 +370,71 @@ class Analytics:
for entry in entries
if entry.source != SOURCE_IGNORE and entry.disabled_by is None
)
@callback
def async_devices_payload(hass: HomeAssistant) -> dict:
"""Return the devices payload."""
integrations_without_model_id: set[str] = set()
devices: list[dict[str, Any]] = []
dev_reg = dr.async_get(hass)
ignored_integrations = {
"bluetooth",
"esphome",
"hassio",
"mqtt",
}
# Devices that need via device info set
new_indexes: dict[str, int] = {}
via_devices: dict[str, str] = {}
for device in dev_reg.devices.values():
# Ignore services
if device.entry_type:
continue
if not device.primary_config_entry:
continue
config_entry = hass.config_entries.async_get_entry(device.primary_config_entry)
if config_entry is None:
continue
if config_entry.domain in ignored_integrations:
continue
if not device.model_id:
integrations_without_model_id.add(config_entry.domain)
continue
if not device.manufacturer:
continue
new_indexes[device.id] = len(devices)
devices.append(
{
"integration": config_entry.domain,
"manufacturer": device.manufacturer,
"model_id": device.model_id,
"model": device.model,
"sw_version": device.sw_version,
"hw_version": device.hw_version,
"has_suggested_area": device.suggested_area is not None,
"has_configuration_url": device.configuration_url is not None,
"via_device": None,
}
)
if device.via_device_id:
via_devices[device.id] = device.via_device_id
for from_device, via_device in via_devices.items():
if via_device not in new_indexes:
continue
devices[new_indexes[from_device]]["via_device"] = new_indexes[via_device]
return {
"version": "home-assistant:1",
"no_model_id": sorted(integrations_without_model_id),
"devices": devices,
}

View file

@ -10,7 +10,10 @@ import pytest
from syrupy import SnapshotAssertion
from syrupy.matchers import path_type
from homeassistant.components.analytics.analytics import Analytics
from homeassistant.components.analytics.analytics import (
Analytics,
async_devices_payload,
)
from homeassistant.components.analytics.const import (
ANALYTICS_ENDPOINT_URL,
ANALYTICS_ENDPOINT_URL_DEV,
@ -22,6 +25,7 @@ from homeassistant.components.analytics.const import (
from homeassistant.config_entries import ConfigEntryDisabler, ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr
from homeassistant.loader import IntegrationNotFound
from homeassistant.setup import async_setup_component
@ -920,3 +924,105 @@ async def test_not_check_config_entries_if_yaml(
assert submitted_data["integrations"] == ["default_config"]
assert submitted_data == logged_data
assert snapshot == submitted_data
async def test_devices_payload(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test devices payload."""
assert async_devices_payload(hass) == {
"version": "home-assistant:1",
"no_model_id": [],
"devices": [],
}
mock_config_entry = MockConfigEntry()
mock_config_entry.add_to_hass(hass)
# Normal entry
device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
identifiers={("device", "1")},
sw_version="test-sw-version",
hw_version="test-hw-version",
name="test-name",
manufacturer="test-manufacturer",
model="test-model",
model_id="test-model-id",
suggested_area="Game Room",
configuration_url="http://example.com/config",
)
# Ignored because service type
device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
identifiers={("device", "2")},
manufacturer="test-manufacturer",
model_id="test-model-id",
entry_type=dr.DeviceEntryType.SERVICE,
)
# Ignored because config entry is ignore list
ignored_config_entry = MockConfigEntry(domain="esphome")
ignored_config_entry.add_to_hass(hass)
device_registry.async_get_or_create(
config_entry_id=ignored_config_entry.entry_id,
identifiers={("device", "3")},
manufacturer="test-manufacturer",
model_id="test-model-id",
)
# Ignored because no model id
no_model_id_config_entry = MockConfigEntry(domain="no_model_id")
no_model_id_config_entry.add_to_hass(hass)
device_registry.async_get_or_create(
config_entry_id=no_model_id_config_entry.entry_id,
identifiers={("device", "4")},
manufacturer="test-manufacturer",
)
# Ignored because no manufacturer
device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
identifiers={("device", "5")},
model_id="test-model-id",
)
# Entry with via device
device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
identifiers={("device", "6")},
manufacturer="test-manufacturer6",
model_id="test-model-id6",
via_device=("device", "1"),
)
assert async_devices_payload(hass) == {
"version": "home-assistant:1",
"no_model_id": ["no_model_id"],
"devices": [
{
"manufacturer": "test-manufacturer",
"model_id": "test-model-id",
"model": "test-model",
"sw_version": "test-sw-version",
"hw_version": "test-hw-version",
"integration": "test",
"has_suggested_area": True,
"has_configuration_url": True,
"via_device": None,
},
{
"manufacturer": "test-manufacturer6",
"model_id": "test-model-id6",
"model": None,
"sw_version": None,
"hw_version": None,
"integration": "test",
"has_suggested_area": False,
"has_configuration_url": False,
"via_device": 0,
},
],
}