Enable strict typing for zeroconf (#48450)
* Enable strict typing for zeroconf * Fix lutron_caseta * Fix pylint warning * Fix tests * Fix xiaomi_aqara test * Add __init__.py in homeassistant.generated module * Restore add_job with type: ignorepull/48520/head
parent
338be8c70b
commit
82c94826fb
|
@ -10,7 +10,6 @@ from pylutron_caseta.smartbridge import Smartbridge
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.zeroconf import ATTR_HOSTNAME
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME
|
||||
from homeassistant.core import callback
|
||||
|
||||
|
@ -66,7 +65,7 @@ class LutronCasetaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_zeroconf(self, discovery_info):
|
||||
"""Handle a flow initialized by zeroconf discovery."""
|
||||
hostname = discovery_info[ATTR_HOSTNAME]
|
||||
hostname = discovery_info["hostname"]
|
||||
if hostname is None or not hostname.startswith("lutron-"):
|
||||
return self.async_abort(reason="not_lutron_device")
|
||||
|
||||
|
|
|
@ -7,16 +7,14 @@ from functools import partial
|
|||
import ipaddress
|
||||
import logging
|
||||
import socket
|
||||
from typing import Any, TypedDict
|
||||
|
||||
import voluptuous as vol
|
||||
from zeroconf import (
|
||||
DNSPointer,
|
||||
DNSRecord,
|
||||
Error as ZeroconfError,
|
||||
InterfaceChoice,
|
||||
IPVersion,
|
||||
NonUniqueNameException,
|
||||
ServiceBrowser,
|
||||
ServiceInfo,
|
||||
ServiceStateChange,
|
||||
Zeroconf,
|
||||
|
@ -24,29 +22,24 @@ from zeroconf import (
|
|||
|
||||
from homeassistant import util
|
||||
from homeassistant.const import (
|
||||
ATTR_NAME,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STARTED,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
__version__,
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.network import NoURLAvailableError, get_url
|
||||
from homeassistant.helpers.singleton import singleton
|
||||
from homeassistant.loader import async_get_homekit, async_get_zeroconf
|
||||
|
||||
from .models import HaServiceBrowser, HaZeroconf
|
||||
from .usage import install_multiple_zeroconf_catcher
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = "zeroconf"
|
||||
|
||||
ATTR_HOST = "host"
|
||||
ATTR_PORT = "port"
|
||||
ATTR_HOSTNAME = "hostname"
|
||||
ATTR_TYPE = "type"
|
||||
ATTR_PROPERTIES = "properties"
|
||||
|
||||
ZEROCONF_TYPE = "_home-assistant._tcp.local."
|
||||
HOMEKIT_TYPES = [
|
||||
"_hap._tcp.local.",
|
||||
|
@ -59,7 +52,6 @@ CONF_IPV6 = "ipv6"
|
|||
DEFAULT_DEFAULT_INTERFACE = True
|
||||
DEFAULT_IPV6 = True
|
||||
|
||||
HOMEKIT_PROPERTIES = "properties"
|
||||
HOMEKIT_PAIRED_STATUS_FLAG = "sf"
|
||||
HOMEKIT_MODEL = "md"
|
||||
|
||||
|
@ -85,20 +77,31 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
)
|
||||
|
||||
|
||||
class HaServiceInfo(TypedDict):
|
||||
"""Prepared info from mDNS entries."""
|
||||
|
||||
host: str
|
||||
port: int | None
|
||||
hostname: str
|
||||
type: str
|
||||
name: str
|
||||
properties: dict[str, Any]
|
||||
|
||||
|
||||
@singleton(DOMAIN)
|
||||
async def async_get_instance(hass):
|
||||
async def async_get_instance(hass: HomeAssistant) -> HaZeroconf:
|
||||
"""Zeroconf instance to be shared with other integrations that use it."""
|
||||
return await _async_get_instance(hass)
|
||||
|
||||
|
||||
async def _async_get_instance(hass, **zcargs):
|
||||
async def _async_get_instance(hass: HomeAssistant, **zcargs: Any) -> HaZeroconf:
|
||||
logging.getLogger("zeroconf").setLevel(logging.NOTSET)
|
||||
|
||||
zeroconf = await hass.async_add_executor_job(partial(HaZeroconf, **zcargs))
|
||||
|
||||
install_multiple_zeroconf_catcher(zeroconf)
|
||||
|
||||
def _stop_zeroconf(_):
|
||||
def _stop_zeroconf(_event: Event) -> None:
|
||||
"""Stop Zeroconf."""
|
||||
zeroconf.ha_close()
|
||||
|
||||
|
@ -107,40 +110,10 @@ async def _async_get_instance(hass, **zcargs):
|
|||
return zeroconf
|
||||
|
||||
|
||||
class HaServiceBrowser(ServiceBrowser):
|
||||
"""ServiceBrowser that only consumes DNSPointer records."""
|
||||
|
||||
def update_record(self, zc: Zeroconf, now: float, record: DNSRecord) -> None:
|
||||
"""Pre-Filter update_record to DNSPointers for the configured type."""
|
||||
|
||||
#
|
||||
# Each ServerBrowser currently runs in its own thread which
|
||||
# processes every A or AAAA record update per instance.
|
||||
#
|
||||
# As the list of zeroconf names we watch for grows, each additional
|
||||
# ServiceBrowser would process all the A and AAAA updates on the network.
|
||||
#
|
||||
# To avoid overwhemling the system we pre-filter here and only process
|
||||
# DNSPointers for the configured record name (type)
|
||||
#
|
||||
if record.name not in self.types or not isinstance(record, DNSPointer):
|
||||
return
|
||||
super().update_record(zc, now, record)
|
||||
|
||||
|
||||
class HaZeroconf(Zeroconf):
|
||||
"""Zeroconf that cannot be closed."""
|
||||
|
||||
def close(self):
|
||||
"""Fake method to avoid integrations closing it."""
|
||||
|
||||
ha_close = Zeroconf.close
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
async def async_setup(hass: HomeAssistant, config: dict) -> bool:
|
||||
"""Set up Zeroconf and make Home Assistant discoverable."""
|
||||
zc_config = config.get(DOMAIN, {})
|
||||
zc_args = {}
|
||||
zc_args: dict = {}
|
||||
if zc_config.get(CONF_DEFAULT_INTERFACE, DEFAULT_DEFAULT_INTERFACE):
|
||||
zc_args["interfaces"] = InterfaceChoice.Default
|
||||
if not zc_config.get(CONF_IPV6, DEFAULT_IPV6):
|
||||
|
@ -148,7 +121,7 @@ async def async_setup(hass, config):
|
|||
|
||||
zeroconf = hass.data[DOMAIN] = await _async_get_instance(hass, **zc_args)
|
||||
|
||||
async def _async_zeroconf_hass_start(_event):
|
||||
async def _async_zeroconf_hass_start(_event: Event) -> None:
|
||||
"""Expose Home Assistant on zeroconf when it starts.
|
||||
|
||||
Wait till started or otherwise HTTP is not up and running.
|
||||
|
@ -158,7 +131,7 @@ async def async_setup(hass, config):
|
|||
_register_hass_zc_service, hass, zeroconf, uuid
|
||||
)
|
||||
|
||||
async def _async_zeroconf_hass_started(_event):
|
||||
async def _async_zeroconf_hass_started(_event: Event) -> None:
|
||||
"""Start the service browser."""
|
||||
|
||||
await _async_start_zeroconf_browser(hass, zeroconf)
|
||||
|
@ -171,7 +144,9 @@ async def async_setup(hass, config):
|
|||
return True
|
||||
|
||||
|
||||
def _register_hass_zc_service(hass, zeroconf, uuid):
|
||||
def _register_hass_zc_service(
|
||||
hass: HomeAssistant, zeroconf: HaZeroconf, uuid: str
|
||||
) -> None:
|
||||
# Get instance UUID
|
||||
valid_location_name = _truncate_location_name_to_valid(hass.config.location_name)
|
||||
|
||||
|
@ -224,7 +199,9 @@ def _register_hass_zc_service(hass, zeroconf, uuid):
|
|||
)
|
||||
|
||||
|
||||
async def _async_start_zeroconf_browser(hass, zeroconf):
|
||||
async def _async_start_zeroconf_browser(
|
||||
hass: HomeAssistant, zeroconf: HaZeroconf
|
||||
) -> None:
|
||||
"""Start the zeroconf browser."""
|
||||
|
||||
zeroconf_types = await async_get_zeroconf(hass)
|
||||
|
@ -236,7 +213,12 @@ async def _async_start_zeroconf_browser(hass, zeroconf):
|
|||
if hk_type not in zeroconf_types:
|
||||
types.append(hk_type)
|
||||
|
||||
def service_update(zeroconf, service_type, name, state_change):
|
||||
def service_update(
|
||||
zeroconf: Zeroconf,
|
||||
service_type: str,
|
||||
name: str,
|
||||
state_change: ServiceStateChange,
|
||||
) -> None:
|
||||
"""Service state changed."""
|
||||
nonlocal zeroconf_types
|
||||
nonlocal homekit_models
|
||||
|
@ -276,12 +258,11 @@ async def _async_start_zeroconf_browser(hass, zeroconf):
|
|||
# offering a second discovery for the same device
|
||||
if (
|
||||
discovery_was_forwarded
|
||||
and HOMEKIT_PROPERTIES in info
|
||||
and HOMEKIT_PAIRED_STATUS_FLAG in info[HOMEKIT_PROPERTIES]
|
||||
and HOMEKIT_PAIRED_STATUS_FLAG in info["properties"]
|
||||
):
|
||||
try:
|
||||
# 0 means paired and not discoverable by iOS clients)
|
||||
if int(info[HOMEKIT_PROPERTIES][HOMEKIT_PAIRED_STATUS_FLAG]):
|
||||
if int(info["properties"][HOMEKIT_PAIRED_STATUS_FLAG]):
|
||||
return
|
||||
except ValueError:
|
||||
# HomeKit pairing status unknown
|
||||
|
@ -289,12 +270,12 @@ async def _async_start_zeroconf_browser(hass, zeroconf):
|
|||
return
|
||||
|
||||
if "name" in info:
|
||||
lowercase_name = info["name"].lower()
|
||||
lowercase_name: str | None = info["name"].lower()
|
||||
else:
|
||||
lowercase_name = None
|
||||
|
||||
if "macaddress" in info.get("properties", {}):
|
||||
uppercase_mac = info["properties"]["macaddress"].upper()
|
||||
if "macaddress" in info["properties"]:
|
||||
uppercase_mac: str | None = info["properties"]["macaddress"].upper()
|
||||
else:
|
||||
uppercase_mac = None
|
||||
|
||||
|
@ -318,20 +299,22 @@ async def _async_start_zeroconf_browser(hass, zeroconf):
|
|||
hass.add_job(
|
||||
hass.config_entries.flow.async_init(
|
||||
entry["domain"], context={"source": DOMAIN}, data=info
|
||||
)
|
||||
) # type: ignore
|
||||
)
|
||||
|
||||
_LOGGER.debug("Starting Zeroconf browser")
|
||||
HaServiceBrowser(zeroconf, types, handlers=[service_update])
|
||||
|
||||
|
||||
def handle_homekit(hass, homekit_models, info) -> bool:
|
||||
def handle_homekit(
|
||||
hass: HomeAssistant, homekit_models: dict[str, str], info: HaServiceInfo
|
||||
) -> bool:
|
||||
"""Handle a HomeKit discovery.
|
||||
|
||||
Return if discovery was forwarded.
|
||||
"""
|
||||
model = None
|
||||
props = info.get(HOMEKIT_PROPERTIES, {})
|
||||
props = info["properties"]
|
||||
|
||||
for key in props:
|
||||
if key.lower() == HOMEKIT_MODEL:
|
||||
|
@ -352,16 +335,16 @@ def handle_homekit(hass, homekit_models, info) -> bool:
|
|||
hass.add_job(
|
||||
hass.config_entries.flow.async_init(
|
||||
homekit_models[test_model], context={"source": "homekit"}, data=info
|
||||
)
|
||||
) # type: ignore
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def info_from_service(service):
|
||||
def info_from_service(service: ServiceInfo) -> HaServiceInfo | None:
|
||||
"""Return prepared info from mDNS entries."""
|
||||
properties = {"_raw": {}}
|
||||
properties: dict[str, Any] = {"_raw": {}}
|
||||
|
||||
for key, value in service.properties.items():
|
||||
# See https://ietf.org/rfc/rfc6763.html#section-6.4 and
|
||||
|
@ -386,19 +369,17 @@ def info_from_service(service):
|
|||
|
||||
address = service.addresses[0]
|
||||
|
||||
info = {
|
||||
ATTR_HOST: str(ipaddress.ip_address(address)),
|
||||
ATTR_PORT: service.port,
|
||||
ATTR_HOSTNAME: service.server,
|
||||
ATTR_TYPE: service.type,
|
||||
ATTR_NAME: service.name,
|
||||
ATTR_PROPERTIES: properties,
|
||||
return {
|
||||
"host": str(ipaddress.ip_address(address)),
|
||||
"port": service.port,
|
||||
"hostname": service.server,
|
||||
"type": service.type,
|
||||
"name": service.name,
|
||||
"properties": properties,
|
||||
}
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def _suppress_invalid_properties(properties):
|
||||
def _suppress_invalid_properties(properties: dict) -> None:
|
||||
"""Suppress any properties that will cause zeroconf to fail to startup."""
|
||||
|
||||
for prop, prop_value in properties.items():
|
||||
|
@ -415,7 +396,7 @@ def _suppress_invalid_properties(properties):
|
|||
properties[prop] = ""
|
||||
|
||||
|
||||
def _truncate_location_name_to_valid(location_name):
|
||||
def _truncate_location_name_to_valid(location_name: str) -> str:
|
||||
"""Truncate or return the location name usable for zeroconf."""
|
||||
if len(location_name.encode("utf-8")) < MAX_NAME_LEN:
|
||||
return location_name
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
"""Models for Zeroconf."""
|
||||
|
||||
from zeroconf import DNSPointer, DNSRecord, ServiceBrowser, Zeroconf
|
||||
|
||||
|
||||
class HaZeroconf(Zeroconf):
|
||||
"""Zeroconf that cannot be closed."""
|
||||
|
||||
def close(self) -> None:
|
||||
"""Fake method to avoid integrations closing it."""
|
||||
|
||||
ha_close = Zeroconf.close
|
||||
|
||||
|
||||
class HaServiceBrowser(ServiceBrowser):
|
||||
"""ServiceBrowser that only consumes DNSPointer records."""
|
||||
|
||||
def update_record(self, zc: Zeroconf, now: float, record: DNSRecord) -> None:
|
||||
"""Pre-Filter update_record to DNSPointers for the configured type."""
|
||||
|
||||
#
|
||||
# Each ServerBrowser currently runs in its own thread which
|
||||
# processes every A or AAAA record update per instance.
|
||||
#
|
||||
# As the list of zeroconf names we watch for grows, each additional
|
||||
# ServiceBrowser would process all the A and AAAA updates on the network.
|
||||
#
|
||||
# To avoid overwhemling the system we pre-filter here and only process
|
||||
# DNSPointers for the configured record name (type)
|
||||
#
|
||||
if record.name not in self.types or not isinstance(record, DNSPointer):
|
||||
return
|
||||
super().update_record(zc, now, record)
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from contextlib import suppress
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
import zeroconf
|
||||
|
||||
|
@ -11,23 +12,25 @@ from homeassistant.helpers.frame import (
|
|||
report_integration,
|
||||
)
|
||||
|
||||
from .models import HaZeroconf
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def install_multiple_zeroconf_catcher(hass_zc) -> None:
|
||||
def install_multiple_zeroconf_catcher(hass_zc: HaZeroconf) -> None:
|
||||
"""Wrap the Zeroconf class to return the shared instance if multiple instances are detected."""
|
||||
|
||||
def new_zeroconf_new(self, *k, **kw):
|
||||
def new_zeroconf_new(self: zeroconf.Zeroconf, *k: Any, **kw: Any) -> HaZeroconf:
|
||||
_report(
|
||||
"attempted to create another Zeroconf instance. Please use the shared Zeroconf via await homeassistant.components.zeroconf.async_get_instance(hass)",
|
||||
)
|
||||
return hass_zc
|
||||
|
||||
def new_zeroconf_init(self, *k, **kw):
|
||||
def new_zeroconf_init(self: zeroconf.Zeroconf, *k: Any, **kw: Any) -> None:
|
||||
return
|
||||
|
||||
zeroconf.Zeroconf.__new__ = new_zeroconf_new
|
||||
zeroconf.Zeroconf.__init__ = new_zeroconf_init
|
||||
zeroconf.Zeroconf.__new__ = new_zeroconf_new # type: ignore
|
||||
zeroconf.Zeroconf.__init__ = new_zeroconf_init # type: ignore
|
||||
|
||||
|
||||
def _report(what: str) -> None:
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
"""All files in this module are automatically generated by hassfest.
|
||||
|
||||
To update, run python3 -m script.hassfest
|
||||
"""
|
|
@ -43,7 +43,7 @@ warn_redundant_casts = true
|
|||
warn_unused_configs = true
|
||||
|
||||
|
||||
[mypy-homeassistant.block_async_io,homeassistant.bootstrap,homeassistant.components,homeassistant.config_entries,homeassistant.config,homeassistant.const,homeassistant.core,homeassistant.data_entry_flow,homeassistant.exceptions,homeassistant.__init__,homeassistant.loader,homeassistant.__main__,homeassistant.requirements,homeassistant.runner,homeassistant.setup,homeassistant.util,homeassistant.auth.*,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.bond.*,homeassistant.components.calendar.*,homeassistant.components.cover.*,homeassistant.components.device_automation.*,homeassistant.components.frontend.*,homeassistant.components.geo_location.*,homeassistant.components.group.*,homeassistant.components.history.*,homeassistant.components.http.*,homeassistant.components.huawei_lte.*,homeassistant.components.hyperion.*,homeassistant.components.image_processing.*,homeassistant.components.integration.*,homeassistant.components.knx.*,homeassistant.components.light.*,homeassistant.components.lock.*,homeassistant.components.mailbox.*,homeassistant.components.media_player.*,homeassistant.components.notify.*,homeassistant.components.number.*,homeassistant.components.persistent_notification.*,homeassistant.components.proximity.*,homeassistant.components.recorder.purge,homeassistant.components.recorder.repack,homeassistant.components.remote.*,homeassistant.components.scene.*,homeassistant.components.sensor.*,homeassistant.components.slack.*,homeassistant.components.sun.*,homeassistant.components.switch.*,homeassistant.components.systemmonitor.*,homeassistant.components.tts.*,homeassistant.components.vacuum.*,homeassistant.components.water_heater.*,homeassistant.components.weather.*,homeassistant.components.websocket_api.*,homeassistant.components.zone.*,homeassistant.components.zwave_js.*,homeassistant.helpers.*,homeassistant.scripts.*,homeassistant.util.*,tests.components.hyperion.*]
|
||||
[mypy-homeassistant.block_async_io,homeassistant.bootstrap,homeassistant.components,homeassistant.config_entries,homeassistant.config,homeassistant.const,homeassistant.core,homeassistant.data_entry_flow,homeassistant.exceptions,homeassistant.__init__,homeassistant.loader,homeassistant.__main__,homeassistant.requirements,homeassistant.runner,homeassistant.setup,homeassistant.util,homeassistant.auth.*,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.bond.*,homeassistant.components.calendar.*,homeassistant.components.cover.*,homeassistant.components.device_automation.*,homeassistant.components.frontend.*,homeassistant.components.geo_location.*,homeassistant.components.group.*,homeassistant.components.history.*,homeassistant.components.http.*,homeassistant.components.huawei_lte.*,homeassistant.components.hyperion.*,homeassistant.components.image_processing.*,homeassistant.components.integration.*,homeassistant.components.knx.*,homeassistant.components.light.*,homeassistant.components.lock.*,homeassistant.components.mailbox.*,homeassistant.components.media_player.*,homeassistant.components.notify.*,homeassistant.components.number.*,homeassistant.components.persistent_notification.*,homeassistant.components.proximity.*,homeassistant.components.recorder.purge,homeassistant.components.recorder.repack,homeassistant.components.remote.*,homeassistant.components.scene.*,homeassistant.components.sensor.*,homeassistant.components.slack.*,homeassistant.components.sun.*,homeassistant.components.switch.*,homeassistant.components.systemmonitor.*,homeassistant.components.tts.*,homeassistant.components.vacuum.*,homeassistant.components.water_heater.*,homeassistant.components.weather.*,homeassistant.components.websocket_api.*,homeassistant.components.zeroconf.*,homeassistant.components.zone.*,homeassistant.components.zwave_js.*,homeassistant.helpers.*,homeassistant.scripts.*,homeassistant.util.*,tests.components.hyperion.*]
|
||||
strict = true
|
||||
ignore_errors = false
|
||||
warn_unreachable = true
|
||||
|
|
|
@ -17,11 +17,12 @@ from homeassistant.components.lutron_caseta.const import (
|
|||
ERROR_CANNOT_CONNECT,
|
||||
STEP_IMPORT_FAILED,
|
||||
)
|
||||
from homeassistant.components.zeroconf import ATTR_HOSTNAME
|
||||
from homeassistant.const import CONF_HOST
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
ATTR_HOSTNAME = "hostname"
|
||||
|
||||
EMPTY_MOCK_CONFIG_ENTRY = {
|
||||
CONF_HOST: "",
|
||||
CONF_KEYFILE: "",
|
||||
|
|
|
@ -5,7 +5,6 @@ from unittest.mock import Mock, patch
|
|||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.components.xiaomi_aqara import config_flow, const
|
||||
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME, CONF_PORT, CONF_PROTOCOL
|
||||
|
||||
|
@ -402,7 +401,7 @@ async def test_zeroconf_success(hass):
|
|||
const.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data={
|
||||
zeroconf.ATTR_HOST: TEST_HOST,
|
||||
CONF_HOST: TEST_HOST,
|
||||
ZEROCONF_NAME: TEST_ZEROCONF_NAME,
|
||||
ZEROCONF_PROP: {ZEROCONF_MAC: TEST_MAC},
|
||||
},
|
||||
|
@ -444,7 +443,7 @@ async def test_zeroconf_missing_data(hass):
|
|||
result = await hass.config_entries.flow.async_init(
|
||||
const.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data={zeroconf.ATTR_HOST: TEST_HOST, ZEROCONF_NAME: TEST_ZEROCONF_NAME},
|
||||
data={CONF_HOST: TEST_HOST, ZEROCONF_NAME: TEST_ZEROCONF_NAME},
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
|
@ -457,7 +456,7 @@ async def test_zeroconf_unknown_device(hass):
|
|||
const.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data={
|
||||
zeroconf.ATTR_HOST: TEST_HOST,
|
||||
CONF_HOST: TEST_HOST,
|
||||
ZEROCONF_NAME: "not-a-xiaomi-aqara-gateway",
|
||||
ZEROCONF_PROP: {ZEROCONF_MAC: TEST_MAC},
|
||||
},
|
||||
|
|
|
@ -4,7 +4,6 @@ from unittest.mock import Mock, patch
|
|||
from miio import DeviceException
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.components.xiaomi_miio import const
|
||||
from homeassistant.components.xiaomi_miio.config_flow import DEFAULT_GATEWAY_NAME
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TOKEN
|
||||
|
@ -106,7 +105,7 @@ async def test_zeroconf_gateway_success(hass):
|
|||
const.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data={
|
||||
zeroconf.ATTR_HOST: TEST_HOST,
|
||||
CONF_HOST: TEST_HOST,
|
||||
ZEROCONF_NAME: TEST_ZEROCONF_NAME,
|
||||
ZEROCONF_PROP: {ZEROCONF_MAC: TEST_MAC},
|
||||
},
|
||||
|
@ -146,7 +145,7 @@ async def test_zeroconf_unknown_device(hass):
|
|||
const.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data={
|
||||
zeroconf.ATTR_HOST: TEST_HOST,
|
||||
CONF_HOST: TEST_HOST,
|
||||
ZEROCONF_NAME: "not-a-xiaomi-miio-device",
|
||||
ZEROCONF_PROP: {ZEROCONF_MAC: TEST_MAC},
|
||||
},
|
||||
|
@ -171,7 +170,7 @@ async def test_zeroconf_missing_data(hass):
|
|||
result = await hass.config_entries.flow.async_init(
|
||||
const.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data={zeroconf.ATTR_HOST: TEST_HOST, ZEROCONF_NAME: TEST_ZEROCONF_NAME},
|
||||
data={CONF_HOST: TEST_HOST, ZEROCONF_NAME: TEST_ZEROCONF_NAME},
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
|
@ -342,7 +341,7 @@ async def zeroconf_device_success(hass, zeroconf_name_to_test, model_to_test):
|
|||
const.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data={
|
||||
zeroconf.ATTR_HOST: TEST_HOST,
|
||||
CONF_HOST: TEST_HOST,
|
||||
ZEROCONF_NAME: zeroconf_name_to_test,
|
||||
ZEROCONF_PROP: {"poch": f"0:mac={TEST_MAC_DEVICE}\x00"},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue