Skip to content

Commit

Permalink
Fix KNX onboarding when there is no yaml config defined yet (#64216)
Browse files Browse the repository at this point in the history
  • Loading branch information
farmio authored and balloob committed Jan 17, 2022
1 parent da5b473 commit ec993b1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 42 deletions.
27 changes: 12 additions & 15 deletions homeassistant/components/knx/__init__.py
Expand Up @@ -206,7 +206,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
return bool(hass.config_entries.async_entries(DOMAIN))

conf = dict(conf)

hass.data[DATA_KNX_CONFIG] = conf

# Only import if we haven't before.
Expand All @@ -223,19 +222,19 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Load a config entry."""
conf = hass.data.get(DATA_KNX_CONFIG)

# When reloading
if conf is None:
conf = await async_integration_yaml_config(hass, DOMAIN)
if not conf or DOMAIN not in conf:
return False

conf = conf[DOMAIN]

# If user didn't have configuration.yaml config, generate defaults
# `conf` is None when reloading the integration or no `knx` key in configuration.yaml
if conf is None:
conf = CONFIG_SCHEMA({DOMAIN: dict(entry.data)})[DOMAIN]

_conf = await async_integration_yaml_config(hass, DOMAIN)
if not _conf or DOMAIN not in _conf:
_LOGGER.warning(
"No `knx:` key found in configuration.yaml. See "
"https://www.home-assistant.io/integrations/knx/ "
"for KNX entity configuration documentation"
)
# generate defaults
conf = CONFIG_SCHEMA({DOMAIN: {}})[DOMAIN]
else:
conf = _conf[DOMAIN]
config = {**conf, **entry.data}

try:
Expand Down Expand Up @@ -363,7 +362,6 @@ def __init__(
self.entry.async_on_unload(
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.stop)
)

self.entry.async_on_unload(self.entry.add_update_listener(async_update_entry))

def init_xknx(self) -> None:
Expand Down Expand Up @@ -403,7 +401,6 @@ def connection_config(self) -> ConnectionConfig:
route_back=self.config.get(ConnectionSchema.CONF_KNX_ROUTE_BACK, False),
auto_reconnect=True,
)

return ConnectionConfig(auto_reconnect=True)

async def connection_state_changed_cb(self, state: XknxConnectionState) -> None:
Expand Down
48 changes: 21 additions & 27 deletions homeassistant/components/knx/config_flow.py
Expand Up @@ -44,7 +44,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):

VERSION = 1

_tunnels: list
_tunnels: list[GatewayDescriptor]
_gateway_ip: str = ""
_gateway_port: int = DEFAULT_MCAST_PORT

Expand All @@ -64,25 +64,6 @@ async def async_step_user(self, user_input: dict | None = None) -> FlowResult:

async def async_step_type(self, user_input: dict | None = None) -> FlowResult:
"""Handle connection type configuration."""
errors: dict = {}
supported_connection_types = CONF_KNX_INITIAL_CONNECTION_TYPES.copy()
fields = {}

if user_input is None:
gateways = await scan_for_gateways()

if gateways:
supported_connection_types.insert(0, CONF_KNX_AUTOMATIC)
self._tunnels = [
gateway for gateway in gateways if gateway.supports_tunnelling
]

fields = {
vol.Required(CONF_KNX_CONNECTION_TYPE): vol.In(
supported_connection_types
)
}

if user_input is not None:
connection_type = user_input[CONF_KNX_CONNECTION_TYPE]
if connection_type == CONF_KNX_AUTOMATIC:
Expand All @@ -99,6 +80,22 @@ async def async_step_type(self, user_input: dict | None = None) -> FlowResult:

return await self.async_step_manual_tunnel()

errors: dict = {}
supported_connection_types = CONF_KNX_INITIAL_CONNECTION_TYPES.copy()
fields = {}
gateways = await scan_for_gateways()

if gateways:
# add automatic only if a gateway responded
supported_connection_types.insert(0, CONF_KNX_AUTOMATIC)
self._tunnels = [
gateway for gateway in gateways if gateway.supports_tunnelling
]

fields = {
vol.Required(CONF_KNX_CONNECTION_TYPE): vol.In(supported_connection_types)
}

return self.async_show_form(
step_id="type", data_schema=vol.Schema(fields), errors=errors
)
Expand All @@ -107,8 +104,6 @@ async def async_step_manual_tunnel(
self, user_input: dict | None = None
) -> FlowResult:
"""General setup."""
errors: dict = {}

if user_input is not None:
return self.async_create_entry(
title=f"{CONF_KNX_TUNNELING.capitalize()} @ {user_input[CONF_HOST]}",
Expand All @@ -129,6 +124,7 @@ async def async_step_manual_tunnel(
},
)

errors: dict = {}
fields = {
vol.Required(CONF_HOST, default=self._gateway_ip): str,
vol.Required(CONF_PORT, default=self._gateway_port): vol.Coerce(int),
Expand All @@ -149,8 +145,6 @@ async def async_step_manual_tunnel(

async def async_step_tunnel(self, user_input: dict | None = None) -> FlowResult:
"""Select a tunnel from a list. Will be skipped if the gateway scan was unsuccessful or if only one gateway was found."""
errors: dict = {}

if user_input is not None:
gateway: GatewayDescriptor = next(
gateway
Expand All @@ -163,6 +157,7 @@ async def async_step_tunnel(self, user_input: dict | None = None) -> FlowResult:

return await self.async_step_manual_tunnel()

errors: dict = {}
tunnel_repr = {
str(tunnel) for tunnel in self._tunnels if tunnel.supports_tunnelling
}
Expand All @@ -182,8 +177,6 @@ async def async_step_tunnel(self, user_input: dict | None = None) -> FlowResult:

async def async_step_routing(self, user_input: dict | None = None) -> FlowResult:
"""Routing setup."""
errors: dict = {}

if user_input is not None:
return self.async_create_entry(
title=CONF_KNX_ROUTING.capitalize(),
Expand All @@ -205,6 +198,7 @@ async def async_step_routing(self, user_input: dict | None = None) -> FlowResult
},
)

errors: dict = {}
fields = {
vol.Required(
CONF_KNX_INDIVIDUAL_ADDRESS, default=XKNX.DEFAULT_ADDRESS
Expand Down Expand Up @@ -434,7 +428,7 @@ async def async_step_init(
)


async def scan_for_gateways(stop_on_found: int = 0) -> list:
async def scan_for_gateways(stop_on_found: int = 0) -> list[GatewayDescriptor]:
"""Scan for gateways within the network."""
xknx = XKNX()
gatewayscanner = GatewayScanner(
Expand Down

0 comments on commit ec993b1

Please sign in to comment.