core/homeassistant/components/upnp/config_flow.py

151 lines
5.2 KiB
Python
Raw Normal View History

2018-09-17 20:08:09 +00:00
"""Config flow for UPNP."""
2018-08-30 14:38:43 +00:00
import voluptuous as vol
2018-09-01 19:20:15 +00:00
from homeassistant import config_entries
from homeassistant import data_entry_flow
2018-08-17 19:28:29 +00:00
2018-09-01 19:20:15 +00:00
from .const import (
CONF_ENABLE_PORT_MAPPING, CONF_ENABLE_SENSORS,
CONF_SSDP_DESCRIPTION, CONF_UDN
)
2018-08-17 19:28:29 +00:00
from .const import DOMAIN
2018-09-02 14:40:39 +00:00
def ensure_domain_data(hass):
"""Ensure hass.data is filled properly."""
hass.data[DOMAIN] = hass.data.get(DOMAIN, {})
hass.data[DOMAIN]['devices'] = hass.data[DOMAIN].get('devices', {})
hass.data[DOMAIN]['sensors'] = hass.data[DOMAIN].get('sensors', {})
hass.data[DOMAIN]['discovered'] = hass.data[DOMAIN].get('discovered', {})
hass.data[DOMAIN]['auto_config'] = hass.data[DOMAIN].get('auto_config', {
'active': False,
'port_forward': False,
'sensors': False,
'ports': {'hass': 'hass'},
2018-09-02 14:40:39 +00:00
})
2018-08-17 19:28:29 +00:00
@config_entries.HANDLERS.register(DOMAIN)
2018-09-17 20:08:09 +00:00
class UpnpFlowHandler(data_entry_flow.FlowHandler):
2018-08-17 19:28:29 +00:00
"""Handle a Hue config flow."""
VERSION = 1
2018-09-01 19:20:15 +00:00
@property
2018-09-17 20:08:09 +00:00
def _configured_upnp_igds(self):
2018-09-01 19:20:15 +00:00
"""Get all configured IGDs."""
return {
entry.data[CONF_UDN]: {
'udn': entry.data[CONF_UDN],
}
for entry in self.hass.config_entries.async_entries(DOMAIN)
}
2018-08-29 19:19:04 +00:00
@property
2018-09-17 20:08:09 +00:00
def _discovered_upnp_igds(self):
2018-08-29 19:19:04 +00:00
"""Get all discovered entries."""
2018-09-01 19:20:15 +00:00
return self.hass.data[DOMAIN]['discovered']
2018-08-29 19:19:04 +00:00
def _store_discovery_info(self, discovery_info):
"""Add discovery info."""
udn = discovery_info['udn']
self.hass.data[DOMAIN]['discovered'][udn] = discovery_info
2018-08-17 19:28:29 +00:00
2018-08-30 14:38:43 +00:00
def _auto_config_settings(self):
"""Check if auto_config has been enabled."""
2018-09-01 19:20:15 +00:00
return self.hass.data[DOMAIN]['auto_config']
2018-08-30 14:38:43 +00:00
2018-08-17 19:28:29 +00:00
async def async_step_discovery(self, discovery_info):
2018-08-29 19:19:04 +00:00
"""
2018-09-17 20:08:09 +00:00
Handle a discovered UPnP/IGD.
2018-08-17 19:28:29 +00:00
This flow is triggered by the discovery component. It will check if the
host is already configured and delegate to the import step if not.
"""
2018-09-01 19:20:15 +00:00
ensure_domain_data(self.hass)
2018-08-17 19:28:29 +00:00
2018-08-29 19:19:04 +00:00
# store discovered device
discovery_info['friendly_name'] = \
'{} ({})'.format(discovery_info['host'], discovery_info['name'])
2018-08-29 19:19:04 +00:00
self._store_discovery_info(discovery_info)
2018-08-17 19:28:29 +00:00
2018-09-01 19:20:15 +00:00
# ensure not already discovered/configured
udn = discovery_info['udn']
2018-09-17 20:08:09 +00:00
if udn in self._configured_upnp_igds:
2018-09-01 19:20:15 +00:00
return self.async_abort(reason='already_configured')
2018-08-30 14:38:43 +00:00
# auto config?
auto_config = self._auto_config_settings()
if auto_config['active']:
import_info = {
'name': discovery_info['friendly_name'],
2018-08-30 14:38:43 +00:00
'sensors': auto_config['sensors'],
'port_forward': auto_config['port_forward'],
}
return await self._async_save_entry(import_info)
2018-08-29 19:19:04 +00:00
return await self.async_step_user()
async def async_step_user(self, user_input=None):
"""Manual set up."""
# if user input given, handle it
user_input = user_input or {}
if 'name' in user_input:
2018-08-29 19:19:04 +00:00
if not user_input['sensors'] and not user_input['port_forward']:
return self.async_abort(reason='no_sensors_or_port_forward')
2018-09-01 19:20:15 +00:00
# ensure not already configured
configured_names = [
entry['friendly_name']
2018-09-17 20:08:09 +00:00
for udn, entry in self._discovered_upnp_igds.items()
if udn in self._configured_upnp_igds
2018-08-29 19:19:04 +00:00
]
2018-09-01 19:20:15 +00:00
if user_input['name'] in configured_names:
2018-08-29 19:19:04 +00:00
return self.async_abort(reason='already_configured')
2018-08-30 14:38:43 +00:00
return await self._async_save_entry(user_input)
2018-08-29 19:19:04 +00:00
2018-09-17 20:08:09 +00:00
# let user choose from all discovered, non-configured, UPnP/IGDs
names = [
entry['friendly_name']
2018-09-17 20:08:09 +00:00
for udn, entry in self._discovered_upnp_igds.items()
if udn not in self._configured_upnp_igds
2018-08-29 19:19:04 +00:00
]
if not names:
2018-08-29 19:19:04 +00:00
return self.async_abort(reason='no_devices_discovered')
2018-08-17 19:28:29 +00:00
return self.async_show_form(
2018-08-29 19:19:04 +00:00
step_id='user',
2018-08-17 19:28:29 +00:00
data_schema=vol.Schema({
vol.Required('name'): vol.In(names),
vol.Optional('sensors', default=False): bool,
vol.Optional('port_forward', default=False): bool,
2018-08-17 19:28:29 +00:00
})
)
2018-08-30 14:38:43 +00:00
async def async_step_import(self, import_info):
2018-09-17 20:08:09 +00:00
"""Import a new UPnP/IGD as a config entry."""
2018-08-30 14:38:43 +00:00
return await self._async_save_entry(import_info)
2018-08-29 19:19:04 +00:00
2018-08-30 14:38:43 +00:00
async def _async_save_entry(self, import_info):
2018-09-17 20:08:09 +00:00
"""Store UPNP/IGD as new entry."""
2018-08-29 19:19:04 +00:00
# ensure we know the host
name = import_info['name']
2018-08-29 19:19:04 +00:00
discovery_infos = [info
2018-09-17 20:08:09 +00:00
for info in self._discovered_upnp_igds.values()
if info['friendly_name'] == name]
2018-08-29 19:19:04 +00:00
if not discovery_infos:
return self.async_abort(reason='host_not_found')
discovery_info = discovery_infos[0]
2018-08-17 19:28:29 +00:00
return self.async_create_entry(
2018-08-29 19:19:04 +00:00
title=discovery_info['name'],
2018-08-17 19:28:29 +00:00
data={
2018-09-01 19:20:15 +00:00
CONF_SSDP_DESCRIPTION: discovery_info['ssdp_description'],
CONF_UDN: discovery_info['udn'],
2018-08-30 14:38:43 +00:00
CONF_ENABLE_SENSORS: import_info['sensors'],
CONF_ENABLE_PORT_MAPPING: import_info['port_forward'],
2018-08-29 19:19:04 +00:00
},
)