Matter handle FeatureMap update (#122544)
This commit is contained in:
parent
f1084a57df
commit
8a4206da99
6 changed files with 93 additions and 74 deletions
|
@ -3,7 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from enum import IntEnum
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import Any
|
||||
|
||||
from chip.clusters import Objects as clusters
|
||||
from matter_server.client.models import device_types
|
||||
|
@ -30,12 +30,6 @@ from .entity import MatterEntity
|
|||
from .helpers import get_matter
|
||||
from .models import MatterDiscoverySchema
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from matter_server.client import MatterClient
|
||||
from matter_server.client.models.node import MatterEndpoint
|
||||
|
||||
from .discovery import MatterEntityInfo
|
||||
|
||||
TEMPERATURE_SCALING_FACTOR = 100
|
||||
HVAC_SYSTEM_MODE_MAP = {
|
||||
HVACMode.OFF: 0,
|
||||
|
@ -105,46 +99,9 @@ class MatterClimate(MatterEntity, ClimateEntity):
|
|||
|
||||
_attr_temperature_unit: str = UnitOfTemperature.CELSIUS
|
||||
_attr_hvac_mode: HVACMode = HVACMode.OFF
|
||||
_feature_map: int | None = None
|
||||
_enable_turn_on_off_backwards_compatibility = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
matter_client: MatterClient,
|
||||
endpoint: MatterEndpoint,
|
||||
entity_info: MatterEntityInfo,
|
||||
) -> None:
|
||||
"""Initialize the Matter climate entity."""
|
||||
super().__init__(matter_client, endpoint, entity_info)
|
||||
product_id = self._endpoint.node.device_info.productID
|
||||
vendor_id = self._endpoint.node.device_info.vendorID
|
||||
|
||||
# set hvac_modes based on feature map
|
||||
self._attr_hvac_modes: list[HVACMode] = [HVACMode.OFF]
|
||||
feature_map = int(
|
||||
self.get_matter_attribute_value(clusters.Thermostat.Attributes.FeatureMap)
|
||||
)
|
||||
self._attr_supported_features = (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.TURN_OFF
|
||||
)
|
||||
if feature_map & ThermostatFeature.kHeating:
|
||||
self._attr_hvac_modes.append(HVACMode.HEAT)
|
||||
if feature_map & ThermostatFeature.kCooling:
|
||||
self._attr_hvac_modes.append(HVACMode.COOL)
|
||||
if (vendor_id, product_id) in SUPPORT_DRY_MODE_DEVICES:
|
||||
self._attr_hvac_modes.append(HVACMode.DRY)
|
||||
if (vendor_id, product_id) in SUPPORT_FAN_MODE_DEVICES:
|
||||
self._attr_hvac_modes.append(HVACMode.FAN_ONLY)
|
||||
if feature_map & ThermostatFeature.kAutoMode:
|
||||
self._attr_hvac_modes.append(HVACMode.HEAT_COOL)
|
||||
# only enable temperature_range feature if the device actually supports that
|
||||
|
||||
if (vendor_id, product_id) not in SINGLE_SETPOINT_DEVICES:
|
||||
self._attr_supported_features |= (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||
)
|
||||
if any(mode for mode in self.hvac_modes if mode != HVACMode.OFF):
|
||||
self._attr_supported_features |= ClimateEntityFeature.TURN_ON
|
||||
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set new target temperature."""
|
||||
target_hvac_mode: HVACMode | None = kwargs.get(ATTR_HVAC_MODE)
|
||||
|
@ -224,6 +181,7 @@ class MatterClimate(MatterEntity, ClimateEntity):
|
|||
@callback
|
||||
def _update_from_device(self) -> None:
|
||||
"""Update from device."""
|
||||
self._calculate_features()
|
||||
self._attr_current_temperature = self._get_temperature_in_degrees(
|
||||
clusters.Thermostat.Attributes.LocalTemperature
|
||||
)
|
||||
|
@ -319,6 +277,46 @@ class MatterClimate(MatterEntity, ClimateEntity):
|
|||
else:
|
||||
self._attr_max_temp = DEFAULT_MAX_TEMP
|
||||
|
||||
@callback
|
||||
def _calculate_features(
|
||||
self,
|
||||
) -> None:
|
||||
"""Calculate features for HA Thermostat platform from Matter FeatureMap."""
|
||||
feature_map = int(
|
||||
self.get_matter_attribute_value(clusters.Thermostat.Attributes.FeatureMap)
|
||||
)
|
||||
# NOTE: the featuremap can dynamically change, so we need to update the
|
||||
# supported features if the featuremap changes.
|
||||
# work out supported features and presets from matter featuremap
|
||||
if self._feature_map == feature_map:
|
||||
return
|
||||
self._feature_map = feature_map
|
||||
product_id = self._endpoint.node.device_info.productID
|
||||
vendor_id = self._endpoint.node.device_info.vendorID
|
||||
self._attr_hvac_modes: list[HVACMode] = [HVACMode.OFF]
|
||||
self._attr_supported_features = (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.TURN_OFF
|
||||
)
|
||||
if feature_map & ThermostatFeature.kHeating:
|
||||
self._attr_hvac_modes.append(HVACMode.HEAT)
|
||||
if feature_map & ThermostatFeature.kCooling:
|
||||
self._attr_hvac_modes.append(HVACMode.COOL)
|
||||
if (vendor_id, product_id) in SUPPORT_DRY_MODE_DEVICES:
|
||||
self._attr_hvac_modes.append(HVACMode.DRY)
|
||||
if (vendor_id, product_id) in SUPPORT_FAN_MODE_DEVICES:
|
||||
self._attr_hvac_modes.append(HVACMode.FAN_ONLY)
|
||||
if feature_map & ThermostatFeature.kAutoMode:
|
||||
self._attr_hvac_modes.append(HVACMode.HEAT_COOL)
|
||||
# only enable temperature_range feature if the device actually supports that
|
||||
|
||||
if (vendor_id, product_id) not in SINGLE_SETPOINT_DEVICES:
|
||||
self._attr_supported_features |= (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||
)
|
||||
if any(mode for mode in self.hvac_modes if mode != HVACMode.OFF):
|
||||
self._attr_supported_features |= ClimateEntityFeature.TURN_ON
|
||||
|
||||
@callback
|
||||
def _get_temperature_in_degrees(
|
||||
self, attribute: type[clusters.ClusterAttributeDescriptor]
|
||||
) -> float | None:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue