Fix KNX onboarding when there is no yaml config defined yet (#64216)
parent
da5b4735da
commit
ec993b12e9
|
@ -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:
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue