mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 23:41:48 -05:00
Add Matter Boolean State Configuration alarm switches (#173233)
Co-authored-by: Ludovic BOUÉ <lboue@users.noreply.github.com> Co-authored-by: Ludovic BOUÉ <938089+lboue@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
Ludovic BOUÉ
Ludovic BOUÉ
Claude Sonnet 5
Copilot Autofix powered by AI
parent
535cc28263
commit
932838840b
@@ -154,6 +154,9 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"audible_alarm_enabled": {
|
||||
"default": "mdi:bullhorn"
|
||||
},
|
||||
"child_lock": {
|
||||
"default": "mdi:lock",
|
||||
"state": {
|
||||
@@ -173,6 +176,9 @@
|
||||
"off": "mdi:volume-high",
|
||||
"on": "mdi:volume-mute"
|
||||
}
|
||||
},
|
||||
"visual_alarm_enabled": {
|
||||
"default": "mdi:alarm-light"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -690,6 +690,9 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"audible_alarm_enabled": {
|
||||
"name": "Audible alarm enabled"
|
||||
},
|
||||
"child_lock": {
|
||||
"name": "Child lock"
|
||||
},
|
||||
@@ -710,6 +713,9 @@
|
||||
},
|
||||
"switch": {
|
||||
"name": "[%key:component::switch::title%]"
|
||||
},
|
||||
"visual_alarm_enabled": {
|
||||
"name": "Visual alarm enabled"
|
||||
}
|
||||
},
|
||||
"vacuum": {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
"""Matter switches."""
|
||||
|
||||
from asyncio import Lock
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, override
|
||||
from weakref import WeakKeyDictionary
|
||||
|
||||
from chip.clusters import Objects as clusters
|
||||
from chip.clusters.Objects import ClusterCommand, NullValue
|
||||
from matter_server.client.models import device_types
|
||||
from matter_server.client.models.node import MatterEndpoint
|
||||
|
||||
from homeassistant.components.switch import (
|
||||
SwitchDeviceClass,
|
||||
@@ -28,6 +31,29 @@ EVSE_SUPPLY_STATE_MAP = {
|
||||
clusters.EnergyEvse.Enums.SupplyStateEnum.kDisabledDiagnostics: False,
|
||||
}
|
||||
|
||||
ALARM_MODE_VISUAL = clusters.BooleanStateConfiguration.Bitmaps.AlarmModeBitmap.kVisual
|
||||
ALARM_MODE_AUDIBLE = clusters.BooleanStateConfiguration.Bitmaps.AlarmModeBitmap.kAudible
|
||||
|
||||
BOOLEAN_STATE_CONFIGURATION_FEATURE_VISUAL = (
|
||||
clusters.BooleanStateConfiguration.Bitmaps.Feature.kVisual
|
||||
)
|
||||
BOOLEAN_STATE_CONFIGURATION_FEATURE_AUDIBLE = (
|
||||
clusters.BooleanStateConfiguration.Bitmaps.Feature.kAudible
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class _AlarmEnabledState:
|
||||
"""Track pending alarm state for an endpoint."""
|
||||
|
||||
lock: Lock = field(default_factory=Lock)
|
||||
pending_alarms_enabled: int | None = None
|
||||
|
||||
|
||||
ALARM_ENABLED_STATES: WeakKeyDictionary[MatterEndpoint, _AlarmEnabledState] = (
|
||||
WeakKeyDictionary()
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@@ -183,6 +209,83 @@ class MatterNumericSwitch(MatterSwitch):
|
||||
self._attr_is_on = value
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class MatterAlarmEnabledSwitchEntityDescription(MatterSwitchEntityDescription):
|
||||
"""Describe Matter alarm enabled Switch entities."""
|
||||
|
||||
alarm_mode: int
|
||||
|
||||
|
||||
class MatterAlarmEnabledSwitch(MatterSwitch):
|
||||
"""Representation of a Matter Boolean State Configuration alarm switch."""
|
||||
|
||||
entity_description: MatterAlarmEnabledSwitchEntityDescription
|
||||
|
||||
async def _async_set_alarm_enabled(self, value: bool) -> None:
|
||||
"""Set the enabled state for an alarm mode."""
|
||||
state = ALARM_ENABLED_STATES.setdefault(self._endpoint, _AlarmEnabledState())
|
||||
async with state.lock:
|
||||
alarms_enabled = state.pending_alarms_enabled
|
||||
if alarms_enabled is None:
|
||||
alarms_enabled = (
|
||||
self.get_matter_attribute_value(
|
||||
clusters.BooleanStateConfiguration.Attributes.AlarmsEnabled
|
||||
)
|
||||
or 0
|
||||
)
|
||||
if value:
|
||||
alarms_enabled |= self.entity_description.alarm_mode
|
||||
else:
|
||||
alarms_enabled &= ~self.entity_description.alarm_mode
|
||||
|
||||
state.pending_alarms_enabled = alarms_enabled
|
||||
try:
|
||||
await self.send_device_command(
|
||||
clusters.BooleanStateConfiguration.Commands.EnableDisableAlarm(
|
||||
alarmsToEnableDisable=alarms_enabled,
|
||||
)
|
||||
)
|
||||
except BaseException:
|
||||
if state.pending_alarms_enabled == alarms_enabled:
|
||||
state.pending_alarms_enabled = None
|
||||
raise
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn alarm mode on."""
|
||||
await self._async_set_alarm_enabled(True)
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn alarm mode off."""
|
||||
await self._async_set_alarm_enabled(False)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _update_from_device(self) -> None:
|
||||
"""Update from device."""
|
||||
alarm_mode = self.entity_description.alarm_mode
|
||||
alarms_supported = (
|
||||
self.get_matter_attribute_value(
|
||||
clusters.BooleanStateConfiguration.Attributes.AlarmsSupported
|
||||
)
|
||||
or 0
|
||||
)
|
||||
self._attr_available = self._attr_available and bool(
|
||||
alarms_supported & alarm_mode
|
||||
)
|
||||
|
||||
alarms_enabled = (
|
||||
self.get_matter_attribute_value(
|
||||
clusters.BooleanStateConfiguration.Attributes.AlarmsEnabled
|
||||
)
|
||||
or 0
|
||||
)
|
||||
if state := ALARM_ENABLED_STATES.get(self._endpoint):
|
||||
state.pending_alarms_enabled = alarms_enabled
|
||||
self._attr_is_on = bool(alarms_enabled & alarm_mode)
|
||||
|
||||
|
||||
# Discovery schema(s) to map Matter Attributes to HA entities
|
||||
DISCOVERY_SCHEMAS = [
|
||||
MatterDiscoverySchema(
|
||||
@@ -346,4 +449,44 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_class=MatterNumericSwitch,
|
||||
required_attributes=(clusters.EveCluster.Attributes.ChildLock,),
|
||||
),
|
||||
MatterDiscoverySchema(
|
||||
platform=Platform.SWITCH,
|
||||
entity_description=MatterAlarmEnabledSwitchEntityDescription(
|
||||
key="BooleanStateConfigurationVisualAlarmEnabled",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
translation_key="visual_alarm_enabled",
|
||||
alarm_mode=ALARM_MODE_VISUAL,
|
||||
),
|
||||
entity_class=MatterAlarmEnabledSwitch,
|
||||
required_attributes=(
|
||||
clusters.BooleanStateConfiguration.Attributes.AlarmsEnabled,
|
||||
clusters.BooleanStateConfiguration.Attributes.AcceptedCommandList,
|
||||
clusters.BooleanStateConfiguration.Attributes.AlarmsSupported,
|
||||
),
|
||||
secondary_value_contains=(
|
||||
clusters.BooleanStateConfiguration.Commands.EnableDisableAlarm.command_id
|
||||
),
|
||||
featuremap_contains=BOOLEAN_STATE_CONFIGURATION_FEATURE_VISUAL,
|
||||
allow_multi=True,
|
||||
),
|
||||
MatterDiscoverySchema(
|
||||
platform=Platform.SWITCH,
|
||||
entity_description=MatterAlarmEnabledSwitchEntityDescription(
|
||||
key="BooleanStateConfigurationAudibleAlarmEnabled",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
translation_key="audible_alarm_enabled",
|
||||
alarm_mode=ALARM_MODE_AUDIBLE,
|
||||
),
|
||||
entity_class=MatterAlarmEnabledSwitch,
|
||||
required_attributes=(
|
||||
clusters.BooleanStateConfiguration.Attributes.AlarmsEnabled,
|
||||
clusters.BooleanStateConfiguration.Attributes.AcceptedCommandList,
|
||||
clusters.BooleanStateConfiguration.Attributes.AlarmsSupported,
|
||||
),
|
||||
secondary_value_contains=(
|
||||
clusters.BooleanStateConfiguration.Commands.EnableDisableAlarm.command_id
|
||||
),
|
||||
featuremap_contains=BOOLEAN_STATE_CONFIGURATION_FEATURE_AUDIBLE,
|
||||
allow_multi=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
{
|
||||
"node_id": 320,
|
||||
"date_commissioned": "2026-02-07T03:40:58.175000",
|
||||
"last_interview": "2026-04-15T04:08:35.891000",
|
||||
"interview_version": 6,
|
||||
"available": true,
|
||||
"is_bridge": false,
|
||||
"attributes": {
|
||||
"0/29/65533": 2,
|
||||
"0/29/65532": 0,
|
||||
"0/29/0": [
|
||||
{
|
||||
"0": 18,
|
||||
"1": 1
|
||||
},
|
||||
{
|
||||
"0": 17,
|
||||
"1": 1
|
||||
},
|
||||
{
|
||||
"0": 22,
|
||||
"1": 1
|
||||
}
|
||||
],
|
||||
"0/29/1": [29, 31, 40, 42, 47, 48, 49, 51, 53, 60, 62, 63, 70],
|
||||
"0/29/2": [41],
|
||||
"0/29/3": [1],
|
||||
"0/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/29/65529": [],
|
||||
"0/29/65528": [],
|
||||
"0/31/1": [],
|
||||
"0/31/65533": 1,
|
||||
"0/31/65532": 0,
|
||||
"0/31/0": [
|
||||
{
|
||||
"1": 5,
|
||||
"2": 2,
|
||||
"3": [112233],
|
||||
"4": null,
|
||||
"254": 3
|
||||
}
|
||||
],
|
||||
"0/31/2": 4,
|
||||
"0/31/3": 3,
|
||||
"0/31/4": 4,
|
||||
"0/31/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/31/65529": [],
|
||||
"0/31/65528": [],
|
||||
"0/40/11": "20251122",
|
||||
"0/40/12": "E2493",
|
||||
"0/40/16": false,
|
||||
"0/40/17": true,
|
||||
"0/40/24": 1,
|
||||
"0/40/65533": 3,
|
||||
"0/40/0": 17,
|
||||
"0/40/1": "IKEA of Sweden",
|
||||
"0/40/2": 4476,
|
||||
"0/40/3": "KLIPPBOK water leak sensor",
|
||||
"0/40/4": 32774,
|
||||
"0/40/5": "",
|
||||
"0/40/6": "**REDACTED**",
|
||||
"0/40/7": 512,
|
||||
"0/40/8": "P2.0",
|
||||
"0/40/9": 16777229,
|
||||
"0/40/10": "1.0.13",
|
||||
"0/40/18": "5022e21a483c1d4f68fa7b871fb705f9",
|
||||
"0/40/19": {
|
||||
"0": 3,
|
||||
"1": 3
|
||||
},
|
||||
"0/40/21": 16973824,
|
||||
"0/40/22": 1,
|
||||
"0/40/65532": 0,
|
||||
"0/40/65531": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 21, 22, 65528,
|
||||
65529, 65531, 65532, 65533
|
||||
],
|
||||
"0/40/65529": [],
|
||||
"0/40/65528": [],
|
||||
"0/42/65533": 1,
|
||||
"0/42/0": [],
|
||||
"0/42/1": true,
|
||||
"0/42/2": 1,
|
||||
"0/42/3": null,
|
||||
"0/42/65532": 0,
|
||||
"0/42/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/42/65529": [0],
|
||||
"0/42/65528": [],
|
||||
"0/47/65532": 10,
|
||||
"0/47/11": 2991,
|
||||
"0/47/12": 200,
|
||||
"0/47/14": 0,
|
||||
"0/47/15": false,
|
||||
"0/47/16": 2,
|
||||
"0/47/19": "AAA",
|
||||
"0/47/20": 1,
|
||||
"0/47/25": 1,
|
||||
"0/47/65533": 2,
|
||||
"0/47/0": 1,
|
||||
"0/47/1": 0,
|
||||
"0/47/2": "Primary Battery",
|
||||
"0/47/31": [],
|
||||
"0/47/65531": [
|
||||
0, 1, 2, 11, 12, 14, 15, 16, 19, 20, 25, 31, 65528, 65529, 65531, 65532,
|
||||
65533
|
||||
],
|
||||
"0/47/65529": [],
|
||||
"0/47/65528": [],
|
||||
"0/48/65533": 1,
|
||||
"0/48/65532": 0,
|
||||
"0/48/0": 0,
|
||||
"0/48/1": {
|
||||
"0": 60,
|
||||
"1": 900
|
||||
},
|
||||
"0/48/2": 0,
|
||||
"0/48/3": 0,
|
||||
"0/48/4": true,
|
||||
"0/48/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/48/65529": [0, 2, 4],
|
||||
"0/48/65528": [1, 3, 5],
|
||||
"0/49/65532": 2,
|
||||
"0/49/2": 10,
|
||||
"0/49/3": 20,
|
||||
"0/49/9": 4,
|
||||
"0/49/10": 4,
|
||||
"0/49/65533": 2,
|
||||
"0/49/0": 1,
|
||||
"0/49/1": [
|
||||
{
|
||||
"0": "/yXnNCiUSvw=",
|
||||
"1": true
|
||||
}
|
||||
],
|
||||
"0/49/4": true,
|
||||
"0/49/5": 0,
|
||||
"0/49/6": "/yXnNCiUSvw=",
|
||||
"0/49/7": null,
|
||||
"0/49/65531": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 65528, 65529, 65531, 65532, 65533
|
||||
],
|
||||
"0/49/65529": [0, 3, 4, 6, 8],
|
||||
"0/49/65528": [1, 5, 7],
|
||||
"0/51/3": 1565,
|
||||
"0/51/4": 6,
|
||||
"0/51/5": [],
|
||||
"0/51/6": [],
|
||||
"0/51/7": [],
|
||||
"0/51/65533": 2,
|
||||
"0/51/65532": 0,
|
||||
"0/51/0": [
|
||||
{
|
||||
"0": "MyHome1895415629",
|
||||
"1": true,
|
||||
"2": null,
|
||||
"3": null,
|
||||
"4": "2kBsLtRvnPA=",
|
||||
"5": [],
|
||||
"6": [
|
||||
"/Rfu+JATAAAvUPrv0kGOrQ==",
|
||||
"/dH8OtkWot0AAAD//gDMNg==",
|
||||
"/dH8OtkWot29tss/JqJ3Mw==",
|
||||
"/oAAAAAAAADYQGwu1G+c8A=="
|
||||
],
|
||||
"7": 4
|
||||
}
|
||||
],
|
||||
"0/51/1": 7,
|
||||
"0/51/2": 218,
|
||||
"0/51/8": false,
|
||||
"0/51/65531": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 65528, 65529, 65531, 65532, 65533
|
||||
],
|
||||
"0/51/65529": [0, 1],
|
||||
"0/51/65528": [2],
|
||||
"0/53/63": null,
|
||||
"0/53/64": null,
|
||||
"0/53/65533": 2,
|
||||
"0/53/65532": 0,
|
||||
"0/53/0": 25,
|
||||
"0/53/1": 2,
|
||||
"0/53/2": "MyHome1895415629",
|
||||
"0/53/3": 49399,
|
||||
"0/53/4": 18385355265015040764,
|
||||
"0/53/5": "QP3R/DrZFqLd",
|
||||
"0/53/7": [
|
||||
{
|
||||
"0": 6260342793904889918,
|
||||
"1": 218,
|
||||
"2": 52224,
|
||||
"3": 878085,
|
||||
"4": 189075,
|
||||
"5": 3,
|
||||
"6": -47,
|
||||
"7": -48,
|
||||
"8": 59,
|
||||
"9": 0,
|
||||
"10": true,
|
||||
"11": true,
|
||||
"12": true,
|
||||
"13": false
|
||||
}
|
||||
],
|
||||
"0/53/8": [
|
||||
{
|
||||
"0": 6260342793904889918,
|
||||
"1": 52224,
|
||||
"2": 51,
|
||||
"3": 0,
|
||||
"4": 0,
|
||||
"5": 3,
|
||||
"6": 0,
|
||||
"7": 218,
|
||||
"8": true,
|
||||
"9": true
|
||||
}
|
||||
],
|
||||
"0/53/9": 2137771856,
|
||||
"0/53/10": 68,
|
||||
"0/53/11": 140,
|
||||
"0/53/12": 230,
|
||||
"0/53/13": 30,
|
||||
"0/53/59": {
|
||||
"0": 672,
|
||||
"1": 8335
|
||||
},
|
||||
"0/53/60": "AB//wA==",
|
||||
"0/53/61": {
|
||||
"0": true,
|
||||
"1": false,
|
||||
"2": true,
|
||||
"3": true,
|
||||
"4": true,
|
||||
"5": true,
|
||||
"6": false,
|
||||
"7": true,
|
||||
"8": true,
|
||||
"9": true,
|
||||
"10": true,
|
||||
"11": true
|
||||
},
|
||||
"0/53/62": [],
|
||||
"0/53/65531": [
|
||||
0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 59, 60, 61, 62, 65528, 65529,
|
||||
65531, 65532, 65533
|
||||
],
|
||||
"0/53/65529": [],
|
||||
"0/53/65528": [],
|
||||
"0/60/65532": 1,
|
||||
"0/60/65533": 1,
|
||||
"0/60/0": 0,
|
||||
"0/60/1": null,
|
||||
"0/60/2": null,
|
||||
"0/60/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/60/65529": [0, 1, 2],
|
||||
"0/60/65528": [],
|
||||
"0/62/65533": 1,
|
||||
"0/62/0": [
|
||||
{
|
||||
"1": "FTABAQgkAgE3AyQTAhgmBL3MNy8mBT0D5UM3BiQVAiURQAEYJAcBJAgBMAlBBB5ZHrs6JznmDwMq4t9+CjNwTfXtyTVZjyVzVOjlI+cY/hetXDmsCC0TNewgULVLEXlQxezlY85QYFPMlaSruqU3CjUBKAEYJAIBNgMEAgQBGDAEFPMDw70atbx08VczmceWWiv83ov+MAUU/eZfRuhWvUFT8WNU1R/sUE0q70YYMAtAIdqlW4sHK/DRdVQpbywUoGRVIc3G7esTDJgnEG3OcDLWXSHwdDfuuFNLN589EbBOEuOVCPCn+6Im65TuI1tJoxg=",
|
||||
"2": "FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQTAhgkBwEkCAEwCUEEJB6axSR6Xj7Ab+FB5+C+slsdDtj0qCvcRHCCpCYTX6svgMPs/yVVEfvJgIUXZ5gkLS9jK1CpsF4u8MZR6qsNZzcKNQEpARgkAmAwBBT95l9G6Fa9QVPxY1TVH+xQTSrvRjAFFLyrP0JigOFmlOJIyXL9CANMKs5NGDALQNykW7UIqcgXgx+UezCVYPRU8/CpHh9CJBqL/7wKfTM62ujWJlrH0P5DEZ5bV9ZihCk4Wg/DMM2BUuUcTOEEqzEY",
|
||||
"254": 3
|
||||
}
|
||||
],
|
||||
"0/62/1": [
|
||||
{
|
||||
"1": "BCZ12LdJK3WZUiquu2PD6iWSaeQK6J6DWw86GihFX4HiWOG1JQip6ILp0IFNffrIGwriEteEhksN56MylydpF/s=",
|
||||
"2": 4939,
|
||||
"3": 2,
|
||||
"4": 320,
|
||||
"5": "Home",
|
||||
"254": 3
|
||||
}
|
||||
],
|
||||
"0/62/2": 5,
|
||||
"0/62/3": 3,
|
||||
"0/62/4": [
|
||||
"FTABAQEkAgE3AycUZweWCkFUxWIYJgQAxikuJgUAzMFTNwYnFGcHlgpBVMViGCQHASQIATAJQQTNp4X8uzw+lDd+17mb6etHu369TrObsUl8Z+oc0Tv7ETpM91vCk6f7cF6b1UzZnUOizSZh/oir5rLjiYmaiyNsNwo1ASkBGCQCYDAEFNTPAx7gkSWXYv+kfe6NSGPo/UiMMAUU1M8DHuCRJZdi/6R97o1IY+j9SIwYMAtA2+qZy7xOxqbY0kyFYHKHQ7oPs6lduN8CwhHGHO11PViHOa8Ghkg8k9z8WbloMSd5Q/ZQyIRJsBFVd2hIBNu1/Rg=",
|
||||
"FTABFAPDl5npnEb4b11grHG1AdwYLxLOJAIBNwMnFGHDECgeEBh7JxVfPgmR153o9xgmBK5z+S8mBa6C9Y03BicUYcMQKB4QGHsnFV8+CZHXnej3GCQHASQIATAJQQRHUJH4AsX5PMwf+CaBm3BgQsag6Si880dCh4Z/nWvAzlsLLY9CTa0+LBwePhweon0IdT3tsHIq1K3OOg5YsbG4Nwo1ASkBGCQCYDAEFLtqXB3f+f0UnYFZUcYXZ654P2A6MAUUu2pcHd/5/RSdgVlRxhdnrng/YDoYMAtAtfPiyCDVwl93HpnYluDMZCQ2mEpiZNTgZSHQDfsMbdSQoYery2KtqPJkglA5+XUKRm57nbTJKENE9evkOD0Ctxg=",
|
||||
"FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEEJnXYt0krdZlSKq67Y8PqJZJp5AronoNbDzoaKEVfgeJY4bUlCKnogunQgU19+sgbCuIS14SGSw3nozKXJ2kX+zcKNQEpARgkAmAwBBS8qz9CYoDhZpTiSMly/QgDTCrOTTAFFLyrP0JigOFmlOJIyXL9CANMKs5NGDALQIfPjG1LeoSoRd3sJ2NeaS3VrHyftI8l6dOwafhoGMQdCRwyadYABiUG/Po1BnWmg4laSh88nP3zAAnQ2j0l4tAY"
|
||||
],
|
||||
"0/62/5": 3,
|
||||
"0/62/65532": 0,
|
||||
"0/62/65531": [0, 1, 2, 3, 4, 5, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/62/65529": [0, 2, 4, 6, 7, 9, 10, 11],
|
||||
"0/62/65528": [1, 3, 5, 8],
|
||||
"0/63/65533": 2,
|
||||
"0/63/65532": 0,
|
||||
"0/63/0": [],
|
||||
"0/63/1": [],
|
||||
"0/63/2": 4,
|
||||
"0/63/3": 3,
|
||||
"0/63/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/63/65529": [0, 1, 3, 4],
|
||||
"0/63/65528": [2, 5],
|
||||
"0/70/65533": 2,
|
||||
"0/70/65532": 0,
|
||||
"0/70/0": 120,
|
||||
"0/70/1": 1000,
|
||||
"0/70/2": 1000,
|
||||
"0/70/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533],
|
||||
"0/70/65529": [],
|
||||
"0/70/65528": [],
|
||||
"1/29/65533": 2,
|
||||
"1/29/65532": 0,
|
||||
"1/29/0": [
|
||||
{
|
||||
"0": 67,
|
||||
"1": 1
|
||||
}
|
||||
],
|
||||
"1/29/1": [3, 29, 69, 128],
|
||||
"1/29/2": [],
|
||||
"1/29/3": [],
|
||||
"1/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533],
|
||||
"1/29/65529": [],
|
||||
"1/29/65528": [],
|
||||
"1/128/65532": 7,
|
||||
"1/128/3": 0,
|
||||
"1/128/4": 0,
|
||||
"1/128/5": 3,
|
||||
"1/128/6": 3,
|
||||
"1/128/65533": 1,
|
||||
"1/128/65531": [3, 4, 5, 6, 65528, 65529, 65531, 65532, 65533],
|
||||
"1/128/65529": [0, 1],
|
||||
"1/128/65528": [],
|
||||
"1/3/65533": 4,
|
||||
"1/3/0": 0,
|
||||
"1/3/1": 2,
|
||||
"1/3/65532": 0,
|
||||
"1/3/65531": [0, 1, 65528, 65529, 65531, 65532, 65533],
|
||||
"1/3/65529": [0],
|
||||
"1/3/65528": [],
|
||||
"1/69/65533": 1,
|
||||
"1/69/0": false,
|
||||
"1/69/65532": 0,
|
||||
"1/69/65531": [0, 65528, 65529, 65531, 65532, 65533],
|
||||
"1/69/65529": [],
|
||||
"1/69/65528": []
|
||||
},
|
||||
"attribute_subscriptions": []
|
||||
}
|
||||
@@ -1,4 +1,104 @@
|
||||
# serializer version: 1
|
||||
# name: test_boolean_state_configuration_alarm_enabled_switches[ikea_klippbok_water_leak][switch.klippbok_water_leak_sensor_audible_alarm_enabled-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.klippbok_water_leak_sensor_audible_alarm_enabled',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Audible alarm enabled',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Audible alarm enabled',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'audible_alarm_enabled',
|
||||
'unique_id': '00000000000004D2-0000000000000140-MatterNodeDevice-1-BooleanStateConfigurationAudibleAlarmEnabled-128-5',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_boolean_state_configuration_alarm_enabled_switches[ikea_klippbok_water_leak][switch.klippbok_water_leak_sensor_audible_alarm_enabled-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'KLIPPBOK water leak sensor Audible alarm enabled',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.klippbok_water_leak_sensor_audible_alarm_enabled',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_boolean_state_configuration_alarm_enabled_switches[ikea_klippbok_water_leak][switch.klippbok_water_leak_sensor_visual_alarm_enabled-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.klippbok_water_leak_sensor_visual_alarm_enabled',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Visual alarm enabled',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Visual alarm enabled',
|
||||
'platform': 'matter',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'visual_alarm_enabled',
|
||||
'unique_id': '00000000000004D2-0000000000000140-MatterNodeDevice-1-BooleanStateConfigurationVisualAlarmEnabled-128-5',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_boolean_state_configuration_alarm_enabled_switches[ikea_klippbok_water_leak][switch.klippbok_water_leak_sensor_visual_alarm_enabled-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'KLIPPBOK water leak sensor Visual alarm enabled',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.klippbok_water_leak_sensor_visual_alarm_enabled',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_switches[eve_energy_20ecn4101][switch.eve_energy_20ecn4101_child_lock_top-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Test Matter switches."""
|
||||
|
||||
import asyncio
|
||||
from unittest.mock import MagicMock, call
|
||||
|
||||
from chip.clusters import Objects as clusters
|
||||
@@ -234,6 +235,120 @@ async def test_evse_sensor(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["ikea_klippbok_water_leak"])
|
||||
async def test_boolean_state_configuration_alarm_enabled_switches(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
matter_client: MagicMock,
|
||||
matter_node: MatterNode,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test Boolean State Configuration alarm enabled switches."""
|
||||
|
||||
visual_entity_id = "switch.klippbok_water_leak_sensor_visual_alarm_enabled"
|
||||
audible_entity_id = "switch.klippbok_water_leak_sensor_audible_alarm_enabled"
|
||||
visual_entry = entity_registry.async_get(visual_entity_id)
|
||||
audible_entry = entity_registry.async_get(audible_entity_id)
|
||||
assert visual_entry
|
||||
assert audible_entry
|
||||
|
||||
visual_state = hass.states.get(visual_entity_id)
|
||||
audible_state = hass.states.get(audible_entity_id)
|
||||
assert visual_state
|
||||
assert audible_state
|
||||
assert visual_entry == snapshot(name=f"{visual_entity_id}-entry")
|
||||
assert visual_state == snapshot(name=f"{visual_entity_id}-state")
|
||||
assert audible_entry == snapshot(name=f"{audible_entity_id}-entry")
|
||||
assert audible_state == snapshot(name=f"{audible_entity_id}-state")
|
||||
assert visual_state.state == "on"
|
||||
assert audible_state.state == "on"
|
||||
|
||||
await hass.services.async_call(
|
||||
"switch",
|
||||
"turn_off",
|
||||
{"entity_id": visual_entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert matter_client.send_device_command.call_count == 1
|
||||
assert matter_client.send_device_command.call_args == call(
|
||||
node_id=matter_node.node_id,
|
||||
endpoint_id=1,
|
||||
command=clusters.BooleanStateConfiguration.Commands.EnableDisableAlarm(
|
||||
alarmsToEnableDisable=2,
|
||||
),
|
||||
)
|
||||
|
||||
set_node_attribute(matter_node, 1, 128, 5, 2)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
visual_state = hass.states.get(visual_entity_id)
|
||||
audible_state = hass.states.get(audible_entity_id)
|
||||
assert visual_state
|
||||
assert audible_state
|
||||
assert visual_state.state == "off"
|
||||
assert audible_state.state == "on"
|
||||
|
||||
await hass.services.async_call(
|
||||
"switch",
|
||||
"turn_on",
|
||||
{"entity_id": visual_entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert matter_client.send_device_command.call_count == 2
|
||||
assert matter_client.send_device_command.call_args == call(
|
||||
node_id=matter_node.node_id,
|
||||
endpoint_id=1,
|
||||
command=clusters.BooleanStateConfiguration.Commands.EnableDisableAlarm(
|
||||
alarmsToEnableDisable=3,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["ikea_klippbok_water_leak"])
|
||||
async def test_boolean_state_configuration_alarm_enabled_switches_are_serialized(
|
||||
hass: HomeAssistant,
|
||||
matter_client: MagicMock,
|
||||
matter_node: MatterNode,
|
||||
) -> None:
|
||||
"""Test alarm switch changes to the shared bitmap are serialized."""
|
||||
visual_entity_id = "switch.klippbok_water_leak_sensor_visual_alarm_enabled"
|
||||
audible_entity_id = "switch.klippbok_water_leak_sensor_audible_alarm_enabled"
|
||||
command_started = asyncio.Event()
|
||||
allow_commands = asyncio.Event()
|
||||
|
||||
async def send_device_command(*args: object, **kwargs: object) -> None:
|
||||
command_started.set()
|
||||
await allow_commands.wait()
|
||||
|
||||
matter_client.send_device_command.side_effect = send_device_command
|
||||
task = hass.async_create_task(
|
||||
hass.services.async_call(
|
||||
"switch",
|
||||
"turn_off",
|
||||
{"entity_id": [visual_entity_id, audible_entity_id]},
|
||||
blocking=True,
|
||||
)
|
||||
)
|
||||
await command_started.wait()
|
||||
await asyncio.sleep(0)
|
||||
|
||||
assert matter_client.send_device_command.call_count == 1
|
||||
|
||||
allow_commands.set()
|
||||
await task
|
||||
|
||||
assert matter_client.send_device_command.call_count == 2
|
||||
assert matter_client.send_device_command.call_args_list[-1] == call(
|
||||
node_id=matter_node.node_id,
|
||||
endpoint_id=1,
|
||||
command=clusters.BooleanStateConfiguration.Commands.EnableDisableAlarm(
|
||||
alarmsToEnableDisable=0,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["mock_speaker"])
|
||||
async def test_speaker_mute_uses_onoff_commands(
|
||||
hass: HomeAssistant,
|
||||
|
||||
Reference in New Issue
Block a user