Add matter sensor platform (#83147)

pull/83149/head
Martin Hjelmare 2022-12-06 21:39:00 +01:00 committed by GitHub
parent e7a06046a7
commit 9d96a021c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 898 additions and 25 deletions

View File

@ -7,6 +7,7 @@ from homeassistant.const import Platform
from .binary_sensor import DEVICE_ENTITY as BINARY_SENSOR_DEVICE_ENTITY
from .light import DEVICE_ENTITY as LIGHT_DEVICE_ENTITY
from .sensor import DEVICE_ENTITY as SENSOR_DEVICE_ENTITY
if TYPE_CHECKING:
from matter_server.common.models.device_types import DeviceType
@ -23,4 +24,5 @@ DEVICE_PLATFORM: dict[
] = {
Platform.BINARY_SENSOR: BINARY_SENSOR_DEVICE_ENTITY,
Platform.LIGHT: LIGHT_DEVICE_ENTITY,
Platform.SENSOR: SENSOR_DEVICE_ENTITY,
}

View File

@ -0,0 +1,167 @@
"""Matter sensors."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from functools import partial
from typing import TYPE_CHECKING, Any
from chip.clusters import Objects as clusters
from chip.clusters.Types import Nullable, NullValue
from matter_server.common.models import device_types
from matter_server.common.models.device_type_instance import MatterDeviceTypeInstance
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
LIGHT_LUX,
PERCENTAGE,
VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
Platform,
UnitOfPressure,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .entity import MatterEntity, MatterEntityDescriptionBaseClass
if TYPE_CHECKING:
from .adapter import MatterAdapter
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Matter sensors from Config Entry."""
matter: MatterAdapter = hass.data[DOMAIN][config_entry.entry_id]
matter.register_platform_handler(Platform.SENSOR, async_add_entities)
class MatterSensor(MatterEntity, SensorEntity):
"""Representation of a Matter sensor."""
_attr_state_class = SensorStateClass.MEASUREMENT
entity_description: MatterSensorEntityDescription
@callback
def _update_from_device(self) -> None:
"""Update from device."""
measurement: Nullable | float | None
measurement = _get_attribute_value(
self._device_type_instance,
# We always subscribe to a single value
self.entity_description.subscribe_attributes[0],
)
if measurement is NullValue or measurement is None:
measurement = None
else:
measurement = self.entity_description.measurement_to_ha(measurement)
self._attr_native_value = measurement
def _get_attribute_value(
device_type_instance: MatterDeviceTypeInstance,
attribute: clusters.ClusterAttributeDescriptor,
) -> Any:
"""Return the value of an attribute."""
# Find the cluster for this attribute. We don't have a lookup table yet.
cluster_cls: clusters.Cluster = next(
cluster
for cluster in device_type_instance.device_type.clusters
if cluster.id == attribute.cluster_id
)
# Find the attribute descriptor so we know the instance variable to fetch
attribute_descriptor: clusters.ClusterObjectFieldDescriptor = next(
descriptor
for descriptor in cluster_cls.descriptor.Fields
if descriptor.Tag == attribute.attribute_id
)
cluster_data = device_type_instance.get_cluster(cluster_cls)
return getattr(cluster_data, attribute_descriptor.Label)
@dataclass
class MatterSensorEntityDescriptionMixin:
"""Required fields for sensor device mapping."""
measurement_to_ha: Callable[[float], float]
@dataclass
class MatterSensorEntityDescription(
SensorEntityDescription,
MatterEntityDescriptionBaseClass,
MatterSensorEntityDescriptionMixin,
):
"""Matter Sensor entity description."""
# You can't set default values on inherited data classes
MatterSensorEntityDescriptionFactory = partial(
MatterSensorEntityDescription, entity_cls=MatterSensor
)
DEVICE_ENTITY: dict[
type[device_types.DeviceType],
MatterEntityDescriptionBaseClass | list[MatterEntityDescriptionBaseClass],
] = {
device_types.TemperatureSensor: MatterSensorEntityDescriptionFactory(
key=device_types.TemperatureSensor,
name="Temperature",
measurement_to_ha=lambda x: x / 100,
subscribe_attributes=(
clusters.TemperatureMeasurement.Attributes.MeasuredValue,
),
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
),
device_types.PressureSensor: MatterSensorEntityDescriptionFactory(
key=device_types.PressureSensor,
name="Pressure",
measurement_to_ha=lambda x: x / 10,
subscribe_attributes=(clusters.PressureMeasurement.Attributes.MeasuredValue,),
native_unit_of_measurement=UnitOfPressure.KPA,
device_class=SensorDeviceClass.PRESSURE,
),
device_types.FlowSensor: MatterSensorEntityDescriptionFactory(
key=device_types.FlowSensor,
name="Flow",
measurement_to_ha=lambda x: x / 10,
subscribe_attributes=(clusters.FlowMeasurement.Attributes.MeasuredValue,),
native_unit_of_measurement=VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
),
device_types.HumiditySensor: MatterSensorEntityDescriptionFactory(
key=device_types.HumiditySensor,
name="Humidity",
measurement_to_ha=lambda x: x / 100,
subscribe_attributes=(
clusters.RelativeHumidityMeasurement.Attributes.MeasuredValue,
),
native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
),
device_types.LightSensor: MatterSensorEntityDescriptionFactory(
key=device_types.LightSensor,
name="Light",
measurement_to_ha=lambda x: round(pow(10, ((x - 1) / 10000)), 1),
subscribe_attributes=(
clusters.IlluminanceMeasurement.Attributes.MeasuredValue,
),
native_unit_of_measurement=LIGHT_LUX,
device_class=SensorDeviceClass.ILLUMINANCE,
),
}

View File

@ -4,6 +4,113 @@
"last_interview": "2022-11-29T21:23:48.485057",
"interview_version": 1,
"attributes": {
"0/29/0": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 0,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.DeviceTypeList",
"attribute_name": "DeviceTypeList",
"value": [
{
"type": 22,
"revision": 1
}
]
},
"0/29/1": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 1,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ServerList",
"attribute_name": "ServerList",
"value": [
4, 29, 31, 40, 42, 43, 44, 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, 62,
63, 64, 65
]
},
"0/29/2": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 2,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClientList",
"attribute_name": "ClientList",
"value": [41]
},
"0/29/3": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 3,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.PartsList",
"attribute_name": "PartsList",
"value": [1]
},
"0/29/65532": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65532,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.FeatureMap",
"attribute_name": "FeatureMap",
"value": 0
},
"0/29/65533": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65533,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClusterRevision",
"attribute_name": "ClusterRevision",
"value": 1
},
"0/29/65528": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65528,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.GeneratedCommandList",
"attribute_name": "GeneratedCommandList",
"value": []
},
"0/29/65529": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65529,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AcceptedCommandList",
"attribute_name": "AcceptedCommandList",
"value": []
},
"0/29/65531": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65531,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AttributeList",
"attribute_name": "AttributeList",
"value": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"0/40/0": {
"node_id": 1,
"endpoint": 0,

View File

@ -4,6 +4,113 @@
"last_interview": "2022-11-29T21:23:48.485057",
"interview_version": 1,
"attributes": {
"0/29/0": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 0,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.DeviceTypeList",
"attribute_name": "DeviceTypeList",
"value": [
{
"type": 22,
"revision": 1
}
]
},
"0/29/1": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 1,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ServerList",
"attribute_name": "ServerList",
"value": [
4, 29, 31, 40, 42, 43, 44, 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, 62,
63, 64, 65
]
},
"0/29/2": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 2,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClientList",
"attribute_name": "ClientList",
"value": [41]
},
"0/29/3": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 3,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.PartsList",
"attribute_name": "PartsList",
"value": [1]
},
"0/29/65532": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65532,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.FeatureMap",
"attribute_name": "FeatureMap",
"value": 0
},
"0/29/65533": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65533,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClusterRevision",
"attribute_name": "ClusterRevision",
"value": 1
},
"0/29/65528": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65528,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.GeneratedCommandList",
"attribute_name": "GeneratedCommandList",
"value": []
},
"0/29/65529": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65529,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AcceptedCommandList",
"attribute_name": "AcceptedCommandList",
"value": []
},
"0/29/65531": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65531,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AttributeList",
"attribute_name": "AttributeList",
"value": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"0/40/0": {
"node_id": 1,
"endpoint": 0,
@ -404,7 +511,7 @@
},
"1/29/65531": {
"node_id": 1,
"endpoint": 0,
"endpoint": 1,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
@ -413,9 +520,9 @@
"attribute_name": "AttributeList",
"value": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"0/1029/0": {
"node_id": 3,
"endpoint": 0,
"1/1029/0": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",
@ -424,9 +531,9 @@
"attribute_name": "MeasuredValue",
"value": 0
},
"0/1029/1": {
"node_id": 3,
"endpoint": 0,
"1/1029/1": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",
@ -435,9 +542,9 @@
"attribute_name": "MinMeasuredValue",
"value": 0
},
"0/1029/2": {
"node_id": 3,
"endpoint": 0,
"1/1029/2": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",
@ -446,9 +553,9 @@
"attribute_name": "MaxMeasuredValue",
"value": 10000
},
"0/1029/65532": {
"node_id": 3,
"endpoint": 0,
"1/1029/65532": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",
@ -457,9 +564,9 @@
"attribute_name": "FeatureMap",
"value": 0
},
"0/1029/65533": {
"node_id": 3,
"endpoint": 0,
"1/1029/65533": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",
@ -468,9 +575,9 @@
"attribute_name": "ClusterRevision",
"value": 3
},
"0/1029/65528": {
"node_id": 3,
"endpoint": 0,
"1/1029/65528": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",
@ -479,9 +586,9 @@
"attribute_name": "GeneratedCommandList",
"value": []
},
"0/1029/65529": {
"node_id": 3,
"endpoint": 0,
"1/1029/65529": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",
@ -490,9 +597,9 @@
"attribute_name": "AcceptedCommandList",
"value": []
},
"0/1029/65531": {
"node_id": 3,
"endpoint": 0,
"1/1029/65531": {
"node_id": 1,
"endpoint": 1,
"cluster_id": 1029,
"cluster_type": "chip.clusters.Objects.RelativeHumidityMeasurement",
"cluster_name": "RelativeHumidityMeasurement",

View File

@ -4,6 +4,113 @@
"last_interview": "2022-11-29T21:23:48.485057",
"interview_version": 1,
"attributes": {
"0/29/0": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 0,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.DeviceTypeList",
"attribute_name": "DeviceTypeList",
"value": [
{
"type": 22,
"revision": 1
}
]
},
"0/29/1": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 1,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ServerList",
"attribute_name": "ServerList",
"value": [
4, 29, 31, 40, 42, 43, 44, 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, 62,
63, 64, 65
]
},
"0/29/2": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 2,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClientList",
"attribute_name": "ClientList",
"value": [41]
},
"0/29/3": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 3,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.PartsList",
"attribute_name": "PartsList",
"value": [1]
},
"0/29/65532": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65532,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.FeatureMap",
"attribute_name": "FeatureMap",
"value": 0
},
"0/29/65533": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65533,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClusterRevision",
"attribute_name": "ClusterRevision",
"value": 1
},
"0/29/65528": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65528,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.GeneratedCommandList",
"attribute_name": "GeneratedCommandList",
"value": []
},
"0/29/65529": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65529,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AcceptedCommandList",
"attribute_name": "AcceptedCommandList",
"value": []
},
"0/29/65531": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65531,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AttributeList",
"attribute_name": "AttributeList",
"value": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"0/40/0": {
"node_id": 1,
"endpoint": 0,

View File

@ -4,6 +4,113 @@
"last_interview": "2022-11-29T21:23:48.485057",
"interview_version": 1,
"attributes": {
"0/29/0": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 0,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.DeviceTypeList",
"attribute_name": "DeviceTypeList",
"value": [
{
"type": 22,
"revision": 1
}
]
},
"0/29/1": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 1,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ServerList",
"attribute_name": "ServerList",
"value": [
4, 29, 31, 40, 42, 43, 44, 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, 62,
63, 64, 65
]
},
"0/29/2": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 2,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClientList",
"attribute_name": "ClientList",
"value": [41]
},
"0/29/3": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 3,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.PartsList",
"attribute_name": "PartsList",
"value": [1]
},
"0/29/65532": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65532,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.FeatureMap",
"attribute_name": "FeatureMap",
"value": 0
},
"0/29/65533": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65533,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClusterRevision",
"attribute_name": "ClusterRevision",
"value": 1
},
"0/29/65528": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65528,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.GeneratedCommandList",
"attribute_name": "GeneratedCommandList",
"value": []
},
"0/29/65529": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65529,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AcceptedCommandList",
"attribute_name": "AcceptedCommandList",
"value": []
},
"0/29/65531": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65531,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AttributeList",
"attribute_name": "AttributeList",
"value": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"0/40/0": {
"node_id": 1,
"endpoint": 0,

View File

@ -4,6 +4,113 @@
"last_interview": "2022-11-29T21:23:48.485057",
"interview_version": 1,
"attributes": {
"0/29/0": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 0,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.DeviceTypeList",
"attribute_name": "DeviceTypeList",
"value": [
{
"type": 22,
"revision": 1
}
]
},
"0/29/1": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 1,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ServerList",
"attribute_name": "ServerList",
"value": [
4, 29, 31, 40, 42, 43, 44, 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, 62,
63, 64, 65
]
},
"0/29/2": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 2,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClientList",
"attribute_name": "ClientList",
"value": [41]
},
"0/29/3": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 3,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.PartsList",
"attribute_name": "PartsList",
"value": [1]
},
"0/29/65532": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65532,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.FeatureMap",
"attribute_name": "FeatureMap",
"value": 0
},
"0/29/65533": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65533,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.ClusterRevision",
"attribute_name": "ClusterRevision",
"value": 1
},
"0/29/65528": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65528,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.GeneratedCommandList",
"attribute_name": "GeneratedCommandList",
"value": []
},
"0/29/65529": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65529,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AcceptedCommandList",
"attribute_name": "AcceptedCommandList",
"value": []
},
"0/29/65531": {
"node_id": 1,
"endpoint": 0,
"cluster_id": 29,
"cluster_type": "chip.clusters.Objects.Descriptor",
"cluster_name": "Descriptor",
"attribute_id": 65531,
"attribute_type": "chip.clusters.Objects.Descriptor.Attributes.AttributeList",
"attribute_name": "AttributeList",
"value": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"0/40/0": {
"node_id": 1,
"endpoint": 0,

View File

@ -0,0 +1,169 @@
"""Test Matter sensors."""
from unittest.mock import MagicMock
from matter_server.common.models.node import MatterNode
import pytest
from homeassistant.core import HomeAssistant
from .common import (
set_node_attribute,
setup_integration_with_node_fixture,
trigger_subscription_callback,
)
@pytest.fixture(name="flow_sensor_node")
async def flow_sensor_node_fixture(
hass: HomeAssistant, matter_client: MagicMock
) -> MatterNode:
"""Fixture for a flow sensor node."""
return await setup_integration_with_node_fixture(hass, "flow-sensor", matter_client)
@pytest.fixture(name="humidity_sensor_node")
async def humidity_sensor_node_fixture(
hass: HomeAssistant, matter_client: MagicMock
) -> MatterNode:
"""Fixture for a humidity sensor node."""
return await setup_integration_with_node_fixture(
hass, "humidity-sensor", matter_client
)
@pytest.fixture(name="light_sensor_node")
async def light_sensor_node_fixture(
hass: HomeAssistant, matter_client: MagicMock
) -> MatterNode:
"""Fixture for a light sensor node."""
return await setup_integration_with_node_fixture(
hass, "light-sensor", matter_client
)
@pytest.fixture(name="pressure_sensor_node")
async def pressure_sensor_node_fixture(
hass: HomeAssistant, matter_client: MagicMock
) -> MatterNode:
"""Fixture for a pressure sensor node."""
return await setup_integration_with_node_fixture(
hass, "pressure-sensor", matter_client
)
@pytest.fixture(name="temperature_sensor_node")
async def temperature_sensor_node_fixture(
hass: HomeAssistant, matter_client: MagicMock
) -> MatterNode:
"""Fixture for a temperature sensor node."""
return await setup_integration_with_node_fixture(
hass, "temperature-sensor", matter_client
)
async def test_sensor_null_value(
hass: HomeAssistant,
matter_client: MagicMock,
flow_sensor_node: MatterNode,
) -> None:
"""Test flow sensor."""
state = hass.states.get("sensor.mock_flow_sensor_flow")
assert state
assert state.state == "0.0"
set_node_attribute(flow_sensor_node, 1, 1028, 0, None)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.mock_flow_sensor_flow")
assert state
assert state.state == "unknown"
async def test_flow_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
flow_sensor_node: MatterNode,
) -> None:
"""Test flow sensor."""
state = hass.states.get("sensor.mock_flow_sensor_flow")
assert state
assert state.state == "0.0"
set_node_attribute(flow_sensor_node, 1, 1028, 0, 20)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.mock_flow_sensor_flow")
assert state
assert state.state == "2.0"
async def test_humidity_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
humidity_sensor_node: MatterNode,
) -> None:
"""Test humidity sensor."""
state = hass.states.get("sensor.mock_humidity_sensor_humidity")
assert state
assert state.state == "0.0"
set_node_attribute(humidity_sensor_node, 1, 1029, 0, 4000)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.mock_humidity_sensor_humidity")
assert state
assert state.state == "40.0"
async def test_light_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
light_sensor_node: MatterNode,
) -> None:
"""Test light sensor."""
state = hass.states.get("sensor.mock_light_sensor_light")
assert state
assert state.state == "1.3"
set_node_attribute(light_sensor_node, 1, 1024, 0, 3000)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.mock_light_sensor_light")
assert state
assert state.state == "2.0"
async def test_pressure_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
pressure_sensor_node: MatterNode,
) -> None:
"""Test pressure sensor."""
state = hass.states.get("sensor.mock_pressure_sensor_pressure")
assert state
assert state.state == "0.0"
set_node_attribute(pressure_sensor_node, 1, 1027, 0, 1010)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.mock_pressure_sensor_pressure")
assert state
assert state.state == "101.0"
async def test_temperature_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
temperature_sensor_node: MatterNode,
) -> None:
"""Test temperature sensor."""
state = hass.states.get("sensor.mock_temperature_sensor_temperature")
assert state
assert state.state == "21.0"
set_node_attribute(temperature_sensor_node, 1, 1026, 0, 2500)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.mock_temperature_sensor_temperature")
assert state
assert state.state == "25.0"