Skip to content

Commit e5b93d3

Browse files
jvmahonlboueTheJulianJESarturpragacz
authored
Add Matter entity labeling capabilities (#154173)
Co-authored-by: Ludovic BOUÉ <lboue@users.noreply.github.com> Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com> Co-authored-by: Artur Pragacz <49985303+arturpragacz@users.noreply.github.com>
1 parent 1c024f5 commit e5b93d3

File tree

10 files changed

+462
-429
lines changed

10 files changed

+462
-429
lines changed

homeassistant/components/matter/entity.py

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@
3636

3737
LOGGER = logging.getLogger(__name__)
3838

39+
# Due to variances in labeling implementations, labels are vendor and product specific.
40+
# This dictionary defines which labels to use for specific vendor/product combinations.
41+
# The keys are vendor IDs, the values are dictionaries with product IDs as keys
42+
# and lists of label names to use as values. If the value is None, no labels are used
43+
VENDOR_LABELING_LIST: dict[int, dict[int, list[str] | None]] = {
44+
4488: {259: ["position"]}, # TP-Link Dual Outdoor Plug US
45+
4874: {105: ["orientation"]}, # Eve Energy dual Outlet US
46+
4961: {
47+
1: ["inovelliname", "label", "name", "button"], # Inovelli VTM31
48+
2: ["label", "devicetype", "button"], # Inovelli VTM35
49+
4: None, # Inovelli VTM36
50+
16: ["label", "name", "button"], # Inovelli VTM30
51+
},
52+
}
53+
3954

4055
def catch_matter_error[_R, **P](
4156
func: Callable[Concatenate[MatterEntity, P], Coroutine[Any, Any, _R]],
@@ -112,30 +127,47 @@ def __init__(
112127
if self._platform_translation_key and not self.translation_key:
113128
self._attr_translation_key = self._platform_translation_key
114129

115-
# prefer the label attribute for the entity name
116-
# Matter has a way for users and/or vendors to specify a name for an endpoint
117-
# which is always preferred over a standard HA (generated) name
118-
for attr in (
119-
clusters.FixedLabel.Attributes.LabelList,
120-
clusters.UserLabel.Attributes.LabelList,
121-
):
122-
if not (labels := self.get_matter_attribute_value(attr)):
123-
continue
124-
for label in labels:
125-
if label.label not in ["Label", "Button"]:
126-
continue
127-
# fixed or user label found: use it
128-
label_value: str = label.value
129-
# in the case the label is only the label id, use it as postfix only
130-
if label_value.isnumeric():
131-
self._name_postfix = label_value
132-
else:
133-
self._attr_name = label_value
134-
break
130+
# Matter labels can be used to modify the entity name
131+
# by appending the text.
132+
if name_modifier := self._get_name_modifier():
133+
self._name_postfix = name_modifier
135134

136135
# make sure to update the attributes once
137136
self._update_from_device()
138137

138+
def _find_matching_labels(self) -> list[str]:
139+
"""Find all labels for a Matter entity."""
140+
141+
device_info = self._endpoint.device_info
142+
labeling_list = VENDOR_LABELING_LIST.get(device_info.vendorID, {}).get(
143+
device_info.productID
144+
)
145+
146+
# get the labels from the UserLabel and FixedLabel clusters
147+
user_label_list: list[clusters.UserLabel.Structs.LabelStruct] = (
148+
self.get_matter_attribute_value(clusters.UserLabel.Attributes.LabelList)
149+
or []
150+
)
151+
fixed_label_list: list[clusters.FixedLabel.Structs.LabelStruct] = (
152+
self.get_matter_attribute_value(clusters.FixedLabel.Attributes.LabelList)
153+
or []
154+
)
155+
156+
found_labels: list[str] = [
157+
lbl.value
158+
for label in labeling_list or []
159+
for lbl in (*user_label_list, *fixed_label_list)
160+
if lbl.label.lower() == label
161+
]
162+
return found_labels
163+
164+
def _get_name_modifier(self) -> str | None:
165+
"""Get the name modifier for the entity."""
166+
167+
if found_labels := self._find_matching_labels():
168+
return found_labels[0]
169+
return None
170+
139171
async def async_added_to_hass(self) -> None:
140172
"""Handle being added to Home Assistant."""
141173
await super().async_added_to_hass()

homeassistant/components/matter/update.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ async def async_will_remove_from_hass(self) -> None:
256256
MatterDiscoverySchema(
257257
platform=Platform.UPDATE,
258258
entity_description=MatterUpdateEntityDescription(
259-
key="MatterUpdate", device_class=UpdateDeviceClass.FIRMWARE
259+
key="MatterUpdate",
260+
device_class=UpdateDeviceClass.FIRMWARE,
260261
),
261262
entity_class=MatterUpdate,
262263
required_attributes=(

0 commit comments

Comments
 (0)