Fix support for Bridge(d) and composed devices in Matter (#88662)
* Refactor discovery of entities to support composed and bridged devices * Bump library version to 3.1.0 * move discovery schemas to platforms * optimize a tiny bit * simplify even more * fixed bug in light platform * fix color control logic * fix some issues * Update homeassistant/components/matter/discovery.py Co-authored-by: Paulus Schoutsen <balloob@gmail.com> * fix some tests * fix light test --------- Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
e0601530a0
commit
301144993c
18 changed files with 582 additions and 526 deletions
109
homeassistant/components/matter/models.py
Normal file
109
homeassistant/components/matter/models.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
"""Models used for the Matter integration."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import asdict, dataclass
|
||||
from typing import Any
|
||||
|
||||
from chip.clusters import Objects as clusters
|
||||
from chip.clusters.Objects import ClusterAttributeDescriptor
|
||||
from matter_server.client.models.device_types import DeviceType
|
||||
from matter_server.client.models.node import MatterEndpoint
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.helpers.entity import EntityDescription
|
||||
|
||||
|
||||
class DataclassMustHaveAtLeastOne:
|
||||
"""A dataclass that must have at least one input parameter that is not None."""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Post dataclass initialization."""
|
||||
if all(val is None for val in asdict(self).values()):
|
||||
raise ValueError("At least one input parameter must not be None")
|
||||
|
||||
|
||||
SensorValueTypes = type[
|
||||
clusters.uint | int | clusters.Nullable | clusters.float32 | float
|
||||
]
|
||||
|
||||
|
||||
@dataclass
|
||||
class MatterEntityInfo:
|
||||
"""Info discovered from (primary) Matter Attribute to create entity."""
|
||||
|
||||
# MatterEndpoint to which the value(s) belongs
|
||||
endpoint: MatterEndpoint
|
||||
|
||||
# the home assistant platform for which an entity should be created
|
||||
platform: Platform
|
||||
|
||||
# All attributes that need to be watched by entity (incl. primary)
|
||||
attributes_to_watch: list[type[ClusterAttributeDescriptor]]
|
||||
|
||||
# the entity description to use
|
||||
entity_description: EntityDescription
|
||||
|
||||
# entity class to use to instantiate the entity
|
||||
entity_class: type
|
||||
|
||||
# [optional] function to call to convert the value from the primary attribute
|
||||
measurement_to_ha: Callable[[SensorValueTypes], SensorValueTypes] | None = None
|
||||
|
||||
@property
|
||||
def primary_attribute(self) -> type[ClusterAttributeDescriptor]:
|
||||
"""Return Primary Attribute belonging to the entity."""
|
||||
return self.attributes_to_watch[0]
|
||||
|
||||
|
||||
@dataclass
|
||||
class MatterDiscoverySchema:
|
||||
"""Matter discovery schema.
|
||||
|
||||
The Matter endpoint and it's (primary) Attribute for an entity must match these conditions.
|
||||
"""
|
||||
|
||||
# specify the hass platform for which this scheme applies (e.g. light, sensor)
|
||||
platform: Platform
|
||||
|
||||
# platform-specific entity description
|
||||
entity_description: EntityDescription
|
||||
|
||||
# entity class to use to instantiate the entity
|
||||
entity_class: type
|
||||
|
||||
# DISCOVERY OPTIONS
|
||||
|
||||
# [required] attributes that ALL need to be present
|
||||
# on the node for this scheme to pass (minimal one == primary)
|
||||
required_attributes: tuple[type[ClusterAttributeDescriptor], ...]
|
||||
|
||||
# [optional] the value's endpoint must contain this devicetype(s)
|
||||
device_type: tuple[type[DeviceType] | DeviceType, ...] | None = None
|
||||
|
||||
# [optional] the value's endpoint must NOT contain this devicetype(s)
|
||||
not_device_type: tuple[type[DeviceType] | DeviceType, ...] | None = None
|
||||
|
||||
# [optional] the endpoint's vendor_id must match ANY of these values
|
||||
vendor_id: tuple[int, ...] | None = None
|
||||
|
||||
# [optional] the endpoint's product_name must match ANY of these values
|
||||
product_name: tuple[str, ...] | None = None
|
||||
|
||||
# [optional] the attribute's endpoint_id must match ANY of these values
|
||||
endpoint_id: tuple[int, ...] | None = None
|
||||
|
||||
# [optional] additional attributes that MAY NOT be present
|
||||
# on the node for this scheme to pass
|
||||
absent_attributes: tuple[type[ClusterAttributeDescriptor], ...] | None = None
|
||||
|
||||
# [optional] additional attributes that may be present
|
||||
# these attributes are copied over to attributes_to_watch and
|
||||
# are not discovered by other entities
|
||||
optional_attributes: tuple[type[ClusterAttributeDescriptor], ...] | None = None
|
||||
|
||||
# [optional] bool to specify if this primary value may be discovered
|
||||
# by multiple platforms
|
||||
allow_multi: bool = False
|
||||
|
||||
# [optional] function to call to convert the value from the primary attribute
|
||||
measurement_to_ha: Callable[[Any], Any] | None = None
|
Loading…
Add table
Add a link
Reference in a new issue