mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Bump Python Matter Server library to 6.1.0(b0) (#118388)
This commit is contained in:
parent
23381ff30c
commit
7136be5047
@ -69,8 +69,8 @@ SUPPORT_FAN_MODE_DEVICES: set[tuple[int, int]] = {
|
|||||||
(0x1209, 0x8007),
|
(0x1209, 0x8007),
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemModeEnum = clusters.Thermostat.Enums.ThermostatSystemMode
|
SystemModeEnum = clusters.Thermostat.Enums.SystemModeEnum
|
||||||
ControlSequenceEnum = clusters.Thermostat.Enums.ThermostatControlSequence
|
ControlSequenceEnum = clusters.Thermostat.Enums.ControlSequenceOfOperationEnum
|
||||||
ThermostatFeature = clusters.Thermostat.Bitmaps.Feature
|
ThermostatFeature = clusters.Thermostat.Bitmaps.Feature
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,7 +118,6 @@ def async_discover_entities(
|
|||||||
attributes_to_watch=attributes_to_watch,
|
attributes_to_watch=attributes_to_watch,
|
||||||
entity_description=schema.entity_description,
|
entity_description=schema.entity_description,
|
||||||
entity_class=schema.entity_class,
|
entity_class=schema.entity_class,
|
||||||
should_poll=schema.should_poll,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# prevent re-discovery of the primary attribute if not allowed
|
# prevent re-discovery of the primary attribute if not allowed
|
||||||
|
@ -4,9 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from contextlib import suppress
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Any, cast
|
from typing import TYPE_CHECKING, Any, cast
|
||||||
|
|
||||||
@ -14,10 +12,9 @@ from chip.clusters.Objects import ClusterAttributeDescriptor, NullValue
|
|||||||
from matter_server.common.helpers.util import create_attribute_path
|
from matter_server.common.helpers.util import create_attribute_path
|
||||||
from matter_server.common.models import EventType, ServerInfoMessage
|
from matter_server.common.models import EventType, ServerInfoMessage
|
||||||
|
|
||||||
from homeassistant.core import CALLBACK_TYPE, callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
from homeassistant.helpers.entity import Entity, EntityDescription
|
from homeassistant.helpers.entity import Entity, EntityDescription
|
||||||
from homeassistant.helpers.event import async_call_later
|
|
||||||
|
|
||||||
from .const import DOMAIN, ID_TYPE_DEVICE_ID
|
from .const import DOMAIN, ID_TYPE_DEVICE_ID
|
||||||
from .helpers import get_device_id
|
from .helpers import get_device_id
|
||||||
@ -30,13 +27,6 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
# For some manually polled values (e.g. custom clusters) we perform
|
|
||||||
# an additional poll as soon as a secondary value changes.
|
|
||||||
# For example update the energy consumption meter when a relay is toggled
|
|
||||||
# of an energy metering powerplug. The below constant defined the delay after
|
|
||||||
# which we poll the primary value (debounced).
|
|
||||||
EXTRA_POLL_DELAY = 3.0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class MatterEntityDescription(EntityDescription):
|
class MatterEntityDescription(EntityDescription):
|
||||||
@ -80,8 +70,6 @@ class MatterEntity(Entity):
|
|||||||
identifiers={(DOMAIN, f"{ID_TYPE_DEVICE_ID}_{node_device_id}")}
|
identifiers={(DOMAIN, f"{ID_TYPE_DEVICE_ID}_{node_device_id}")}
|
||||||
)
|
)
|
||||||
self._attr_available = self._endpoint.node.available
|
self._attr_available = self._endpoint.node.available
|
||||||
self._attr_should_poll = entity_info.should_poll
|
|
||||||
self._extra_poll_timer_unsub: CALLBACK_TYPE | None = None
|
|
||||||
|
|
||||||
# make sure to update the attributes once
|
# make sure to update the attributes once
|
||||||
self._update_from_device()
|
self._update_from_device()
|
||||||
@ -116,40 +104,10 @@ class MatterEntity(Entity):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
|
||||||
"""Run when entity will be removed from hass."""
|
|
||||||
if self._extra_poll_timer_unsub:
|
|
||||||
self._extra_poll_timer_unsub()
|
|
||||||
for unsub in self._unsubscribes:
|
|
||||||
with suppress(ValueError):
|
|
||||||
# suppress ValueError to prevent race conditions
|
|
||||||
unsub()
|
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
|
||||||
"""Call when the entity needs to be updated."""
|
|
||||||
if not self._endpoint.node.available:
|
|
||||||
# skip poll when the node is not (yet) available
|
|
||||||
return
|
|
||||||
# manually poll/refresh the primary value
|
|
||||||
await self.matter_client.refresh_attribute(
|
|
||||||
self._endpoint.node.node_id,
|
|
||||||
self.get_matter_attribute_path(self._entity_info.primary_attribute),
|
|
||||||
)
|
|
||||||
self._update_from_device()
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _on_matter_event(self, event: EventType, data: Any = None) -> None:
|
def _on_matter_event(self, event: EventType, data: Any = None) -> None:
|
||||||
"""Call on update from the device."""
|
"""Call on update from the device."""
|
||||||
self._attr_available = self._endpoint.node.available
|
self._attr_available = self._endpoint.node.available
|
||||||
if self._attr_should_poll:
|
|
||||||
# secondary attribute updated of a polled primary value
|
|
||||||
# enforce poll of the primary value a few seconds later
|
|
||||||
if self._extra_poll_timer_unsub:
|
|
||||||
self._extra_poll_timer_unsub()
|
|
||||||
self._extra_poll_timer_unsub = async_call_later(
|
|
||||||
self.hass, EXTRA_POLL_DELAY, self._do_extra_poll
|
|
||||||
)
|
|
||||||
return
|
|
||||||
self._update_from_device()
|
self._update_from_device()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@ -176,9 +134,3 @@ class MatterEntity(Entity):
|
|||||||
return create_attribute_path(
|
return create_attribute_path(
|
||||||
self._endpoint.endpoint_id, attribute.cluster_id, attribute.attribute_id
|
self._endpoint.endpoint_id, attribute.cluster_id, attribute.attribute_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
|
||||||
def _do_extra_poll(self, called_at: datetime) -> None:
|
|
||||||
"""Perform (extra) poll of primary value."""
|
|
||||||
# scheduling the regulat update is enough to perform a poll/refresh
|
|
||||||
self.async_schedule_update_ha_state(True)
|
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
"dependencies": ["websocket_api"],
|
"dependencies": ["websocket_api"],
|
||||||
"documentation": "https://www.home-assistant.io/integrations/matter",
|
"documentation": "https://www.home-assistant.io/integrations/matter",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"requirements": ["python-matter-server==5.10.0"],
|
"requirements": ["python-matter-server==6.1.0b1"],
|
||||||
"zeroconf": ["_matter._tcp.local.", "_matterc._udp.local."]
|
"zeroconf": ["_matter._tcp.local.", "_matterc._udp.local."]
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,6 @@ class MatterEntityInfo:
|
|||||||
# entity class to use to instantiate the entity
|
# entity class to use to instantiate the entity
|
||||||
entity_class: type
|
entity_class: type
|
||||||
|
|
||||||
# [optional] bool to specify if this primary value should be polled
|
|
||||||
should_poll: bool
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def primary_attribute(self) -> type[ClusterAttributeDescriptor]:
|
def primary_attribute(self) -> type[ClusterAttributeDescriptor]:
|
||||||
"""Return Primary Attribute belonging to the entity."""
|
"""Return Primary Attribute belonging to the entity."""
|
||||||
|
@ -6,7 +6,7 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
from chip.clusters import Objects as clusters
|
from chip.clusters import Objects as clusters
|
||||||
from chip.clusters.Types import Nullable, NullValue
|
from chip.clusters.Types import Nullable, NullValue
|
||||||
from matter_server.client.models.clusters import EveEnergyCluster
|
from matter_server.common.custom_clusters import EveCluster
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
@ -159,11 +159,10 @@ DISCOVERY_SCHEMAS = [
|
|||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
entity_class=MatterSensor,
|
entity_class=MatterSensor,
|
||||||
required_attributes=(EveEnergyCluster.Attributes.Watt,),
|
required_attributes=(EveCluster.Attributes.Watt,),
|
||||||
# Add OnOff Attribute as optional attribute to poll
|
# Add OnOff Attribute as optional attribute to poll
|
||||||
# the primary value when the relay is toggled
|
# the primary value when the relay is toggled
|
||||||
optional_attributes=(clusters.OnOff.Attributes.OnOff,),
|
optional_attributes=(clusters.OnOff.Attributes.OnOff,),
|
||||||
should_poll=True,
|
|
||||||
),
|
),
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.SENSOR,
|
platform=Platform.SENSOR,
|
||||||
@ -176,8 +175,7 @@ DISCOVERY_SCHEMAS = [
|
|||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
entity_class=MatterSensor,
|
entity_class=MatterSensor,
|
||||||
required_attributes=(EveEnergyCluster.Attributes.Voltage,),
|
required_attributes=(EveCluster.Attributes.Voltage,),
|
||||||
should_poll=True,
|
|
||||||
),
|
),
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.SENSOR,
|
platform=Platform.SENSOR,
|
||||||
@ -190,8 +188,7 @@ DISCOVERY_SCHEMAS = [
|
|||||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||||
),
|
),
|
||||||
entity_class=MatterSensor,
|
entity_class=MatterSensor,
|
||||||
required_attributes=(EveEnergyCluster.Attributes.WattAccumulated,),
|
required_attributes=(EveCluster.Attributes.WattAccumulated,),
|
||||||
should_poll=True,
|
|
||||||
),
|
),
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.SENSOR,
|
platform=Platform.SENSOR,
|
||||||
@ -204,11 +201,10 @@ DISCOVERY_SCHEMAS = [
|
|||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
entity_class=MatterSensor,
|
entity_class=MatterSensor,
|
||||||
required_attributes=(EveEnergyCluster.Attributes.Current,),
|
required_attributes=(EveCluster.Attributes.Current,),
|
||||||
# Add OnOff Attribute as optional attribute to poll
|
# Add OnOff Attribute as optional attribute to poll
|
||||||
# the primary value when the relay is toggled
|
# the primary value when the relay is toggled
|
||||||
optional_attributes=(clusters.OnOff.Attributes.OnOff,),
|
optional_attributes=(clusters.OnOff.Attributes.OnOff,),
|
||||||
should_poll=True,
|
|
||||||
),
|
),
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.SENSOR,
|
platform=Platform.SENSOR,
|
||||||
|
@ -2272,7 +2272,7 @@ python-kasa[speedups]==0.6.2.1
|
|||||||
# python-lirc==1.2.3
|
# python-lirc==1.2.3
|
||||||
|
|
||||||
# homeassistant.components.matter
|
# homeassistant.components.matter
|
||||||
python-matter-server==5.10.0
|
python-matter-server==6.1.0b1
|
||||||
|
|
||||||
# homeassistant.components.xiaomi_miio
|
# homeassistant.components.xiaomi_miio
|
||||||
python-miio==0.5.12
|
python-miio==0.5.12
|
||||||
|
@ -1766,7 +1766,7 @@ python-juicenet==1.1.0
|
|||||||
python-kasa[speedups]==0.6.2.1
|
python-kasa[speedups]==0.6.2.1
|
||||||
|
|
||||||
# homeassistant.components.matter
|
# homeassistant.components.matter
|
||||||
python-matter-server==5.10.0
|
python-matter-server==6.1.0b1
|
||||||
|
|
||||||
# homeassistant.components.xiaomi_miio
|
# homeassistant.components.xiaomi_miio
|
||||||
python-miio==0.5.12
|
python-miio==0.5.12
|
||||||
|
@ -354,11 +354,11 @@
|
|||||||
],
|
],
|
||||||
"1/29/0": [
|
"1/29/0": [
|
||||||
{
|
{
|
||||||
"type": 257,
|
"0": 256,
|
||||||
"revision": 1
|
"1": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"1/29/1": [3, 4, 6, 8, 29, 768, 1030],
|
"1/29/1": [3, 4, 6, 29],
|
||||||
"1/29/2": [],
|
"1/29/2": [],
|
||||||
"1/29/3": [],
|
"1/29/3": [],
|
||||||
"1/29/65532": 0,
|
"1/29/65532": 0,
|
||||||
|
@ -354,11 +354,11 @@
|
|||||||
],
|
],
|
||||||
"1/29/0": [
|
"1/29/0": [
|
||||||
{
|
{
|
||||||
"type": 257,
|
"0": 256,
|
||||||
"revision": 1
|
"1": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"1/29/1": [3, 4, 6, 8, 29, 768, 1030],
|
"1/29/1": [3, 4, 6, 29],
|
||||||
"1/29/2": [],
|
"1/29/2": [],
|
||||||
"1/29/3": [],
|
"1/29/3": [],
|
||||||
"1/29/65532": 0,
|
"1/29/65532": 0,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""Test Matter sensors."""
|
"""Test Matter sensors."""
|
||||||
|
|
||||||
from datetime import UTC, datetime, timedelta
|
from unittest.mock import MagicMock
|
||||||
from unittest.mock import MagicMock, patch
|
|
||||||
|
|
||||||
from matter_server.client.models.node import MatterNode
|
from matter_server.client.models.node import MatterNode
|
||||||
import pytest
|
import pytest
|
||||||
@ -16,8 +15,6 @@ from .common import (
|
|||||||
trigger_subscription_callback,
|
trigger_subscription_callback,
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="flow_sensor_node")
|
@pytest.fixture(name="flow_sensor_node")
|
||||||
async def flow_sensor_node_fixture(
|
async def flow_sensor_node_fixture(
|
||||||
@ -280,26 +277,6 @@ async def test_eve_energy_sensors(
|
|||||||
assert state.attributes["device_class"] == "current"
|
assert state.attributes["device_class"] == "current"
|
||||||
assert state.attributes["friendly_name"] == "Eve Energy Plug Current"
|
assert state.attributes["friendly_name"] == "Eve Energy Plug Current"
|
||||||
|
|
||||||
# test if the sensor gets polled on interval
|
|
||||||
eve_energy_plug_node.update_attribute("1/319486977/319422472", 237.0)
|
|
||||||
async_fire_time_changed(hass, datetime.now(UTC) + timedelta(seconds=31))
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
entity_id = "sensor.eve_energy_plug_voltage"
|
|
||||||
state = hass.states.get(entity_id)
|
|
||||||
assert state
|
|
||||||
assert state.state == "237.0"
|
|
||||||
|
|
||||||
# test extra poll triggered when secondary value (switch state) changes
|
|
||||||
set_node_attribute(eve_energy_plug_node, 1, 6, 0, True)
|
|
||||||
eve_energy_plug_node.update_attribute("1/319486977/319422474", 5.0)
|
|
||||||
with patch("homeassistant.components.matter.entity.EXTRA_POLL_DELAY", 0.0):
|
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
entity_id = "sensor.eve_energy_plug_power"
|
|
||||||
state = hass.states.get(entity_id)
|
|
||||||
assert state
|
|
||||||
assert state.state == "5.0"
|
|
||||||
|
|
||||||
|
|
||||||
# This tests needs to be adjusted to remove lingering tasks
|
# This tests needs to be adjusted to remove lingering tasks
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user