1 """Support for TP-Link LTE modems."""
3 from __future__
import annotations
12 import voluptuous
as vol
19 EVENT_HOMEASSISTANT_STOP,
27 _LOGGER = logging.getLogger(__name__)
30 DATA_KEY =
"tplink_lte"
32 CONF_NOTIFY =
"notify"
34 _NOTIFY_SCHEMA = vol.Schema(
36 vol.Optional(CONF_NAME): cv.string,
37 vol.Optional(CONF_RECIPIENT): vol.All(cv.ensure_list, [cv.string]),
41 CONFIG_SCHEMA = vol.Schema(
48 vol.Required(CONF_HOST): cv.string,
49 vol.Required(CONF_PASSWORD): cv.string,
50 vol.Optional(CONF_NOTIFY): vol.All(
51 cv.ensure_list, [_NOTIFY_SCHEMA]
58 extra=vol.ALLOW_EXTRA,
64 """Class for modem state."""
67 modem: tp_connected.Modem = attr.ib()
69 connected: bool = attr.ib(init=
False, default=
True)
76 websession: aiohttp.ClientSession = attr.ib()
77 modem_data: dict[str, ModemData] = attr.ib(init=
False, factory=dict)
80 """Get the requested or the only modem_data value."""
81 if CONF_HOST
in config:
82 return self.modem_data.
get(config[CONF_HOST])
83 if len(self.modem_data) == 1:
84 return next(iter(self.modem_data.values()))
89 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
90 """Set up TP-Link LTE component."""
91 if DATA_KEY
not in hass.data:
93 hass, cookie_jar=aiohttp.CookieJar(unsafe=
True)
95 hass.data[DATA_KEY] =
LTEData(websession)
97 domain_config = config.get(DOMAIN, [])
99 tasks = [
_setup_lte(hass, conf)
for conf
in domain_config]
101 await asyncio.gather(*tasks)
103 for conf
in domain_config:
104 for notify_conf
in conf.get(CONF_NOTIFY, []):
105 hass.async_create_task(
106 discovery.async_load_platform(
107 hass, Platform.NOTIFY, DOMAIN, notify_conf, config
115 hass: HomeAssistant, lte_config: dict[str, Any], delay: int = 0
117 """Set up a TP-Link LTE modem."""
119 host: str = lte_config[CONF_HOST]
120 password: str = lte_config[CONF_PASSWORD]
122 lte_data: LTEData = hass.data[DATA_KEY]
123 modem = tp_connected.Modem(hostname=host, websession=lte_data.websession)
128 await
_login(hass, modem_data, password)
129 except tp_connected.Error:
130 retry_task = hass.loop.create_task(
_retry_login(hass, modem_data, password))
133 def cleanup_retry(event: Event) ->
None:
134 """Clean up retry task resources."""
135 if not retry_task.done():
138 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_retry)
141 async
def _login(hass: HomeAssistant, modem_data: ModemData, password: str) ->
None:
142 """Log in and complete setup."""
143 await modem_data.modem.login(password=password)
144 modem_data.connected =
True
145 lte_data: LTEData = hass.data[DATA_KEY]
146 lte_data.modem_data[modem_data.host] = modem_data
148 async
def cleanup(event: Event) ->
None:
149 """Clean up resources."""
150 await modem_data.modem.logout()
152 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, cleanup)
156 hass: HomeAssistant, modem_data: ModemData, password: str
158 """Sleep and retry setup."""
160 _LOGGER.warning(
"Could not connect to %s. Will keep trying", modem_data.host)
162 modem_data.connected =
False
165 while not modem_data.connected:
166 await asyncio.sleep(delay)
169 await
_login(hass, modem_data, password)
170 _LOGGER.warning(
"Connected to %s", modem_data.host)
171 except tp_connected.Error:
172 delay =
min(2 * delay, 300)
ModemData|None get_modem_data(self, dict[str, Any] config)
web.Response get(self, web.Request request, str config_key)
aiohttp.ClientSession async_create_clientsession()
None _retry_login(HomeAssistant hass, ModemData modem_data, str password)
bool async_setup(HomeAssistant hass, ConfigType config)
None _login(HomeAssistant hass, ModemData modem_data, str password)
None _setup_lte(HomeAssistant hass, dict[str, Any] lte_config, int delay=0)