mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Store Switcher runtime data in config entry (#118054)
This commit is contained in:
parent
3f76b865fa
commit
e8226a8056
@ -4,15 +4,14 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from aioswitcher.bridge import SwitcherBridge
|
||||
from aioswitcher.device import SwitcherBase
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform
|
||||
from homeassistant.core import Event, HomeAssistant, callback
|
||||
|
||||
from .const import DATA_DEVICE, DOMAIN
|
||||
from .coordinator import SwitcherDataUpdateCoordinator
|
||||
from .utils import async_start_bridge, async_stop_bridge
|
||||
|
||||
PLATFORMS = [
|
||||
Platform.BUTTON,
|
||||
@ -25,20 +24,20 @@ PLATFORMS = [
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
type SwitcherConfigEntry = ConfigEntry[dict[str, SwitcherDataUpdateCoordinator]]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: SwitcherConfigEntry) -> bool:
|
||||
"""Set up Switcher from a config entry."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN][DATA_DEVICE] = {}
|
||||
|
||||
@callback
|
||||
def on_device_data_callback(device: SwitcherBase) -> None:
|
||||
"""Use as a callback for device data."""
|
||||
|
||||
coordinators = entry.runtime_data
|
||||
|
||||
# Existing device update device data
|
||||
if device.device_id in hass.data[DOMAIN][DATA_DEVICE]:
|
||||
coordinator: SwitcherDataUpdateCoordinator = hass.data[DOMAIN][DATA_DEVICE][
|
||||
device.device_id
|
||||
]
|
||||
if coordinator := coordinators.get(device.device_id):
|
||||
coordinator.async_set_updated_data(device)
|
||||
return
|
||||
|
||||
@ -52,18 +51,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
device.device_type.hex_rep,
|
||||
)
|
||||
|
||||
coordinator = hass.data[DOMAIN][DATA_DEVICE][device.device_id] = (
|
||||
SwitcherDataUpdateCoordinator(hass, entry, device)
|
||||
)
|
||||
coordinator = SwitcherDataUpdateCoordinator(hass, entry, device)
|
||||
coordinator.async_setup()
|
||||
coordinators[device.device_id] = coordinator
|
||||
|
||||
# Must be ready before dispatcher is called
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
await async_start_bridge(hass, on_device_data_callback)
|
||||
entry.runtime_data = {}
|
||||
bridge = SwitcherBridge(on_device_data_callback)
|
||||
await bridge.start()
|
||||
|
||||
async def stop_bridge(event: Event) -> None:
|
||||
await async_stop_bridge(hass)
|
||||
async def stop_bridge(event: Event | None = None) -> None:
|
||||
await bridge.stop()
|
||||
|
||||
entry.async_on_unload(stop_bridge)
|
||||
|
||||
entry.async_on_unload(
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_bridge)
|
||||
@ -72,12 +74,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: SwitcherConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
await async_stop_bridge(hass)
|
||||
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].pop(DATA_DEVICE)
|
||||
|
||||
return unload_ok
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
@ -15,7 +15,6 @@ from aioswitcher.api.remotes import SwitcherBreezeRemote
|
||||
from aioswitcher.device import DeviceCategory
|
||||
|
||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
@ -25,6 +24,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import SwitcherConfigEntry
|
||||
from .const import SIGNAL_DEVICE_ADD
|
||||
from .coordinator import SwitcherDataUpdateCoordinator
|
||||
from .utils import get_breeze_remote_manager
|
||||
@ -78,7 +78,7 @@ THERMOSTAT_BUTTONS = [
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
config_entry: SwitcherConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up Switcher button from config entry."""
|
||||
|
@ -25,7 +25,6 @@ from homeassistant.components.climate import (
|
||||
ClimateEntityFeature,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
@ -35,6 +34,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import SwitcherConfigEntry
|
||||
from .const import SIGNAL_DEVICE_ADD
|
||||
from .coordinator import SwitcherDataUpdateCoordinator
|
||||
from .utils import get_breeze_remote_manager
|
||||
@ -61,7 +61,7 @@ HA_TO_DEVICE_FAN = {value: key for key, value in DEVICE_FAN_TO_HA.items()}
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
config_entry: SwitcherConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up Switcher climate from config entry."""
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
DOMAIN = "switcher_kis"
|
||||
|
||||
DATA_BRIDGE = "bridge"
|
||||
DATA_DEVICE = "device"
|
||||
|
||||
DISCOVERY_TIME_SEC = 12
|
||||
|
||||
SIGNAL_DEVICE_ADD = "switcher_device_add"
|
||||
|
@ -6,24 +6,23 @@ from dataclasses import asdict
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import DATA_DEVICE, DOMAIN
|
||||
from . import SwitcherConfigEntry
|
||||
|
||||
TO_REDACT = {"device_id", "device_key", "ip_address", "mac_address"}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, entry: ConfigEntry
|
||||
hass: HomeAssistant, entry: SwitcherConfigEntry
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a config entry."""
|
||||
devices = hass.data[DOMAIN][DATA_DEVICE]
|
||||
coordinators = entry.runtime_data
|
||||
|
||||
return async_redact_data(
|
||||
{
|
||||
"entry": entry.as_dict(),
|
||||
"devices": [asdict(devices[d].data) for d in devices],
|
||||
"devices": [asdict(coordinators[d].data) for d in coordinators],
|
||||
},
|
||||
TO_REDACT,
|
||||
)
|
||||
|
@ -3,9 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from aioswitcher.api.remotes import SwitcherBreezeRemoteManager
|
||||
from aioswitcher.bridge import SwitcherBase, SwitcherBridge
|
||||
@ -13,29 +11,11 @@ from aioswitcher.bridge import SwitcherBase, SwitcherBridge
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import singleton
|
||||
|
||||
from .const import DATA_BRIDGE, DISCOVERY_TIME_SEC, DOMAIN
|
||||
from .const import DISCOVERY_TIME_SEC
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_start_bridge(
|
||||
hass: HomeAssistant, on_device_callback: Callable[[SwitcherBase], Any]
|
||||
) -> None:
|
||||
"""Start switcher UDP bridge."""
|
||||
bridge = hass.data[DOMAIN][DATA_BRIDGE] = SwitcherBridge(on_device_callback)
|
||||
_LOGGER.debug("Starting Switcher bridge")
|
||||
await bridge.start()
|
||||
|
||||
|
||||
async def async_stop_bridge(hass: HomeAssistant) -> None:
|
||||
"""Stop switcher UDP bridge."""
|
||||
bridge: SwitcherBridge = hass.data[DOMAIN].get(DATA_BRIDGE)
|
||||
if bridge is not None:
|
||||
_LOGGER.debug("Stopping Switcher bridge")
|
||||
await bridge.stop()
|
||||
hass.data[DOMAIN].pop(DATA_BRIDGE)
|
||||
|
||||
|
||||
async def async_has_devices(hass: HomeAssistant) -> bool:
|
||||
"""Discover Switcher devices."""
|
||||
_LOGGER.debug("Starting discovery")
|
||||
|
@ -18,9 +18,15 @@ def mock_setup_entry() -> Generator[AsyncMock, None, None]:
|
||||
@pytest.fixture
|
||||
def mock_bridge(request):
|
||||
"""Return a mocked SwitcherBridge."""
|
||||
with patch(
|
||||
"homeassistant.components.switcher_kis.utils.SwitcherBridge", autospec=True
|
||||
) as bridge_mock:
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.switcher_kis.SwitcherBridge", autospec=True
|
||||
) as bridge_mock,
|
||||
patch(
|
||||
"homeassistant.components.switcher_kis.utils.SwitcherBridge",
|
||||
new=bridge_mock,
|
||||
),
|
||||
):
|
||||
bridge = bridge_mock.return_value
|
||||
|
||||
bridge.devices = []
|
||||
|
@ -4,11 +4,7 @@ from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.switcher_kis.const import (
|
||||
DATA_DEVICE,
|
||||
DOMAIN,
|
||||
MAX_UPDATE_INTERVAL_SEC,
|
||||
)
|
||||
from homeassistant.components.switcher_kis.const import MAX_UPDATE_INTERVAL_SEC
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import STATE_UNAVAILABLE
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -24,15 +20,14 @@ async def test_update_fail(
|
||||
hass: HomeAssistant, mock_bridge, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test entities state unavailable when updates fail.."""
|
||||
await init_integration(hass)
|
||||
entry = await init_integration(hass)
|
||||
assert mock_bridge
|
||||
|
||||
mock_bridge.mock_callbacks(DUMMY_SWITCHER_DEVICES)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_bridge.is_running is True
|
||||
assert len(hass.data[DOMAIN]) == 2
|
||||
assert len(hass.data[DOMAIN][DATA_DEVICE]) == 2
|
||||
assert len(entry.runtime_data) == 2
|
||||
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + timedelta(seconds=MAX_UPDATE_INTERVAL_SEC + 1)
|
||||
@ -77,11 +72,9 @@ async def test_entry_unload(hass: HomeAssistant, mock_bridge) -> None:
|
||||
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
assert mock_bridge.is_running is True
|
||||
assert len(hass.data[DOMAIN]) == 2
|
||||
|
||||
await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert mock_bridge.is_running is False
|
||||
assert len(hass.data[DOMAIN]) == 0
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.switcher_kis.const import DATA_DEVICE, DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import slugify
|
||||
@ -32,12 +31,11 @@ DEVICE_SENSORS_TUPLE = (
|
||||
@pytest.mark.parametrize("mock_bridge", [DUMMY_SWITCHER_DEVICES], indirect=True)
|
||||
async def test_sensor_platform(hass: HomeAssistant, mock_bridge) -> None:
|
||||
"""Test sensor platform."""
|
||||
await init_integration(hass)
|
||||
entry = await init_integration(hass)
|
||||
assert mock_bridge
|
||||
|
||||
assert mock_bridge.is_running is True
|
||||
assert len(hass.data[DOMAIN]) == 2
|
||||
assert len(hass.data[DOMAIN][DATA_DEVICE]) == 2
|
||||
assert len(entry.runtime_data) == 2
|
||||
|
||||
for device, sensors in DEVICE_SENSORS_TUPLE:
|
||||
for sensor, field in sensors:
|
||||
|
Loading…
x
Reference in New Issue
Block a user