From b9247f395273b2b80ae5760996c58b8b2e922469 Mon Sep 17 00:00:00 2001 From: Marvin Wichmann <marvin@fam-wichmann.de> Date: Thu, 30 Dec 2021 01:13:58 +0100 Subject: [PATCH] Fix local_ip handling in KNX options flow (#62969) --- homeassistant/components/knx/config_flow.py | 21 +++-- homeassistant/components/knx/strings.json | 6 +- .../components/knx/translations/en.json | 7 +- tests/components/knx/test_config_flow.py | 77 ++++++++++++++----- 4 files changed, 79 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/knx/config_flow.py b/homeassistant/components/knx/config_flow.py index 96aa8f67e3b..01e71eb37af 100644 --- a/homeassistant/components/knx/config_flow.py +++ b/homeassistant/components/knx/config_flow.py @@ -28,6 +28,7 @@ from .schema import ConnectionSchema CONF_KNX_GATEWAY: Final = "gateway" CONF_MAX_RATE_LIMIT: Final = 60 +CONF_DEFAULT_LOCAL_IP: Final = "0.0.0.0" DEFAULT_ENTRY_DATA: Final = { ConnectionSchema.CONF_KNX_STATE_UPDATER: ConnectionSchema.CONF_KNX_DEFAULT_STATE_UPDATER, @@ -328,6 +329,12 @@ class KNXOptionsFlowHandler(OptionsFlow): entry_data = { **DEFAULT_ENTRY_DATA, **self.general_settings, + ConnectionSchema.CONF_KNX_LOCAL_IP: self.general_settings.get( + ConnectionSchema.CONF_KNX_LOCAL_IP + ) + if self.general_settings.get(ConnectionSchema.CONF_KNX_LOCAL_IP) + != CONF_DEFAULT_LOCAL_IP + else None, CONF_HOST: self.current_config.get(CONF_HOST, ""), } @@ -337,7 +344,7 @@ class KNXOptionsFlowHandler(OptionsFlow): **user_input, } - entry_title = entry_data[CONF_KNX_CONNECTION_TYPE].capitalize() + entry_title = str(entry_data[CONF_KNX_CONNECTION_TYPE]).capitalize() if entry_data[CONF_KNX_CONNECTION_TYPE] == CONF_KNX_TUNNELING: entry_title = f"{CONF_KNX_TUNNELING.capitalize()} @ {entry_data[CONF_HOST]}" @@ -388,12 +395,16 @@ class KNXOptionsFlowHandler(OptionsFlow): } if self.show_advanced_options: + local_ip = ( + self.current_config.get(ConnectionSchema.CONF_KNX_LOCAL_IP) + if self.current_config.get(ConnectionSchema.CONF_KNX_LOCAL_IP) + is not None + else CONF_DEFAULT_LOCAL_IP + ) data_schema[ - vol.Optional( + vol.Required( ConnectionSchema.CONF_KNX_LOCAL_IP, - default=self.current_config.get( - ConnectionSchema.CONF_KNX_LOCAL_IP, - ), + default=local_ip, ) ] = str data_schema[ diff --git a/homeassistant/components/knx/strings.json b/homeassistant/components/knx/strings.json index 4db92888aab..d219880be5c 100644 --- a/homeassistant/components/knx/strings.json +++ b/homeassistant/components/knx/strings.json @@ -20,7 +20,7 @@ "host": "[%key:common::config_flow::data::host%]", "individual_address": "Individual address for the connection", "route_back": "Route Back / NAT Mode", - "local_ip": "Local IP (leave empty if unsure)" + "local_ip": "Local IP of Home Assistant (leave empty for automatic detection)" } }, "routing": { @@ -29,7 +29,7 @@ "individual_address": "Individual address for the routing connection", "multicast_group": "The multicast group used for routing", "multicast_port": "The multicast port used for routing", - "local_ip": "Local IP (leave empty if unsure)" + "local_ip": "Local IP of Home Assistant (leave empty for automatic detection)" } } }, @@ -49,7 +49,7 @@ "individual_address": "Default individual address", "multicast_group": "Multicast group used for routing and discovery", "multicast_port": "Multicast port used for routing and discovery", - "local_ip": "Local IP (leave empty if unsure)", + "local_ip": "Local IP of Home Assistant (use 0.0.0.0 for automatic detection)", "state_updater": "Globally enable reading states from the KNX Bus", "rate_limit": "Maximum outgoing telegrams per second" } diff --git a/homeassistant/components/knx/translations/en.json b/homeassistant/components/knx/translations/en.json index 8f812a7baf1..354675c5007 100644 --- a/homeassistant/components/knx/translations/en.json +++ b/homeassistant/components/knx/translations/en.json @@ -12,7 +12,7 @@ "data": { "host": "Host", "individual_address": "Individual address for the connection", - "local_ip": "Local IP (leave empty if unsure)", + "local_ip": "Local IP of Home Assistant (leave empty for automatic detection)", "port": "Port", "route_back": "Route Back / NAT Mode" }, @@ -21,7 +21,7 @@ "routing": { "data": { "individual_address": "Individual address for the routing connection", - "local_ip": "Local IP (leave empty if unsure)", + "local_ip": "Local IP of Home Assistant (leave empty for automatic detection)", "multicast_group": "The multicast group used for routing", "multicast_port": "The multicast port used for routing" }, @@ -47,7 +47,7 @@ "data": { "connection_type": "KNX Connection Type", "individual_address": "Default individual address", - "local_ip": "Local IP (leave empty if unsure)", + "local_ip": "Local IP of Home Assistant (use 0.0.0.0 for automatic detection)", "multicast_group": "Multicast group used for routing and discovery", "multicast_port": "Multicast port used for routing and discovery", "rate_limit": "Maximum outgoing telegrams per second", @@ -57,7 +57,6 @@ "tunnel": { "data": { "host": "Host", - "local_ip": "Local IP (leave empty if unsure)", "port": "Port", "route_back": "Route Back / NAT Mode" } diff --git a/tests/components/knx/test_config_flow.py b/tests/components/knx/test_config_flow.py index 4f3e1734b69..aec757a1086 100644 --- a/tests/components/knx/test_config_flow.py +++ b/tests/components/knx/test_config_flow.py @@ -1,6 +1,7 @@ """Test the KNX config flow.""" from unittest.mock import patch +import pytest from xknx import XKNX from xknx.io import DEFAULT_MCAST_GRP from xknx.io.gateway_scanner import GatewayDescriptor @@ -8,6 +9,7 @@ from xknx.io.gateway_scanner import GatewayDescriptor from homeassistant import config_entries from homeassistant.components.knx import ConnectionSchema from homeassistant.components.knx.config_flow import ( + CONF_DEFAULT_LOCAL_IP, CONF_KNX_GATEWAY, DEFAULT_ENTRY_DATA, ) @@ -585,6 +587,7 @@ async def test_options_flow( CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC, CONF_KNX_INDIVIDUAL_ADDRESS: "15.15.255", CONF_HOST: "", + ConnectionSchema.CONF_KNX_LOCAL_IP: None, ConnectionSchema.CONF_KNX_MCAST_PORT: 3675, ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, ConnectionSchema.CONF_KNX_RATE_LIMIT: 20, @@ -643,14 +646,65 @@ async def test_tunneling_options_flow( ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, ConnectionSchema.CONF_KNX_RATE_LIMIT: 20, ConnectionSchema.CONF_KNX_STATE_UPDATER: True, + ConnectionSchema.CONF_KNX_LOCAL_IP: None, CONF_HOST: "192.168.1.1", CONF_PORT: 3675, ConnectionSchema.CONF_KNX_ROUTE_BACK: True, } +@pytest.mark.parametrize( + "user_input,config_entry_data", + [ + ( + { + CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC, + CONF_KNX_INDIVIDUAL_ADDRESS: "15.15.250", + ConnectionSchema.CONF_KNX_MCAST_PORT: 3675, + ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, + ConnectionSchema.CONF_KNX_RATE_LIMIT: 25, + ConnectionSchema.CONF_KNX_STATE_UPDATER: False, + ConnectionSchema.CONF_KNX_LOCAL_IP: "192.168.1.112", + }, + { + CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC, + CONF_KNX_INDIVIDUAL_ADDRESS: "15.15.250", + CONF_HOST: "", + ConnectionSchema.CONF_KNX_MCAST_PORT: 3675, + ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, + ConnectionSchema.CONF_KNX_RATE_LIMIT: 25, + ConnectionSchema.CONF_KNX_STATE_UPDATER: False, + ConnectionSchema.CONF_KNX_LOCAL_IP: "192.168.1.112", + }, + ), + ( + { + CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC, + CONF_KNX_INDIVIDUAL_ADDRESS: "15.15.250", + ConnectionSchema.CONF_KNX_MCAST_PORT: 3675, + ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, + ConnectionSchema.CONF_KNX_RATE_LIMIT: 25, + ConnectionSchema.CONF_KNX_STATE_UPDATER: False, + ConnectionSchema.CONF_KNX_LOCAL_IP: CONF_DEFAULT_LOCAL_IP, + }, + { + CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC, + CONF_KNX_INDIVIDUAL_ADDRESS: "15.15.250", + CONF_HOST: "", + ConnectionSchema.CONF_KNX_MCAST_PORT: 3675, + ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, + ConnectionSchema.CONF_KNX_RATE_LIMIT: 25, + ConnectionSchema.CONF_KNX_STATE_UPDATER: False, + ConnectionSchema.CONF_KNX_LOCAL_IP: None, + }, + ), + ], +) async def test_advanced_options( - hass: HomeAssistant, mock_config_entry: MockConfigEntry + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + user_input, + config_entry_data, ) -> None: """Test options config flow.""" mock_config_entry.add_to_hass(hass) @@ -668,28 +722,11 @@ async def test_advanced_options( result2 = await hass.config_entries.options.async_configure( result["flow_id"], - user_input={ - CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC, - CONF_KNX_INDIVIDUAL_ADDRESS: "15.15.250", - ConnectionSchema.CONF_KNX_MCAST_PORT: 3675, - ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, - ConnectionSchema.CONF_KNX_RATE_LIMIT: 25, - ConnectionSchema.CONF_KNX_STATE_UPDATER: False, - ConnectionSchema.CONF_KNX_LOCAL_IP: "192.168.1.112", - }, + user_input=user_input, ) await hass.async_block_till_done() assert result2.get("type") == RESULT_TYPE_CREATE_ENTRY assert not result2.get("data") - assert mock_config_entry.data == { - CONF_KNX_CONNECTION_TYPE: CONF_KNX_AUTOMATIC, - CONF_KNX_INDIVIDUAL_ADDRESS: "15.15.250", - CONF_HOST: "", - ConnectionSchema.CONF_KNX_MCAST_PORT: 3675, - ConnectionSchema.CONF_KNX_MCAST_GRP: DEFAULT_MCAST_GRP, - ConnectionSchema.CONF_KNX_RATE_LIMIT: 25, - ConnectionSchema.CONF_KNX_STATE_UPDATER: False, - ConnectionSchema.CONF_KNX_LOCAL_IP: "192.168.1.112", - } + assert mock_config_entry.data == config_entry_data