core/homeassistant/components/plugwise/coordinator.py

94 lines
3.4 KiB
Python
Raw Normal View History

"""DataUpdateCoordinator for Plugwise."""
from datetime import timedelta
from typing import NamedTuple, cast
from plugwise import Smile
from plugwise.constants import DeviceData, GatewayData
from plugwise.exceptions import (
ConnectionFailedError,
InvalidAuthentication,
InvalidXMLError,
ResponseError,
UnsupportedDeviceError,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DEFAULT_PORT, DEFAULT_SCAN_INTERVAL, DEFAULT_USERNAME, DOMAIN, LOGGER
2022-02-08 10:13:05 +00:00
class PlugwiseData(NamedTuple):
"""Plugwise data stored in the DataUpdateCoordinator."""
gateway: GatewayData
devices: dict[str, DeviceData]
2022-02-08 10:13:05 +00:00
class PlugwiseDataUpdateCoordinator(DataUpdateCoordinator[PlugwiseData]):
"""Class to manage fetching Plugwise data from single endpoint."""
_connected: bool = False
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Initialize the coordinator."""
super().__init__(
hass,
LOGGER,
name=DOMAIN,
update_interval=timedelta(seconds=60),
# Don't refresh immediately, give the device time to process
# the change in state before we query it.
request_refresh_debouncer=Debouncer(
hass,
LOGGER,
cooldown=1.5,
immediate=False,
),
)
self.api = Smile(
host=entry.data[CONF_HOST],
username=entry.data.get(CONF_USERNAME, DEFAULT_USERNAME),
password=entry.data[CONF_PASSWORD],
port=entry.data.get(CONF_PORT, DEFAULT_PORT),
timeout=30,
websession=async_get_clientsession(hass, verify_ssl=False),
)
async def _connect(self) -> None:
"""Connect to the Plugwise Smile."""
self._connected = await self.api.connect()
self.api.get_all_devices()
self.name = self.api.smile_name
self.update_interval = DEFAULT_SCAN_INTERVAL.get(
str(self.api.smile_type), timedelta(seconds=60)
)
2022-02-08 10:13:05 +00:00
async def _async_update_data(self) -> PlugwiseData:
"""Fetch data from Plugwise."""
try:
if not self._connected:
await self._connect()
2022-02-08 10:13:05 +00:00
data = await self.api.async_update()
except InvalidAuthentication as err:
raise ConfigEntryError("Invalid username or Smile ID") from err
except (InvalidXMLError, ResponseError) as err:
2022-02-08 10:13:05 +00:00
raise UpdateFailed(
"Invalid XML data, or error indication received for the Plugwise"
" Adam/Smile/Stretch"
2022-02-08 10:13:05 +00:00
) from err
except UnsupportedDeviceError as err:
raise ConfigEntryError("Device with unsupported firmware") from err
except ConnectionFailedError as err:
raise UpdateFailed("Failed to connect to the Plugwise Smile") from err
return PlugwiseData(
gateway=cast(GatewayData, data[0]),
devices=cast(dict[str, DeviceData], data[1]),
)