From 23b90f5984b2091be18da9546aae957ffaf4508a Mon Sep 17 00:00:00 2001 From: Josef Zweck Date: Tue, 24 Jun 2025 13:30:13 +0200 Subject: [PATCH] Add door state sensors to tedee (#147386) --- .../components/tedee/binary_sensor.py | 18 ++++++- tests/components/tedee/fixtures/locks.json | 6 ++- .../tedee/snapshots/test_binary_sensor.ambr | 49 +++++++++++++++++++ .../tedee/snapshots/test_diagnostics.ambr | 2 +- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/tedee/binary_sensor.py b/homeassistant/components/tedee/binary_sensor.py index 6570d9c5428..e67db7b2a9b 100644 --- a/homeassistant/components/tedee/binary_sensor.py +++ b/homeassistant/components/tedee/binary_sensor.py @@ -4,7 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass from aiotedee import TedeeLock -from aiotedee.lock import TedeeLockState +from aiotedee.lock import TedeeDoorState, TedeeLockState from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, @@ -29,6 +29,8 @@ class TedeeBinarySensorEntityDescription( """Describes Tedee binary sensor entity.""" is_on_fn: Callable[[TedeeLock], bool | None] + supported_fn: Callable[[TedeeLock], bool] = lambda _: True + available_fn: Callable[[TedeeLock], bool] = lambda _: True ENTITIES: tuple[TedeeBinarySensorEntityDescription, ...] = ( @@ -61,6 +63,14 @@ ENTITIES: tuple[TedeeBinarySensorEntityDescription, ...] = ( entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, ), + TedeeBinarySensorEntityDescription( + key="door_state", + is_on_fn=lambda lock: lock.door_state is TedeeDoorState.OPENED, + device_class=BinarySensorDeviceClass.DOOR, + supported_fn=lambda lock: lock.door_state is not TedeeDoorState.NOT_PAIRED, + available_fn=lambda lock: lock.door_state + not in [TedeeDoorState.UNCALIBRATED, TedeeDoorState.DISCONNECTED], + ), ) @@ -77,6 +87,7 @@ async def async_setup_entry( TedeeBinarySensorEntity(lock, coordinator, entity_description) for entity_description in ENTITIES for lock in locks + if entity_description.supported_fn(lock) ) coordinator.new_lock_callbacks.append(_async_add_new_lock) @@ -92,3 +103,8 @@ class TedeeBinarySensorEntity(TedeeDescriptionEntity, BinarySensorEntity): def is_on(self) -> bool | None: """Return true if the binary sensor is on.""" return self.entity_description.is_on_fn(self._lock) + + @property + def available(self) -> bool: + """Return true if the binary sensor is available.""" + return self.entity_description.available_fn(self._lock) and super().available diff --git a/tests/components/tedee/fixtures/locks.json b/tests/components/tedee/fixtures/locks.json index 6a8eb77d7ee..95a1adf40ec 100644 --- a/tests/components/tedee/fixtures/locks.json +++ b/tests/components/tedee/fixtures/locks.json @@ -9,7 +9,8 @@ "is_charging": false, "state_change_result": 0, "is_enabled_pullspring": 1, - "duration_pullspring": 2 + "duration_pullspring": 2, + "door_state": 0 }, { "lock_name": "Lock-2C3D", @@ -21,6 +22,7 @@ "is_charging": false, "state_change_result": 0, "is_enabled_pullspring": 0, - "duration_pullspring": 0 + "duration_pullspring": 0, + "door_state": 2 } ] diff --git a/tests/components/tedee/snapshots/test_binary_sensor.ambr b/tests/components/tedee/snapshots/test_binary_sensor.ambr index 05d0e34037e..dbde7932a6d 100644 --- a/tests/components/tedee/snapshots/test_binary_sensor.ambr +++ b/tests/components/tedee/snapshots/test_binary_sensor.ambr @@ -242,6 +242,55 @@ 'state': 'off', }) # --- +# name: test_binary_sensors[binary_sensor.lock_2c3d_door-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.lock_2c3d_door', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Door', + 'platform': 'tedee', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '98765-door_state', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.lock_2c3d_door-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'door', + 'friendly_name': 'Lock-2C3D Door', + }), + 'context': , + 'entity_id': 'binary_sensor.lock_2c3d_door', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- # name: test_binary_sensors[binary_sensor.lock_2c3d_lock_uncalibrated-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ diff --git a/tests/components/tedee/snapshots/test_diagnostics.ambr b/tests/components/tedee/snapshots/test_diagnostics.ambr index 63707477df9..d66b2601b72 100644 --- a/tests/components/tedee/snapshots/test_diagnostics.ambr +++ b/tests/components/tedee/snapshots/test_diagnostics.ambr @@ -17,7 +17,7 @@ }), '1': dict({ 'battery_level': 70, - 'door_state': 0, + 'door_state': 2, 'duration_pullspring': 0, 'is_charging': False, 'is_connected': True,