From 59645aeb0f0251692ee3112efe950245630d3300 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Thu, 16 May 2024 13:29:57 +0200 Subject: [PATCH] Move risco coordinator to separate module (#117549) --- homeassistant/components/risco/__init__.py | 76 +---------------- .../components/risco/alarm_control_panel.py | 3 +- .../components/risco/binary_sensor.py | 3 +- homeassistant/components/risco/coordinator.py | 81 +++++++++++++++++++ homeassistant/components/risco/entity.py | 3 +- homeassistant/components/risco/sensor.py | 3 +- homeassistant/components/risco/switch.py | 3 +- tests/components/risco/test_sensor.py | 11 +-- 8 files changed, 97 insertions(+), 86 deletions(-) create mode 100644 homeassistant/components/risco/coordinator.py diff --git a/homeassistant/components/risco/__init__.py b/homeassistant/components/risco/__init__.py index d25579343c8..b1847b002ea 100644 --- a/homeassistant/components/risco/__init__.py +++ b/homeassistant/components/risco/__init__.py @@ -4,19 +4,10 @@ from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass, field -from datetime import timedelta import logging from typing import Any -from pyrisco import ( - CannotConnectError, - OperationError, - RiscoCloud, - RiscoLocal, - UnauthorizedError, -) -from pyrisco.cloud.alarm import Alarm -from pyrisco.cloud.event import Event +from pyrisco import CannotConnectError, RiscoCloud, RiscoLocal, UnauthorizedError from pyrisco.common import Partition, System, Zone from homeassistant.config_entries import ConfigEntry @@ -34,8 +25,6 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.dispatcher import async_dispatcher_send -from homeassistant.helpers.storage import Store -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import ( CONF_CONCURRENCY, @@ -47,6 +36,7 @@ from .const import ( SYSTEM_UPDATE_SIGNAL, TYPE_LOCAL, ) +from .coordinator import RiscoDataUpdateCoordinator, RiscoEventsDataUpdateCoordinator PLATFORMS = [ Platform.ALARM_CONTROL_PANEL, @@ -54,8 +44,6 @@ PLATFORMS = [ Platform.SENSOR, Platform.SWITCH, ] -LAST_EVENT_STORAGE_VERSION = 1 -LAST_EVENT_TIMESTAMP_KEY = "last_event_timestamp" _LOGGER = logging.getLogger(__name__) @@ -190,63 +178,3 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def _update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None: """Handle options update.""" await hass.config_entries.async_reload(entry.entry_id) - - -class RiscoDataUpdateCoordinator(DataUpdateCoordinator[Alarm]): # pylint: disable=hass-enforce-coordinator-module - """Class to manage fetching risco data.""" - - def __init__( - self, hass: HomeAssistant, risco: RiscoCloud, scan_interval: int - ) -> None: - """Initialize global risco data updater.""" - self.risco = risco - interval = timedelta(seconds=scan_interval) - super().__init__( - hass, - _LOGGER, - name=DOMAIN, - update_interval=interval, - ) - - async def _async_update_data(self) -> Alarm: - """Fetch data from risco.""" - try: - return await self.risco.get_state() - except (CannotConnectError, UnauthorizedError, OperationError) as error: - raise UpdateFailed(error) from error - - -class RiscoEventsDataUpdateCoordinator(DataUpdateCoordinator[list[Event]]): # pylint: disable=hass-enforce-coordinator-module - """Class to manage fetching risco data.""" - - def __init__( - self, hass: HomeAssistant, risco: RiscoCloud, eid: str, scan_interval: int - ) -> None: - """Initialize global risco data updater.""" - self.risco = risco - self._store = Store[dict[str, Any]]( - hass, LAST_EVENT_STORAGE_VERSION, f"risco_{eid}_last_event_timestamp" - ) - interval = timedelta(seconds=scan_interval) - super().__init__( - hass, - _LOGGER, - name=f"{DOMAIN}_events", - update_interval=interval, - ) - - async def _async_update_data(self) -> list[Event]: - """Fetch data from risco.""" - last_store = await self._store.async_load() or {} - last_timestamp = last_store.get( - LAST_EVENT_TIMESTAMP_KEY, "2020-01-01T00:00:00Z" - ) - try: - events = await self.risco.get_events(last_timestamp, 10) - except (CannotConnectError, UnauthorizedError, OperationError) as error: - raise UpdateFailed(error) from error - - if len(events) > 0: - await self._store.async_save({LAST_EVENT_TIMESTAMP_KEY: events[0].time}) - - return events diff --git a/homeassistant/components/risco/alarm_control_panel.py b/homeassistant/components/risco/alarm_control_panel.py index 580842e78ad..08dee936d37 100644 --- a/homeassistant/components/risco/alarm_control_panel.py +++ b/homeassistant/components/risco/alarm_control_panel.py @@ -29,7 +29,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import LocalData, RiscoDataUpdateCoordinator, is_local +from . import LocalData, is_local from .const import ( CONF_CODE_ARM_REQUIRED, CONF_CODE_DISARM_REQUIRED, @@ -42,6 +42,7 @@ from .const import ( RISCO_GROUPS, RISCO_PARTIAL_ARM, ) +from .coordinator import RiscoDataUpdateCoordinator from .entity import RiscoCloudEntity _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/risco/binary_sensor.py b/homeassistant/components/risco/binary_sensor.py index afb65ee226f..a7ca0129b06 100644 --- a/homeassistant/components/risco/binary_sensor.py +++ b/homeassistant/components/risco/binary_sensor.py @@ -21,8 +21,9 @@ from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import LocalData, RiscoDataUpdateCoordinator, is_local +from . import LocalData, is_local from .const import DATA_COORDINATOR, DOMAIN, SYSTEM_UPDATE_SIGNAL +from .coordinator import RiscoDataUpdateCoordinator from .entity import RiscoCloudZoneEntity, RiscoLocalZoneEntity SYSTEM_ENTITY_DESCRIPTIONS = [ diff --git a/homeassistant/components/risco/coordinator.py b/homeassistant/components/risco/coordinator.py new file mode 100644 index 00000000000..8430b6a6172 --- /dev/null +++ b/homeassistant/components/risco/coordinator.py @@ -0,0 +1,81 @@ +"""Coordinator for the Risco integration.""" + +from __future__ import annotations + +from datetime import timedelta +import logging +from typing import Any + +from pyrisco import CannotConnectError, OperationError, RiscoCloud, UnauthorizedError +from pyrisco.cloud.alarm import Alarm +from pyrisco.cloud.event import Event + +from homeassistant.core import HomeAssistant +from homeassistant.helpers.storage import Store +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed + +from .const import DOMAIN + +LAST_EVENT_STORAGE_VERSION = 1 +LAST_EVENT_TIMESTAMP_KEY = "last_event_timestamp" +_LOGGER = logging.getLogger(__name__) + + +class RiscoDataUpdateCoordinator(DataUpdateCoordinator[Alarm]): + """Class to manage fetching risco data.""" + + def __init__( + self, hass: HomeAssistant, risco: RiscoCloud, scan_interval: int + ) -> None: + """Initialize global risco data updater.""" + self.risco = risco + interval = timedelta(seconds=scan_interval) + super().__init__( + hass, + _LOGGER, + name=DOMAIN, + update_interval=interval, + ) + + async def _async_update_data(self) -> Alarm: + """Fetch data from risco.""" + try: + return await self.risco.get_state() + except (CannotConnectError, UnauthorizedError, OperationError) as error: + raise UpdateFailed(error) from error + + +class RiscoEventsDataUpdateCoordinator(DataUpdateCoordinator[list[Event]]): + """Class to manage fetching risco data.""" + + def __init__( + self, hass: HomeAssistant, risco: RiscoCloud, eid: str, scan_interval: int + ) -> None: + """Initialize global risco data updater.""" + self.risco = risco + self._store = Store[dict[str, Any]]( + hass, LAST_EVENT_STORAGE_VERSION, f"risco_{eid}_last_event_timestamp" + ) + interval = timedelta(seconds=scan_interval) + super().__init__( + hass, + _LOGGER, + name=f"{DOMAIN}_events", + update_interval=interval, + ) + + async def _async_update_data(self) -> list[Event]: + """Fetch data from risco.""" + last_store = await self._store.async_load() or {} + last_timestamp = last_store.get( + LAST_EVENT_TIMESTAMP_KEY, "2020-01-01T00:00:00Z" + ) + try: + events = await self.risco.get_events(last_timestamp, 10) + except (CannotConnectError, UnauthorizedError, OperationError) as error: + raise UpdateFailed(error) from error + + if len(events) > 0: + await self._store.async_save({LAST_EVENT_TIMESTAMP_KEY: events[0].time}) + + return events diff --git a/homeassistant/components/risco/entity.py b/homeassistant/components/risco/entity.py index b3a3cdd1d4d..f448f60f4d9 100644 --- a/homeassistant/components/risco/entity.py +++ b/homeassistant/components/risco/entity.py @@ -13,8 +13,9 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity import Entity from homeassistant.helpers.update_coordinator import CoordinatorEntity -from . import RiscoDataUpdateCoordinator, zone_update_signal +from . import zone_update_signal from .const import DOMAIN +from .coordinator import RiscoDataUpdateCoordinator def zone_unique_id(risco: RiscoCloud, zone_id: int) -> str: diff --git a/homeassistant/components/risco/sensor.py b/homeassistant/components/risco/sensor.py index 8f97c76c879..50067cedccd 100644 --- a/homeassistant/components/risco/sensor.py +++ b/homeassistant/components/risco/sensor.py @@ -17,8 +17,9 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util import dt as dt_util -from . import RiscoEventsDataUpdateCoordinator, is_local +from . import is_local from .const import DOMAIN, EVENTS_COORDINATOR +from .coordinator import RiscoEventsDataUpdateCoordinator from .entity import zone_unique_id CATEGORIES = { diff --git a/homeassistant/components/risco/switch.py b/homeassistant/components/risco/switch.py index c43b55b0233..8bad2c6c15e 100644 --- a/homeassistant/components/risco/switch.py +++ b/homeassistant/components/risco/switch.py @@ -12,8 +12,9 @@ from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import LocalData, RiscoDataUpdateCoordinator, is_local +from . import LocalData, is_local from .const import DATA_COORDINATOR, DOMAIN +from .coordinator import RiscoDataUpdateCoordinator from .entity import RiscoCloudZoneEntity, RiscoLocalZoneEntity diff --git a/tests/components/risco/test_sensor.py b/tests/components/risco/test_sensor.py index a8236ad3d87..ec3f2d14026 100644 --- a/tests/components/risco/test_sensor.py +++ b/tests/components/risco/test_sensor.py @@ -5,11 +5,8 @@ from unittest.mock import MagicMock, PropertyMock, patch import pytest -from homeassistant.components.risco import ( - LAST_EVENT_TIMESTAMP_KEY, - CannotConnectError, - UnauthorizedError, -) +from homeassistant.components.risco import CannotConnectError, UnauthorizedError +from homeassistant.components.risco.coordinator import LAST_EVENT_TIMESTAMP_KEY from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.util import dt as dt_util @@ -169,7 +166,7 @@ def _set_utc_time_zone(hass): def save_mock(): """Create a mock for async_save.""" with patch( - "homeassistant.components.risco.Store.async_save", + "homeassistant.components.risco.coordinator.Store.async_save", ) as save_mock: yield save_mock @@ -196,7 +193,7 @@ async def test_cloud_setup( "homeassistant.components.risco.RiscoCloud.get_events", return_value=[] ) as events_mock, patch( - "homeassistant.components.risco.Store.async_load", + "homeassistant.components.risco.coordinator.Store.async_load", return_value={LAST_EVENT_TIMESTAMP_KEY: TEST_EVENTS[0].time}, ), ):