mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Add config flow to generic thermostat (#119930)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
parent
6a34e1b7ca
commit
4d982a9227
@ -1,6 +1,25 @@
|
||||
"""The generic_thermostat component."""
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
DOMAIN = "generic_thermostat"
|
||||
PLATFORMS = [Platform.CLIMATE]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up from a config entry."""
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
entry.async_on_unload(entry.add_update_listener(config_entry_update_listener))
|
||||
return True
|
||||
|
||||
|
||||
async def config_entry_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
"""Update listener, called when the config entry options are changed."""
|
||||
await hass.config_entries.async_reload(entry.entry_id)
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Mapping
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
import math
|
||||
@ -25,6 +26,7 @@ from homeassistant.components.climate import (
|
||||
HVACAction,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_TEMPERATURE,
|
||||
@ -51,8 +53,7 @@ from homeassistant.core import (
|
||||
callback,
|
||||
)
|
||||
from homeassistant.exceptions import ConditionError
|
||||
from homeassistant.helpers import condition
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers import condition, config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import (
|
||||
async_track_state_change_event,
|
||||
@ -95,7 +96,7 @@ CONF_PRESETS = {
|
||||
)
|
||||
}
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
PLATFORM_SCHEMA_COMMON = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HEATER): cv.entity_id,
|
||||
vol.Required(CONF_SENSOR): cv.entity_id,
|
||||
@ -111,15 +112,34 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
vol.Optional(CONF_INITIAL_HVAC_MODE): vol.In(
|
||||
[HVACMode.COOL, HVACMode.HEAT, HVACMode.OFF]
|
||||
),
|
||||
vol.Optional(CONF_PRECISION): vol.In(
|
||||
[PRECISION_TENTHS, PRECISION_HALVES, PRECISION_WHOLE]
|
||||
vol.Optional(CONF_PRECISION): vol.All(
|
||||
vol.Coerce(float),
|
||||
vol.In([PRECISION_TENTHS, PRECISION_HALVES, PRECISION_WHOLE]),
|
||||
),
|
||||
vol.Optional(CONF_TEMP_STEP): vol.In(
|
||||
[PRECISION_TENTHS, PRECISION_HALVES, PRECISION_WHOLE]
|
||||
vol.Optional(CONF_TEMP_STEP): vol.All(
|
||||
vol.In([PRECISION_TENTHS, PRECISION_HALVES, PRECISION_WHOLE])
|
||||
),
|
||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||
**{vol.Optional(v): vol.Coerce(float) for v in CONF_PRESETS.values()},
|
||||
}
|
||||
).extend({vol.Optional(v): vol.Coerce(float) for (k, v) in CONF_PRESETS.items()})
|
||||
)
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(PLATFORM_SCHEMA_COMMON.schema)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Initialize config entry."""
|
||||
await _async_setup_config(
|
||||
hass,
|
||||
PLATFORM_SCHEMA_COMMON(dict(config_entry.options)),
|
||||
config_entry.entry_id,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
@ -131,6 +151,18 @@ async def async_setup_platform(
|
||||
"""Set up the generic thermostat platform."""
|
||||
|
||||
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
|
||||
await _async_setup_config(
|
||||
hass, config, config.get(CONF_UNIQUE_ID), async_add_entities
|
||||
)
|
||||
|
||||
|
||||
async def _async_setup_config(
|
||||
hass: HomeAssistant,
|
||||
config: Mapping[str, Any],
|
||||
unique_id: str | None,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the generic thermostat platform."""
|
||||
|
||||
name: str = config[CONF_NAME]
|
||||
heater_entity_id: str = config[CONF_HEATER]
|
||||
@ -150,7 +182,6 @@ async def async_setup_platform(
|
||||
precision: float | None = config.get(CONF_PRECISION)
|
||||
target_temperature_step: float | None = config.get(CONF_TEMP_STEP)
|
||||
unit = hass.config.units.temperature_unit
|
||||
unique_id: str | None = config.get(CONF_UNIQUE_ID)
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
|
96
homeassistant/components/generic_thermostat/config_flow.py
Normal file
96
homeassistant/components/generic_thermostat/config_flow.py
Normal file
@ -0,0 +1,96 @@
|
||||
"""Config flow for Generic hygrostat."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, cast
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN, SensorDeviceClass
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.const import CONF_NAME, DEGREE
|
||||
from homeassistant.helpers import selector
|
||||
from homeassistant.helpers.schema_config_entry_flow import (
|
||||
SchemaConfigFlowHandler,
|
||||
SchemaFlowFormStep,
|
||||
)
|
||||
|
||||
from .climate import (
|
||||
CONF_AC_MODE,
|
||||
CONF_COLD_TOLERANCE,
|
||||
CONF_HEATER,
|
||||
CONF_HOT_TOLERANCE,
|
||||
CONF_MIN_DUR,
|
||||
CONF_PRESETS,
|
||||
CONF_SENSOR,
|
||||
DEFAULT_TOLERANCE,
|
||||
DOMAIN,
|
||||
)
|
||||
|
||||
OPTIONS_SCHEMA = {
|
||||
vol.Required(CONF_AC_MODE): selector.BooleanSelector(
|
||||
selector.BooleanSelectorConfig(),
|
||||
),
|
||||
vol.Required(CONF_SENSOR): selector.EntitySelector(
|
||||
selector.EntitySelectorConfig(
|
||||
domain=SENSOR_DOMAIN, device_class=SensorDeviceClass.TEMPERATURE
|
||||
)
|
||||
),
|
||||
vol.Required(CONF_HEATER): selector.EntitySelector(
|
||||
selector.EntitySelectorConfig(domain=SWITCH_DOMAIN)
|
||||
),
|
||||
vol.Required(
|
||||
CONF_COLD_TOLERANCE, default=DEFAULT_TOLERANCE
|
||||
): selector.NumberSelector(
|
||||
selector.NumberSelectorConfig(
|
||||
mode=selector.NumberSelectorMode.BOX, unit_of_measurement=DEGREE, step=0.1
|
||||
)
|
||||
),
|
||||
vol.Required(
|
||||
CONF_HOT_TOLERANCE, default=DEFAULT_TOLERANCE
|
||||
): selector.NumberSelector(
|
||||
selector.NumberSelectorConfig(
|
||||
mode=selector.NumberSelectorMode.BOX, unit_of_measurement=DEGREE, step=0.1
|
||||
)
|
||||
),
|
||||
vol.Optional(CONF_MIN_DUR): selector.DurationSelector(
|
||||
selector.DurationSelectorConfig(allow_negative=False)
|
||||
),
|
||||
}
|
||||
|
||||
PRESETS_SCHEMA = {
|
||||
vol.Optional(v): selector.NumberSelector(
|
||||
selector.NumberSelectorConfig(
|
||||
mode=selector.NumberSelectorMode.BOX, unit_of_measurement=DEGREE
|
||||
)
|
||||
)
|
||||
for v in CONF_PRESETS.values()
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
vol.Required(CONF_NAME): selector.TextSelector(),
|
||||
**OPTIONS_SCHEMA,
|
||||
}
|
||||
|
||||
|
||||
CONFIG_FLOW = {
|
||||
"user": SchemaFlowFormStep(vol.Schema(CONFIG_SCHEMA), next_step="presets"),
|
||||
"presets": SchemaFlowFormStep(vol.Schema(PRESETS_SCHEMA)),
|
||||
}
|
||||
|
||||
OPTIONS_FLOW = {
|
||||
"init": SchemaFlowFormStep(vol.Schema(OPTIONS_SCHEMA), next_step="presets"),
|
||||
"presets": SchemaFlowFormStep(vol.Schema(PRESETS_SCHEMA)),
|
||||
}
|
||||
|
||||
|
||||
class ConfigFlowHandler(SchemaConfigFlowHandler, domain=DOMAIN):
|
||||
"""Handle a config or options flow."""
|
||||
|
||||
config_flow = CONFIG_FLOW
|
||||
options_flow = OPTIONS_FLOW
|
||||
|
||||
def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
|
||||
"""Return config entry title."""
|
||||
return cast(str, options["name"])
|
@ -2,7 +2,9 @@
|
||||
"domain": "generic_thermostat",
|
||||
"name": "Generic Thermostat",
|
||||
"codeowners": [],
|
||||
"config_flow": true,
|
||||
"dependencies": ["sensor", "switch"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/generic_thermostat",
|
||||
"integration_type": "helper",
|
||||
"iot_class": "local_polling"
|
||||
}
|
||||
|
@ -1,4 +1,74 @@
|
||||
{
|
||||
"title": "Generic thermostat",
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Add generic thermostat helper",
|
||||
"description": "Create a climate entity that controls the temperature via a switch and sensor.",
|
||||
"data": {
|
||||
"ac_mode": "Cooling mode",
|
||||
"heater": "Actuator switch",
|
||||
"target_sensor": "Temperature sensor",
|
||||
"min_cycle_duration": "Minimum cycle duration",
|
||||
"name": "[%key:common::config_flow::data::name%]",
|
||||
"cold_tolerance": "Cold tolerance",
|
||||
"hot_tolerance": "Hot tolerance"
|
||||
},
|
||||
"data_description": {
|
||||
"ac_mode": "Set the actuator specified to be treated as a cooling device instead of a heating device.",
|
||||
"heater": "Switch entity used to cool or heat depending on A/C mode.",
|
||||
"target_sensor": "Temperature sensor that reflect the current temperature.",
|
||||
"min_cycle_duration": "Set a minimum amount of time that the switch specified must be in its current state prior to being switched either off or on. This option will be ignored if the keep alive option is set.",
|
||||
"cold_tolerance": "Minimum amount of difference between the temperature read by the temperature sensor the target temperature that must change prior to being switched on. For example, if the target temperature is 25 and the tolerance is 0.5 the heater will start when the sensor equals or goes below 24.5.",
|
||||
"hot_tolerance": "Minimum amount of difference between the temperature read by the temperature sensor the target temperature that must change prior to being switched off. For example, if the target temperature is 25 and the tolerance is 0.5 the heater will stop when the sensor equals or goes above 25.5."
|
||||
}
|
||||
},
|
||||
"presets": {
|
||||
"title": "Temperature presets",
|
||||
"data": {
|
||||
"away_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::away%]",
|
||||
"comfort_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::comfort%]",
|
||||
"eco_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::eco%]",
|
||||
"home_temp": "[%common::state::home%]",
|
||||
"sleep_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::sleep%]",
|
||||
"activity_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::activity%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ac_mode": "[%key:component::generic_thermostat::config::step::user::data::ac_mode%]",
|
||||
"heater": "[%key:component::generic_thermostat::config::step::user::data::heater%]",
|
||||
"target_sensor": "[%key:component::generic_thermostat::config::step::user::data::target_sensor%]",
|
||||
"min_cycle_duration": "[%key:component::generic_thermostat::config::step::user::data::min_cycle_duration%]",
|
||||
"cold_tolerance": "[%key:component::generic_thermostat::config::step::user::data::cold_tolerance%]",
|
||||
"hot_tolerance": "[%key:component::generic_thermostat::config::step::user::data::hot_tolerance%]"
|
||||
},
|
||||
"data_description": {
|
||||
"heater": "[%key:component::generic_thermostat::config::step::user::data_description::heater%]",
|
||||
"target_sensor": "[%key:component::generic_thermostat::config::step::user::data_description::target_sensor%]",
|
||||
"ac_mode": "[%key:component::generic_thermostat::config::step::user::data_description::ac_mode%]",
|
||||
"min_cycle_duration": "[%key:component::generic_thermostat::config::step::user::data_description::min_cycle_duration%]",
|
||||
"cold_tolerance": "[%key:component::generic_thermostat::config::step::user::data_description::cold_tolerance%]",
|
||||
"hot_tolerance": "[%key:component::generic_thermostat::config::step::user::data_description::hot_tolerance%]"
|
||||
}
|
||||
},
|
||||
"presets": {
|
||||
"title": "[%key:component::generic_thermostat::config::step::presets::title%]",
|
||||
"data": {
|
||||
"away_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::away%]",
|
||||
"comfort_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::comfort%]",
|
||||
"eco_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::eco%]",
|
||||
"home_temp": "[%key:common::state::home%]",
|
||||
"sleep_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::sleep%]",
|
||||
"activity_temp": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::activity%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"reload": {
|
||||
"name": "[%key:common::action::reload%]",
|
||||
|
@ -6,6 +6,7 @@ To update, run python3 -m script.hassfest
|
||||
FLOWS = {
|
||||
"helper": [
|
||||
"derivative",
|
||||
"generic_thermostat",
|
||||
"group",
|
||||
"integration",
|
||||
"min_max",
|
||||
|
@ -2133,12 +2133,6 @@
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"generic_thermostat": {
|
||||
"name": "Generic Thermostat",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"geniushub": {
|
||||
"name": "Genius Hub",
|
||||
"integration_type": "hub",
|
||||
@ -7166,6 +7160,11 @@
|
||||
"config_flow": true,
|
||||
"iot_class": "calculated"
|
||||
},
|
||||
"generic_thermostat": {
|
||||
"integration_type": "helper",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"group": {
|
||||
"integration_type": "helper",
|
||||
"config_flow": true,
|
||||
@ -7266,6 +7265,7 @@
|
||||
"filesize",
|
||||
"garages_amsterdam",
|
||||
"generic",
|
||||
"generic_thermostat",
|
||||
"google_travel_time",
|
||||
"group",
|
||||
"growatt_server",
|
||||
|
@ -0,0 +1,89 @@
|
||||
# serializer version: 1
|
||||
# name: test_config_flow[create_entry]
|
||||
FlowResultSnapshot({
|
||||
'result': ConfigEntrySnapshot({
|
||||
'title': 'My thermostat',
|
||||
}),
|
||||
'title': 'My thermostat',
|
||||
'type': <FlowResultType.CREATE_ENTRY: 'create_entry'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_config_flow[init]
|
||||
FlowResultSnapshot({
|
||||
'type': <FlowResultType.FORM: 'form'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_config_flow[presets]
|
||||
FlowResultSnapshot({
|
||||
'type': <FlowResultType.FORM: 'form'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_options[create_entry]
|
||||
FlowResultSnapshot({
|
||||
'result': True,
|
||||
'type': <FlowResultType.CREATE_ENTRY: 'create_entry'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_options[init]
|
||||
FlowResultSnapshot({
|
||||
'type': <FlowResultType.FORM: 'form'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_options[presets]
|
||||
FlowResultSnapshot({
|
||||
'type': <FlowResultType.FORM: 'form'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_options[with_away]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'current_temperature': 15.0,
|
||||
'friendly_name': 'My thermostat',
|
||||
'hvac_action': <HVACAction.OFF: 'off'>,
|
||||
'hvac_modes': list([
|
||||
<HVACMode.HEAT: 'heat'>,
|
||||
<HVACMode.OFF: 'off'>,
|
||||
]),
|
||||
'max_temp': 35,
|
||||
'min_temp': 7,
|
||||
'preset_mode': 'none',
|
||||
'preset_modes': list([
|
||||
'none',
|
||||
'away',
|
||||
]),
|
||||
'supported_features': <ClimateEntityFeature: 401>,
|
||||
'target_temp_step': 0.1,
|
||||
'temperature': 7,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'climate.my_thermostat',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_options[without_away]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'current_temperature': 15.0,
|
||||
'friendly_name': 'My thermostat',
|
||||
'hvac_action': <HVACAction.OFF: 'off'>,
|
||||
'hvac_modes': list([
|
||||
<HVACMode.HEAT: 'heat'>,
|
||||
<HVACMode.OFF: 'off'>,
|
||||
]),
|
||||
'max_temp': 35,
|
||||
'min_temp': 7,
|
||||
'supported_features': <ClimateEntityFeature: 385>,
|
||||
'target_temp_step': 0.1,
|
||||
'temperature': 7.0,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'climate.my_thermostat',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
134
tests/components/generic_thermostat/test_config_flow.py
Normal file
134
tests/components/generic_thermostat/test_config_flow.py
Normal file
@ -0,0 +1,134 @@
|
||||
"""Test the generic hygrostat config flow."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from syrupy.filters import props
|
||||
|
||||
from homeassistant.components.climate import PRESET_AWAY
|
||||
from homeassistant.components.generic_thermostat.climate import (
|
||||
CONF_AC_MODE,
|
||||
CONF_COLD_TOLERANCE,
|
||||
CONF_HEATER,
|
||||
CONF_HOT_TOLERANCE,
|
||||
CONF_NAME,
|
||||
CONF_PRESETS,
|
||||
CONF_SENSOR,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.config_entries import SOURCE_USER
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
STATE_OFF,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
SNAPSHOT_FLOW_PROPS = props("type", "title", "result", "error")
|
||||
|
||||
|
||||
async def test_config_flow(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None:
|
||||
"""Test the config flow."""
|
||||
with patch(
|
||||
"homeassistant.components.generic_thermostat.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result == snapshot(name="init", include=SNAPSHOT_FLOW_PROPS)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_NAME: "My thermostat",
|
||||
CONF_HEATER: "switch.run",
|
||||
CONF_SENSOR: "sensor.temperature",
|
||||
CONF_AC_MODE: False,
|
||||
CONF_COLD_TOLERANCE: 0.3,
|
||||
CONF_HOT_TOLERANCE: 0.3,
|
||||
},
|
||||
)
|
||||
assert result == snapshot(name="presets", include=SNAPSHOT_FLOW_PROPS)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_PRESETS[PRESET_AWAY]: 20,
|
||||
},
|
||||
)
|
||||
assert result == snapshot(name="create_entry", include=SNAPSHOT_FLOW_PROPS)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
config_entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||
assert config_entry.data == {}
|
||||
assert config_entry.title == "My thermostat"
|
||||
|
||||
|
||||
async def test_options(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None:
|
||||
"""Test reconfiguring."""
|
||||
|
||||
config_entry = MockConfigEntry(
|
||||
data={},
|
||||
domain=DOMAIN,
|
||||
options={
|
||||
CONF_NAME: "My thermostat",
|
||||
CONF_HEATER: "switch.run",
|
||||
CONF_SENSOR: "sensor.temperature",
|
||||
CONF_AC_MODE: False,
|
||||
CONF_COLD_TOLERANCE: 0.3,
|
||||
CONF_HOT_TOLERANCE: 0.3,
|
||||
CONF_PRESETS[PRESET_AWAY]: 20,
|
||||
},
|
||||
title="My dehumidifier",
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
hass.states.async_set(
|
||||
"sensor.temperature",
|
||||
"15",
|
||||
{
|
||||
ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.CELSIUS,
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
},
|
||||
)
|
||||
hass.states.async_set("switch.run", STATE_OFF)
|
||||
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
# check that it is setup
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("climate.my_thermostat") == snapshot(name="with_away")
|
||||
|
||||
# remove away preset
|
||||
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||
assert result == snapshot(name="init", include=SNAPSHOT_FLOW_PROPS)
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_HEATER: "switch.run",
|
||||
CONF_SENSOR: "sensor.temperature",
|
||||
CONF_AC_MODE: False,
|
||||
CONF_COLD_TOLERANCE: 0.3,
|
||||
CONF_HOT_TOLERANCE: 0.3,
|
||||
},
|
||||
)
|
||||
assert result == snapshot(name="presets", include=SNAPSHOT_FLOW_PROPS)
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={},
|
||||
)
|
||||
assert result == snapshot(name="create_entry", include=SNAPSHOT_FLOW_PROPS)
|
||||
|
||||
# Check config entry is reloaded with new options
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("climate.my_thermostat") == snapshot(name="without_away")
|
Loading…
x
Reference in New Issue
Block a user