mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Add tedee bridge as via_device for tedee integration (#106914)
* add bridge as via_device * add bridge as via_device * move getting bridge to update_data * add bridge property
This commit is contained in:
parent
5003993658
commit
87c79ef57f
@ -4,6 +4,7 @@ import logging
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import TedeeApiCoordinator
|
||||
@ -24,6 +25,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={(DOMAIN, coordinator.bridge.serial)},
|
||||
manufacturer="Tedee",
|
||||
name=coordinator.bridge.name,
|
||||
model="Bridge",
|
||||
serial_number=coordinator.bridge.serial,
|
||||
)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
@ -11,6 +11,7 @@ from pytedee_async import (
|
||||
TedeeLocalAuthException,
|
||||
TedeeLock,
|
||||
)
|
||||
from pytedee_async.bridge import TedeeBridge
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST
|
||||
@ -40,6 +41,7 @@ class TedeeApiCoordinator(DataUpdateCoordinator[dict[int, TedeeLock]]):
|
||||
update_interval=SCAN_INTERVAL,
|
||||
)
|
||||
|
||||
self._bridge: TedeeBridge | None = None
|
||||
self.tedee_client = TedeeClient(
|
||||
local_token=self.config_entry.data[CONF_LOCAL_ACCESS_TOKEN],
|
||||
local_ip=self.config_entry.data[CONF_HOST],
|
||||
@ -47,18 +49,31 @@ class TedeeApiCoordinator(DataUpdateCoordinator[dict[int, TedeeLock]]):
|
||||
|
||||
self._next_get_locks = time.time()
|
||||
|
||||
@property
|
||||
def bridge(self) -> TedeeBridge:
|
||||
"""Return bridge."""
|
||||
assert self._bridge
|
||||
return self._bridge
|
||||
|
||||
async def _async_update_data(self) -> dict[int, TedeeLock]:
|
||||
"""Fetch data from API endpoint."""
|
||||
if self._bridge is None:
|
||||
|
||||
async def _async_get_bridge() -> None:
|
||||
self._bridge = await self.tedee_client.get_local_bridge()
|
||||
|
||||
_LOGGER.debug("Update coordinator: Getting bridge from API")
|
||||
await self._async_update(_async_get_bridge)
|
||||
|
||||
_LOGGER.debug("Update coordinator: Getting locks from API")
|
||||
# once every hours get all lock details, otherwise use the sync endpoint
|
||||
if self._next_get_locks <= time.time():
|
||||
_LOGGER.debug("Updating through /my/lock endpoint")
|
||||
await self._async_update_locks(self.tedee_client.get_locks)
|
||||
await self._async_update(self.tedee_client.get_locks)
|
||||
self._next_get_locks = time.time() + GET_LOCKS_INTERVAL_SECONDS
|
||||
else:
|
||||
_LOGGER.debug("Updating through /sync endpoint")
|
||||
await self._async_update_locks(self.tedee_client.sync)
|
||||
await self._async_update(self.tedee_client.sync)
|
||||
|
||||
_LOGGER.debug(
|
||||
"available_locks: %s",
|
||||
@ -67,9 +82,7 @@ class TedeeApiCoordinator(DataUpdateCoordinator[dict[int, TedeeLock]]):
|
||||
|
||||
return self.tedee_client.locks_dict
|
||||
|
||||
async def _async_update_locks(
|
||||
self, update_fn: Callable[[], Awaitable[None]]
|
||||
) -> None:
|
||||
async def _async_update(self, update_fn: Callable[[], Awaitable[None]]) -> None:
|
||||
"""Update locks based on update function."""
|
||||
try:
|
||||
await update_fn()
|
||||
|
@ -32,6 +32,7 @@ class TedeeEntity(CoordinatorEntity[TedeeApiCoordinator]):
|
||||
name=lock.lock_name,
|
||||
manufacturer="Tedee",
|
||||
model=lock.lock_type,
|
||||
via_device=(DOMAIN, coordinator.bridge.serial),
|
||||
)
|
||||
|
||||
@callback
|
||||
|
29
tests/components/tedee/snapshots/test_init.ambr
Normal file
29
tests/components/tedee/snapshots/test_init.ambr
Normal file
@ -0,0 +1,29 @@
|
||||
# serializer version: 1
|
||||
# name: test_bridge_device
|
||||
DeviceRegistryEntrySnapshot({
|
||||
'area_id': None,
|
||||
'config_entries': <ANY>,
|
||||
'configuration_url': None,
|
||||
'connections': set({
|
||||
}),
|
||||
'disabled_by': None,
|
||||
'entry_type': None,
|
||||
'hw_version': None,
|
||||
'id': <ANY>,
|
||||
'identifiers': set({
|
||||
tuple(
|
||||
'tedee',
|
||||
'0000-0000',
|
||||
),
|
||||
}),
|
||||
'is_new': False,
|
||||
'manufacturer': 'Tedee',
|
||||
'model': 'Bridge',
|
||||
'name': 'Bridge-AB1C',
|
||||
'name_by_user': None,
|
||||
'serial_number': '0000-0000',
|
||||
'suggested_area': None,
|
||||
'sw_version': None,
|
||||
'via_device_id': None,
|
||||
})
|
||||
# ---
|
@ -68,7 +68,7 @@
|
||||
'serial_number': None,
|
||||
'suggested_area': None,
|
||||
'sw_version': None,
|
||||
'via_device_id': None,
|
||||
'via_device_id': <ANY>,
|
||||
})
|
||||
# ---
|
||||
# name: test_lock_without_pullspring
|
||||
@ -140,6 +140,6 @@
|
||||
'serial_number': None,
|
||||
'suggested_area': None,
|
||||
'sw_version': None,
|
||||
'via_device_id': None,
|
||||
'via_device_id': <ANY>,
|
||||
})
|
||||
# ---
|
||||
|
@ -3,9 +3,11 @@ from unittest.mock import MagicMock
|
||||
|
||||
from pytedee_async.exception import TedeeAuthException, TedeeClientException
|
||||
import pytest
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -37,7 +39,7 @@ async def test_config_entry_not_ready(
|
||||
mock_tedee: MagicMock,
|
||||
side_effect: Exception,
|
||||
) -> None:
|
||||
"""Test the LaMetric configuration entry not ready."""
|
||||
"""Test the Tedee configuration entry not ready."""
|
||||
mock_tedee.get_locks.side_effect = side_effect
|
||||
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
@ -46,3 +48,22 @@ async def test_config_entry_not_ready(
|
||||
|
||||
assert len(mock_tedee.get_locks.mock_calls) == 1
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_bridge_device(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_tedee: MagicMock,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Ensure the bridge device is registered."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(
|
||||
{(mock_config_entry.domain, mock_tedee.get_local_bridge.return_value.serial)}
|
||||
)
|
||||
assert device
|
||||
assert device == snapshot
|
||||
|
Loading…
x
Reference in New Issue
Block a user