""" Support for Netgear LTE modems. For more details about this component, please refer to the documentation at https://home-assistant.io/components/netgear_lte/ """ import asyncio from datetime import timedelta import logging import voluptuous as vol import attr import aiohttp from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, EVENT_HOMEASSISTANT_STOP) from homeassistant.helpers import config_validation as cv from homeassistant.helpers.aiohttp_client import async_create_clientsession from homeassistant.util import Throttle REQUIREMENTS = ['eternalegypt==0.0.5'] _LOGGER = logging.getLogger(__name__) MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10) DOMAIN = 'netgear_lte' DATA_KEY = 'netgear_lte' CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.All(cv.ensure_list, [vol.Schema({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_PASSWORD): cv.string, })]) }, extra=vol.ALLOW_EXTRA) @attr.s class ModemData: """Class for modem state.""" modem = attr.ib() serial_number = attr.ib(init=False, default=None) unread_count = attr.ib(init=False, default=None) usage = attr.ib(init=False, default=None) @Throttle(MIN_TIME_BETWEEN_UPDATES) async def async_update(self): """Call the API to update the data.""" import eternalegypt try: information = await self.modem.information() self.serial_number = information.serial_number self.unread_count = sum(1 for x in information.sms if x.unread) self.usage = information.usage except eternalegypt.Error: self.unread_count = None self.usage = None @attr.s class LTEData: """Shared state.""" websession = attr.ib() modem_data = attr.ib(init=False, factory=dict) def get_modem_data(self, config): """Get the requested or the only modem_data value.""" if CONF_HOST in config: return self.modem_data.get(config[CONF_HOST]) if len(self.modem_data) == 1: return next(iter(self.modem_data.values())) return None async def async_setup(hass, config): """Set up Netgear LTE component.""" if DATA_KEY not in hass.data: websession = async_create_clientsession( hass, cookie_jar=aiohttp.CookieJar(unsafe=True)) hass.data[DATA_KEY] = LTEData(websession) tasks = [_setup_lte(hass, conf) for conf in config.get(DOMAIN, [])] if tasks: await asyncio.wait(tasks) return True async def _setup_lte(hass, lte_config, delay=0): """Set up a Netgear LTE modem.""" import eternalegypt if delay: await asyncio.sleep(delay) host = lte_config[CONF_HOST] password = lte_config[CONF_PASSWORD] websession = hass.data[DATA_KEY].websession modem = eternalegypt.Modem(hostname=host, websession=websession) try: await modem.login(password=password) except eternalegypt.Error: delay = max(15, min(2*delay, 300)) _LOGGER.warning("Retrying %s in %d seconds", host, delay) hass.loop.create_task(_setup_lte(hass, lte_config, delay)) return modem_data = ModemData(modem) await modem_data.async_update() hass.data[DATA_KEY].modem_data[host] = modem_data async def cleanup(event): """Clean up resources.""" await modem.logout() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, cleanup)