"""Common vera code.""" import logging from typing import DefaultDict, List, NamedTuple, Set import pyvera as pv from homeassistant.components.scene import DOMAIN as SCENE_DOMAIN from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.event import call_later from .const import DOMAIN _LOGGER = logging.getLogger(__name__) class ControllerData(NamedTuple): """Controller data.""" controller: pv.VeraController devices: DefaultDict[str, List[pv.VeraDevice]] scenes: List[pv.VeraScene] config_entry: ConfigEntry def get_configured_platforms(controller_data: ControllerData) -> Set[str]: """Get configured platforms for a controller.""" platforms = [] for platform in controller_data.devices: platforms.append(platform) if controller_data.scenes: platforms.append(SCENE_DOMAIN) return set(platforms) def get_controller_data( hass: HomeAssistant, config_entry: ConfigEntry ) -> ControllerData: """Get controller data from hass data.""" return hass.data[DOMAIN][config_entry.entry_id] def set_controller_data( hass: HomeAssistant, config_entry: ConfigEntry, data: ControllerData ) -> None: """Set controller data in hass data.""" hass.data[DOMAIN][config_entry.entry_id] = data class SubscriptionRegistry(pv.AbstractSubscriptionRegistry): """Manages polling for data from vera.""" def __init__(self, hass: HomeAssistant) -> None: """Initialize the object.""" super().__init__() self._hass = hass self._cancel_poll = None def start(self) -> None: """Start polling for data.""" self.stop() self._schedule_poll(1) def stop(self) -> None: """Stop polling for data.""" if self._cancel_poll: self._cancel_poll() self._cancel_poll = None def _schedule_poll(self, delay: float) -> None: self._cancel_poll = call_later(self._hass, delay, self._run_poll_server) def _run_poll_server(self, now) -> None: delay = 1 # Long poll for changes. The downstream API instructs the endpoint to wait a # a minimum of 200ms before returning data and a maximum of 9s before timing out. if not self.poll_server_once(): # If an error was encountered, wait a bit longer before trying again. delay = 60 self._schedule_poll(delay)