mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Use Airzone WebServer MAC address as unique ID (#70287)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
7d51da1b39
commit
add7103d55
@ -1,14 +1,17 @@
|
|||||||
"""The Airzone integration."""
|
"""The Airzone integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aioairzone.const import (
|
from aioairzone.const import (
|
||||||
AZD_ID,
|
AZD_ID,
|
||||||
|
AZD_MAC,
|
||||||
AZD_NAME,
|
AZD_NAME,
|
||||||
AZD_SYSTEM,
|
AZD_SYSTEM,
|
||||||
AZD_THERMOSTAT_FW,
|
AZD_THERMOSTAT_FW,
|
||||||
AZD_THERMOSTAT_MODEL,
|
AZD_THERMOSTAT_MODEL,
|
||||||
|
AZD_WEBSERVER,
|
||||||
AZD_ZONES,
|
AZD_ZONES,
|
||||||
DEFAULT_SYSTEM_ID,
|
DEFAULT_SYSTEM_ID,
|
||||||
)
|
)
|
||||||
@ -16,8 +19,12 @@ from aioairzone.localapi import AirzoneLocalApi, ConnectionOptions
|
|||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT, Platform
|
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import aiohttp_client
|
from homeassistant.helpers import (
|
||||||
|
aiohttp_client,
|
||||||
|
device_registry as dr,
|
||||||
|
entity_registry as er,
|
||||||
|
)
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
@ -26,6 +33,8 @@ from .coordinator import AirzoneUpdateCoordinator
|
|||||||
|
|
||||||
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR]
|
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR]
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]):
|
class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]):
|
||||||
"""Define an Airzone entity."""
|
"""Define an Airzone entity."""
|
||||||
@ -59,6 +68,9 @@ class AirzoneZoneEntity(AirzoneEntity):
|
|||||||
"name": f"Airzone [{system_zone_id}] {zone_data[AZD_NAME]}",
|
"name": f"Airzone [{system_zone_id}] {zone_data[AZD_NAME]}",
|
||||||
"sw_version": self.get_airzone_value(AZD_THERMOSTAT_FW),
|
"sw_version": self.get_airzone_value(AZD_THERMOSTAT_FW),
|
||||||
}
|
}
|
||||||
|
self._attr_unique_id = (
|
||||||
|
entry.entry_id if entry.unique_id is None else entry.unique_id
|
||||||
|
)
|
||||||
|
|
||||||
def get_airzone_value(self, key) -> Any:
|
def get_airzone_value(self, key) -> Any:
|
||||||
"""Return zone value by key."""
|
"""Return zone value by key."""
|
||||||
@ -70,6 +82,46 @@ class AirzoneZoneEntity(AirzoneEntity):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_migrate_unique_ids(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: ConfigEntry,
|
||||||
|
coordinator: AirzoneUpdateCoordinator,
|
||||||
|
) -> None:
|
||||||
|
"""Migrate entities when the mac address gets discovered."""
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_migrator(entity_entry: er.RegistryEntry) -> dict[str, Any] | None:
|
||||||
|
updates = None
|
||||||
|
|
||||||
|
unique_id = entry.unique_id
|
||||||
|
entry_id = entry.entry_id
|
||||||
|
entity_unique_id = entity_entry.unique_id
|
||||||
|
|
||||||
|
if entity_unique_id.startswith(entry_id):
|
||||||
|
new_unique_id = f"{unique_id}{entity_unique_id[len(entry_id):]}"
|
||||||
|
_LOGGER.info(
|
||||||
|
"Migrating unique_id from [%s] to [%s]",
|
||||||
|
entity_unique_id,
|
||||||
|
new_unique_id,
|
||||||
|
)
|
||||||
|
updates = {"new_unique_id": new_unique_id}
|
||||||
|
|
||||||
|
return updates
|
||||||
|
|
||||||
|
if (
|
||||||
|
entry.unique_id is None
|
||||||
|
and AZD_WEBSERVER in coordinator.data
|
||||||
|
and AZD_MAC in coordinator.data[AZD_WEBSERVER]
|
||||||
|
and (mac := coordinator.data[AZD_WEBSERVER][AZD_MAC]) is not None
|
||||||
|
):
|
||||||
|
updates: dict[str, Any] = {
|
||||||
|
"unique_id": dr.format_mac(mac),
|
||||||
|
}
|
||||||
|
hass.config_entries.async_update_entry(entry, **updates)
|
||||||
|
|
||||||
|
await er.async_migrate_entries(hass, entry.entry_id, _async_migrator)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up Airzone from a config entry."""
|
"""Set up Airzone from a config entry."""
|
||||||
options = ConnectionOptions(
|
options = ConnectionOptions(
|
||||||
@ -79,9 +131,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
airzone = AirzoneLocalApi(aiohttp_client.async_get_clientsession(hass), options)
|
airzone = AirzoneLocalApi(aiohttp_client.async_get_clientsession(hass), options)
|
||||||
|
|
||||||
coordinator = AirzoneUpdateCoordinator(hass, airzone)
|
coordinator = AirzoneUpdateCoordinator(hass, airzone)
|
||||||
await coordinator.async_config_entry_first_refresh()
|
await coordinator.async_config_entry_first_refresh()
|
||||||
|
await _async_migrate_unique_ids(hass, entry, coordinator)
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
|
||||||
|
|
||||||
|
@ -122,6 +122,10 @@ class AirzoneZoneBinarySensor(AirzoneZoneEntity, AirzoneBinarySensor):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize."""
|
"""Initialize."""
|
||||||
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
||||||
|
|
||||||
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
|
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
|
||||||
self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}_{description.key}"
|
self._attr_unique_id = (
|
||||||
|
f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
|
||||||
|
)
|
||||||
|
self.attributes = description.attributes
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
@ -99,8 +99,9 @@ class AirzoneClimate(AirzoneZoneEntity, ClimateEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize Airzone climate entity."""
|
"""Initialize Airzone climate entity."""
|
||||||
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
||||||
|
|
||||||
self._attr_name = f"{zone_data[AZD_NAME]}"
|
self._attr_name = f"{zone_data[AZD_NAME]}"
|
||||||
self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}"
|
self._attr_unique_id = f"{self._attr_unique_id}_{system_zone_id}"
|
||||||
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||||
self._attr_target_temperature_step = API_TEMPERATURE_STEP
|
self._attr_target_temperature_step = API_TEMPERATURE_STEP
|
||||||
self._attr_max_temp = self.get_airzone_value(AZD_TEMP_MAX)
|
self._attr_max_temp = self.get_airzone_value(AZD_TEMP_MAX)
|
||||||
|
@ -12,6 +12,7 @@ from homeassistant import config_entries
|
|||||||
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT
|
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT
|
||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
from homeassistant.helpers import aiohttp_client
|
from homeassistant.helpers import aiohttp_client
|
||||||
|
from homeassistant.helpers.device_registry import format_mac
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
@ -51,13 +52,22 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await airzone.validate()
|
mac = await airzone.validate()
|
||||||
except InvalidSystem:
|
except InvalidSystem:
|
||||||
data_schema = SYSTEM_ID_SCHEMA
|
data_schema = SYSTEM_ID_SCHEMA
|
||||||
errors[CONF_ID] = "invalid_system_id"
|
errors[CONF_ID] = "invalid_system_id"
|
||||||
except AirzoneError:
|
except AirzoneError:
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
else:
|
else:
|
||||||
|
if mac:
|
||||||
|
await self.async_set_unique_id(format_mac(mac))
|
||||||
|
self._abort_if_unique_id_configured(
|
||||||
|
updates={
|
||||||
|
CONF_HOST: user_input[CONF_HOST],
|
||||||
|
CONF_PORT: user_input[CONF_PORT],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
title = f"Airzone {user_input[CONF_HOST]}:{user_input[CONF_PORT]}"
|
title = f"Airzone {user_input[CONF_HOST]}:{user_input[CONF_PORT]}"
|
||||||
return self.async_create_entry(title=title, data=user_input)
|
return self.async_create_entry(title=title, data=user_input)
|
||||||
|
|
||||||
|
@ -83,8 +83,11 @@ class AirzoneZoneSensor(AirzoneZoneEntity, AirzoneSensor):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize."""
|
"""Initialize."""
|
||||||
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
||||||
|
|
||||||
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
|
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
|
||||||
self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}_{description.key}"
|
self._attr_unique_id = (
|
||||||
|
f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
|
||||||
|
)
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
|
||||||
if description.key == AZD_TEMP:
|
if description.key == AZD_TEMP:
|
||||||
|
@ -16,7 +16,7 @@ from homeassistant.config_entries import SOURCE_USER, ConfigEntryState
|
|||||||
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT
|
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .util import CONFIG, CONFIG_ID1, HVAC_MOCK
|
from .util import CONFIG, CONFIG_ID1, HVAC_MOCK, HVAC_WEBSERVER_MOCK
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ async def test_form(hass: HomeAssistant) -> None:
|
|||||||
side_effect=SystemOutOfRange,
|
side_effect=SystemOutOfRange,
|
||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
||||||
side_effect=InvalidMethod,
|
return_value=HVAC_WEBSERVER_MOCK,
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
@ -118,8 +118,12 @@ async def test_form_invalid_system_id(hass: HomeAssistant) -> None:
|
|||||||
async def test_form_duplicated_id(hass: HomeAssistant) -> None:
|
async def test_form_duplicated_id(hass: HomeAssistant) -> None:
|
||||||
"""Test setting up duplicated entry."""
|
"""Test setting up duplicated entry."""
|
||||||
|
|
||||||
entry = MockConfigEntry(domain=DOMAIN, data=CONFIG)
|
config_entry = MockConfigEntry(
|
||||||
entry.add_to_hass(hass)
|
data=CONFIG,
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="airzone_unique_id",
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
|
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
|
||||||
|
@ -18,8 +18,12 @@ from tests.common import MockConfigEntry, async_fire_time_changed
|
|||||||
async def test_coordinator_client_connector_error(hass: HomeAssistant) -> None:
|
async def test_coordinator_client_connector_error(hass: HomeAssistant) -> None:
|
||||||
"""Test ClientConnectorError on coordinator update."""
|
"""Test ClientConnectorError on coordinator update."""
|
||||||
|
|
||||||
entry = MockConfigEntry(domain=DOMAIN, data=CONFIG)
|
config_entry = MockConfigEntry(
|
||||||
entry.add_to_hass(hass)
|
data=CONFIG,
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="airzone_unique_id",
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.airzone.AirzoneLocalApi.get_hvac",
|
"homeassistant.components.airzone.AirzoneLocalApi.get_hvac",
|
||||||
@ -31,7 +35,7 @@ async def test_coordinator_client_connector_error(hass: HomeAssistant) -> None:
|
|||||||
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
||||||
side_effect=InvalidMethod,
|
side_effect=InvalidMethod,
|
||||||
):
|
):
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_hvac.assert_called_once()
|
mock_hvac.assert_called_once()
|
||||||
mock_hvac.reset_mock()
|
mock_hvac.reset_mock()
|
||||||
|
@ -7,18 +7,19 @@ from aioairzone.exceptions import InvalidMethod, SystemOutOfRange
|
|||||||
from homeassistant.components.airzone.const import DOMAIN
|
from homeassistant.components.airzone.const import DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
from .util import CONFIG, HVAC_MOCK
|
from .util import CONFIG, HVAC_MOCK, HVAC_WEBSERVER_MOCK
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
async def test_unload_entry(hass: HomeAssistant) -> None:
|
async def test_unique_id_migrate(hass: HomeAssistant) -> None:
|
||||||
"""Test unload."""
|
"""Test unique id migration."""
|
||||||
|
|
||||||
config_entry = MockConfigEntry(
|
entity_registry = er.async_get(hass)
|
||||||
domain=DOMAIN, unique_id="airzone_unique_id", data=CONFIG
|
|
||||||
)
|
config_entry = MockConfigEntry(domain=DOMAIN, data=CONFIG)
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
@ -30,6 +31,52 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
|
|||||||
), patch(
|
), patch(
|
||||||
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
||||||
side_effect=InvalidMethod,
|
side_effect=InvalidMethod,
|
||||||
|
):
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert not config_entry.unique_id
|
||||||
|
assert (
|
||||||
|
entity_registry.async_get("sensor.salon_temperature").unique_id
|
||||||
|
== f"{config_entry.entry_id}_1:1_temp"
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.airzone.AirzoneLocalApi.get_hvac",
|
||||||
|
return_value=HVAC_MOCK,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.airzone.AirzoneLocalApi.get_hvac_systems",
|
||||||
|
side_effect=SystemOutOfRange,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
||||||
|
return_value=HVAC_WEBSERVER_MOCK,
|
||||||
|
):
|
||||||
|
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert config_entry.unique_id
|
||||||
|
assert (
|
||||||
|
entity_registry.async_get("sensor.salon_temperature").unique_id
|
||||||
|
== f"{config_entry.unique_id}_1:1_temp"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_unload_entry(hass: HomeAssistant) -> None:
|
||||||
|
"""Test unload."""
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
data=CONFIG,
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="airzone_unique_id",
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.airzone.AirzoneLocalApi.validate",
|
||||||
|
return_value=None,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.airzone.AirzoneLocalApi.update",
|
||||||
|
return_value=None,
|
||||||
):
|
):
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -12,6 +12,7 @@ from aioairzone.const import (
|
|||||||
API_HEAT_STAGE,
|
API_HEAT_STAGE,
|
||||||
API_HEAT_STAGES,
|
API_HEAT_STAGES,
|
||||||
API_HUMIDITY,
|
API_HUMIDITY,
|
||||||
|
API_MAC,
|
||||||
API_MAX_TEMP,
|
API_MAX_TEMP,
|
||||||
API_MIN_TEMP,
|
API_MIN_TEMP,
|
||||||
API_MODE,
|
API_MODE,
|
||||||
@ -26,6 +27,8 @@ from aioairzone.const import (
|
|||||||
API_THERMOS_RADIO,
|
API_THERMOS_RADIO,
|
||||||
API_THERMOS_TYPE,
|
API_THERMOS_TYPE,
|
||||||
API_UNITS,
|
API_UNITS,
|
||||||
|
API_WIFI_CHANNEL,
|
||||||
|
API_WIFI_RSSI,
|
||||||
API_ZONE_ID,
|
API_ZONE_ID,
|
||||||
)
|
)
|
||||||
from aioairzone.exceptions import InvalidMethod, SystemOutOfRange
|
from aioairzone.exceptions import InvalidMethod, SystemOutOfRange
|
||||||
@ -175,14 +178,24 @@ HVAC_MOCK = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HVAC_WEBSERVER_MOCK = {
|
||||||
|
API_MAC: "11:22:33:44:55:66",
|
||||||
|
API_WIFI_CHANNEL: 6,
|
||||||
|
API_WIFI_RSSI: -42,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def async_init_integration(
|
async def async_init_integration(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the Airzone integration in Home Assistant."""
|
"""Set up the Airzone integration in Home Assistant."""
|
||||||
|
|
||||||
entry = MockConfigEntry(domain=DOMAIN, data=CONFIG)
|
config_entry = MockConfigEntry(
|
||||||
entry.add_to_hass(hass)
|
data=CONFIG,
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="airzone_unique_id",
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.airzone.AirzoneLocalApi.get_hvac",
|
"homeassistant.components.airzone.AirzoneLocalApi.get_hvac",
|
||||||
@ -194,5 +207,5 @@ async def async_init_integration(
|
|||||||
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
||||||
side_effect=InvalidMethod,
|
side_effect=InvalidMethod,
|
||||||
):
|
):
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user