Skip to content

Commit

Permalink
Migrate Nuki to use dataclass for entry data (home-assistant#101785)
Browse files Browse the repository at this point in the history
Co-authored-by: J. Nick Koston <[email protected]>
Co-authored-by: Franck Nijhof <[email protected]>
  • Loading branch information
3 people authored Oct 22, 2023
1 parent 06a2664 commit 3259e39
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 45 deletions.
45 changes: 25 additions & 20 deletions homeassistant/components/nuki/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import asyncio
from collections import defaultdict
from dataclasses import dataclass
from datetime import timedelta
from http import HTTPStatus
import logging
Expand Down Expand Up @@ -38,15 +39,7 @@
UpdateFailed,
)

from .const import (
DATA_BRIDGE,
DATA_COORDINATOR,
DATA_LOCKS,
DATA_OPENERS,
DEFAULT_TIMEOUT,
DOMAIN,
ERROR_STATES,
)
from .const import DEFAULT_TIMEOUT, DOMAIN, ERROR_STATES
from .helpers import NukiWebhookException, parse_id

_NukiDeviceT = TypeVar("_NukiDeviceT", bound=NukiDevice)
Expand All @@ -57,6 +50,16 @@
UPDATE_INTERVAL = timedelta(seconds=30)


@dataclass(slots=True)
class NukiEntryData:
"""Class to hold Nuki data."""

coordinator: NukiCoordinator
bridge: NukiBridge
locks: list[NukiLock]
openers: list[NukiOpener]


def _get_bridge_devices(bridge: NukiBridge) -> tuple[list[NukiLock], list[NukiOpener]]:
return bridge.locks, bridge.openers

Expand All @@ -74,14 +77,15 @@ async def handle_webhook(
except ValueError:
return web.Response(status=HTTPStatus.BAD_REQUEST)

locks = hass.data[DOMAIN][entry.entry_id][DATA_LOCKS]
openers = hass.data[DOMAIN][entry.entry_id][DATA_OPENERS]
entry_data: NukiEntryData = hass.data[DOMAIN][entry.entry_id]
locks = entry_data.locks
openers = entry_data.openers

devices = [x for x in locks + openers if x.nuki_id == data["nukiId"]]
if len(devices) == 1:
devices[0].update_from_callback(data)

coordinator = hass.data[DOMAIN][entry.entry_id][DATA_COORDINATOR]
coordinator = entry_data.coordinator
coordinator.async_set_updated_data(None)

return web.Response(status=HTTPStatus.OK)
Expand Down Expand Up @@ -232,13 +236,12 @@ async def _stop_nuki(_: Event):
)

coordinator = NukiCoordinator(hass, bridge, locks, openers)

hass.data[DOMAIN][entry.entry_id] = {
DATA_COORDINATOR: coordinator,
DATA_BRIDGE: bridge,
DATA_LOCKS: locks,
DATA_OPENERS: openers,
}
hass.data[DOMAIN][entry.entry_id] = NukiEntryData(
coordinator=coordinator,
bridge=bridge,
locks=locks,
openers=openers,
)

# Fetch initial data so we have data when entities subscribe
await coordinator.async_refresh()
Expand All @@ -251,11 +254,13 @@ async def _stop_nuki(_: Event):
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload the Nuki entry."""
webhook.async_unregister(hass, entry.entry_id)
entry_data: NukiEntryData = hass.data[DOMAIN][entry.entry_id]

try:
async with asyncio.timeout(10):
await hass.async_add_executor_job(
_remove_webhook,
hass.data[DOMAIN][entry.entry_id][DATA_BRIDGE],
entry_data.bridge,
entry.entry_id,
)
except InvalidCredentialsException as err:
Expand Down
11 changes: 5 additions & 6 deletions homeassistant/components/nuki/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,21 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import NukiCoordinator, NukiEntity
from .const import ATTR_NUKI_ID, DATA_COORDINATOR, DATA_LOCKS, DOMAIN as NUKI_DOMAIN
from . import NukiEntity, NukiEntryData
from .const import ATTR_NUKI_ID, DOMAIN as NUKI_DOMAIN


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the Nuki lock binary sensor."""
data = hass.data[NUKI_DOMAIN][entry.entry_id]
coordinator: NukiCoordinator = data[DATA_COORDINATOR]
entry_data: NukiEntryData = hass.data[NUKI_DOMAIN][entry.entry_id]

entities = []

for lock in data[DATA_LOCKS]:
for lock in entry_data.locks:
if lock.is_door_sensor_activated:
entities.extend([NukiDoorsensorEntity(coordinator, lock)])
entities.extend([NukiDoorsensorEntity(entry_data.coordinator, lock)])

async_add_entities(entities)

Expand Down
6 changes: 0 additions & 6 deletions homeassistant/components/nuki/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@
ATTR_ENABLE = "enable"
ATTR_UNLATCH = "unlatch"

# Data
DATA_BRIDGE = "nuki_bridge_data"
DATA_LOCKS = "nuki_locks_data"
DATA_OPENERS = "nuki_openers_data"
DATA_COORDINATOR = "nuki_coordinator"

# Defaults
DEFAULT_PORT = 8080
DEFAULT_TIMEOUT = 20
Expand Down
13 changes: 5 additions & 8 deletions homeassistant/components/nuki/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import NukiCoordinator, NukiEntity
from . import NukiEntity, NukiEntryData
from .const import (
ATTR_BATTERY_CRITICAL,
ATTR_ENABLE,
ATTR_NUKI_ID,
ATTR_UNLATCH,
DATA_COORDINATOR,
DATA_LOCKS,
DATA_OPENERS,
DOMAIN as NUKI_DOMAIN,
ERROR_STATES,
)
Expand All @@ -37,14 +34,14 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the Nuki lock platform."""
data = hass.data[NUKI_DOMAIN][entry.entry_id]
coordinator: NukiCoordinator = data[DATA_COORDINATOR]
entry_data: NukiEntryData = hass.data[NUKI_DOMAIN][entry.entry_id]
coordinator = entry_data.coordinator

entities: list[NukiDeviceEntity] = [
NukiLockEntity(coordinator, lock) for lock in data[DATA_LOCKS]
NukiLockEntity(coordinator, lock) for lock in entry_data.locks
]
entities.extend(
[NukiOpenerEntity(coordinator, opener) for opener in data[DATA_OPENERS]]
[NukiOpenerEntity(coordinator, opener) for opener in entry_data.openers]
)
async_add_entities(entities)

Expand Down
9 changes: 4 additions & 5 deletions homeassistant/components/nuki/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,18 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import NukiEntity
from .const import ATTR_NUKI_ID, DATA_COORDINATOR, DATA_LOCKS, DOMAIN as NUKI_DOMAIN
from . import NukiEntity, NukiEntryData
from .const import ATTR_NUKI_ID, DOMAIN as NUKI_DOMAIN


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the Nuki lock sensor."""
data = hass.data[NUKI_DOMAIN][entry.entry_id]
coordinator = data[DATA_COORDINATOR]
entry_data: NukiEntryData = hass.data[NUKI_DOMAIN][entry.entry_id]

async_add_entities(
NukiBatterySensor(coordinator, lock) for lock in data[DATA_LOCKS]
NukiBatterySensor(entry_data.coordinator, lock) for lock in entry_data.locks
)


Expand Down

0 comments on commit 3259e39

Please sign in to comment.