diff --git a/homeassistant/components/knx/config_flow.py b/homeassistant/components/knx/config_flow.py index 3cedf518e1a..e7e8854a9fb 100644 --- a/homeassistant/components/knx/config_flow.py +++ b/homeassistant/components/knx/config_flow.py @@ -15,7 +15,7 @@ from homeassistant.config_entries import ConfigEntry, OptionsFlow from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult -import homeassistant.helpers.config_validation as cv +from homeassistant.helpers import selector from homeassistant.helpers.storage import STORAGE_DIR from .const import ( @@ -63,6 +63,10 @@ CONF_KNX_LABEL_TUNNELING_TCP_SECURE: Final = "TCP with IP Secure" CONF_KNX_LABEL_TUNNELING_UDP: Final = "UDP" CONF_KNX_LABEL_TUNNELING_UDP_ROUTE_BACK: Final = "UDP with route back / NAT mode" +_IA_SELECTOR = selector.selector({"text": {}}) +_IP_SELECTOR = selector.selector({"text": {}}) +_PORT_SELECTOR = selector.selector({"number": {"min": 1, "max": 65535, "mode": "box"}}) + class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """Handle a KNX config flow.""" @@ -164,7 +168,6 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): **DEFAULT_ENTRY_DATA, # type: ignore[misc] CONF_HOST: user_input[CONF_HOST], CONF_PORT: user_input[CONF_PORT], - CONF_KNX_INDIVIDUAL_ADDRESS: user_input[CONF_KNX_INDIVIDUAL_ADDRESS], CONF_KNX_ROUTE_BACK: ( connection_type == CONF_KNX_LABEL_TUNNELING_UDP_ROUTE_BACK ), @@ -202,18 +205,16 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): port = self._selected_tunnel.port if not self._selected_tunnel.supports_tunnelling_tcp: connection_methods.remove(CONF_KNX_LABEL_TUNNELING_TCP) + connection_methods.remove(CONF_KNX_LABEL_TUNNELING_TCP_SECURE) fields = { vol.Required(CONF_KNX_TUNNELING_TYPE): vol.In(connection_methods), - vol.Required(CONF_HOST, default=ip_address): str, - vol.Required(CONF_PORT, default=port): cv.port, - vol.Required( - CONF_KNX_INDIVIDUAL_ADDRESS, default=XKNX.DEFAULT_ADDRESS - ): str, + vol.Required(CONF_HOST, default=ip_address): _IP_SELECTOR, + vol.Required(CONF_PORT, default=port): _PORT_SELECTOR, } if self.show_advanced_options: - fields[vol.Optional(CONF_KNX_LOCAL_IP)] = str + fields[vol.Optional(CONF_KNX_LOCAL_IP)] = _IP_SELECTOR return self.async_show_form( step_id="manual_tunnel", data_schema=vol.Schema(fields), errors=errors @@ -245,9 +246,15 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) fields = { - vol.Required(CONF_KNX_SECURE_USER_ID): int, - vol.Required(CONF_KNX_SECURE_USER_PASSWORD): str, - vol.Required(CONF_KNX_SECURE_DEVICE_AUTHENTICATION): str, + vol.Required(CONF_KNX_SECURE_USER_ID, default=2): selector.selector( + {"number": {"min": 1, "max": 127, "mode": "box"}} + ), + vol.Required(CONF_KNX_SECURE_USER_PASSWORD): selector.selector( + {"text": {"type": "password"}} + ), + vol.Required(CONF_KNX_SECURE_DEVICE_AUTHENTICATION): selector.selector( + {"text": {"type": "password"}} + ), } return self.async_show_form( @@ -290,8 +297,8 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): errors["base"] = "file_not_found" fields = { - vol.Required(CONF_KNX_KNXKEY_FILENAME): str, - vol.Required(CONF_KNX_KNXKEY_PASSWORD): str, + vol.Required(CONF_KNX_KNXKEY_FILENAME): selector.selector({"text": {}}), + vol.Required(CONF_KNX_KNXKEY_PASSWORD): selector.selector({"text": {}}), } return self.async_show_form( @@ -319,13 +326,15 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): fields = { vol.Required( CONF_KNX_INDIVIDUAL_ADDRESS, default=XKNX.DEFAULT_ADDRESS - ): str, - vol.Required(CONF_KNX_MCAST_GRP, default=DEFAULT_MCAST_GRP): str, - vol.Required(CONF_KNX_MCAST_PORT, default=DEFAULT_MCAST_PORT): cv.port, + ): _IA_SELECTOR, + vol.Required(CONF_KNX_MCAST_GRP, default=DEFAULT_MCAST_GRP): _IP_SELECTOR, + vol.Required( + CONF_KNX_MCAST_PORT, default=DEFAULT_MCAST_PORT + ): _PORT_SELECTOR, } if self.show_advanced_options: - fields[vol.Optional(CONF_KNX_LOCAL_IP)] = str + fields[vol.Optional(CONF_KNX_LOCAL_IP)] = _IP_SELECTOR return self.async_show_form( step_id="routing", data_schema=vol.Schema(fields), errors=errors @@ -370,17 +379,17 @@ class KNXOptionsFlowHandler(OptionsFlow): vol.Required( CONF_KNX_INDIVIDUAL_ADDRESS, default=self.current_config[CONF_KNX_INDIVIDUAL_ADDRESS], - ): str, + ): selector.selector({"text": {}}), vol.Required( CONF_KNX_MCAST_GRP, default=self.current_config.get(CONF_KNX_MCAST_GRP, DEFAULT_MCAST_GRP), - ): str, + ): _IP_SELECTOR, vol.Required( CONF_KNX_MCAST_PORT, default=self.current_config.get( CONF_KNX_MCAST_PORT, DEFAULT_MCAST_PORT ), - ): cv.port, + ): _PORT_SELECTOR, } if self.show_advanced_options: @@ -394,7 +403,7 @@ class KNXOptionsFlowHandler(OptionsFlow): CONF_KNX_LOCAL_IP, default=local_ip, ) - ] = str + ] = _IP_SELECTOR data_schema[ vol.Required( CONF_KNX_STATE_UPDATER, @@ -403,7 +412,7 @@ class KNXOptionsFlowHandler(OptionsFlow): CONF_KNX_DEFAULT_STATE_UPDATER, ), ) - ] = bool + ] = selector.selector({"boolean": {}}) data_schema[ vol.Required( CONF_KNX_RATE_LIMIT, @@ -412,7 +421,15 @@ class KNXOptionsFlowHandler(OptionsFlow): CONF_KNX_DEFAULT_RATE_LIMIT, ), ) - ] = vol.All(vol.Coerce(int), vol.Range(min=1, max=CONF_MAX_RATE_LIMIT)) + ] = selector.selector( + { + "number": { + "min": 1, + "max": CONF_MAX_RATE_LIMIT, + "mode": "box", + } + } + ) return self.async_show_form( step_id="init", @@ -444,10 +461,10 @@ class KNXOptionsFlowHandler(OptionsFlow): ): vol.In(connection_methods), vol.Required( CONF_HOST, default=self.current_config.get(CONF_HOST) - ): str, + ): _IP_SELECTOR, vol.Required( CONF_PORT, default=self.current_config.get(CONF_PORT, 3671) - ): cv.port, + ): _PORT_SELECTOR, } ), last_step=True, diff --git a/homeassistant/components/knx/strings.json b/homeassistant/components/knx/strings.json index 1a7f3481a1a..2149dd96a47 100644 --- a/homeassistant/components/knx/strings.json +++ b/homeassistant/components/knx/strings.json @@ -19,39 +19,56 @@ "tunneling_type": "KNX Tunneling Type", "port": "[%key:common::config_flow::data::port%]", "host": "[%key:common::config_flow::data::host%]", - "individual_address": "Individual address for the connection", - "local_ip": "Local IP of Home Assistant (leave empty for automatic detection)" + "local_ip": "Local IP of Home Assistant" + }, + "data_description": { + "port": "Port of the KNX/IP tunneling device.", + "host": "IP address of the KNX/IP tunneling device.", + "local_ip": "Leave blank to use auto-discovery." } }, "secure_tunneling": { - "description": "Select how you want to configure IP Secure.", + "description": "Select how you want to configure KNX/IP Secure.", "menu_options": { - "secure_knxkeys": "Configure a knxkeys file containing IP secure information", - "secure_manual": "Configure IP secure manually" + "secure_knxkeys": "Use a `.knxkeys` file containing IP secure keys", + "secure_manual": "Configure IP secure keys manually" } }, "secure_knxkeys": { - "description": "Please enter the information for your knxkeys file.", + "description": "Please enter the information for your `.knxkeys` file.", "data": { - "knxkeys_filename": "The full name of your knxkeys file", - "knxkeys_password": "The password to decrypt the knxkeys file" + "knxkeys_filename": "The filename of your `.knxkeys` file (including extension)", + "knxkeys_password": "The password to decrypt the `.knxkeys` file" + }, + "data_description": { + "knxkeys_filename": "The file is expected to be found in your config directory in `.storage/knx/`.\nIn Home Assistant OS this would be `/config/.storage/knx/`\nExample: `my_project.knxkeys`", + "knxkeys_password": "This was set when exporting the file from ETS." } }, "secure_manual": { - "description": "Please enter the IP secure information.", + "description": "Please enter your IP secure information.", "data": { "user_id": "User ID", "user_password": "User password", "device_authentication": "Device authentication password" + }, + "data_description": { + "user_id": "This is often tunnel number +1. So 'Tunnel 2' would have User-ID '3'.", + "user_password": "Password for the specific tunnel connection set in the 'Properties' panel of the tunnel in ETS.", + "device_authentication": "This is set in the 'IP' panel of the interface in ETS." } }, "routing": { "description": "Please configure the routing options.", "data": { - "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 of Home Assistant (leave empty for automatic detection)" + "individual_address": "Individual address", + "multicast_group": "Multicast group used for routing", + "multicast_port": "Multicast port used for routing", + "local_ip": "Local IP of Home Assistant" + }, + "data_description": { + "individual_address": "KNX address to be used by Home Assistant, e.g. `0.0.4`", + "local_ip": "Leave blank to use auto-discovery." } } }, @@ -71,11 +88,19 @@ "data": { "connection_type": "KNX Connection Type", "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 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" + "multicast_group": "Multicast group", + "multicast_port": "Multicast port", + "local_ip": "Local IP of Home Assistant", + "state_updater": "State updater", + "rate_limit": "Rate limit" + }, + "data_description": { + "individual_address": "KNX address to be used by Home Assistant, e.g. `0.0.4`", + "multicast_group": "Used for routing and discovery. Default: `224.0.23.12`", + "multicast_port": "Used for routing and discovery. Default: `3671`", + "local_ip": "Use `0.0.0.0` for auto-discovery.", + "state_updater": "Globally enable or disable reading states from the KNX Bus. When disabled, Home Assistant will not actively retrieve states from the KNX Bus, `sync_state` entity options will have no effect.", + "rate_limit": "Maximum outgoing telegrams per second.\nRecommended: 20 to 40" } }, "tunnel": { @@ -83,6 +108,10 @@ "tunneling_type": "KNX Tunneling Type", "port": "[%key:common::config_flow::data::port%]", "host": "[%key:common::config_flow::data::host%]" + }, + "data_description": { + "port": "Port of the KNX/IP tunneling device.", + "host": "IP address of the KNX/IP tunneling device." } } } diff --git a/homeassistant/components/knx/translations/en.json b/homeassistant/components/knx/translations/en.json index f5ec7afc46b..640cb4a5358 100644 --- a/homeassistant/components/knx/translations/en.json +++ b/homeassistant/components/knx/translations/en.json @@ -13,44 +13,61 @@ "manual_tunnel": { "data": { "host": "Host", - "individual_address": "Individual address for the connection", - "local_ip": "Local IP of Home Assistant (leave empty for automatic detection)", + "local_ip": "Local IP of Home Assistant", "port": "Port", "tunneling_type": "KNX Tunneling Type" }, + "data_description": { + "host": "IP address of the KNX/IP tunneling device.", + "local_ip": "Leave blank to use auto-discovery.", + "port": "Port of the KNX/IP tunneling device." + }, "description": "Please enter the connection information of your tunneling device." }, "routing": { "data": { - "individual_address": "Individual address for the routing connection", - "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" + "individual_address": "Individual address", + "local_ip": "Local IP of Home Assistant", + "multicast_group": "Multicast group used for routing", + "multicast_port": "Multicast port used for routing" + }, + "data_description": { + "individual_address": "KNX address to be used by Home Assistant, e.g. `0.0.4`", + "local_ip": "Leave blank to use auto-discovery." }, "description": "Please configure the routing options." }, "secure_knxkeys": { "data": { - "knxkeys_filename": "The full name of your knxkeys file", - "knxkeys_password": "The password to decrypt the knxkeys file." + "knxkeys_filename": "The filename of your `.knxkeys` file (including extension)", + "knxkeys_password": "The password to decrypt the `.knxkeys` file" }, - "description": "Please enter the information for your knxkeys file." - }, - "secure_tunneling": { - "description": "Select how you want to configure IP Secure.", - "menu_options": { - "secure_knxkeys": "Configure a knxkeys file containing IP secure information", - "secure_manual": "Configure IP secure manually" - } + "data_description": { + "knxkeys_filename": "The file is expected to be found in your config directory in `.storage/knx/`.\nIn Home Assistant OS this would be `/config/.storage/knx/`\nExample: `my_project.knxkeys`", + "knxkeys_password": "This was set when exporting the file from ETS." + }, + "description": "Please enter the information for your `.knxkeys` file." }, "secure_manual": { - "description": "Please enter the IP secure information.", "data": { - "user_id": "User ID", - "user_password": "User password", - "device_authentication": "Device authentication password" + "device_authentication": "Device authentication password", + "user_id": "User ID", + "user_password": "User password" + }, + "data_description": { + "device_authentication": "This is set in the 'IP' panel of the interface in ETS.", + "user_id": "This is often tunnel number +1. So 'Tunnel 2' would have User-ID '3'.", + "user_password": "Password for the specific tunnel connection set in the 'Properties' panel of the tunnel in ETS." + }, + "description": "Please enter your IP secure information." + }, + "secure_tunneling": { + "description": "Select how you want to configure KNX/IP Secure.", + "menu_options": { + "secure_knxkeys": "Use a `.knxkeys` file containing IP secure keys", + "secure_manual": "Configure IP secure keys manually" } - }, + }, "tunnel": { "data": { "gateway": "KNX Tunnel Connection" @@ -71,11 +88,19 @@ "data": { "connection_type": "KNX Connection Type", "individual_address": "Default individual address", - "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", - "state_updater": "Globally enable reading states from the KNX Bus" + "local_ip": "Local IP of Home Assistant", + "multicast_group": "Multicast group", + "multicast_port": "Multicast port", + "rate_limit": "Rate limit", + "state_updater": "State updater" + }, + "data_description": { + "individual_address": "KNX address to be used by Home Assistant, e.g. `0.0.4`", + "local_ip": "Use `0.0.0.0` for auto-discovery.", + "multicast_group": "Used for routing and discovery. Default: `224.0.23.12`", + "multicast_port": "Used for routing and discovery. Default: `3671`", + "rate_limit": "Maximum outgoing telegrams per second.\nRecommended: 20 to 40", + "state_updater": "Globally enable or disable reading states from the KNX Bus. When disabled, Home Assistant will not actively retrieve states from the KNX Bus, `sync_state` entity options will have no effect." } }, "tunnel": { @@ -83,6 +108,10 @@ "host": "Host", "port": "Port", "tunneling_type": "KNX Tunneling Type" + }, + "data_description": { + "host": "IP address of the KNX/IP tunneling device.", + "port": "Port of the KNX/IP tunneling device." } } }