mirror of
https://github.com/home-assistant/core.git
synced 2025-09-07 13:51:39 +02:00
Add Matter lock event changed_by (#149861)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import asyncio
|
||||
from typing import Any
|
||||
|
||||
from chip.clusters import Objects as clusters
|
||||
from matter_server.common.models import EventType, MatterNodeEvent
|
||||
|
||||
from homeassistant.components.lock import (
|
||||
LockEntity,
|
||||
@@ -22,6 +23,22 @@ from .entity import MatterEntity
|
||||
from .helpers import get_matter
|
||||
from .models import MatterDiscoverySchema
|
||||
|
||||
DOOR_LOCK_OPERATION_SOURCE = {
|
||||
# mapping from operation source id's to textual representation
|
||||
0: "Unspecified",
|
||||
1: "Manual", # [Optional]
|
||||
2: "Proprietary Remote", # [Optional]
|
||||
3: "Keypad", # [Optional]
|
||||
4: "Auto", # [Optional]
|
||||
5: "Button", # [Optional]
|
||||
6: "Schedule", # [HDSCH]
|
||||
7: "Remote", # [M]
|
||||
8: "RFID", # [RID]
|
||||
9: "Biometric", # [USR]
|
||||
10: "Aliro", # [Aliro]
|
||||
}
|
||||
|
||||
|
||||
DoorLockFeature = clusters.DoorLock.Bitmaps.Feature
|
||||
|
||||
|
||||
@@ -41,6 +58,52 @@ class MatterLock(MatterEntity, LockEntity):
|
||||
_feature_map: int | None = None
|
||||
_optimistic_timer: asyncio.TimerHandle | None = None
|
||||
_platform_translation_key = "lock"
|
||||
_attr_changed_by = "Unknown"
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Subscribe to events."""
|
||||
await super().async_added_to_hass()
|
||||
# subscribe to NodeEvent events
|
||||
self._unsubscribes.append(
|
||||
self.matter_client.subscribe_events(
|
||||
callback=self._on_matter_node_event,
|
||||
event_filter=EventType.NODE_EVENT,
|
||||
node_filter=self._endpoint.node.node_id,
|
||||
)
|
||||
)
|
||||
|
||||
@callback
|
||||
def _on_matter_node_event(
|
||||
self,
|
||||
event: EventType,
|
||||
node_event: MatterNodeEvent,
|
||||
) -> None:
|
||||
"""Call on NodeEvent."""
|
||||
if (node_event.endpoint_id != self._endpoint.endpoint_id) or (
|
||||
node_event.cluster_id != clusters.DoorLock.id
|
||||
):
|
||||
return
|
||||
|
||||
LOGGER.debug(
|
||||
"Received node_event: event type %s, event id %s for %s with data %s",
|
||||
event,
|
||||
node_event.event_id,
|
||||
self.entity_id,
|
||||
node_event.data,
|
||||
)
|
||||
|
||||
# handle the DoorLock events
|
||||
node_event_data: dict[str, int] = node_event.data or {}
|
||||
match node_event.event_id:
|
||||
case (
|
||||
clusters.DoorLock.Events.LockOperation.event_id
|
||||
): # Lock cluster event 2
|
||||
# update the changed_by attribute to indicate lock operation source
|
||||
operation_source: int = node_event_data.get("operationSource", -1)
|
||||
self._attr_changed_by = DOOR_LOCK_OPERATION_SOURCE.get(
|
||||
operation_source, "Unknown"
|
||||
)
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def code_format(self) -> str | None:
|
||||
|
@@ -37,6 +37,7 @@
|
||||
# name: test_locks[door_lock][lock.mock_door_lock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'changed_by': 'Unknown',
|
||||
'friendly_name': 'Mock Door Lock',
|
||||
'supported_features': <LockEntityFeature: 0>,
|
||||
}),
|
||||
@@ -86,6 +87,7 @@
|
||||
# name: test_locks[door_lock_with_unbolt][lock.mock_door_lock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'changed_by': 'Unknown',
|
||||
'friendly_name': 'Mock Door Lock',
|
||||
'supported_features': <LockEntityFeature: 1>,
|
||||
}),
|
||||
|
@@ -4,10 +4,11 @@ from unittest.mock import MagicMock, call
|
||||
|
||||
from chip.clusters import Objects as clusters
|
||||
from matter_server.client.models.node import MatterNode
|
||||
from matter_server.common.models import EventType, MatterNodeEvent
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.lock import LockEntityFeature, LockState
|
||||
from homeassistant.components.lock import ATTR_CHANGED_BY, LockEntityFeature, LockState
|
||||
from homeassistant.const import ATTR_CODE, STATE_UNKNOWN, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
@@ -112,6 +113,26 @@ async def test_lock(
|
||||
state = hass.states.get("lock.mock_door_lock")
|
||||
assert state.attributes["supported_features"] & LockEntityFeature.OPEN
|
||||
|
||||
# test handling of a node LockOperation event
|
||||
await trigger_subscription_callback(
|
||||
hass,
|
||||
matter_client,
|
||||
EventType.NODE_EVENT,
|
||||
MatterNodeEvent(
|
||||
node_id=matter_node.node_id,
|
||||
endpoint_id=1,
|
||||
cluster_id=257,
|
||||
event_id=2,
|
||||
event_number=0,
|
||||
priority=1,
|
||||
timestamp=0,
|
||||
timestamp_type=0,
|
||||
data={"operationSource": 3},
|
||||
),
|
||||
)
|
||||
state = hass.states.get("lock.mock_door_lock")
|
||||
assert state.attributes[ATTR_CHANGED_BY] == "Keypad"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["door_lock"])
|
||||
async def test_lock_requires_pin(
|
||||
|
Reference in New Issue
Block a user