mirror of
https://github.com/home-assistant/core.git
synced 2026-04-18 07:56:03 +01:00
Migrate nuki to use runtime_data (#166943)
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from dataclasses import dataclass
|
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -14,7 +13,6 @@ from requests.exceptions import RequestException
|
|||||||
|
|
||||||
from homeassistant import exceptions
|
from homeassistant import exceptions
|
||||||
from homeassistant.components import webhook
|
from homeassistant.components import webhook
|
||||||
from homeassistant.config_entries import ConfigEntry
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
@@ -28,7 +26,7 @@ from homeassistant.helpers.network import NoURLAvailableError, get_url
|
|||||||
from homeassistant.helpers.update_coordinator import UpdateFailed
|
from homeassistant.helpers.update_coordinator import UpdateFailed
|
||||||
|
|
||||||
from .const import CONF_ENCRYPT_TOKEN, DEFAULT_TIMEOUT, DOMAIN
|
from .const import CONF_ENCRYPT_TOKEN, DEFAULT_TIMEOUT, DOMAIN
|
||||||
from .coordinator import NukiCoordinator
|
from .coordinator import NukiConfigEntry, NukiCoordinator, NukiEntryData
|
||||||
from .helpers import NukiWebhookException, parse_id
|
from .helpers import NukiWebhookException, parse_id
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -36,22 +34,12 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.LOCK, Platform.SENSOR]
|
PLATFORMS = [Platform.BINARY_SENSOR, Platform.LOCK, Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
@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]]:
|
def _get_bridge_devices(bridge: NukiBridge) -> tuple[list[NukiLock], list[NukiOpener]]:
|
||||||
return bridge.locks, bridge.openers
|
return bridge.locks, bridge.openers
|
||||||
|
|
||||||
|
|
||||||
async def _create_webhook(
|
async def _create_webhook(
|
||||||
hass: HomeAssistant, entry: ConfigEntry, bridge: NukiBridge
|
hass: HomeAssistant, entry: NukiConfigEntry, bridge: NukiBridge
|
||||||
) -> None:
|
) -> None:
|
||||||
# Create HomeAssistant webhook
|
# Create HomeAssistant webhook
|
||||||
async def handle_webhook(
|
async def handle_webhook(
|
||||||
@@ -63,16 +51,14 @@ async def _create_webhook(
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return web.Response(status=HTTPStatus.BAD_REQUEST)
|
return web.Response(status=HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
entry_data: NukiEntryData = hass.data[DOMAIN][entry.entry_id]
|
locks = entry.runtime_data.locks
|
||||||
locks = entry_data.locks
|
openers = entry.runtime_data.openers
|
||||||
openers = entry_data.openers
|
|
||||||
|
|
||||||
devices = [x for x in locks + openers if x.nuki_id == data["nukiId"]]
|
devices = [x for x in locks + openers if x.nuki_id == data["nukiId"]]
|
||||||
if len(devices) == 1:
|
if len(devices) == 1:
|
||||||
devices[0].update_from_callback(data)
|
devices[0].update_from_callback(data)
|
||||||
|
|
||||||
coordinator = entry_data.coordinator
|
entry.runtime_data.coordinator.async_set_updated_data(None)
|
||||||
coordinator.async_set_updated_data(None)
|
|
||||||
|
|
||||||
return web.Response(status=HTTPStatus.OK)
|
return web.Response(status=HTTPStatus.OK)
|
||||||
|
|
||||||
@@ -157,11 +143,9 @@ def _remove_webhook(bridge: NukiBridge, entry_id: str) -> None:
|
|||||||
bridge.callback_remove(item["id"])
|
bridge.callback_remove(item["id"])
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: NukiConfigEntry) -> bool:
|
||||||
"""Set up the Nuki entry."""
|
"""Set up the Nuki entry."""
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})
|
|
||||||
|
|
||||||
# Migration of entry unique_id
|
# Migration of entry unique_id
|
||||||
if isinstance(entry.unique_id, int):
|
if isinstance(entry.unique_id, int):
|
||||||
new_id = parse_id(entry.unique_id)
|
new_id = parse_id(entry.unique_id)
|
||||||
@@ -225,7 +209,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
coordinator = NukiCoordinator(hass, entry, bridge, locks, openers)
|
coordinator = NukiCoordinator(hass, entry, bridge, locks, openers)
|
||||||
hass.data[DOMAIN][entry.entry_id] = NukiEntryData(
|
entry.runtime_data = NukiEntryData(
|
||||||
coordinator=coordinator,
|
coordinator=coordinator,
|
||||||
bridge=bridge,
|
bridge=bridge,
|
||||||
locks=locks,
|
locks=locks,
|
||||||
@@ -240,16 +224,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_unload_entry(hass: HomeAssistant, entry: NukiConfigEntry) -> bool:
|
||||||
"""Unload the Nuki entry."""
|
"""Unload the Nuki entry."""
|
||||||
webhook.async_unregister(hass, entry.entry_id)
|
webhook.async_unregister(hass, entry.entry_id)
|
||||||
entry_data: NukiEntryData = hass.data[DOMAIN][entry.entry_id]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with asyncio.timeout(10):
|
async with asyncio.timeout(10):
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
_remove_webhook,
|
_remove_webhook,
|
||||||
entry_data.bridge,
|
entry.runtime_data.bridge,
|
||||||
entry.entry_id,
|
entry.entry_id,
|
||||||
)
|
)
|
||||||
except InvalidCredentialsException as err:
|
except InvalidCredentialsException as err:
|
||||||
@@ -261,8 +244,4 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
f"Unable to remove callback. Error communicating with Bridge: {err}"
|
f"Unable to remove callback. Error communicating with Bridge: {err}"
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
if unload_ok:
|
|
||||||
hass.data[DOMAIN].pop(entry.entry_id)
|
|
||||||
|
|
||||||
return unload_ok
|
|
||||||
|
|||||||
@@ -9,23 +9,21 @@ from homeassistant.components.binary_sensor import (
|
|||||||
BinarySensorDeviceClass,
|
BinarySensorDeviceClass,
|
||||||
BinarySensorEntity,
|
BinarySensorEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
|
||||||
from homeassistant.const import EntityCategory
|
from homeassistant.const import EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
from . import NukiEntryData
|
from .coordinator import NukiConfigEntry
|
||||||
from .const import DOMAIN
|
|
||||||
from .entity import NukiEntity
|
from .entity import NukiEntity
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: NukiConfigEntry,
|
||||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the Nuki binary sensors."""
|
"""Set up the Nuki binary sensors."""
|
||||||
entry_data: NukiEntryData = hass.data[DOMAIN][entry.entry_id]
|
entry_data = entry.runtime_data
|
||||||
|
|
||||||
entities: list[NukiEntity] = []
|
entities: list[NukiEntity] = []
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from dataclasses import dataclass
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -25,16 +26,28 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
UPDATE_INTERVAL = timedelta(seconds=30)
|
UPDATE_INTERVAL = timedelta(seconds=30)
|
||||||
|
|
||||||
|
type NukiConfigEntry = ConfigEntry[NukiEntryData]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class NukiEntryData:
|
||||||
|
"""Class to hold Nuki data."""
|
||||||
|
|
||||||
|
coordinator: NukiCoordinator
|
||||||
|
bridge: NukiBridge
|
||||||
|
locks: list[NukiLock]
|
||||||
|
openers: list[NukiOpener]
|
||||||
|
|
||||||
|
|
||||||
class NukiCoordinator(DataUpdateCoordinator[None]):
|
class NukiCoordinator(DataUpdateCoordinator[None]):
|
||||||
"""Data Update Coordinator for the Nuki integration."""
|
"""Data Update Coordinator for the Nuki integration."""
|
||||||
|
|
||||||
config_entry: ConfigEntry
|
config_entry: NukiConfigEntry
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: NukiConfigEntry,
|
||||||
bridge: NukiBridge,
|
bridge: NukiBridge,
|
||||||
locks: list[NukiLock],
|
locks: list[NukiLock],
|
||||||
openers: list[NukiOpener],
|
openers: list[NukiOpener],
|
||||||
|
|||||||
@@ -12,24 +12,23 @@ from requests.exceptions import RequestException
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.lock import LockEntity, LockEntityFeature
|
from homeassistant.components.lock import LockEntity, LockEntityFeature
|
||||||
from homeassistant.config_entries import ConfigEntry
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
from . import NukiEntryData
|
from .const import ATTR_ENABLE, ATTR_UNLATCH, ERROR_STATES
|
||||||
from .const import ATTR_ENABLE, ATTR_UNLATCH, DOMAIN, ERROR_STATES
|
from .coordinator import NukiConfigEntry
|
||||||
from .entity import NukiEntity
|
from .entity import NukiEntity
|
||||||
from .helpers import CannotConnect
|
from .helpers import CannotConnect
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: NukiConfigEntry,
|
||||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the Nuki lock platform."""
|
"""Set up the Nuki lock platform."""
|
||||||
entry_data: NukiEntryData = hass.data[DOMAIN][entry.entry_id]
|
entry_data = entry.runtime_data
|
||||||
coordinator = entry_data.coordinator
|
coordinator = entry_data.coordinator
|
||||||
|
|
||||||
entities: list[NukiDeviceEntity] = [
|
entities: list[NukiDeviceEntity] = [
|
||||||
|
|||||||
@@ -9,23 +9,21 @@ from homeassistant.components.sensor import (
|
|||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorStateClass,
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
|
||||||
from homeassistant.const import PERCENTAGE, EntityCategory
|
from homeassistant.const import PERCENTAGE, EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
from . import NukiEntryData
|
from .coordinator import NukiConfigEntry
|
||||||
from .const import DOMAIN
|
|
||||||
from .entity import NukiEntity
|
from .entity import NukiEntity
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: NukiConfigEntry,
|
||||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the Nuki lock sensor."""
|
"""Set up the Nuki lock sensor."""
|
||||||
entry_data: NukiEntryData = hass.data[DOMAIN][entry.entry_id]
|
entry_data = entry.runtime_data
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
NukiBatterySensor(entry_data.coordinator, lock) for lock in entry_data.locks
|
NukiBatterySensor(entry_data.coordinator, lock) for lock in entry_data.locks
|
||||||
|
|||||||
Reference in New Issue
Block a user