Add binary sensors for tedee (#106773)

* fix tests

* Update homeassistant/components/tedee/binary_sensor.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Josef Zweck 2023-12-31 13:16:01 +01:00 committed by GitHub
parent 0549c9e113
commit 83b0934138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 252 additions and 0 deletions

View File

@ -9,6 +9,7 @@ from .const import DOMAIN
from .coordinator import TedeeApiCoordinator
PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.LOCK,
Platform.SENSOR,
]

View File

@ -0,0 +1,78 @@
"""Tedee sensor entities."""
from collections.abc import Callable
from dataclasses import dataclass
from pytedee_async import TedeeLock
from pytedee_async.lock import TedeeLockState
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .entity import TedeeDescriptionEntity
@dataclass(frozen=True, kw_only=True)
class TedeeBinarySensorEntityDescription(
BinarySensorEntityDescription,
):
"""Describes Tedee binary sensor entity."""
is_on_fn: Callable[[TedeeLock], bool | None]
ENTITIES: tuple[TedeeBinarySensorEntityDescription, ...] = (
TedeeBinarySensorEntityDescription(
key="charging",
device_class=BinarySensorDeviceClass.BATTERY_CHARGING,
is_on_fn=lambda lock: lock.is_charging,
entity_category=EntityCategory.DIAGNOSTIC,
),
TedeeBinarySensorEntityDescription(
key="semi_locked",
translation_key="semi_locked",
is_on_fn=lambda lock: lock.state == TedeeLockState.HALF_OPEN,
entity_category=EntityCategory.DIAGNOSTIC,
),
TedeeBinarySensorEntityDescription(
key="pullspring_enabled",
translation_key="pullspring_enabled",
is_on_fn=lambda lock: lock.is_enabled_pullspring,
entity_category=EntityCategory.DIAGNOSTIC,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Tedee sensor entity."""
coordinator = hass.data[DOMAIN][entry.entry_id]
for entity_description in ENTITIES:
async_add_entities(
[
TedeeBinarySensorEntity(lock, coordinator, entity_description)
for lock in coordinator.data.values()
]
)
class TedeeBinarySensorEntity(TedeeDescriptionEntity, BinarySensorEntity):
"""Tedee sensor entity."""
entity_description: TedeeBinarySensorEntityDescription
@property
def is_on(self) -> bool | None:
"""Return true if the binary sensor is on."""
return self.entity_description.is_on_fn(self._lock)

View File

@ -23,6 +23,14 @@
}
},
"entity": {
"binary_sensor": {
"pullspring_enabled": {
"name": "Pullspring enabled"
},
"semi_locked": {
"name": "Semi locked"
}
},
"sensor": {
"pullspring_duration": {
"name": "Pullspring duration"

View File

@ -0,0 +1,131 @@
# serializer version: 1
# name: test_binary_sensors[entry-charging]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.lock_1a2b_charging',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.BATTERY_CHARGING: 'battery_charging'>,
'original_icon': None,
'original_name': 'Charging',
'platform': 'tedee',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '12345-charging',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensors[entry-pullspring_enabled]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.lock_1a2b_pullspring_enabled',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Pullspring enabled',
'platform': 'tedee',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'pullspring_enabled',
'unique_id': '12345-pullspring_enabled',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensors[entry-semi_locked]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.lock_1a2b_semi_locked',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Semi locked',
'platform': 'tedee',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'semi_locked',
'unique_id': '12345-semi_locked',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensors[state-charging]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery_charging',
'friendly_name': 'Lock-1A2B Charging',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.lock_1a2b_charging',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensors[state-pullspring_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Lock-1A2B Pullspring enabled',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.lock_1a2b_pullspring_enabled',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensors[state-semi_locked]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Lock-1A2B Semi locked',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.lock_1a2b_semi_locked',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---

View File

@ -0,0 +1,34 @@
"""Tests for the Tedee Binary Sensors."""
from unittest.mock import MagicMock
import pytest
from syrupy import SnapshotAssertion
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
pytestmark = pytest.mark.usefixtures("init_integration")
BINARY_SENSORS = (
"charging",
"semi_locked",
"pullspring_enabled",
)
async def test_binary_sensors(
hass: HomeAssistant,
mock_tedee: MagicMock,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test tedee battery charging sensor."""
for key in BINARY_SENSORS:
state = hass.states.get(f"binary_sensor.lock_1a2b_{key}")
assert state
assert state == snapshot(name=f"state-{key}")
entry = entity_registry.async_get(state.entity_id)
assert entry
assert entry == snapshot(name=f"entry-{key}")