Home Assistant Unofficial Reference 2024.12.1
valve.py
Go to the documentation of this file.
1 """Matter valve platform."""
2 
3 from __future__ import annotations
4 
5 from chip.clusters import Objects as clusters
6 from matter_server.client.models import device_types
7 
9  ValveDeviceClass,
10  ValveEntity,
11  ValveEntityDescription,
12  ValveEntityFeature,
13 )
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.const import Platform
16 from homeassistant.core import HomeAssistant, callback
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
18 
19 from .entity import MatterEntity
20 from .helpers import get_matter
21 from .models import MatterDiscoverySchema
22 
23 ValveConfigurationAndControl = clusters.ValveConfigurationAndControl
24 
25 ValveStateEnum = ValveConfigurationAndControl.Enums.ValveStateEnum
26 
27 
29  hass: HomeAssistant,
30  config_entry: ConfigEntry,
31  async_add_entities: AddEntitiesCallback,
32 ) -> None:
33  """Set up Matter valve platform from Config Entry."""
34  matter = get_matter(hass)
35  matter.register_platform_handler(Platform.VALVE, async_add_entities)
36 
37 
39  """Representation of a Matter Valve."""
40 
41  _feature_map: int | None = None
42  entity_description: ValveEntityDescription
43  _platform_translation_key = "valve"
44 
46  self,
47  command: clusters.ClusterCommand,
48  ) -> None:
49  """Send a command to the device."""
50  await self.matter_clientmatter_client.send_device_command(
51  node_id=self._endpoint_endpoint.node.node_id,
52  endpoint_id=self._endpoint_endpoint.endpoint_id,
53  command=command,
54  )
55 
56  async def async_open_valve(self) -> None:
57  """Open the valve."""
58  await self.send_device_commandsend_device_command(ValveConfigurationAndControl.Commands.Open())
59 
60  async def async_close_valve(self) -> None:
61  """Close the valve."""
62  await self.send_device_commandsend_device_command(ValveConfigurationAndControl.Commands.Close())
63 
64  async def async_set_valve_position(self, position: int) -> None:
65  """Move the valve to a specific position."""
66  await self.send_device_commandsend_device_command(
67  ValveConfigurationAndControl.Commands.Open(targetLevel=position)
68  )
69 
70  @callback
71  def _update_from_device(self) -> None:
72  """Update from device."""
73  self._calculate_features_calculate_features()
74  current_state: int
75  current_state = self.get_matter_attribute_valueget_matter_attribute_value(
76  ValveConfigurationAndControl.Attributes.CurrentState
77  )
78  target_state: int
79  target_state = self.get_matter_attribute_valueget_matter_attribute_value(
80  ValveConfigurationAndControl.Attributes.TargetState
81  )
82  if (
83  current_state == ValveStateEnum.kTransitioning
84  and target_state == ValveStateEnum.kOpen
85  ):
86  self._attr_is_opening_attr_is_opening = True
87  self._attr_is_closing_attr_is_closing = False
88  elif (
89  current_state == ValveStateEnum.kTransitioning
90  and target_state == ValveStateEnum.kClosed
91  ):
92  self._attr_is_opening_attr_is_opening = False
93  self._attr_is_closing_attr_is_closing = True
94  elif current_state == ValveStateEnum.kClosed:
95  self._attr_is_opening_attr_is_opening = False
96  self._attr_is_closing_attr_is_closing = False
97  self._attr_is_closed_attr_is_closed = True
98  else:
99  self._attr_is_opening_attr_is_opening = False
100  self._attr_is_closing_attr_is_closing = False
101  self._attr_is_closed_attr_is_closed = False
102  # handle optional position
103  if self.supported_featuressupported_featuressupported_features & ValveEntityFeature.SET_POSITION:
104  self._attr_current_valve_position_attr_current_valve_position = self.get_matter_attribute_valueget_matter_attribute_value(
105  ValveConfigurationAndControl.Attributes.CurrentLevel
106  )
107 
108  @callback
110  self,
111  ) -> None:
112  """Calculate features for HA Valve platform from Matter FeatureMap."""
113  feature_map = int(
114  self.get_matter_attribute_valueget_matter_attribute_value(
115  ValveConfigurationAndControl.Attributes.FeatureMap
116  )
117  )
118  # NOTE: the featuremap can dynamically change, so we need to update the
119  # supported features if the featuremap changes.
120  # work out supported features and presets from matter featuremap
121  if self._feature_map_feature_map == feature_map:
122  return
123  self._feature_map_feature_map = feature_map
124  self._attr_supported_features_attr_supported_features = ValveEntityFeature(0)
125  if feature_map & ValveConfigurationAndControl.Bitmaps.Feature.kLevel:
126  self._attr_supported_features_attr_supported_features |= ValveEntityFeature.SET_POSITION
127  self._attr_reports_position_attr_reports_position = True
128  else:
129  self._attr_reports_position_attr_reports_position = False
130 
131  self._attr_supported_features_attr_supported_features |= (
132  ValveEntityFeature.CLOSE | ValveEntityFeature.OPEN
133  )
134 
135 
136 # Discovery schema(s) to map Matter Attributes to HA entities
137 DISCOVERY_SCHEMAS = [
139  platform=Platform.VALVE,
140  entity_description=ValveEntityDescription(
141  key="MatterValve",
142  device_class=ValveDeviceClass.WATER,
143  name=None,
144  ),
145  entity_class=MatterValve,
146  required_attributes=(
147  ValveConfigurationAndControl.Attributes.CurrentState,
148  ValveConfigurationAndControl.Attributes.TargetState,
149  ),
150  optional_attributes=(ValveConfigurationAndControl.Attributes.CurrentLevel,),
151  device_type=(device_types.WaterValve,),
152  ),
153 ]
Any get_matter_attribute_value(self, type[ClusterAttributeDescriptor] attribute, bool null_as_none=True)
Definition: entity.py:206
None async_set_valve_position(self, int position)
Definition: valve.py:64
None send_device_command(self, clusters.ClusterCommand command)
Definition: valve.py:48
ValveEntityFeature supported_features(self)
Definition: __init__.py:199
int|None supported_features(self)
Definition: entity.py:861
MatterAdapter get_matter(HomeAssistant hass)
Definition: helpers.py:35
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: valve.py:32