diff --git a/homeassistant/components/hue/config_flow.py b/homeassistant/components/hue/config_flow.py index 72938ebfe0a..7149b4d9442 100644 --- a/homeassistant/components/hue/config_flow.py +++ b/homeassistant/components/hue/config_flow.py @@ -11,11 +11,12 @@ import async_timeout import voluptuous as vol from homeassistant import config_entries, core -from homeassistant.components import ssdp +from homeassistant.components import ssdp, zeroconf from homeassistant.const import CONF_HOST, CONF_USERNAME from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import aiohttp_client +from homeassistant.helpers.typing import DiscoveryInfoType from .bridge import authenticate_bridge from .const import ( @@ -207,14 +208,17 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): self.bridge = bridge return await self.async_step_link() - async def async_step_zeroconf(self, discovery_info): + async def async_step_zeroconf( + self, discovery_info: DiscoveryInfoType + ) -> FlowResult: """Handle a discovered Hue bridge. This flow is triggered by the Zeroconf component. It will check if the host is already configured and delegate to the import step if not. """ bridge = self._async_get_bridge( - discovery_info["host"], discovery_info["properties"]["bridgeid"] + discovery_info[zeroconf.ATTR_HOST], + discovery_info[zeroconf.ATTR_PROPERTIES]["bridgeid"], ) await self.async_set_unique_id(bridge.id) diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index 4062200972d..cd48b572577 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -8,7 +8,7 @@ from ipaddress import IPv4Address, IPv6Address, ip_address import logging import socket import sys -from typing import Any, TypedDict, cast +from typing import Any, Final, TypedDict, cast import voluptuous as vol from zeroconf import InterfaceChoice, IPVersion, ServiceStateChange @@ -61,6 +61,12 @@ MAX_PROPERTY_VALUE_LEN = 230 # Dns label max length MAX_NAME_LEN = 63 +# Attributes for HaServiceInfo +ATTR_HOST: Final = "host" +ATTR_NAME: Final = "name" +ATTR_PROPERTIES: Final = "properties" + + CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.All( @@ -349,7 +355,7 @@ class ZeroconfDiscovery: # If we can handle it as a HomeKit discovery, we do that here. if service_type in HOMEKIT_TYPES: - props = info["properties"] + props = info[ATTR_PROPERTIES] if domain := async_get_homekit_discovery_domain(self.homekit_models, props): discovery_flow.async_create_flow( self.hass, domain, {"source": config_entries.SOURCE_HOMEKIT}, info @@ -371,18 +377,18 @@ class ZeroconfDiscovery: # likely bad homekit data return - if "name" in info: - lowercase_name: str | None = info["name"].lower() + if ATTR_NAME in info: + lowercase_name: str | None = info[ATTR_NAME].lower() else: lowercase_name = None - if "macaddress" in info["properties"]: - uppercase_mac: str | None = info["properties"]["macaddress"].upper() + if "macaddress" in info[ATTR_PROPERTIES]: + uppercase_mac: str | None = info[ATTR_PROPERTIES]["macaddress"].upper() else: uppercase_mac = None - if "manufacturer" in info["properties"]: - lowercase_manufacturer: str | None = info["properties"][ + if "manufacturer" in info[ATTR_PROPERTIES]: + lowercase_manufacturer: str | None = info[ATTR_PROPERTIES][ "manufacturer" ].lower() else: @@ -474,14 +480,14 @@ def info_from_service(service: AsyncServiceInfo) -> HaServiceInfo | None: if (host := _first_non_link_local_or_v6_address(addresses)) is None: return None - return { - "host": str(host), - "port": service.port, - "hostname": service.server, - "type": service.type, - "name": service.name, - "properties": properties, - } + return HaServiceInfo( + host=str(host), + port=service.port, + hostname=service.server, + type=service.type, + name=service.name, + properties=properties, + ) def _first_non_link_local_or_v6_address(addresses: list[bytes]) -> str | None: