mirror of
https://github.com/home-assistant/core.git
synced 2025-08-04 13:15:18 +02:00
Merge pull request #68493 from home-assistant/rc
This commit is contained in:
@@ -149,9 +149,19 @@ def _async_register_mac(
|
||||
return
|
||||
|
||||
# Make sure entity has a config entry and was disabled by the
|
||||
# default disable logic in the integration.
|
||||
# default disable logic in the integration and new entities
|
||||
# are allowed to be added.
|
||||
if (
|
||||
entity_entry.config_entry_id is None
|
||||
or (
|
||||
(
|
||||
config_entry := hass.config_entries.async_get_entry(
|
||||
entity_entry.config_entry_id
|
||||
)
|
||||
)
|
||||
is not None
|
||||
and config_entry.pref_disable_new_entities
|
||||
)
|
||||
or entity_entry.disabled_by != er.RegistryEntryDisabler.INTEGRATION
|
||||
):
|
||||
return
|
||||
|
@@ -16,6 +16,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.httpx_client import get_async_client
|
||||
from homeassistant.util.network import is_ipv4_address
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
@@ -86,6 +87,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
self, discovery_info: zeroconf.ZeroconfServiceInfo
|
||||
) -> FlowResult:
|
||||
"""Handle a flow initialized by zeroconf discovery."""
|
||||
if not is_ipv4_address(discovery_info.host):
|
||||
return self.async_abort(reason="not_ipv4_address")
|
||||
serial = discovery_info.properties["serialnum"]
|
||||
await self.async_set_unique_id(serial)
|
||||
self.ip_address = discovery_info.host
|
||||
|
@@ -2,7 +2,8 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Device is already configured",
|
||||
"reauth_successful": "Re-authentication was successful"
|
||||
"reauth_successful": "Re-authentication was successful",
|
||||
"not_ipv4_address": "Only IPv4 addresess are supported"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Failed to connect",
|
||||
|
@@ -6,6 +6,7 @@ import logging
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import aiohttp
|
||||
from aiohue import LinkButtonNotPressed, create_app_key
|
||||
from aiohue.discovery import DiscoveredHueBridge, discover_bridge, discover_nupnp
|
||||
from aiohue.util import normalize_bridge_id
|
||||
@@ -70,9 +71,12 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
self, host: str, bridge_id: str | None = None
|
||||
) -> DiscoveredHueBridge:
|
||||
"""Return a DiscoveredHueBridge object."""
|
||||
bridge = await discover_bridge(
|
||||
host, websession=aiohttp_client.async_get_clientsession(self.hass)
|
||||
)
|
||||
try:
|
||||
bridge = await discover_bridge(
|
||||
host, websession=aiohttp_client.async_get_clientsession(self.hass)
|
||||
)
|
||||
except aiohttp.ClientError:
|
||||
return None
|
||||
if bridge_id is not None:
|
||||
bridge_id = normalize_bridge_id(bridge_id)
|
||||
assert bridge_id == bridge.id
|
||||
|
@@ -42,6 +42,14 @@ ALLOWED_ERRORS = [
|
||||
'device (groupedLight) is "soft off", command (on) may not have effect',
|
||||
"device (light) has communication issues, command (on) may not have effect",
|
||||
'device (light) is "soft off", command (on) may not have effect',
|
||||
"device (grouped_light) has communication issues, command (.on) may not have effect",
|
||||
'device (grouped_light) is "soft off", command (.on) may not have effect'
|
||||
"device (grouped_light) has communication issues, command (.on.on) may not have effect",
|
||||
'device (grouped_light) is "soft off", command (.on.on) may not have effect'
|
||||
"device (light) has communication issues, command (.on) may not have effect",
|
||||
'device (light) is "soft off", command (.on) may not have effect',
|
||||
"device (light) has communication issues, command (.on.on) may not have effect",
|
||||
'device (light) is "soft off", command (.on.on) may not have effect',
|
||||
]
|
||||
|
||||
|
||||
|
@@ -39,6 +39,10 @@ from .helpers import (
|
||||
ALLOWED_ERRORS = [
|
||||
"device (light) has communication issues, command (on) may not have effect",
|
||||
'device (light) is "soft off", command (on) may not have effect',
|
||||
"device (light) has communication issues, command (.on) may not have effect",
|
||||
'device (light) is "soft off", command (.on) may not have effect',
|
||||
"device (light) has communication issues, command (.on.on) may not have effect",
|
||||
'device (light) is "soft off", command (.on.on) may not have effect',
|
||||
]
|
||||
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
"""Support for Honeywell Lyric climate platform."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from time import localtime, strftime, time
|
||||
|
||||
@@ -22,6 +23,7 @@ from homeassistant.components.climate.const import (
|
||||
HVAC_MODE_OFF,
|
||||
SUPPORT_PRESET_MODE,
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
SUPPORT_TARGET_TEMPERATURE_RANGE,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_TEMPERATURE
|
||||
@@ -45,7 +47,11 @@ from .const import (
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
|
||||
# Only LCC models support presets
|
||||
SUPPORT_FLAGS_LCC = (
|
||||
SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE | SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||
)
|
||||
SUPPORT_FLAGS_TCC = SUPPORT_TARGET_TEMPERATURE | SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||
|
||||
LYRIC_HVAC_ACTION_OFF = "EquipmentOff"
|
||||
LYRIC_HVAC_ACTION_HEAT = "Heat"
|
||||
@@ -166,7 +172,11 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
@property
|
||||
def supported_features(self) -> int:
|
||||
"""Return the list of supported features."""
|
||||
return SUPPORT_FLAGS
|
||||
if self.device.changeableValues.thermostatSetpointStatus:
|
||||
support_flags = SUPPORT_FLAGS_LCC
|
||||
else:
|
||||
support_flags = SUPPORT_FLAGS_TCC
|
||||
return support_flags
|
||||
|
||||
@property
|
||||
def temperature_unit(self) -> str:
|
||||
@@ -200,25 +210,28 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
def target_temperature(self) -> float | None:
|
||||
"""Return the temperature we try to reach."""
|
||||
device = self.device
|
||||
if not device.hasDualSetpointStatus:
|
||||
if (
|
||||
not device.changeableValues.autoChangeoverActive
|
||||
and HVAC_MODES[device.changeableValues.mode] != HVAC_MODE_OFF
|
||||
):
|
||||
if self.hvac_mode == HVAC_MODE_COOL:
|
||||
return device.changeableValues.coolSetpoint
|
||||
return device.changeableValues.heatSetpoint
|
||||
return None
|
||||
|
||||
@property
|
||||
def target_temperature_low(self) -> float | None:
|
||||
"""Return the upper bound temperature we try to reach."""
|
||||
def target_temperature_high(self) -> float | None:
|
||||
"""Return the highbound target temperature we try to reach."""
|
||||
device = self.device
|
||||
if device.hasDualSetpointStatus:
|
||||
if device.changeableValues.autoChangeoverActive:
|
||||
return device.changeableValues.coolSetpoint
|
||||
return None
|
||||
|
||||
@property
|
||||
def target_temperature_high(self) -> float | None:
|
||||
"""Return the upper bound temperature we try to reach."""
|
||||
def target_temperature_low(self) -> float | None:
|
||||
"""Return the lowbound target temperature we try to reach."""
|
||||
device = self.device
|
||||
if device.hasDualSetpointStatus:
|
||||
if device.changeableValues.autoChangeoverActive:
|
||||
return device.changeableValues.heatSetpoint
|
||||
return None
|
||||
|
||||
@@ -256,11 +269,11 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
|
||||
async def async_set_temperature(self, **kwargs) -> None:
|
||||
"""Set new target temperature."""
|
||||
device = self.device
|
||||
target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
|
||||
target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
|
||||
|
||||
device = self.device
|
||||
if device.hasDualSetpointStatus:
|
||||
if device.changeableValues.autoChangeoverActive:
|
||||
if target_temp_low is None or target_temp_high is None:
|
||||
raise HomeAssistantError(
|
||||
"Could not find target_temp_low and/or target_temp_high in arguments"
|
||||
@@ -270,11 +283,13 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
await self._update_thermostat(
|
||||
self.location,
|
||||
device,
|
||||
coolSetpoint=target_temp_low,
|
||||
heatSetpoint=target_temp_high,
|
||||
coolSetpoint=target_temp_high,
|
||||
heatSetpoint=target_temp_low,
|
||||
mode=HVAC_MODES[device.changeableValues.heatCoolMode],
|
||||
)
|
||||
except LYRIC_EXCEPTIONS as exception:
|
||||
_LOGGER.error(exception)
|
||||
await self.coordinator.async_refresh()
|
||||
else:
|
||||
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||
_LOGGER.debug("Set temperature: %s", temp)
|
||||
@@ -289,15 +304,58 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||
)
|
||||
except LYRIC_EXCEPTIONS as exception:
|
||||
_LOGGER.error(exception)
|
||||
await self.coordinator.async_refresh()
|
||||
await self.coordinator.async_refresh()
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: str) -> None:
|
||||
"""Set hvac mode."""
|
||||
_LOGGER.debug("Set hvac mode: %s", hvac_mode)
|
||||
_LOGGER.debug("HVAC mode: %s", hvac_mode)
|
||||
try:
|
||||
await self._update_thermostat(
|
||||
self.location, self.device, mode=LYRIC_HVAC_MODES[hvac_mode]
|
||||
)
|
||||
if LYRIC_HVAC_MODES[hvac_mode] == LYRIC_HVAC_MODE_HEAT_COOL:
|
||||
# If the system is off, turn it to Heat first then to Auto, otherwise it turns to
|
||||
# Auto briefly and then reverts to Off (perhaps related to heatCoolMode). This is the
|
||||
# behavior that happens with the native app as well, so likely a bug in the api itself
|
||||
|
||||
if HVAC_MODES[self.device.changeableValues.mode] == HVAC_MODE_OFF:
|
||||
_LOGGER.debug(
|
||||
"HVAC mode passed to lyric: %s",
|
||||
HVAC_MODES[LYRIC_HVAC_MODE_COOL],
|
||||
)
|
||||
await self._update_thermostat(
|
||||
self.location,
|
||||
self.device,
|
||||
mode=HVAC_MODES[LYRIC_HVAC_MODE_HEAT],
|
||||
autoChangeoverActive=False,
|
||||
)
|
||||
# Sleep 3 seconds before proceeding
|
||||
await asyncio.sleep(3)
|
||||
_LOGGER.debug(
|
||||
"HVAC mode passed to lyric: %s",
|
||||
HVAC_MODES[LYRIC_HVAC_MODE_HEAT],
|
||||
)
|
||||
await self._update_thermostat(
|
||||
self.location,
|
||||
self.device,
|
||||
mode=HVAC_MODES[LYRIC_HVAC_MODE_HEAT],
|
||||
autoChangeoverActive=True,
|
||||
)
|
||||
else:
|
||||
_LOGGER.debug(
|
||||
"HVAC mode passed to lyric: %s",
|
||||
HVAC_MODES[self.device.changeableValues.mode],
|
||||
)
|
||||
await self._update_thermostat(
|
||||
self.location, self.device, autoChangeoverActive=True
|
||||
)
|
||||
else:
|
||||
_LOGGER.debug(
|
||||
"HVAC mode passed to lyric: %s", LYRIC_HVAC_MODES[hvac_mode]
|
||||
)
|
||||
await self._update_thermostat(
|
||||
self.location,
|
||||
self.device,
|
||||
mode=LYRIC_HVAC_MODES[hvac_mode],
|
||||
autoChangeoverActive=False,
|
||||
)
|
||||
except LYRIC_EXCEPTIONS as exception:
|
||||
_LOGGER.error(exception)
|
||||
await self.coordinator.async_refresh()
|
||||
|
@@ -243,7 +243,10 @@ class MatrixBot:
|
||||
room.update_aliases()
|
||||
self._aliases_fetched_for.add(room.room_id)
|
||||
|
||||
if room_id_or_alias in room.aliases:
|
||||
if (
|
||||
room_id_or_alias in room.aliases
|
||||
or room_id_or_alias == room.canonical_alias
|
||||
):
|
||||
_LOGGER.debug(
|
||||
"Already in room %s (known as %s)", room.room_id, room_id_or_alias
|
||||
)
|
||||
|
@@ -43,7 +43,7 @@ async def async_setup_platform(
|
||||
station_id = config[CONF_STATION_ID]
|
||||
|
||||
session = async_get_clientsession(hass)
|
||||
osm_api = OpenSenseMapData(OpenSenseMap(station_id, hass.loop, session))
|
||||
osm_api = OpenSenseMapData(OpenSenseMap(station_id, session))
|
||||
|
||||
await osm_api.async_update()
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"domain": "opensensemap",
|
||||
"name": "openSenseMap",
|
||||
"documentation": "https://www.home-assistant.io/integrations/opensensemap",
|
||||
"requirements": ["opensensemap-api==0.1.5"],
|
||||
"requirements": ["opensensemap-api==0.2.0"],
|
||||
"codeowners": [],
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["opensensemap_api"]
|
||||
|
@@ -97,6 +97,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
token_saver=token_saver,
|
||||
)
|
||||
try:
|
||||
# pylint: disable-next=fixme
|
||||
# TODO Remove authlib constraint when refactoring this code
|
||||
await session.ensure_active_token()
|
||||
except ConnectTimeout as err:
|
||||
_LOGGER.debug("Connection Timeout")
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/renault",
|
||||
"requirements": [
|
||||
"renault-api==0.1.9"
|
||||
"renault-api==0.1.10"
|
||||
],
|
||||
"codeowners": [
|
||||
"@epenet"
|
||||
|
@@ -319,8 +319,9 @@ class SamsungTVWSBridge(SamsungTVBridge):
|
||||
def _get_app_list(self) -> dict[str, str] | None:
|
||||
"""Get installed app list."""
|
||||
if self._app_list is None and (remote := self._get_remote()):
|
||||
with contextlib.suppress(WebSocketTimeoutException):
|
||||
with contextlib.suppress(TypeError, WebSocketTimeoutException):
|
||||
raw_app_list: list[dict[str, str]] = remote.app_list()
|
||||
LOGGER.debug("Received app list: %s", raw_app_list)
|
||||
self._app_list = {
|
||||
app["name"]: app["appId"]
|
||||
for app in sorted(raw_app_list, key=lambda app: app["name"])
|
||||
|
@@ -88,7 +88,10 @@ class TPLinkSmartBulb(CoordinatedTPLinkEntity, LightEntity):
|
||||
|
||||
# Handle turning to temp mode
|
||||
if ATTR_COLOR_TEMP in kwargs:
|
||||
color_tmp = mired_to_kelvin(int(kwargs[ATTR_COLOR_TEMP]))
|
||||
# Handle temp conversion mireds -> kelvin being slightly outside of valid range
|
||||
kelvin = mired_to_kelvin(int(kwargs[ATTR_COLOR_TEMP]))
|
||||
kelvin_range = self.device.valid_temperature_range
|
||||
color_tmp = max(kelvin_range.min, min(kelvin_range.max, kelvin))
|
||||
_LOGGER.debug("Changing color temp to %s", color_tmp)
|
||||
await self.device.set_color_temp(
|
||||
color_tmp, brightness=brightness, transition=transition
|
||||
|
@@ -78,4 +78,4 @@ class VelbusCover(VelbusEntity, CoverEntity):
|
||||
|
||||
async def async_set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Move the cover to a specific position."""
|
||||
self._channel.set_position(100 - kwargs[ATTR_POSITION])
|
||||
await self._channel.set_position(100 - kwargs[ATTR_POSITION])
|
||||
|
@@ -7,7 +7,7 @@ from .backports.enum import StrEnum
|
||||
|
||||
MAJOR_VERSION: Final = 2022
|
||||
MINOR_VERSION: Final = 3
|
||||
PATCH_VERSION: Final = "5"
|
||||
PATCH_VERSION: Final = "6"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
|
||||
|
@@ -95,3 +95,7 @@ python-socketio>=4.6.0,<5.0
|
||||
# Constrain multidict to avoid typing issues
|
||||
# https://github.com/home-assistant/core/pull/67046
|
||||
multidict>=6.0.2
|
||||
|
||||
# Required for compatibility with point integration - ensure_active_token
|
||||
# https://github.com/home-assistant/core/pull/68176
|
||||
authlib<1.0
|
||||
|
@@ -1180,7 +1180,7 @@ openevsewifi==1.1.0
|
||||
openhomedevice==2.0.1
|
||||
|
||||
# homeassistant.components.opensensemap
|
||||
opensensemap-api==0.1.5
|
||||
opensensemap-api==0.2.0
|
||||
|
||||
# homeassistant.components.enigma2
|
||||
openwebifpy==3.2.7
|
||||
@@ -2097,7 +2097,7 @@ raspyrfm-client==1.2.8
|
||||
regenmaschine==2022.01.0
|
||||
|
||||
# homeassistant.components.renault
|
||||
renault-api==0.1.9
|
||||
renault-api==0.1.10
|
||||
|
||||
# homeassistant.components.python_script
|
||||
restrictedpython==5.2
|
||||
|
@@ -1301,7 +1301,7 @@ radios==0.1.1
|
||||
regenmaschine==2022.01.0
|
||||
|
||||
# homeassistant.components.renault
|
||||
renault-api==0.1.9
|
||||
renault-api==0.1.10
|
||||
|
||||
# homeassistant.components.python_script
|
||||
restrictedpython==5.2
|
||||
|
@@ -124,6 +124,10 @@ python-socketio>=4.6.0,<5.0
|
||||
# Constrain multidict to avoid typing issues
|
||||
# https://github.com/home-assistant/core/pull/67046
|
||||
multidict>=6.0.2
|
||||
|
||||
# Required for compatibility with point integration - ensure_active_token
|
||||
# https://github.com/home-assistant/core/pull/68176
|
||||
authlib<1.0
|
||||
"""
|
||||
|
||||
IGNORE_PRE_COMMIT_HOOK_ID = (
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = homeassistant
|
||||
version = 2022.3.5
|
||||
version = 2022.3.6
|
||||
author = The Home Assistant Authors
|
||||
author_email = hello@home-assistant.io
|
||||
license = Apache-2.0
|
||||
|
@@ -137,6 +137,39 @@ async def test_register_mac(hass):
|
||||
assert entity_entry_1.disabled_by is None
|
||||
|
||||
|
||||
async def test_register_mac_ignored(hass):
|
||||
"""Test ignoring registering a mac."""
|
||||
dev_reg = dr.async_get(hass)
|
||||
ent_reg = er.async_get(hass)
|
||||
|
||||
config_entry = MockConfigEntry(domain="test", pref_disable_new_entities=True)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
mac1 = "12:34:56:AB:CD:EF"
|
||||
|
||||
entity_entry_1 = ent_reg.async_get_or_create(
|
||||
"device_tracker",
|
||||
"test",
|
||||
mac1 + "yo1",
|
||||
original_name="name 1",
|
||||
config_entry=config_entry,
|
||||
disabled_by=er.RegistryEntryDisabler.INTEGRATION,
|
||||
)
|
||||
|
||||
ce._async_register_mac(hass, "test", mac1, mac1 + "yo1")
|
||||
|
||||
dev_reg.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, mac1)},
|
||||
)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_entry_1 = ent_reg.async_get(entity_entry_1.entity_id)
|
||||
|
||||
assert entity_entry_1.disabled_by == er.RegistryEntryDisabler.INTEGRATION
|
||||
|
||||
|
||||
async def test_connected_device_registered(hass):
|
||||
"""Test dispatch on connected device being registered."""
|
||||
|
||||
|
@@ -6,6 +6,7 @@ import httpx
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.components.enphase_envoy.const import DOMAIN
|
||||
from homeassistant.const import CONF_HOST
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
@@ -312,8 +313,8 @@ async def test_zeroconf_serial_already_exists(hass: HomeAssistant) -> None:
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data=zeroconf.ZeroconfServiceInfo(
|
||||
host="1.1.1.1",
|
||||
addresses=["1.1.1.1"],
|
||||
host="4.4.4.4",
|
||||
addresses=["4.4.4.4"],
|
||||
hostname="mock_hostname",
|
||||
name="mock_name",
|
||||
port=None,
|
||||
@@ -324,6 +325,42 @@ async def test_zeroconf_serial_already_exists(hass: HomeAssistant) -> None:
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_configured"
|
||||
assert config_entry.data[CONF_HOST] == "4.4.4.4"
|
||||
|
||||
|
||||
async def test_zeroconf_serial_already_exists_ignores_ipv6(hass: HomeAssistant) -> None:
|
||||
"""Test serial number already exists from zeroconf but the discovery is ipv6."""
|
||||
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
"host": "1.1.1.1",
|
||||
"name": "Envoy",
|
||||
"username": "test-username",
|
||||
"password": "test-password",
|
||||
},
|
||||
unique_id="1234",
|
||||
title="Envoy",
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
data=zeroconf.ZeroconfServiceInfo(
|
||||
host="fd00::b27c:63bb:cc85:4ea0",
|
||||
addresses=["fd00::b27c:63bb:cc85:4ea0"],
|
||||
hostname="mock_hostname",
|
||||
name="mock_name",
|
||||
port=None,
|
||||
properties={"serialnum": "1234"},
|
||||
type="mock_type",
|
||||
),
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "not_ipv4_address"
|
||||
assert config_entry.data[CONF_HOST] == "1.1.1.1"
|
||||
|
||||
|
||||
async def test_zeroconf_host_already_exists(hass: HomeAssistant) -> None:
|
||||
|
Reference in New Issue
Block a user