Fix KNX onboarding when there is no yaml config defined yet (#64216)

pull/64317/head
Matthias Alphart 2022-01-17 05:44:21 +01:00 committed by Paulus Schoutsen
parent da5b4735da
commit ec993b12e9
2 changed files with 33 additions and 42 deletions

View File

@ -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.
@ -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
# `conf` is None when reloading the integration or no `knx` key in configuration.yaml
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
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:
@ -363,7 +362,6 @@ class KNXModule:
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:
@ -403,7 +401,6 @@ class KNXModule:
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:

View File

@ -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
@ -64,25 +64,6 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
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:
@ -99,6 +80,22 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
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
)
@ -107,8 +104,6 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
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]}",
@ -129,6 +124,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
},
)
errors: dict = {}
fields = {
vol.Required(CONF_HOST, default=self._gateway_ip): str,
vol.Required(CONF_PORT, default=self._gateway_port): vol.Coerce(int),
@ -149,8 +145,6 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
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
@ -163,6 +157,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
return await self.async_step_manual_tunnel()
errors: dict = {}
tunnel_repr = {
str(tunnel) for tunnel in self._tunnels if tunnel.supports_tunnelling
}
@ -182,8 +177,6 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
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(),
@ -205,6 +198,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
},
)
errors: dict = {}
fields = {
vol.Required(
CONF_KNX_INDIVIDUAL_ADDRESS, default=XKNX.DEFAULT_ADDRESS
@ -434,7 +428,7 @@ class KNXOptionsFlowHandler(OptionsFlow):
)
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(