mirror of
https://github.com/home-assistant/core
synced 2024-08-28 03:36:46 +02:00
Add new locks automatically to tedee integration (#107372)
* remove removed locks * move duplicated code to function * remove entities by removing device * add new locks automatically * add locks from coordinator * remove other PR stuff * add pullspring lock to test for coverage * requested changes
This commit is contained in:
parent
d6aaaf1f1a
commit
7385da626e
@ -66,6 +66,17 @@ async def async_setup_entry(
|
||||
]
|
||||
)
|
||||
|
||||
def _async_add_new_lock(lock_id: int) -> None:
|
||||
lock = coordinator.data[lock_id]
|
||||
async_add_entities(
|
||||
[
|
||||
TedeeBinarySensorEntity(lock, coordinator, entity_description)
|
||||
for entity_description in ENTITIES
|
||||
]
|
||||
)
|
||||
|
||||
coordinator.new_lock_callbacks.append(_async_add_new_lock)
|
||||
|
||||
|
||||
class TedeeBinarySensorEntity(TedeeDescriptionEntity, BinarySensorEntity):
|
||||
"""Tedee sensor entity."""
|
||||
|
@ -50,6 +50,8 @@ class TedeeApiCoordinator(DataUpdateCoordinator[dict[int, TedeeLock]]):
|
||||
)
|
||||
|
||||
self._next_get_locks = time.time()
|
||||
self._current_locks: set[int] = set()
|
||||
self.new_lock_callbacks: list[Callable[[int], None]] = []
|
||||
|
||||
@property
|
||||
def bridge(self) -> TedeeBridge:
|
||||
@ -82,6 +84,15 @@ class TedeeApiCoordinator(DataUpdateCoordinator[dict[int, TedeeLock]]):
|
||||
", ".join(map(str, self.tedee_client.locks_dict.keys())),
|
||||
)
|
||||
|
||||
if not self._current_locks:
|
||||
self._current_locks = set(self.tedee_client.locks_dict.keys())
|
||||
|
||||
if new_locks := set(self.tedee_client.locks_dict.keys()) - self._current_locks:
|
||||
_LOGGER.debug("New locks found: %s", ", ".join(map(str, new_locks)))
|
||||
for lock_id in new_locks:
|
||||
for callback in self.new_lock_callbacks:
|
||||
callback(lock_id)
|
||||
|
||||
return self.tedee_client.locks_dict
|
||||
|
||||
async def _async_update(self, update_fn: Callable[[], Awaitable[None]]) -> None:
|
||||
|
@ -29,6 +29,15 @@ async def async_setup_entry(
|
||||
else:
|
||||
entities.append(TedeeLockEntity(lock, coordinator))
|
||||
|
||||
def _async_add_new_lock(lock_id: int) -> None:
|
||||
lock = coordinator.data[lock_id]
|
||||
if lock.is_enabled_pullspring:
|
||||
async_add_entities([TedeeLockWithLatchEntity(lock, coordinator)])
|
||||
else:
|
||||
async_add_entities([TedeeLockEntity(lock, coordinator)])
|
||||
|
||||
coordinator.new_lock_callbacks.append(_async_add_new_lock)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
|
@ -62,6 +62,17 @@ async def async_setup_entry(
|
||||
]
|
||||
)
|
||||
|
||||
def _async_add_new_lock(lock_id: int) -> None:
|
||||
lock = coordinator.data[lock_id]
|
||||
async_add_entities(
|
||||
[
|
||||
TedeeSensorEntity(lock, coordinator, entity_description)
|
||||
for entity_description in ENTITIES
|
||||
]
|
||||
)
|
||||
|
||||
coordinator.new_lock_callbacks.append(_async_add_new_lock)
|
||||
|
||||
|
||||
class TedeeSensorEntity(TedeeDescriptionEntity, SensorEntity):
|
||||
"""Tedee sensor entity."""
|
||||
|
@ -128,4 +128,4 @@
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# ---
|
@ -26,4 +26,4 @@
|
||||
'sw_version': None,
|
||||
'via_device_id': None,
|
||||
})
|
||||
# ---
|
||||
# ---
|
@ -1,13 +1,18 @@
|
||||
"""Tests for the Tedee Binary Sensors."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from pytedee_async import TedeeLock
|
||||
import pytest
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("init_integration")
|
||||
|
||||
BINARY_SENSORS = (
|
||||
@ -32,3 +37,25 @@ async def test_binary_sensors(
|
||||
entry = entity_registry.async_get(state.entity_id)
|
||||
assert entry
|
||||
assert entry == snapshot(name=f"entry-{key}")
|
||||
|
||||
|
||||
async def test_new_binary_sensors(
|
||||
hass: HomeAssistant,
|
||||
mock_tedee: MagicMock,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Ensure binary sensors for new lock are added automatically."""
|
||||
|
||||
for key in BINARY_SENSORS:
|
||||
state = hass.states.get(f"binary_sensor.lock_4e5f_{key}")
|
||||
assert state is None
|
||||
|
||||
mock_tedee.locks_dict[666666] = TedeeLock("Lock-4E5F", 666666, 2)
|
||||
|
||||
freezer.tick(timedelta(minutes=10))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
for key in BINARY_SENSORS:
|
||||
state = hass.states.get(f"binary_sensor.lock_4e5f_{key}")
|
||||
assert state
|
||||
|
@ -3,6 +3,7 @@ from datetime import timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from pytedee_async import TedeeLock
|
||||
from pytedee_async.exception import (
|
||||
TedeeClientException,
|
||||
TedeeDataUpdateException,
|
||||
@ -207,3 +208,31 @@ async def test_update_failed(
|
||||
state = hass.states.get("lock.lock_1a2b")
|
||||
assert state is not None
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
async def test_new_lock(
|
||||
hass: HomeAssistant,
|
||||
mock_tedee: MagicMock,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Ensure new lock is added automatically."""
|
||||
|
||||
state = hass.states.get("lock.lock_4e5f")
|
||||
assert state is None
|
||||
|
||||
mock_tedee.locks_dict[666666] = TedeeLock("Lock-4E5F", 666666, 2)
|
||||
mock_tedee.locks_dict[777777] = TedeeLock(
|
||||
"Lock-6G7H",
|
||||
777777,
|
||||
4,
|
||||
is_enabled_pullspring=True,
|
||||
)
|
||||
|
||||
freezer.tick(timedelta(minutes=10))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("lock.lock_4e5f")
|
||||
assert state
|
||||
state = hass.states.get("lock.lock_6g7h")
|
||||
assert state
|
||||
|
@ -1,14 +1,19 @@
|
||||
"""Tests for the Tedee Sensors."""
|
||||
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from pytedee_async import TedeeLock
|
||||
import pytest
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("init_integration")
|
||||
|
||||
|
||||
@ -34,3 +39,25 @@ async def test_sensors(
|
||||
assert entry
|
||||
assert entry.device_id
|
||||
assert entry == snapshot(name=f"entry-{key}")
|
||||
|
||||
|
||||
async def test_new_sensors(
|
||||
hass: HomeAssistant,
|
||||
mock_tedee: MagicMock,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Ensure sensors for new lock are added automatically."""
|
||||
|
||||
for key in SENSORS:
|
||||
state = hass.states.get(f"sensor.lock_4e5f_{key}")
|
||||
assert state is None
|
||||
|
||||
mock_tedee.locks_dict[666666] = TedeeLock("Lock-4E5F", 666666, 2)
|
||||
|
||||
freezer.tick(timedelta(minutes=10))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
for key in SENSORS:
|
||||
state = hass.states.get(f"sensor.lock_4e5f_{key}")
|
||||
assert state
|
||||
|
Loading…
Reference in New Issue
Block a user