mirror of
https://github.com/home-assistant/core.git
synced 2025-08-02 18:18:21 +00:00
Merge branch 'dev' into dev-rc
This commit is contained in:
commit
02f87cba9b
@ -41,7 +41,6 @@ PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.CLIMATE,
|
||||
Platform.DEVICE_TRACKER,
|
||||
Platform.SELECT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.WATER_HEATER,
|
||||
|
@ -73,8 +73,6 @@ class TadoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
"weather": {},
|
||||
"geofence": {},
|
||||
"zone": {},
|
||||
"zone_control": {},
|
||||
"heating_circuits": {},
|
||||
}
|
||||
|
||||
@property
|
||||
@ -101,14 +99,11 @@ class TadoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
self.home_name = tado_home["name"]
|
||||
|
||||
devices = await self._async_update_devices()
|
||||
zones, zone_controls = await self._async_update_zones()
|
||||
zones = await self._async_update_zones()
|
||||
home = await self._async_update_home()
|
||||
heating_circuits = await self._async_update_heating_circuits()
|
||||
|
||||
self.data["device"] = devices
|
||||
self.data["zone"] = zones
|
||||
self.data["zone_control"] = zone_controls
|
||||
self.data["heating_circuits"] = heating_circuits
|
||||
self.data["weather"] = home["weather"]
|
||||
self.data["geofence"] = home["geofence"]
|
||||
|
||||
@ -171,7 +166,7 @@ class TadoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
|
||||
return mapped_devices
|
||||
|
||||
async def _async_update_zones(self) -> tuple[dict[int, dict], dict[int, dict]]:
|
||||
async def _async_update_zones(self) -> dict[int, dict]:
|
||||
"""Update the zone data from Tado."""
|
||||
|
||||
try:
|
||||
@ -184,12 +179,10 @@ class TadoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
raise UpdateFailed(f"Error updating Tado zones: {err}") from err
|
||||
|
||||
mapped_zones: dict[int, dict] = {}
|
||||
mapped_zone_controls: dict[int, dict] = {}
|
||||
for zone in zone_states:
|
||||
mapped_zones[int(zone)] = await self._update_zone(int(zone))
|
||||
mapped_zone_controls[int(zone)] = await self._update_zone_control(int(zone))
|
||||
|
||||
return mapped_zones, mapped_zone_controls
|
||||
return mapped_zones
|
||||
|
||||
async def _update_zone(self, zone_id: int) -> dict[str, str]:
|
||||
"""Update the internal data of a zone."""
|
||||
@ -206,24 +199,6 @@ class TadoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
_LOGGER.debug("Zone %s updated, with data: %s", zone_id, data)
|
||||
return data
|
||||
|
||||
async def _update_zone_control(self, zone_id: int) -> dict[str, Any]:
|
||||
"""Update the internal zone control data of a zone."""
|
||||
|
||||
_LOGGER.debug("Updating zone control for zone %s", zone_id)
|
||||
try:
|
||||
zone_control_data = await self.hass.async_add_executor_job(
|
||||
self._tado.get_zone_control, zone_id
|
||||
)
|
||||
except RequestException as err:
|
||||
_LOGGER.error(
|
||||
"Error updating Tado zone control for zone %s: %s", zone_id, err
|
||||
)
|
||||
raise UpdateFailed(
|
||||
f"Error updating Tado zone control for zone {zone_id}: {err}"
|
||||
) from err
|
||||
|
||||
return zone_control_data
|
||||
|
||||
async def _async_update_home(self) -> dict[str, dict]:
|
||||
"""Update the home data from Tado."""
|
||||
|
||||
@ -242,23 +217,6 @@ class TadoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
|
||||
return {"weather": weather, "geofence": geofence}
|
||||
|
||||
async def _async_update_heating_circuits(self) -> dict[str, dict]:
|
||||
"""Update the heating circuits data from Tado."""
|
||||
|
||||
try:
|
||||
heating_circuits = await self.hass.async_add_executor_job(
|
||||
self._tado.get_heating_circuits
|
||||
)
|
||||
except RequestException as err:
|
||||
_LOGGER.error("Error updating Tado heating circuits: %s", err)
|
||||
raise UpdateFailed(f"Error updating Tado heating circuits: {err}") from err
|
||||
|
||||
mapped_heating_circuits: dict[str, dict] = {}
|
||||
for circuit in heating_circuits:
|
||||
mapped_heating_circuits[circuit["driverShortSerialNo"]] = circuit
|
||||
|
||||
return mapped_heating_circuits
|
||||
|
||||
async def get_capabilities(self, zone_id: int | str) -> dict:
|
||||
"""Fetch the capabilities from Tado."""
|
||||
|
||||
@ -406,20 +364,6 @@ class TadoDataUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
except RequestException as exc:
|
||||
raise HomeAssistantError(f"Error setting Tado child lock: {exc}") from exc
|
||||
|
||||
async def set_heating_circuit(self, zone_id: int, circuit_id: int | None) -> None:
|
||||
"""Set heating circuit for zone."""
|
||||
try:
|
||||
await self.hass.async_add_executor_job(
|
||||
self._tado.set_zone_heating_circuit,
|
||||
zone_id,
|
||||
circuit_id,
|
||||
)
|
||||
except RequestException as exc:
|
||||
raise HomeAssistantError(
|
||||
f"Error setting Tado heating circuit: {exc}"
|
||||
) from exc
|
||||
await self._update_zone_control(zone_id)
|
||||
|
||||
|
||||
class TadoMobileDeviceUpdateCoordinator(DataUpdateCoordinator[dict[str, dict]]):
|
||||
"""Class to manage the mobile devices from Tado via PyTado."""
|
||||
|
@ -1,108 +0,0 @@
|
||||
"""Module for Tado select entities."""
|
||||
|
||||
import logging
|
||||
|
||||
from homeassistant.components.select import SelectEntity
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import TadoConfigEntry
|
||||
from .entity import TadoDataUpdateCoordinator, TadoZoneEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
NO_HEATING_CIRCUIT_OPTION = "no_heating_circuit"
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: TadoConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Tado select platform."""
|
||||
|
||||
tado = entry.runtime_data.coordinator
|
||||
entities: list[SelectEntity] = [
|
||||
TadoHeatingCircuitSelectEntity(tado, zone["name"], zone["id"])
|
||||
for zone in tado.zones
|
||||
if zone["type"] == "HEATING"
|
||||
]
|
||||
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
class TadoHeatingCircuitSelectEntity(TadoZoneEntity, SelectEntity):
|
||||
"""Representation of a Tado heating circuit select entity."""
|
||||
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
_attr_has_entity_name = True
|
||||
_attr_icon = "mdi:water-boiler"
|
||||
_attr_translation_key = "heating_circuit"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: TadoDataUpdateCoordinator,
|
||||
zone_name: str,
|
||||
zone_id: int,
|
||||
) -> None:
|
||||
"""Initialize the Tado heating circuit select entity."""
|
||||
super().__init__(zone_name, coordinator.home_id, zone_id, coordinator)
|
||||
|
||||
self._attr_unique_id = f"{zone_id} {coordinator.home_id} heating_circuit"
|
||||
|
||||
self._attr_options = []
|
||||
self._attr_current_option = None
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Update the selected heating circuit."""
|
||||
heating_circuit_id = (
|
||||
None
|
||||
if option == NO_HEATING_CIRCUIT_OPTION
|
||||
else self.coordinator.data["heating_circuits"].get(option, {}).get("number")
|
||||
)
|
||||
await self.coordinator.set_heating_circuit(self.zone_id, heating_circuit_id)
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle updated data from the coordinator."""
|
||||
self._async_update_callback()
|
||||
super()._handle_coordinator_update()
|
||||
|
||||
@callback
|
||||
def _async_update_callback(self) -> None:
|
||||
"""Handle update callbacks."""
|
||||
# Heating circuits list
|
||||
heating_circuits = self.coordinator.data["heating_circuits"].values()
|
||||
self._attr_options = [NO_HEATING_CIRCUIT_OPTION]
|
||||
self._attr_options.extend(hc["driverShortSerialNo"] for hc in heating_circuits)
|
||||
|
||||
# Current heating circuit
|
||||
zone_control = self.coordinator.data["zone_control"].get(self.zone_id)
|
||||
if zone_control and "heatingCircuit" in zone_control:
|
||||
heating_circuit_number = zone_control["heatingCircuit"]
|
||||
if heating_circuit_number is None:
|
||||
self._attr_current_option = NO_HEATING_CIRCUIT_OPTION
|
||||
else:
|
||||
# Find heating circuit by number
|
||||
heating_circuit = next(
|
||||
(
|
||||
hc
|
||||
for hc in heating_circuits
|
||||
if hc.get("number") == heating_circuit_number
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
if heating_circuit is None:
|
||||
_LOGGER.error(
|
||||
"Heating circuit with number %s not found for zone %s",
|
||||
heating_circuit_number,
|
||||
self.zone_name,
|
||||
)
|
||||
self._attr_current_option = NO_HEATING_CIRCUIT_OPTION
|
||||
else:
|
||||
self._attr_current_option = heating_circuit.get(
|
||||
"driverShortSerialNo"
|
||||
)
|
@ -59,14 +59,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"heating_circuit": {
|
||||
"name": "Heating circuit",
|
||||
"state": {
|
||||
"no_heating_circuit": "No circuit"
|
||||
}
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"child_lock": {
|
||||
"name": "Child lock"
|
||||
|
@ -89,6 +89,7 @@ from .light import (
|
||||
CONF_TEMPERATURE_ACTION,
|
||||
async_create_preview_light,
|
||||
)
|
||||
from .lock import CONF_LOCK, CONF_OPEN, CONF_UNLOCK, async_create_preview_lock
|
||||
from .number import (
|
||||
CONF_MAX,
|
||||
CONF_MIN,
|
||||
@ -103,6 +104,18 @@ from .select import CONF_OPTIONS, CONF_SELECT_OPTION, async_create_preview_selec
|
||||
from .sensor import async_create_preview_sensor
|
||||
from .switch import async_create_preview_switch
|
||||
from .template_entity import TemplateEntity
|
||||
from .vacuum import (
|
||||
CONF_FAN_SPEED,
|
||||
CONF_FAN_SPEED_LIST,
|
||||
SERVICE_CLEAN_SPOT,
|
||||
SERVICE_LOCATE,
|
||||
SERVICE_PAUSE,
|
||||
SERVICE_RETURN_TO_BASE,
|
||||
SERVICE_SET_FAN_SPEED,
|
||||
SERVICE_START,
|
||||
SERVICE_STOP,
|
||||
async_create_preview_vacuum,
|
||||
)
|
||||
|
||||
_SCHEMA_STATE: dict[vol.Marker, Any] = {
|
||||
vol.Required(CONF_STATE): selector.TemplateSelector(),
|
||||
@ -221,6 +234,14 @@ def generate_schema(domain: str, flow_type: str) -> vol.Schema:
|
||||
vol.Optional(CONF_TEMPERATURE_ACTION): selector.ActionSelector(),
|
||||
}
|
||||
|
||||
if domain == Platform.LOCK:
|
||||
schema |= _SCHEMA_STATE | {
|
||||
vol.Required(CONF_LOCK): selector.ActionSelector(),
|
||||
vol.Required(CONF_UNLOCK): selector.ActionSelector(),
|
||||
vol.Optional(CONF_CODE_FORMAT): selector.TemplateSelector(),
|
||||
vol.Optional(CONF_OPEN): selector.ActionSelector(),
|
||||
}
|
||||
|
||||
if domain == Platform.NUMBER:
|
||||
schema |= {
|
||||
vol.Required(CONF_STATE): selector.TemplateSelector(),
|
||||
@ -294,6 +315,26 @@ def generate_schema(domain: str, flow_type: str) -> vol.Schema:
|
||||
vol.Optional(CONF_TURN_OFF): selector.ActionSelector(),
|
||||
}
|
||||
|
||||
if domain == Platform.VACUUM:
|
||||
schema |= _SCHEMA_STATE | {
|
||||
vol.Required(SERVICE_START): selector.ActionSelector(),
|
||||
vol.Optional(CONF_FAN_SPEED): selector.TemplateSelector(),
|
||||
vol.Optional(CONF_FAN_SPEED_LIST): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=[],
|
||||
multiple=True,
|
||||
custom_value=True,
|
||||
mode=selector.SelectSelectorMode.DROPDOWN,
|
||||
)
|
||||
),
|
||||
vol.Optional(SERVICE_SET_FAN_SPEED): selector.ActionSelector(),
|
||||
vol.Optional(SERVICE_STOP): selector.ActionSelector(),
|
||||
vol.Optional(SERVICE_PAUSE): selector.ActionSelector(),
|
||||
vol.Optional(SERVICE_RETURN_TO_BASE): selector.ActionSelector(),
|
||||
vol.Optional(SERVICE_CLEAN_SPOT): selector.ActionSelector(),
|
||||
vol.Optional(SERVICE_LOCATE): selector.ActionSelector(),
|
||||
}
|
||||
|
||||
schema |= {
|
||||
vol.Optional(CONF_DEVICE_ID): selector.DeviceSelector(),
|
||||
vol.Optional(CONF_ADVANCED_OPTIONS): section(
|
||||
@ -403,10 +444,12 @@ TEMPLATE_TYPES = [
|
||||
Platform.FAN,
|
||||
Platform.IMAGE,
|
||||
Platform.LIGHT,
|
||||
Platform.LOCK,
|
||||
Platform.NUMBER,
|
||||
Platform.SELECT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.VACUUM,
|
||||
]
|
||||
|
||||
CONFIG_FLOW = {
|
||||
@ -445,6 +488,11 @@ CONFIG_FLOW = {
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.LIGHT),
|
||||
),
|
||||
Platform.LOCK: SchemaFlowFormStep(
|
||||
config_schema(Platform.LOCK),
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.LOCK),
|
||||
),
|
||||
Platform.NUMBER: SchemaFlowFormStep(
|
||||
config_schema(Platform.NUMBER),
|
||||
preview="template",
|
||||
@ -465,6 +513,11 @@ CONFIG_FLOW = {
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.SWITCH),
|
||||
),
|
||||
Platform.VACUUM: SchemaFlowFormStep(
|
||||
config_schema(Platform.VACUUM),
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.VACUUM),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@ -504,6 +557,11 @@ OPTIONS_FLOW = {
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.LIGHT),
|
||||
),
|
||||
Platform.LOCK: SchemaFlowFormStep(
|
||||
options_schema(Platform.LOCK),
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.LOCK),
|
||||
),
|
||||
Platform.NUMBER: SchemaFlowFormStep(
|
||||
options_schema(Platform.NUMBER),
|
||||
preview="template",
|
||||
@ -524,6 +582,11 @@ OPTIONS_FLOW = {
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.SWITCH),
|
||||
),
|
||||
Platform.VACUUM: SchemaFlowFormStep(
|
||||
options_schema(Platform.VACUUM),
|
||||
preview="template",
|
||||
validate_user_input=validate_user_input(Platform.VACUUM),
|
||||
),
|
||||
}
|
||||
|
||||
CREATE_PREVIEW_ENTITY: dict[
|
||||
@ -535,10 +598,12 @@ CREATE_PREVIEW_ENTITY: dict[
|
||||
Platform.COVER: async_create_preview_cover,
|
||||
Platform.FAN: async_create_preview_fan,
|
||||
Platform.LIGHT: async_create_preview_light,
|
||||
Platform.LOCK: async_create_preview_lock,
|
||||
Platform.NUMBER: async_create_preview_number,
|
||||
Platform.SELECT: async_create_preview_select,
|
||||
Platform.SENSOR: async_create_preview_sensor,
|
||||
Platform.SWITCH: async_create_preview_switch,
|
||||
Platform.VACUUM: async_create_preview_vacuum,
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@ from homeassistant.components.lock import (
|
||||
LockEntityFeature,
|
||||
LockState,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_CODE,
|
||||
CONF_NAME,
|
||||
@ -26,15 +27,23 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import ServiceValidationError, TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import TriggerUpdateCoordinator
|
||||
from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
from .helpers import (
|
||||
async_setup_template_entry,
|
||||
async_setup_template_platform,
|
||||
async_setup_template_preview,
|
||||
)
|
||||
from .template_entity import (
|
||||
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY,
|
||||
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
|
||||
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
|
||||
TemplateEntity,
|
||||
make_template_entity_common_modern_schema,
|
||||
@ -82,6 +91,10 @@ PLATFORM_SCHEMA = LOCK_PLATFORM_SCHEMA.extend(
|
||||
}
|
||||
).extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY.schema)
|
||||
|
||||
LOCK_CONFIG_ENTRY_SCHEMA = LOCK_COMMON_SCHEMA.extend(
|
||||
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA.schema
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
@ -102,6 +115,35 @@ async def async_setup_platform(
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Initialize config entry."""
|
||||
await async_setup_template_entry(
|
||||
hass,
|
||||
config_entry,
|
||||
async_add_entities,
|
||||
StateLockEntity,
|
||||
LOCK_CONFIG_ENTRY_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def async_create_preview_lock(
|
||||
hass: HomeAssistant, name: str, config: dict[str, Any]
|
||||
) -> StateLockEntity:
|
||||
"""Create a preview."""
|
||||
return async_setup_template_preview(
|
||||
hass,
|
||||
name,
|
||||
config,
|
||||
StateLockEntity,
|
||||
LOCK_CONFIG_ENTRY_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
class AbstractTemplateLock(AbstractTemplateEntity, LockEntity):
|
||||
"""Representation of a template lock features."""
|
||||
|
||||
|
@ -188,6 +188,29 @@
|
||||
},
|
||||
"title": "Template light"
|
||||
},
|
||||
"lock": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
"name": "[%key:common::config_flow::data::name%]",
|
||||
"state": "[%key:component::template::common::state%]",
|
||||
"lock": "Actions on lock",
|
||||
"unlock": "Actions on unlock",
|
||||
"code_format": "[%key:component::template::common::code_format%]",
|
||||
"open": "Actions on open"
|
||||
},
|
||||
"data_description": {
|
||||
"device_id": "[%key:component::template::common::device_id_description%]"
|
||||
},
|
||||
"sections": {
|
||||
"advanced_options": {
|
||||
"name": "[%key:component::template::common::advanced_options%]",
|
||||
"data": {
|
||||
"availability": "[%key:component::template::common::availability%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": "Template lock"
|
||||
},
|
||||
"number": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
@ -265,10 +288,12 @@
|
||||
"fan": "Template a fan",
|
||||
"image": "Template an image",
|
||||
"light": "Template a light",
|
||||
"lock": "Template a lock",
|
||||
"number": "Template a number",
|
||||
"select": "Template a select",
|
||||
"sensor": "Template a sensor",
|
||||
"switch": "Template a switch"
|
||||
"switch": "Template a switch",
|
||||
"vacuum": "Template a vacuum"
|
||||
},
|
||||
"title": "Template helper"
|
||||
},
|
||||
@ -293,6 +318,34 @@
|
||||
}
|
||||
},
|
||||
"title": "Template switch"
|
||||
},
|
||||
"vacuum": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
"name": "[%key:common::config_flow::data::name%]",
|
||||
"state": "[%key:component::template::common::state%]",
|
||||
"start": "Actions on turn off",
|
||||
"fan_speed": "Fan speed",
|
||||
"fan_speeds": "Fan speeds",
|
||||
"set_fan_speed": "Actions on set fan speed",
|
||||
"stop": "Actions on stop",
|
||||
"pause": "Actions on pause",
|
||||
"return_to_base": "Actions on return to base",
|
||||
"clean_spot": "Actions on clean spot",
|
||||
"locate": "Actions on locate"
|
||||
},
|
||||
"data_description": {
|
||||
"device_id": "[%key:component::template::common::device_id_description%]"
|
||||
},
|
||||
"sections": {
|
||||
"advanced_options": {
|
||||
"name": "[%key:component::template::common::advanced_options%]",
|
||||
"data": {
|
||||
"availability": "[%key:component::template::common::availability%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": "Template vacuum"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -466,6 +519,28 @@
|
||||
},
|
||||
"title": "[%key:component::template::config::step::light::title%]"
|
||||
},
|
||||
"lock": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
"state": "[%key:component::template::common::state%]",
|
||||
"lock": "[%key:component::template::config::step::lock::data::lock%]",
|
||||
"unlock": "[%key:component::template::config::step::lock::data::unlock%]",
|
||||
"code_format": "[%key:component::template::common::code_format%]",
|
||||
"open": "[%key:component::template::config::step::lock::data::open%]"
|
||||
},
|
||||
"data_description": {
|
||||
"device_id": "[%key:component::template::common::device_id_description%]"
|
||||
},
|
||||
"sections": {
|
||||
"advanced_options": {
|
||||
"name": "[%key:component::template::common::advanced_options%]",
|
||||
"data": {
|
||||
"availability": "[%key:component::template::common::availability%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": "[%key:component::template::config::step::lock::title%]"
|
||||
},
|
||||
"number": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
@ -552,6 +627,34 @@
|
||||
}
|
||||
},
|
||||
"title": "[%key:component::template::config::step::switch::title%]"
|
||||
},
|
||||
"vacuum": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
"name": "[%key:common::config_flow::data::name%]",
|
||||
"state": "[%key:component::template::common::state%]",
|
||||
"start": "[%key:component::template::config::step::vacuum::data::start%]",
|
||||
"fan_speed": "[%key:component::template::config::step::vacuum::data::fan_speed%]",
|
||||
"fan_speeds": "[%key:component::template::config::step::vacuum::data::fan_speeds%]",
|
||||
"set_fan_speed": "[%key:component::template::config::step::vacuum::data::set_fan_speed%]",
|
||||
"stop": "[%key:component::template::config::step::vacuum::data::stop%]",
|
||||
"pause": "[%key:component::template::config::step::vacuum::data::pause%]",
|
||||
"return_to_base": "[%key:component::template::config::step::vacuum::data::return_to_base%]",
|
||||
"clean_spot": "[%key:component::template::config::step::vacuum::data::clean_spot%]",
|
||||
"locate": "[%key:component::template::config::step::vacuum::data::locate%]"
|
||||
},
|
||||
"data_description": {
|
||||
"device_id": "[%key:component::template::common::device_id_description%]"
|
||||
},
|
||||
"sections": {
|
||||
"advanced_options": {
|
||||
"name": "[%key:component::template::common::advanced_options%]",
|
||||
"data": {
|
||||
"availability": "[%key:component::template::common::availability%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": "Template vacuum"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -22,6 +22,7 @@ from homeassistant.components.vacuum import (
|
||||
VacuumActivity,
|
||||
VacuumEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_ENTITY_ID,
|
||||
CONF_FRIENDLY_NAME,
|
||||
@ -34,16 +35,24 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import TriggerUpdateCoordinator
|
||||
from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
from .helpers import (
|
||||
async_setup_template_entry,
|
||||
async_setup_template_platform,
|
||||
async_setup_template_preview,
|
||||
)
|
||||
from .template_entity import (
|
||||
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY,
|
||||
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY,
|
||||
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
|
||||
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
|
||||
TemplateEntity,
|
||||
make_template_entity_common_modern_attributes_schema,
|
||||
@ -125,6 +134,10 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend(
|
||||
{vol.Required(CONF_VACUUMS): cv.schema_with_slug_keys(VACUUM_LEGACY_YAML_SCHEMA)}
|
||||
)
|
||||
|
||||
VACUUM_CONFIG_ENTRY_SCHEMA = VACUUM_COMMON_SCHEMA.extend(
|
||||
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA.schema
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
@ -146,6 +159,35 @@ async def async_setup_platform(
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Initialize config entry."""
|
||||
await async_setup_template_entry(
|
||||
hass,
|
||||
config_entry,
|
||||
async_add_entities,
|
||||
TemplateStateVacuumEntity,
|
||||
VACUUM_CONFIG_ENTRY_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def async_create_preview_vacuum(
|
||||
hass: HomeAssistant, name: str, config: dict[str, Any]
|
||||
) -> TemplateStateVacuumEntity:
|
||||
"""Create a preview."""
|
||||
return async_setup_template_preview(
|
||||
hass,
|
||||
name,
|
||||
config,
|
||||
TemplateStateVacuumEntity,
|
||||
VACUUM_CONFIG_ENTRY_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
class AbstractTemplateVacuum(AbstractTemplateEntity, StateVacuumEntity):
|
||||
"""Representation of a template vacuum features."""
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
[
|
||||
{
|
||||
"number": 1,
|
||||
"driverSerialNo": "RU1234567890",
|
||||
"driverShortSerialNo": "RU1234567890"
|
||||
}
|
||||
]
|
@ -1,80 +0,0 @@
|
||||
{
|
||||
"type": "HEATING",
|
||||
"earlyStartEnabled": false,
|
||||
"heatingCircuit": 1,
|
||||
"duties": {
|
||||
"type": "HEATING",
|
||||
"leader": {
|
||||
"deviceType": "RU01",
|
||||
"serialNo": "RU1234567890",
|
||||
"shortSerialNo": "RU1234567890",
|
||||
"currentFwVersion": "54.20",
|
||||
"connectionState": {
|
||||
"value": true,
|
||||
"timestamp": "2025-06-30T19:53:40.710Z"
|
||||
},
|
||||
"characteristics": {
|
||||
"capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"]
|
||||
},
|
||||
"batteryState": "NORMAL"
|
||||
},
|
||||
"drivers": [
|
||||
{
|
||||
"deviceType": "VA01",
|
||||
"serialNo": "VA1234567890",
|
||||
"shortSerialNo": "VA1234567890",
|
||||
"currentFwVersion": "54.20",
|
||||
"connectionState": {
|
||||
"value": true,
|
||||
"timestamp": "2025-06-30T19:54:15.166Z"
|
||||
},
|
||||
"characteristics": {
|
||||
"capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"]
|
||||
},
|
||||
"mountingState": {
|
||||
"value": "CALIBRATED",
|
||||
"timestamp": "2025-06-09T23:25:12.678Z"
|
||||
},
|
||||
"mountingStateWithError": "CALIBRATED",
|
||||
"batteryState": "LOW",
|
||||
"childLockEnabled": false
|
||||
}
|
||||
],
|
||||
"uis": [
|
||||
{
|
||||
"deviceType": "RU01",
|
||||
"serialNo": "RU1234567890",
|
||||
"shortSerialNo": "RU1234567890",
|
||||
"currentFwVersion": "54.20",
|
||||
"connectionState": {
|
||||
"value": true,
|
||||
"timestamp": "2025-06-30T19:53:40.710Z"
|
||||
},
|
||||
"characteristics": {
|
||||
"capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"]
|
||||
},
|
||||
"batteryState": "NORMAL"
|
||||
},
|
||||
{
|
||||
"deviceType": "VA01",
|
||||
"serialNo": "VA1234567890",
|
||||
"shortSerialNo": "VA1234567890",
|
||||
"currentFwVersion": "54.20",
|
||||
"connectionState": {
|
||||
"value": true,
|
||||
"timestamp": "2025-06-30T19:54:15.166Z"
|
||||
},
|
||||
"characteristics": {
|
||||
"capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"]
|
||||
},
|
||||
"mountingState": {
|
||||
"value": "CALIBRATED",
|
||||
"timestamp": "2025-06-09T23:25:12.678Z"
|
||||
},
|
||||
"mountingStateWithError": "CALIBRATED",
|
||||
"batteryState": "LOW",
|
||||
"childLockEnabled": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -62,13 +62,6 @@
|
||||
'presence': 'HOME',
|
||||
'presenceLocked': False,
|
||||
}),
|
||||
'heating_circuits': dict({
|
||||
'RU1234567890': dict({
|
||||
'driverSerialNo': 'RU1234567890',
|
||||
'driverShortSerialNo': 'RU1234567890',
|
||||
'number': 1,
|
||||
}),
|
||||
}),
|
||||
'weather': dict({
|
||||
'outsideTemperature': dict({
|
||||
'celsius': 7.46,
|
||||
@ -117,560 +110,6 @@
|
||||
'repr': "TadoZone(zone_id=6, current_temp=24.3, connection=None, current_temp_timestamp='2024-06-28T22: 23: 15.679Z', current_humidity=70.9, current_humidity_timestamp='2024-06-28T22: 23: 15.679Z', is_away=False, current_hvac_action='HEATING', current_fan_speed='AUTO', current_fan_level='LEVEL3', current_hvac_mode='HEAT', current_swing_mode='OFF', current_vertical_swing_mode='ON', current_horizontal_swing_mode='ON', target_temp=25.0, available=True, power='ON', link='ONLINE', ac_power_timestamp='2022-07-13T18: 06: 58.183Z', heating_power_timestamp=None, ac_power='ON', heating_power=None, heating_power_percentage=None, tado_mode='HOME', overlay_termination_type='MANUAL', overlay_termination_timestamp=None, default_overlay_termination_type='MANUAL', default_overlay_termination_duration=None, preparation=False, open_window=False, open_window_detected=False, open_window_attr={}, precision=0.1)",
|
||||
}),
|
||||
}),
|
||||
'zone_control': dict({
|
||||
'1': dict({
|
||||
'duties': dict({
|
||||
'drivers': list([
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
'leader': dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
'type': 'HEATING',
|
||||
'uis': list([
|
||||
dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
'earlyStartEnabled': False,
|
||||
'heatingCircuit': 1,
|
||||
'type': 'HEATING',
|
||||
}),
|
||||
'2': dict({
|
||||
'duties': dict({
|
||||
'drivers': list([
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
'leader': dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
'type': 'HEATING',
|
||||
'uis': list([
|
||||
dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
'earlyStartEnabled': False,
|
||||
'heatingCircuit': 1,
|
||||
'type': 'HEATING',
|
||||
}),
|
||||
'3': dict({
|
||||
'duties': dict({
|
||||
'drivers': list([
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
'leader': dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
'type': 'HEATING',
|
||||
'uis': list([
|
||||
dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
'earlyStartEnabled': False,
|
||||
'heatingCircuit': 1,
|
||||
'type': 'HEATING',
|
||||
}),
|
||||
'4': dict({
|
||||
'duties': dict({
|
||||
'drivers': list([
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
'leader': dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
'type': 'HEATING',
|
||||
'uis': list([
|
||||
dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
'earlyStartEnabled': False,
|
||||
'heatingCircuit': 1,
|
||||
'type': 'HEATING',
|
||||
}),
|
||||
'5': dict({
|
||||
'duties': dict({
|
||||
'drivers': list([
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
'leader': dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
'type': 'HEATING',
|
||||
'uis': list([
|
||||
dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
'earlyStartEnabled': False,
|
||||
'heatingCircuit': 1,
|
||||
'type': 'HEATING',
|
||||
}),
|
||||
'6': dict({
|
||||
'duties': dict({
|
||||
'drivers': list([
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
'leader': dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
'type': 'HEATING',
|
||||
'uis': list([
|
||||
dict({
|
||||
'batteryState': 'NORMAL',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:53:40.710Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'RU01',
|
||||
'serialNo': 'RU1234567890',
|
||||
'shortSerialNo': 'RU1234567890',
|
||||
}),
|
||||
dict({
|
||||
'batteryState': 'LOW',
|
||||
'characteristics': dict({
|
||||
'capabilities': list([
|
||||
'INSIDE_TEMPERATURE_MEASUREMENT',
|
||||
'IDENTIFY',
|
||||
]),
|
||||
}),
|
||||
'childLockEnabled': False,
|
||||
'connectionState': dict({
|
||||
'timestamp': '2025-06-30T19:54:15.166Z',
|
||||
'value': True,
|
||||
}),
|
||||
'currentFwVersion': '54.20',
|
||||
'deviceType': 'VA01',
|
||||
'mountingState': dict({
|
||||
'timestamp': '2025-06-09T23:25:12.678Z',
|
||||
'value': 'CALIBRATED',
|
||||
}),
|
||||
'mountingStateWithError': 'CALIBRATED',
|
||||
'serialNo': 'VA1234567890',
|
||||
'shortSerialNo': 'VA1234567890',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
'earlyStartEnabled': False,
|
||||
'heatingCircuit': 1,
|
||||
'type': 'HEATING',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'mobile_devices': dict({
|
||||
'mobile_device': dict({
|
||||
|
@ -1,91 +0,0 @@
|
||||
"""The select tests for the tado platform."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.select import (
|
||||
DOMAIN as SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_OPTION
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .util import async_init_integration
|
||||
|
||||
HEATING_CIRCUIT_SELECT_ENTITY = "select.baseboard_heater_heating_circuit"
|
||||
NO_HEATING_CIRCUIT = "no_heating_circuit"
|
||||
HEATING_CIRCUIT_OPTION = "RU1234567890"
|
||||
ZONE_ID = 1
|
||||
HEATING_CIRCUIT_ID = 1
|
||||
|
||||
|
||||
async def test_heating_circuit_select(hass: HomeAssistant) -> None:
|
||||
"""Test creation of heating circuit select entity."""
|
||||
|
||||
await async_init_integration(hass)
|
||||
state = hass.states.get(HEATING_CIRCUIT_SELECT_ENTITY)
|
||||
assert state is not None
|
||||
assert state.state == HEATING_CIRCUIT_OPTION
|
||||
assert NO_HEATING_CIRCUIT in state.attributes["options"]
|
||||
assert HEATING_CIRCUIT_OPTION in state.attributes["options"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("option", "expected_circuit_id"),
|
||||
[(HEATING_CIRCUIT_OPTION, HEATING_CIRCUIT_ID), (NO_HEATING_CIRCUIT, None)],
|
||||
)
|
||||
async def test_heating_circuit_select_action(
|
||||
hass: HomeAssistant, option, expected_circuit_id
|
||||
) -> None:
|
||||
"""Test selecting heating circuit option."""
|
||||
|
||||
await async_init_integration(hass)
|
||||
|
||||
# Test selecting a specific heating circuit
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.tado.PyTado.interface.api.Tado.set_zone_heating_circuit"
|
||||
) as mock_set_zone_heating_circuit,
|
||||
patch(
|
||||
"homeassistant.components.tado.PyTado.interface.api.Tado.get_zone_control"
|
||||
) as mock_get_zone_control,
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: HEATING_CIRCUIT_SELECT_ENTITY,
|
||||
ATTR_OPTION: option,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_set_zone_heating_circuit.assert_called_with(ZONE_ID, expected_circuit_id)
|
||||
assert mock_get_zone_control.called
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("caplog")
|
||||
async def test_heating_circuit_not_found(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test when a heating circuit with a specific number is not found."""
|
||||
circuit_not_matching_zone_control = 999
|
||||
heating_circuits = [
|
||||
{
|
||||
"number": circuit_not_matching_zone_control,
|
||||
"driverSerialNo": "RU1234567890",
|
||||
"driverShortSerialNo": "RU1234567890",
|
||||
}
|
||||
]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.tado.PyTado.interface.api.Tado.get_heating_circuits",
|
||||
return_value=heating_circuits,
|
||||
):
|
||||
await async_init_integration(hass)
|
||||
|
||||
state = hass.states.get(HEATING_CIRCUIT_SELECT_ENTITY)
|
||||
assert state.state == NO_HEATING_CIRCUIT
|
||||
|
||||
assert "Heating circuit with number 1 not found for zone" in caplog.text
|
@ -20,10 +20,8 @@ async def async_init_integration(
|
||||
me_fixture = "me.json"
|
||||
weather_fixture = "weather.json"
|
||||
home_fixture = "home.json"
|
||||
home_heating_circuits_fixture = "heating_circuits.json"
|
||||
home_state_fixture = "home_state.json"
|
||||
zones_fixture = "zones.json"
|
||||
zone_control_fixture = "zone_control.json"
|
||||
zone_states_fixture = "zone_states.json"
|
||||
|
||||
# WR1 Device
|
||||
@ -72,10 +70,6 @@ async def async_init_integration(
|
||||
"https://my.tado.com/api/v2/homes/1/",
|
||||
text=await async_load_fixture(hass, home_fixture, DOMAIN),
|
||||
)
|
||||
m.get(
|
||||
"https://my.tado.com/api/v2/homes/1/heatingCircuits",
|
||||
text=await async_load_fixture(hass, home_heating_circuits_fixture, DOMAIN),
|
||||
)
|
||||
m.get(
|
||||
"https://my.tado.com/api/v2/homes/1/weather",
|
||||
text=await async_load_fixture(hass, weather_fixture, DOMAIN),
|
||||
@ -184,12 +178,6 @@ async def async_init_integration(
|
||||
"https://my.tado.com/api/v2/homes/1/zones/1/state",
|
||||
text=await async_load_fixture(hass, zone_1_state_fixture, DOMAIN),
|
||||
)
|
||||
zone_ids = [1, 2, 3, 4, 5, 6]
|
||||
for zone_id in zone_ids:
|
||||
m.get(
|
||||
f"https://my.tado.com/api/v2/homes/1/zones/{zone_id}/control",
|
||||
text=await async_load_fixture(hass, zone_control_fixture, DOMAIN),
|
||||
)
|
||||
m.post(
|
||||
"https://login.tado.com/oauth2/token",
|
||||
text=await async_load_fixture(hass, token_fixture, DOMAIN),
|
||||
|
15
tests/components/template/snapshots/test_lock.ambr
Normal file
15
tests/components/template/snapshots/test_lock.ambr
Normal file
@ -0,0 +1,15 @@
|
||||
# serializer version: 1
|
||||
# name: test_setup_config_entry
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'My template',
|
||||
'supported_features': <LockEntityFeature: 0>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'lock.my_template',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'locked',
|
||||
})
|
||||
# ---
|
15
tests/components/template/snapshots/test_vacuum.ambr
Normal file
15
tests/components/template/snapshots/test_vacuum.ambr
Normal file
@ -0,0 +1,15 @@
|
||||
# serializer version: 1
|
||||
# name: test_setup_config_entry
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'My template',
|
||||
'supported_features': <VacuumEntityFeature: 12288>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'vacuum.my_template',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'docked',
|
||||
})
|
||||
# ---
|
@ -179,6 +179,16 @@ BINARY_SENSOR_OPTIONS = {
|
||||
{"turn_on": [], "turn_off": []},
|
||||
{},
|
||||
),
|
||||
(
|
||||
"lock",
|
||||
{"state": "{{ states('lock.one') }}"},
|
||||
"locked",
|
||||
{"one": "locked", "two": "unlocked"},
|
||||
{},
|
||||
{"lock": [], "unlock": []},
|
||||
{"lock": [], "unlock": []},
|
||||
{},
|
||||
),
|
||||
(
|
||||
"number",
|
||||
{"state": "{{ states('number.one') }}"},
|
||||
@ -229,6 +239,16 @@ BINARY_SENSOR_OPTIONS = {
|
||||
{},
|
||||
{},
|
||||
),
|
||||
(
|
||||
"vacuum",
|
||||
{"state": "{{ states('vacuum.one') }}"},
|
||||
"docked",
|
||||
{"one": "docked", "two": "cleaning"},
|
||||
{},
|
||||
{"start": []},
|
||||
{"start": []},
|
||||
{},
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.freeze_time("2024-07-09 00:00:00+00:00")
|
||||
@ -362,6 +382,12 @@ async def test_config_flow(
|
||||
{"turn_on": [], "turn_off": []},
|
||||
{"turn_on": [], "turn_off": []},
|
||||
),
|
||||
(
|
||||
"lock",
|
||||
{"state": "{{ states('lock.one') }}"},
|
||||
{"lock": [], "unlock": []},
|
||||
{"lock": [], "unlock": []},
|
||||
),
|
||||
(
|
||||
"number",
|
||||
{"state": "{{ states('number.one') }}"},
|
||||
@ -398,6 +424,12 @@ async def test_config_flow(
|
||||
{"options": "{{ ['off', 'on', 'auto'] }}"},
|
||||
{"options": "{{ ['off', 'on', 'auto'] }}"},
|
||||
),
|
||||
(
|
||||
"vacuum",
|
||||
{"state": "{{ states('vacuum.one') }}"},
|
||||
{"start": []},
|
||||
{"start": []},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_config_flow_device(
|
||||
@ -587,6 +619,16 @@ async def test_config_flow_device(
|
||||
{"turn_on": [], "turn_off": []},
|
||||
"state",
|
||||
),
|
||||
(
|
||||
"lock",
|
||||
{"state": "{{ states('lock.one') }}"},
|
||||
{"state": "{{ states('lock.two') }}"},
|
||||
["locked", "unlocked"],
|
||||
{"one": "locked", "two": "unlocked"},
|
||||
{"lock": [], "unlock": []},
|
||||
{"lock": [], "unlock": []},
|
||||
"state",
|
||||
),
|
||||
(
|
||||
"number",
|
||||
{"state": "{{ states('number.one') }}"},
|
||||
@ -647,6 +689,16 @@ async def test_config_flow_device(
|
||||
{},
|
||||
"value_template",
|
||||
),
|
||||
(
|
||||
"vacuum",
|
||||
{"state": "{{ states('vacuum.one') }}"},
|
||||
{"state": "{{ states('vacuum.two') }}"},
|
||||
["docked", "cleaning"],
|
||||
{"one": "docked", "two": "cleaning"},
|
||||
{"start": []},
|
||||
{"start": []},
|
||||
"state",
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.freeze_time("2024-07-09 00:00:00+00:00")
|
||||
@ -1438,6 +1490,12 @@ async def test_option_flow_sensor_preview_config_entry_removed(
|
||||
{"turn_on": [], "turn_off": []},
|
||||
{"turn_on": [], "turn_off": []},
|
||||
),
|
||||
(
|
||||
"lock",
|
||||
{"state": "{{ states('lock.one') }}"},
|
||||
{"lock": [], "unlock": []},
|
||||
{"lock": [], "unlock": []},
|
||||
),
|
||||
(
|
||||
"number",
|
||||
{"state": "{{ states('number.one') }}"},
|
||||
@ -1480,6 +1538,12 @@ async def test_option_flow_sensor_preview_config_entry_removed(
|
||||
{},
|
||||
{},
|
||||
),
|
||||
(
|
||||
"vacuum",
|
||||
{"state": "{{ states('vacuum.one') }}"},
|
||||
{"start": []},
|
||||
{"start": []},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_options_flow_change_device(
|
||||
|
@ -3,6 +3,7 @@
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant import setup
|
||||
from homeassistant.components import lock, template
|
||||
@ -19,9 +20,10 @@ from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .conftest import ConfigurationStyle
|
||||
from .conftest import ConfigurationStyle, async_get_flow_preview_state
|
||||
|
||||
from tests.common import assert_setup_component
|
||||
from tests.common import MockConfigEntry, assert_setup_component
|
||||
from tests.typing import WebSocketGenerator
|
||||
|
||||
TEST_OBJECT_ID = "test_template_lock"
|
||||
TEST_ENTITY_ID = f"lock.{TEST_OBJECT_ID}"
|
||||
@ -1186,3 +1188,58 @@ async def test_optimistic(hass: HomeAssistant) -> None:
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == LockState.UNLOCKED
|
||||
|
||||
|
||||
async def test_setup_config_entry(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Tests creating a lock from a config entry."""
|
||||
|
||||
hass.states.async_set(
|
||||
"sensor.test_state",
|
||||
LockState.LOCKED,
|
||||
{},
|
||||
)
|
||||
|
||||
template_config_entry = MockConfigEntry(
|
||||
data={},
|
||||
domain=template.DOMAIN,
|
||||
options={
|
||||
"name": "My template",
|
||||
"state": "{{ states('sensor.test_state') }}",
|
||||
"lock": [],
|
||||
"unlock": [],
|
||||
"template_type": lock.DOMAIN,
|
||||
},
|
||||
title="My template",
|
||||
)
|
||||
template_config_entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("lock.my_template")
|
||||
assert state is not None
|
||||
assert state == snapshot
|
||||
|
||||
|
||||
async def test_flow_preview(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test the config flow preview."""
|
||||
|
||||
state = await async_get_flow_preview_state(
|
||||
hass,
|
||||
hass_ws_client,
|
||||
lock.DOMAIN,
|
||||
{
|
||||
"name": "My template",
|
||||
"state": "{{ 'locked' }}",
|
||||
"lock": [],
|
||||
"unlock": [],
|
||||
},
|
||||
)
|
||||
|
||||
assert state["state"] == LockState.LOCKED
|
||||
|
@ -3,6 +3,7 @@
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import template, vacuum
|
||||
from homeassistant.components.vacuum import (
|
||||
@ -18,10 +19,11 @@ from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.entity_component import async_update_entity
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .conftest import ConfigurationStyle
|
||||
from .conftest import ConfigurationStyle, async_get_flow_preview_state
|
||||
|
||||
from tests.common import assert_setup_component
|
||||
from tests.common import MockConfigEntry, assert_setup_component
|
||||
from tests.components.vacuum import common
|
||||
from tests.typing import WebSocketGenerator
|
||||
|
||||
TEST_OBJECT_ID = "test_vacuum"
|
||||
TEST_ENTITY_ID = f"vacuum.{TEST_OBJECT_ID}"
|
||||
@ -1261,3 +1263,56 @@ async def test_optimistic_option(
|
||||
|
||||
state = hass.states.get(TEST_ENTITY_ID)
|
||||
assert state.state == VacuumActivity.DOCKED
|
||||
|
||||
|
||||
async def test_setup_config_entry(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Tests creating a vacuum from a config entry."""
|
||||
|
||||
hass.states.async_set(
|
||||
"sensor.test_sensor",
|
||||
"docked",
|
||||
{},
|
||||
)
|
||||
|
||||
template_config_entry = MockConfigEntry(
|
||||
data={},
|
||||
domain=template.DOMAIN,
|
||||
options={
|
||||
"name": "My template",
|
||||
"state": "{{ states('sensor.test_sensor') }}",
|
||||
"start": [],
|
||||
"template_type": vacuum.DOMAIN,
|
||||
},
|
||||
title="My template",
|
||||
)
|
||||
template_config_entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("vacuum.my_template")
|
||||
assert state is not None
|
||||
assert state == snapshot
|
||||
|
||||
|
||||
async def test_flow_preview(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test the config flow preview."""
|
||||
|
||||
state = await async_get_flow_preview_state(
|
||||
hass,
|
||||
hass_ws_client,
|
||||
vacuum.DOMAIN,
|
||||
{
|
||||
"name": "My template",
|
||||
"state": "{{ 'cleaning' }}",
|
||||
"start": [],
|
||||
},
|
||||
)
|
||||
|
||||
assert state["state"] == VacuumActivity.CLEANING
|
||||
|
Loading…
x
Reference in New Issue
Block a user