Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matter TemperatureNumber feature from TemperatureControl cluster #128838

Open
wants to merge 41 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5010f44
Create temperature_control.py
lboue Oct 20, 2024
ab9c7a0
Update temperature_control.py
lboue Oct 20, 2024
3dcfd71
Update temperature_control.py
lboue Oct 20, 2024
41615a0
Update temperature_control.py
lboue Oct 20, 2024
3713603
Update temperature_control.py
lboue Oct 20, 2024
be1cd73
Update temperature_control.py
lboue Oct 20, 2024
1bc8a01
Update temperature_control.py
lboue Oct 20, 2024
ae7d853
ruff-format
lboue Oct 20, 2024
008b5b9
Update temperature_control.py
lboue Oct 20, 2024
ded711e
Update temperature_control.py
lboue Oct 20, 2024
d7aee69
Update temperature_control.py
lboue Oct 20, 2024
70887f9
TemperatureControl SelectedTemperatureLevel
lboue Oct 20, 2024
b857efe
Update climate.py
lboue Oct 20, 2024
46c18ea
TemperatureControlFeature
lboue Oct 20, 2024
a9af663
Delete homeassistant/components/matter/temperature_control.py
lboue Oct 20, 2024
22a4c18
TemperatureControl mode
lboue Oct 20, 2024
2acd72e
StrEnum
lboue Oct 20, 2024
43ef56c
Update climate.py
lboue Oct 20, 2024
564821d
Update climate.py
lboue Oct 20, 2024
7a68c68
Update climate.py
lboue Oct 20, 2024
d5c4f1b
Use feature name instead of feature code
lboue Oct 20, 2024
68bf4df
Update climate.py
lboue Oct 20, 2024
ddca2d4
Update climate.py
lboue Oct 20, 2024
e1c332d
Create silabs_laundrywasher.json
lboue Oct 20, 2024
f0b6716
Update silabs_laundrywasher.json
lboue Oct 20, 2024
8297fd4
Merge branch 'dev' into TemperatureControlled
lboue Dec 13, 2024
35183bc
Update silabs_laundrywasher.json
lboue Jan 3, 2025
fefe07a
Remove the select part
lboue Jan 3, 2025
bbee0ed
Fixture
lboue Jan 3, 2025
d2d4f39
TemperatureControl / TemperatureSetpoint
lboue Jan 4, 2025
59d1391
Delete tests/components/matter/fixtures/nodes/silabs_laundrywasher.json
lboue Jan 4, 2025
ad5de14
Tests for TemperatureControl cluster
lboue Jan 4, 2025
08fa381
Update climate.py
lboue Jan 4, 2025
3e59c9b
Add fixture to conftest
lboue Jan 8, 2025
08c9b4d
Update tests
lboue Jan 8, 2025
b8432cb
Update tests
lboue Jan 8, 2025
72684c2
Update homeassistant/components/matter/climate.py
lboue Jan 25, 2025
f26de81
Update homeassistant/components/matter/climate.py
lboue Jan 25, 2025
b449484
Merge branch 'dev' into TemperatureControlled
lboue Jan 26, 2025
8d0441b
Set TemperatureSetpoint as primary attribute
lboue Jan 26, 2025
0876e57
Only update featuremap if it changes
lboue Jan 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions homeassistant/components/matter/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
SystemModeEnum = clusters.Thermostat.Enums.SystemModeEnum
ControlSequenceEnum = clusters.Thermostat.Enums.ControlSequenceOfOperationEnum
ThermostatFeature = clusters.Thermostat.Bitmaps.Feature
TemperatureControlFeature = clusters.TemperatureControl.Bitmaps.Feature


class ThermostatRunningState(IntEnum):
Expand Down Expand Up @@ -420,6 +421,91 @@ def _get_temperature_in_degrees(
return None


class MatterTemperatureControlClimate(MatterEntity, ClimateEntity):
"""Representation of a climate entity from the Matter TemperatureControl cluster."""

_attr_temperature_unit: str = UnitOfTemperature.CELSIUS
_attr_hvac_mode: HVACMode = HVACMode.HEAT_COOL
_attr_hvac_modes: list[HVACMode] = [HVACMode.HEAT_COOL]
_attr_target_temperature_step: float | None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is already defined in the base model, no need to repeat here

_feature_map: int | None = None

_platform_translation_key = "thermostat"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the thing I'm in doubt about. We could choose to define a translation key for "Temperature Control" instead of the default Thermostat label. What do you think ?


async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
target_hvac_mode: HVACMode | None = kwargs.get(ATTR_HVAC_MODE)
target_temperature: float | None = kwargs.get(ATTR_TEMPERATURE)

if target_hvac_mode is not None:
await self.async_set_hvac_mode(target_hvac_mode)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a small test case where the mode is also set in the set temperature


if target_temperature is not None:
# single setpoint control
if self.target_temperature != target_temperature:
await self.matter_client.send_device_command(
node_id=self._endpoint.node.node_id,
endpoint_id=self._endpoint.endpoint_id,
command=clusters.TemperatureControl.Commands.SetTemperature(
targetTemperature=int(
target_temperature * TEMPERATURE_SCALING_FACTOR
)
),
)
return

@callback
def _update_from_device(self) -> None:
"""Update from device."""
self._calculate_features()
self._attr_hvac_action = None
# update target_temperature
self._attr_target_temperature = self._get_temperature_in_degrees(
clusters.TemperatureControl.Attributes.TemperatureSetpoint
)
# update min_temp
attribute = clusters.TemperatureControl.Attributes.MinTemperature
if (value := self._get_temperature_in_degrees(attribute)) is not None:
self._attr_min_temp = value
# update max_temp
attribute = clusters.TemperatureControl.Attributes.MaxTemperature
if (value := self._get_temperature_in_degrees(attribute)) is not None:
self._attr_max_temp = value

@callback
def _calculate_features(
self,
) -> None:
"""Calculate features for HA Thermostat platform from Matter FeatureMap."""
feature_map = int(
self.get_matter_attribute_value(
clusters.TemperatureControl.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
lboue marked this conversation as resolved.
Show resolved Hide resolved
self._attr_hvac_modes: list[HVACMode] = [HVACMode.HEAT_COOL]
if feature_map & TemperatureControlFeature.kTemperatureNumber:
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
if feature_map & TemperatureControlFeature.kTemperatureStep:
self._attr_target_temperature_step = self._get_temperature_in_degrees(
clusters.TemperatureControl.Attributes.Step
)

@callback
def _get_temperature_in_degrees(
self, attribute: type[clusters.ClusterAttributeDescriptor]
) -> float | None:
"""Return the scaled temperature value for the given attribute."""
if value := self.get_matter_attribute_value(attribute):
return float(value) / TEMPERATURE_SCALING_FACTOR
return None


# Discovery schema(s) to map Matter Attributes to HA entities
DISCOVERY_SCHEMAS = [
MatterDiscoverySchema(
Expand All @@ -446,4 +532,19 @@ def _get_temperature_in_degrees(
),
device_type=(device_types.Thermostat, device_types.RoomAirConditioner),
),
MatterDiscoverySchema(
platform=Platform.CLIMATE,
entity_description=ClimateEntityDescription(
key="MatterTemperatureControl",
name=None,
),
entity_class=MatterTemperatureControlClimate,
required_attributes=(
clusters.TemperatureControl.Attributes.TemperatureSetpoint,
clusters.TemperatureControl.Attributes.FeatureMap,
lboue marked this conversation as resolved.
Show resolved Hide resolved
clusters.TemperatureControl.Attributes.MinTemperature,
clusters.TemperatureControl.Attributes.MaxTemperature,
),
optional_attributes=(clusters.TemperatureControl.Attributes.Step,),
),
]
1 change: 1 addition & 0 deletions tests/components/matter/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ async def integration_fixture(
"room_airconditioner",
"silabs_dishwasher",
"silabs_laundrywasher",
"silabs_refrigerator",
"smoke_detector",
"switch_unit",
"temperature_sensor",
Expand Down
Loading
Loading