Skip to content

Commit 375f536

Browse files
authored
Add Matter DoorPositionSensor open/closed count sensors (home-assistant#155809)
1 parent 5cff813 commit 375f536

File tree

6 files changed

+177
-2
lines changed

6 files changed

+177
-2
lines changed

homeassistant/components/matter/icons.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@
8686
"current_phase": {
8787
"default": "mdi:state-machine"
8888
},
89+
"door_closed_events": {
90+
"default": "mdi:door-closed"
91+
},
92+
"door_open_events": {
93+
"default": "mdi:door-open"
94+
},
8995
"esa_opt_out_state": {
9096
"default": "mdi:home-lightning-bolt"
9197
},

homeassistant/components/matter/sensor.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,4 +1488,30 @@ def _update_from_device(self) -> None:
14881488
entity_class=MatterSensor,
14891489
required_attributes=(clusters.ServiceArea.Attributes.EstimatedEndTime,),
14901490
),
1491+
MatterDiscoverySchema(
1492+
platform=Platform.SENSOR,
1493+
entity_description=MatterSensorEntityDescription(
1494+
key="DoorLockDoorOpenEvents",
1495+
translation_key="door_open_events",
1496+
entity_category=EntityCategory.DIAGNOSTIC,
1497+
entity_registry_enabled_default=False,
1498+
state_class=SensorStateClass.TOTAL_INCREASING,
1499+
),
1500+
entity_class=MatterSensor,
1501+
required_attributes=(clusters.DoorLock.Attributes.DoorOpenEvents,),
1502+
featuremap_contains=clusters.DoorLock.Bitmaps.Feature.kDoorPositionSensor,
1503+
),
1504+
MatterDiscoverySchema(
1505+
platform=Platform.SENSOR,
1506+
entity_description=MatterSensorEntityDescription(
1507+
key="DoorLockDoorClosedEvents",
1508+
translation_key="door_closed_events",
1509+
entity_category=EntityCategory.DIAGNOSTIC,
1510+
entity_registry_enabled_default=False,
1511+
state_class=SensorStateClass.TOTAL_INCREASING,
1512+
),
1513+
entity_class=MatterSensor,
1514+
required_attributes=(clusters.DoorLock.Attributes.DoorClosedEvents,),
1515+
featuremap_contains=clusters.DoorLock.Bitmaps.Feature.kDoorPositionSensor,
1516+
),
14911517
]

homeassistant/components/matter/strings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,12 @@
375375
"current_phase": {
376376
"name": "Current phase"
377377
},
378+
"door_closed_events": {
379+
"name": "Door closed events"
380+
},
381+
"door_open_events": {
382+
"name": "Door open events"
383+
},
378384
"energy_exported": {
379385
"name": "Energy exported"
380386
},

tests/components/matter/fixtures/nodes/mock_lock.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@
421421
"1/257/1": 0,
422422
"1/257/2": true,
423423
"1/257/3": 1,
424-
"1/257/4": 10,
425-
"1/257/5": 10,
424+
"1/257/4": 5,
425+
"1/257/5": 3,
426426
"1/257/17": 10,
427427
"1/257/18": 10,
428428
"1/257/19": 10,

tests/components/matter/snapshots/test_sensor.ambr

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7532,6 +7532,108 @@
75327532
'state': 'stopped',
75337533
})
75347534
# ---
7535+
# name: test_sensors[mock_lock][sensor.mock_lock_door_closed_events-entry]
7536+
EntityRegistryEntrySnapshot({
7537+
'aliases': set({
7538+
}),
7539+
'area_id': None,
7540+
'capabilities': dict({
7541+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
7542+
}),
7543+
'config_entry_id': <ANY>,
7544+
'config_subentry_id': <ANY>,
7545+
'device_class': None,
7546+
'device_id': <ANY>,
7547+
'disabled_by': None,
7548+
'domain': 'sensor',
7549+
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
7550+
'entity_id': 'sensor.mock_lock_door_closed_events',
7551+
'has_entity_name': True,
7552+
'hidden_by': None,
7553+
'icon': None,
7554+
'id': <ANY>,
7555+
'labels': set({
7556+
}),
7557+
'name': None,
7558+
'options': dict({
7559+
}),
7560+
'original_device_class': None,
7561+
'original_icon': None,
7562+
'original_name': 'Door closed events',
7563+
'platform': 'matter',
7564+
'previous_unique_id': None,
7565+
'suggested_object_id': None,
7566+
'supported_features': 0,
7567+
'translation_key': 'door_closed_events',
7568+
'unique_id': '00000000000004D2-0000000000000097-MatterNodeDevice-1-DoorLockDoorClosedEvents-257-5',
7569+
'unit_of_measurement': None,
7570+
})
7571+
# ---
7572+
# name: test_sensors[mock_lock][sensor.mock_lock_door_closed_events-state]
7573+
StateSnapshot({
7574+
'attributes': ReadOnlyDict({
7575+
'friendly_name': 'Mock Lock Door closed events',
7576+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
7577+
}),
7578+
'context': <ANY>,
7579+
'entity_id': 'sensor.mock_lock_door_closed_events',
7580+
'last_changed': <ANY>,
7581+
'last_reported': <ANY>,
7582+
'last_updated': <ANY>,
7583+
'state': '3',
7584+
})
7585+
# ---
7586+
# name: test_sensors[mock_lock][sensor.mock_lock_door_open_events-entry]
7587+
EntityRegistryEntrySnapshot({
7588+
'aliases': set({
7589+
}),
7590+
'area_id': None,
7591+
'capabilities': dict({
7592+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
7593+
}),
7594+
'config_entry_id': <ANY>,
7595+
'config_subentry_id': <ANY>,
7596+
'device_class': None,
7597+
'device_id': <ANY>,
7598+
'disabled_by': None,
7599+
'domain': 'sensor',
7600+
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
7601+
'entity_id': 'sensor.mock_lock_door_open_events',
7602+
'has_entity_name': True,
7603+
'hidden_by': None,
7604+
'icon': None,
7605+
'id': <ANY>,
7606+
'labels': set({
7607+
}),
7608+
'name': None,
7609+
'options': dict({
7610+
}),
7611+
'original_device_class': None,
7612+
'original_icon': None,
7613+
'original_name': 'Door open events',
7614+
'platform': 'matter',
7615+
'previous_unique_id': None,
7616+
'suggested_object_id': None,
7617+
'supported_features': 0,
7618+
'translation_key': 'door_open_events',
7619+
'unique_id': '00000000000004D2-0000000000000097-MatterNodeDevice-1-DoorLockDoorOpenEvents-257-4',
7620+
'unit_of_measurement': None,
7621+
})
7622+
# ---
7623+
# name: test_sensors[mock_lock][sensor.mock_lock_door_open_events-state]
7624+
StateSnapshot({
7625+
'attributes': ReadOnlyDict({
7626+
'friendly_name': 'Mock Lock Door open events',
7627+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
7628+
}),
7629+
'context': <ANY>,
7630+
'entity_id': 'sensor.mock_lock_door_open_events',
7631+
'last_changed': <ANY>,
7632+
'last_reported': <ANY>,
7633+
'last_updated': <ANY>,
7634+
'state': '5',
7635+
})
7636+
# ---
75357637
# name: test_sensors[multi_endpoint_light][sensor.inovelli_current_switch_position_config-entry]
75367638
EntityRegistryEntrySnapshot({
75377639
'aliases': set({

tests/components/matter/test_sensor.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,3 +697,38 @@ async def test_vacuum_operational_error_sensor(
697697
state = hass.states.get("sensor.mock_vacuum_operational_error")
698698
assert state
699699
assert state.state == "unknown"
700+
701+
702+
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
703+
@pytest.mark.parametrize("node_fixture", ["mock_lock"])
704+
async def test_optional_door_event_sensors_from_featuremap(
705+
hass: HomeAssistant,
706+
entity_registry: er.EntityRegistry,
707+
matter_client: MagicMock,
708+
matter_node: MatterNode,
709+
) -> None:
710+
"""Test discovery of optional door event sensors in doorlock featuremap."""
711+
entity_id_open = "sensor.mock_lock_door_open_events"
712+
entity_id_closed = "sensor.mock_lock_door_closed_events"
713+
714+
# Check that the entities are created
715+
state = hass.states.get(entity_id_open)
716+
assert state
717+
assert state.state == "5"
718+
719+
state = hass.states.get(entity_id_closed)
720+
assert state
721+
assert state.state == "3"
722+
723+
# Test updating the sensor values
724+
set_node_attribute(matter_node, 1, 257, 4, 10)
725+
await trigger_subscription_callback(hass, matter_client)
726+
state = hass.states.get(entity_id_open)
727+
assert state
728+
assert state.state == "10"
729+
730+
set_node_attribute(matter_node, 1, 257, 5, 8)
731+
await trigger_subscription_callback(hass, matter_client)
732+
state = hass.states.get(entity_id_closed)
733+
assert state
734+
assert state.state == "8"

0 commit comments

Comments
 (0)