From e983370c2792d79b8ec11f9ffdb1f62cf7372548 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 2 Nov 2021 18:27:06 +0100 Subject: [PATCH] Use zeroconf attributes (A-D) (#58835) Co-authored-by: epenet --- .../components/apple_tv/config_flow.py | 22 +++++++-------- homeassistant/components/axis/config_flow.py | 17 +++++++---- homeassistant/components/bond/config_flow.py | 5 ++-- .../components/bosch_shc/config_flow.py | 28 +++++++++---------- .../components/brother/config_flow.py | 5 ++-- homeassistant/components/cast/config_flow.py | 6 +++- .../components/daikin/config_flow.py | 13 ++++++--- .../devolo_home_control/config_flow.py | 6 +++- .../devolo_home_network/config_flow.py | 10 +++---- .../components/doorbird/config_flow.py | 13 ++++++--- homeassistant/components/zeroconf/__init__.py | 3 ++ 11 files changed, 78 insertions(+), 50 deletions(-) diff --git a/homeassistant/components/apple_tv/config_flow.py b/homeassistant/components/apple_tv/config_flow.py index 56ad1e83e23..f1a89688ad4 100644 --- a/homeassistant/components/apple_tv/config_flow.py +++ b/homeassistant/components/apple_tv/config_flow.py @@ -9,17 +9,13 @@ from pyatv.convert import protocol_str import voluptuous as vol from homeassistant import config_entries -from homeassistant.const import ( - CONF_ADDRESS, - CONF_NAME, - CONF_PIN, - CONF_PROTOCOL, - CONF_TYPE, -) +from homeassistant.components import zeroconf +from homeassistant.const import CONF_ADDRESS, CONF_NAME, CONF_PIN, CONF_PROTOCOL from homeassistant.core import callback -from homeassistant.data_entry_flow import AbortFlow +from homeassistant.data_entry_flow import AbortFlow, FlowResult from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.helpers.typing import DiscoveryInfoType from .const import CONF_CREDENTIALS, CONF_IDENTIFIER, CONF_START_OFF, DOMAIN @@ -148,16 +144,18 @@ class AppleTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): description_placeholders={"devices": self._devices_str()}, ) - async def async_step_zeroconf(self, discovery_info): + async def async_step_zeroconf( + self, discovery_info: DiscoveryInfoType + ) -> FlowResult: """Handle device found via zeroconf.""" - service_type = discovery_info[CONF_TYPE] - properties = discovery_info["properties"] + service_type = discovery_info[zeroconf.ATTR_TYPE] + properties = discovery_info[zeroconf.ATTR_PROPERTIES] if service_type == "_mediaremotetv._tcp.local.": identifier = properties["UniqueIdentifier"] name = properties["Name"] elif service_type == "_touch-able._tcp.local.": - identifier = discovery_info["name"].split(".")[0] + identifier = discovery_info[zeroconf.ATTR_NAME].split(".")[0] name = properties["CtlN"] else: return self.async_abort(reason="unknown") diff --git a/homeassistant/components/axis/config_flow.py b/homeassistant/components/axis/config_flow.py index d313e4b2745..e3994cedd39 100644 --- a/homeassistant/components/axis/config_flow.py +++ b/homeassistant/components/axis/config_flow.py @@ -6,6 +6,7 @@ from urllib.parse import urlsplit import voluptuous as vol from homeassistant import config_entries +from homeassistant.components import zeroconf from homeassistant.components.dhcp import HOSTNAME, IP_ADDRESS, MAC_ADDRESS from homeassistant.config_entries import SOURCE_IGNORE from homeassistant.const import ( @@ -17,7 +18,9 @@ from homeassistant.const import ( CONF_USERNAME, ) from homeassistant.core import callback +from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers.device_registry import format_mac +from homeassistant.helpers.typing import DiscoveryInfoType from homeassistant.util.network import is_link_local from .const import ( @@ -174,14 +177,18 @@ class AxisFlowHandler(config_entries.ConfigFlow, domain=AXIS_DOMAIN): } ) - async def async_step_zeroconf(self, discovery_info: dict): + async def async_step_zeroconf( + self, discovery_info: DiscoveryInfoType + ) -> FlowResult: """Prepare configuration for a Zeroconf discovered Axis device.""" return await self._process_discovered_device( { - CONF_HOST: discovery_info[CONF_HOST], - CONF_MAC: format_mac(discovery_info["properties"]["macaddress"]), - CONF_NAME: discovery_info["name"].split(".", 1)[0], - CONF_PORT: discovery_info[CONF_PORT], + CONF_HOST: discovery_info[zeroconf.ATTR_HOST], + CONF_MAC: format_mac( + discovery_info[zeroconf.ATTR_PROPERTIES]["macaddress"] + ), + CONF_NAME: discovery_info[zeroconf.ATTR_NAME].split(".", 1)[0], + CONF_PORT: discovery_info[zeroconf.ATTR_PORT], } ) diff --git a/homeassistant/components/bond/config_flow.py b/homeassistant/components/bond/config_flow.py index 6f70d37e0a1..5996cd03bae 100644 --- a/homeassistant/components/bond/config_flow.py +++ b/homeassistant/components/bond/config_flow.py @@ -10,6 +10,7 @@ from bond_api import Bond import voluptuous as vol from homeassistant import config_entries, exceptions +from homeassistant.components import zeroconf from homeassistant.config_entries import ConfigEntryState from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST, CONF_NAME from homeassistant.core import HomeAssistant @@ -94,8 +95,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self, discovery_info: DiscoveryInfoType ) -> FlowResult: """Handle a flow initialized by zeroconf discovery.""" - name: str = discovery_info[CONF_NAME] - host: str = discovery_info[CONF_HOST] + name: str = discovery_info[zeroconf.ATTR_NAME] + host: str = discovery_info[zeroconf.ATTR_HOST] bond_id = name.partition(".")[0] await self.async_set_unique_id(bond_id) for entry in self._async_current_entries(): diff --git a/homeassistant/components/bosch_shc/config_flow.py b/homeassistant/components/bosch_shc/config_flow.py index 416dc6cf304..c86569d6a4d 100644 --- a/homeassistant/components/bosch_shc/config_flow.py +++ b/homeassistant/components/bosch_shc/config_flow.py @@ -12,7 +12,7 @@ from boschshcpy.exceptions import ( import voluptuous as vol from homeassistant import config_entries, core -from homeassistant.components.zeroconf import async_get_instance +from homeassistant.components import zeroconf from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_TOKEN from .const import ( @@ -40,7 +40,7 @@ def write_tls_asset(hass: core.HomeAssistant, filename: str, asset: bytes) -> No file_handle.write(asset.decode("utf-8")) -def create_credentials_and_validate(hass, host, user_input, zeroconf): +def create_credentials_and_validate(hass, host, user_input, zeroconf_instance): """Create and store credentials and validate session.""" helper = SHCRegisterClient(host, user_input[CONF_PASSWORD]) result = helper.register(host, "HomeAssistant") @@ -54,21 +54,21 @@ def create_credentials_and_validate(hass, host, user_input, zeroconf): hass.config.path(DOMAIN, CONF_SHC_CERT), hass.config.path(DOMAIN, CONF_SHC_KEY), True, - zeroconf, + zeroconf_instance, ) session.authenticate() return result -def get_info_from_host(hass, host, zeroconf): +def get_info_from_host(hass, host, zeroconf_instance): """Get information from host.""" session = SHCSession( host, "", "", True, - zeroconf, + zeroconf_instance, ) information = session.mdns_info() return {"title": information.name, "unique_id": information.unique_id} @@ -123,14 +123,14 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle the credentials step.""" errors = {} if user_input is not None: - zeroconf = await async_get_instance(self.hass) + zeroconf_instance = await zeroconf.async_get_instance(self.hass) try: result = await self.hass.async_add_executor_job( create_credentials_and_validate, self.hass, self.host, user_input, - zeroconf, + zeroconf_instance, ) except SHCAuthenticationError: errors["base"] = "invalid_auth" @@ -183,14 +183,14 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): async def async_step_zeroconf(self, discovery_info): """Handle zeroconf discovery.""" - if not discovery_info.get("name", "").startswith("Bosch SHC"): + if not discovery_info.get(zeroconf.ATTR_NAME, "").startswith("Bosch SHC"): return self.async_abort(reason="not_bosch_shc") try: hosts = ( - discovery_info["host"] - if isinstance(discovery_info["host"], list) - else [discovery_info["host"]] + discovery_info[zeroconf.ATTR_HOST] + if isinstance(discovery_info[zeroconf.ATTR_HOST], list) + else [discovery_info[zeroconf.ATTR_HOST]] ) for host in hosts: if host.startswith("169."): # skip link local address @@ -202,7 +202,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): except SHCConnectionError: return self.async_abort(reason="cannot_connect") - local_name = discovery_info["hostname"][:-1] + local_name = discovery_info[zeroconf.ATTR_HOSTNAME][:-1] node_name = local_name[: -len(".local")] await self.async_set_unique_id(self.info["unique_id"]) @@ -227,11 +227,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): async def _get_info(self, host): """Get additional information.""" - zeroconf = await async_get_instance(self.hass) + zeroconf_instance = await zeroconf.async_get_instance(self.hass) return await self.hass.async_add_executor_job( get_info_from_host, self.hass, host, - zeroconf, + zeroconf_instance, ) diff --git a/homeassistant/components/brother/config_flow.py b/homeassistant/components/brother/config_flow.py index 20e5938884f..fa743e68d56 100644 --- a/homeassistant/components/brother/config_flow.py +++ b/homeassistant/components/brother/config_flow.py @@ -9,6 +9,7 @@ from brother import Brother, SnmpError, UnsupportedModel import voluptuous as vol from homeassistant import config_entries, exceptions +from homeassistant.components import zeroconf from homeassistant.const import CONF_HOST, CONF_TYPE from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers.typing import DiscoveryInfoType @@ -84,13 +85,13 @@ class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): ) -> FlowResult: """Handle zeroconf discovery.""" # Hostname is format: brother.local. - self.host = discovery_info["hostname"].rstrip(".") + self.host = discovery_info[zeroconf.ATTR_HOSTNAME].rstrip(".") # Do not probe the device if the host is already configured self._async_abort_entries_match({CONF_HOST: self.host}) snmp_engine = get_snmp_engine(self.hass) - model = discovery_info.get("properties", {}).get("product") + model = discovery_info.get(zeroconf.ATTR_PROPERTIES, {}).get("product") try: self.brother = Brother(self.host, snmp_engine=snmp_engine, model=model) diff --git a/homeassistant/components/cast/config_flow.py b/homeassistant/components/cast/config_flow.py index bb316f2b511..dbf52a8f238 100644 --- a/homeassistant/components/cast/config_flow.py +++ b/homeassistant/components/cast/config_flow.py @@ -2,7 +2,9 @@ import voluptuous as vol from homeassistant import config_entries +from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.typing import DiscoveryInfoType from .const import CONF_IGNORE_CEC, CONF_KNOWN_HOSTS, CONF_UUID, DOMAIN @@ -49,7 +51,9 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self.async_step_config() - async def async_step_zeroconf(self, discovery_info): + async def async_step_zeroconf( + self, discovery_info: DiscoveryInfoType + ) -> FlowResult: """Handle a flow initialized by zeroconf discovery.""" if self._async_in_progress() or self._async_current_entries(): return self.async_abort(reason="single_instance_allowed") diff --git a/homeassistant/components/daikin/config_flow.py b/homeassistant/components/daikin/config_flow.py index 18447c56d18..52e4fa255aa 100644 --- a/homeassistant/components/daikin/config_flow.py +++ b/homeassistant/components/daikin/config_flow.py @@ -10,7 +10,10 @@ from pydaikin.discovery import Discovery import voluptuous as vol from homeassistant import config_entries +from homeassistant.components import zeroconf from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PASSWORD +from homeassistant.data_entry_flow import FlowResult +from homeassistant.helpers.typing import DiscoveryInfoType from .const import CONF_UUID, DOMAIN, KEY_MAC, TIMEOUT @@ -123,18 +126,20 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN): user_input.get(CONF_PASSWORD), ) - async def async_step_zeroconf(self, discovery_info): + async def async_step_zeroconf( + self, discovery_info: DiscoveryInfoType + ) -> FlowResult: """Prepare configuration for a discovered Daikin device.""" _LOGGER.debug("Zeroconf user_input: %s", discovery_info) - devices = Discovery().poll(ip=discovery_info[CONF_HOST]) + devices = Discovery().poll(ip=discovery_info[zeroconf.ATTR_HOST]) if not devices: _LOGGER.debug( "Could not find MAC-address for %s," " make sure the required UDP ports are open (see integration documentation)", - discovery_info[CONF_HOST], + discovery_info[zeroconf.ATTR_HOST], ) return self.async_abort(reason="cannot_connect") await self.async_set_unique_id(next(iter(devices))[KEY_MAC]) self._abort_if_unique_id_configured() - self.host = discovery_info[CONF_HOST] + self.host = discovery_info[zeroconf.ATTR_HOST] return await self.async_step_user() diff --git a/homeassistant/components/devolo_home_control/config_flow.py b/homeassistant/components/devolo_home_control/config_flow.py index e6b3dcbe329..0cff72a4321 100644 --- a/homeassistant/components/devolo_home_control/config_flow.py +++ b/homeassistant/components/devolo_home_control/config_flow.py @@ -6,6 +6,7 @@ from typing import Any import voluptuous as vol from homeassistant import config_entries +from homeassistant.components import zeroconf from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import callback @@ -49,7 +50,10 @@ class DevoloHomeControlFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) -> FlowResult: """Handle zeroconf discovery.""" # Check if it is a gateway - if discovery_info.get("properties", {}).get("MT") in SUPPORTED_MODEL_TYPES: + if ( + discovery_info.get(zeroconf.ATTR_PROPERTIES, {}).get("MT") + in SUPPORTED_MODEL_TYPES + ): await self._async_handle_discovery_without_unique_id() return await self.async_step_zeroconf_confirm() return self.async_abort(reason="Not a devolo Home Control gateway.") diff --git a/homeassistant/components/devolo_home_network/config_flow.py b/homeassistant/components/devolo_home_network/config_flow.py index fa0ee983b69..20efe388407 100644 --- a/homeassistant/components/devolo_home_network/config_flow.py +++ b/homeassistant/components/devolo_home_network/config_flow.py @@ -77,17 +77,17 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self, discovery_info: DiscoveryInfoType ) -> FlowResult: """Handle zerooconf discovery.""" - if discovery_info["properties"]["MT"] in ["2600", "2601"]: + if discovery_info[zeroconf.ATTR_PROPERTIES]["MT"] in ["2600", "2601"]: return self.async_abort(reason="home_control") - await self.async_set_unique_id(discovery_info["properties"]["SN"]) + await self.async_set_unique_id(discovery_info[zeroconf.ATTR_PROPERTIES]["SN"]) self._abort_if_unique_id_configured() # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 - self.context[CONF_HOST] = discovery_info["host"] + self.context[CONF_HOST] = discovery_info[zeroconf.ATTR_HOST] self.context["title_placeholders"] = { - PRODUCT: discovery_info["properties"]["Product"], - CONF_NAME: discovery_info["hostname"].split(".")[0], + PRODUCT: discovery_info[zeroconf.ATTR_PROPERTIES]["Product"], + CONF_NAME: discovery_info[zeroconf.ATTR_HOSTNAME].split(".")[0], } return await self.async_step_zeroconf_confirm() diff --git a/homeassistant/components/doorbird/config_flow.py b/homeassistant/components/doorbird/config_flow.py index 01fcc2b2c22..a2c8496277d 100644 --- a/homeassistant/components/doorbird/config_flow.py +++ b/homeassistant/components/doorbird/config_flow.py @@ -8,8 +8,11 @@ import requests import voluptuous as vol from homeassistant import config_entries, core, exceptions +from homeassistant.components import zeroconf from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME from homeassistant.core import callback +from homeassistant.data_entry_flow import FlowResult +from homeassistant.helpers.typing import DiscoveryInfoType from homeassistant.util.network import is_link_local from .const import CONF_EVENTS, DOMAIN, DOORBIRD_OUI @@ -90,10 +93,12 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): data = self.discovery_schema or _schema_with_defaults() return self.async_show_form(step_id="user", data_schema=data, errors=errors) - async def async_step_zeroconf(self, discovery_info): + async def async_step_zeroconf( + self, discovery_info: DiscoveryInfoType + ) -> FlowResult: """Prepare configuration for a discovered doorbird device.""" - macaddress = discovery_info["properties"]["macaddress"] - host = discovery_info[CONF_HOST] + macaddress = discovery_info[zeroconf.ATTR_PROPERTIES]["macaddress"] + host = discovery_info[zeroconf.ATTR_HOST] if macaddress[:6] != DOORBIRD_OUI: return self.async_abort(reason="not_doorbird_device") @@ -109,7 +114,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): return self.async_abort(reason="not_doorbird_device") chop_ending = "._axis-video._tcp.local." - friendly_hostname = discovery_info["name"] + friendly_hostname = discovery_info[zeroconf.ATTR_NAME] if friendly_hostname.endswith(chop_ending): friendly_hostname = friendly_hostname[: -len(chop_ending)] diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index cd48b572577..f49fc708a1f 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -63,8 +63,11 @@ MAX_NAME_LEN = 63 # Attributes for HaServiceInfo ATTR_HOST: Final = "host" +ATTR_HOSTNAME: Final = "hostname" ATTR_NAME: Final = "name" +ATTR_PORT: Final = "port" ATTR_PROPERTIES: Final = "properties" +ATTR_TYPE: Final = "type" CONFIG_SCHEMA = vol.Schema(