Matter handle FeatureMap update (#122544)

This commit is contained in:
Marcel van der Veldt 2024-07-31 20:37:57 +02:00 committed by GitHub
parent f1084a57df
commit 8a4206da99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 93 additions and 74 deletions

View file

@ -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: