1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 12:59:34 +00:00

Move device info validation to device registry (#96465)

* Move device info validation to device registry

* Don't move DeviceInfo

* Fix type annotation

* Don't block adding device for unknown config entry

* Fix test

* Remove use of locals()

* Improve error message
This commit is contained in:
Erik Montnemery
2023-07-14 14:55:17 +02:00
committed by GitHub
parent 3b32dcb613
commit 614f3c6a15
6 changed files with 159 additions and 126 deletions

View File

@@ -7,7 +7,6 @@ from contextvars import ContextVar
from datetime import datetime, timedelta
from logging import Logger, getLogger
from typing import TYPE_CHECKING, Any, Protocol
from urllib.parse import urlparse
import voluptuous as vol
@@ -48,7 +47,7 @@ from .issue_registry import IssueSeverity, async_create_issue
from .typing import UNDEFINED, ConfigType, DiscoveryInfoType
if TYPE_CHECKING:
from .entity import DeviceInfo, Entity
from .entity import Entity
SLOW_SETUP_WARNING = 10
@@ -60,37 +59,6 @@ PLATFORM_NOT_READY_RETRIES = 10
DATA_ENTITY_PLATFORM = "entity_platform"
PLATFORM_NOT_READY_BASE_WAIT_TIME = 30 # seconds
DEVICE_INFO_TYPES = {
# Device info is categorized by finding the first device info type which has all
# the keys of the device info. The link device info type must be kept first
# to make it preferred over primary.
"link": {
"connections",
"identifiers",
},
"primary": {
"configuration_url",
"connections",
"entry_type",
"hw_version",
"identifiers",
"manufacturer",
"model",
"name",
"suggested_area",
"sw_version",
"via_device",
},
"secondary": {
"connections",
"default_manufacturer",
"default_model",
"default_name",
# Used by Fritz
"via_device",
},
}
_LOGGER = getLogger(__name__)
@@ -646,7 +614,14 @@ class EntityPlatform:
return
if self.config_entry and (device_info := entity.device_info):
device = self._async_process_device_info(device_info)
try:
device = dev_reg.async_get(self.hass).async_get_or_create(
config_entry_id=self.config_entry.entry_id,
**device_info,
)
except dev_reg.DeviceInfoError as exc:
self.logger.error("Ignoring invalid device info: %s", str(exc))
device = None
else:
device = None
@@ -773,62 +748,6 @@ class EntityPlatform:
await entity.add_to_platform_finish()
@callback
def _async_process_device_info(
self, device_info: DeviceInfo
) -> dev_reg.DeviceEntry | None:
"""Process a device info."""
keys = set(device_info)
# If no keys or not enough info to match up, abort
if len(keys & {"connections", "identifiers"}) == 0:
self.logger.error(
"Ignoring device info without identifiers or connections: %s",
device_info,
)
return None
device_info_type: str | None = None
# Find the first device info type which has all keys in the device info
for possible_type, allowed_keys in DEVICE_INFO_TYPES.items():
if keys <= allowed_keys:
device_info_type = possible_type
break
if device_info_type is None:
self.logger.error(
"Device info for %s needs to either describe a device, "
"link to existing device or provide extra information.",
device_info,
)
return None
if (config_url := device_info.get("configuration_url")) is not None:
if type(config_url) is not str or urlparse(config_url).scheme not in [
"http",
"https",
"homeassistant",
]:
self.logger.error(
"Ignoring device info with invalid configuration_url '%s'",
config_url,
)
return None
assert self.config_entry is not None
if device_info_type == "primary" and not device_info.get("name"):
device_info = {
**device_info, # type: ignore[misc]
"name": self.config_entry.title,
}
return dev_reg.async_get(self.hass).async_get_or_create(
config_entry_id=self.config_entry.entry_id,
**device_info,
)
async def async_reset(self) -> None:
"""Remove all entities and reset data.