1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00
ha-core/homeassistant/components/smart_meter_texas/__init__.py
2022-01-10 17:10:46 +01:00

127 lines
3.9 KiB
Python

"""The Smart Meter Texas integration."""
import asyncio
import logging
import ssl
from smart_meter_texas import Account, Client, ClientSSLContext
from smart_meter_texas.exceptions import (
SmartMeterTexasAPIError,
SmartMeterTexasAuthError,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import (
DATA_COORDINATOR,
DATA_SMART_METER,
DEBOUNCE_COOLDOWN,
DOMAIN,
SCAN_INTERVAL,
)
_LOGGER = logging.getLogger(__name__)
PLATFORMS = [Platform.SENSOR]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Smart Meter Texas from a config entry."""
username = entry.data[CONF_USERNAME]
password = entry.data[CONF_PASSWORD]
account = Account(username, password)
client_ssl_context = ClientSSLContext()
ssl_context = await client_ssl_context.get_ssl_context()
smart_meter_texas_data = SmartMeterTexasData(hass, entry, account, ssl_context)
try:
await smart_meter_texas_data.client.authenticate()
except SmartMeterTexasAuthError:
_LOGGER.error("Username or password was not accepted")
return False
except asyncio.TimeoutError as error:
raise ConfigEntryNotReady from error
await smart_meter_texas_data.setup()
async def async_update_data():
_LOGGER.debug("Fetching latest data")
await smart_meter_texas_data.read_meters()
return smart_meter_texas_data
# Use a DataUpdateCoordinator to manage the updates. This is due to the
# Smart Meter Texas API which takes around 30 seconds to read a meter.
# This avoids Home Assistant from complaining about the component taking
# too long to update.
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name="Smart Meter Texas",
update_method=async_update_data,
update_interval=SCAN_INTERVAL,
request_refresh_debouncer=Debouncer(
hass, _LOGGER, cooldown=DEBOUNCE_COOLDOWN, immediate=True
),
)
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = {
DATA_COORDINATOR: coordinator,
DATA_SMART_METER: smart_meter_texas_data,
}
asyncio.create_task(coordinator.async_refresh())
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
return True
class SmartMeterTexasData:
"""Manages coordinatation of API data updates."""
def __init__(
self,
hass: HomeAssistant,
entry: ConfigEntry,
account: Account,
ssl_context: ssl.SSLContext,
) -> None:
"""Initialize the data coordintator."""
self._entry = entry
self.account = account
websession = aiohttp_client.async_get_clientsession(hass)
self.client = Client(websession, account, ssl_context=ssl_context)
self.meters: list = []
async def setup(self):
"""Fetch all of the user's meters."""
self.meters = await self.account.fetch_meters(self.client)
_LOGGER.debug("Discovered %s meter(s)", len(self.meters))
async def read_meters(self):
"""Read each meter."""
for meter in self.meters:
try:
await meter.read_meter(self.client)
except (SmartMeterTexasAPIError, SmartMeterTexasAuthError) as error:
raise UpdateFailed(error) from error
return self.meters
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok