diff --git a/homeassistant/components/automation/template.py b/homeassistant/components/automation/template.py index f2b4134de42..95b6b857c9d 100644 --- a/homeassistant/components/automation/template.py +++ b/homeassistant/components/automation/template.py @@ -28,7 +28,9 @@ TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema( ) -async def async_attach_trigger(hass, config, action, automation_info): +async def async_attach_trigger( + hass, config, action, automation_info, *, platform_type="numeric_state" +): """Listen for state changes based on configuration.""" value_template = config.get(CONF_VALUE_TEMPLATE) value_template.hass = hass @@ -65,7 +67,7 @@ async def async_attach_trigger(hass, config, action, automation_info): variables = { "trigger": { - "platform": "template", + "platform": platform_type, "entity_id": entity_id, "from_state": from_s, "to_state": to_s, diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py index af67be5eccc..0c8d6103b12 100644 --- a/homeassistant/components/climate/__init__.py +++ b/homeassistant/components/climate/__init__.py @@ -35,7 +35,7 @@ from .const import ( ATTR_FAN_MODE, ATTR_FAN_MODES, ATTR_HUMIDITY, - ATTR_HVAC_ACTIONS, + ATTR_HVAC_ACTION, ATTR_HVAC_MODE, ATTR_HVAC_MODES, ATTR_MAX_HUMIDITY, @@ -239,7 +239,7 @@ class ClimateDevice(Entity): data[ATTR_FAN_MODES] = self.fan_modes if self.hvac_action: - data[ATTR_HVAC_ACTIONS] = self.hvac_action + data[ATTR_HVAC_ACTION] = self.hvac_action if supported_features & SUPPORT_PRESET_MODE: data[ATTR_PRESET_MODE] = self.preset_mode diff --git a/homeassistant/components/climate/const.py b/homeassistant/components/climate/const.py index 4012aa8be1b..26cec7efbeb 100644 --- a/homeassistant/components/climate/const.py +++ b/homeassistant/components/climate/const.py @@ -97,7 +97,7 @@ ATTR_MAX_HUMIDITY = "max_humidity" ATTR_MIN_HUMIDITY = "min_humidity" ATTR_MAX_TEMP = "max_temp" ATTR_MIN_TEMP = "min_temp" -ATTR_HVAC_ACTIONS = "hvac_action" +ATTR_HVAC_ACTION = "hvac_action" ATTR_HVAC_MODES = "hvac_modes" ATTR_HVAC_MODE = "hvac_mode" ATTR_SWING_MODES = "swing_modes" diff --git a/homeassistant/components/climate/device_trigger.py b/homeassistant/components/climate/device_trigger.py new file mode 100644 index 00000000000..e814bdc88de --- /dev/null +++ b/homeassistant/components/climate/device_trigger.py @@ -0,0 +1,192 @@ +"""Provides device automations for Climate.""" +from typing import List +import voluptuous as vol + +from homeassistant.const import ( + CONF_DOMAIN, + CONF_TYPE, + CONF_PLATFORM, + CONF_DEVICE_ID, + CONF_ENTITY_ID, + CONF_FOR, + CONF_ABOVE, + CONF_BELOW, +) +from homeassistant.core import HomeAssistant, CALLBACK_TYPE +from homeassistant.helpers import config_validation as cv, entity_registry +from homeassistant.helpers.typing import ConfigType +from homeassistant.components.automation import ( + state as state_automation, + numeric_state as numeric_state_automation, + AutomationActionType, +) +from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA +from . import DOMAIN, const + +TRIGGER_TYPES = { + "current_temperature_changed", + "current_humidity_changed", + "hvac_mode_changed", +} + +HVAC_MODE_TRIGGER_SCHEMA = TRIGGER_BASE_SCHEMA.extend( + { + vol.Required(CONF_ENTITY_ID): cv.entity_id, + vol.Required(CONF_TYPE): "hvac_mode_changed", + vol.Required(state_automation.CONF_TO): vol.In(const.HVAC_MODES), + } +) + +CURRENT_TRIGGER_SCHEMA = vol.All( + TRIGGER_BASE_SCHEMA.extend( + { + vol.Required(CONF_ENTITY_ID): cv.entity_id, + vol.Required(CONF_TYPE): vol.In( + ["current_temperature_changed", "current_humidity_changed"] + ), + vol.Optional(CONF_BELOW): vol.Any(vol.Coerce(float)), + vol.Optional(CONF_ABOVE): vol.Any(vol.Coerce(float)), + vol.Optional(CONF_FOR): cv.positive_time_period_dict, + } + ), + cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE), +) + +TRIGGER_SCHEMA = vol.Any(HVAC_MODE_TRIGGER_SCHEMA, CURRENT_TRIGGER_SCHEMA) + + +async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]: + """List device triggers for Climate devices.""" + registry = await entity_registry.async_get_registry(hass) + triggers = [] + + # Get all the integrations entities for this device + for entry in entity_registry.async_entries_for_device(registry, device_id): + if entry.domain != DOMAIN: + continue + + state = hass.states.get(entry.entity_id) + + # Add triggers for each entity that belongs to this integration + triggers.append( + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: device_id, + CONF_DOMAIN: DOMAIN, + CONF_ENTITY_ID: entry.entity_id, + CONF_TYPE: "hvac_mode_changed", + } + ) + + if state and const.ATTR_CURRENT_TEMPERATURE in state.attributes: + triggers.append( + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: device_id, + CONF_DOMAIN: DOMAIN, + CONF_ENTITY_ID: entry.entity_id, + CONF_TYPE: "current_temperature_changed", + } + ) + + if state and const.ATTR_CURRENT_HUMIDITY in state.attributes: + triggers.append( + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: device_id, + CONF_DOMAIN: DOMAIN, + CONF_ENTITY_ID: entry.entity_id, + CONF_TYPE: "current_humidity_changed", + } + ) + + return triggers + + +async def async_attach_trigger( + hass: HomeAssistant, + config: ConfigType, + action: AutomationActionType, + automation_info: dict, +) -> CALLBACK_TYPE: + """Attach a trigger.""" + config = TRIGGER_SCHEMA(config) + trigger_type = config[CONF_TYPE] + + if trigger_type == "hvac_mode_changed": + state_config = { + state_automation.CONF_PLATFORM: "state", + state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID], + state_automation.CONF_TO: config[state_automation.CONF_TO], + state_automation.CONF_FROM: [ + mode + for mode in const.HVAC_MODES + if mode != config[state_automation.CONF_TO] + ], + } + if CONF_FOR in config: + state_config[CONF_FOR] = config[CONF_FOR] + state_config = state_automation.TRIGGER_SCHEMA(state_config) + return await state_automation.async_attach_trigger( + hass, state_config, action, automation_info, platform_type="device" + ) + + numeric_state_config = { + numeric_state_automation.CONF_PLATFORM: "numeric_state", + numeric_state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID], + } + + if trigger_type == "current_temperature_changed": + numeric_state_config[ + numeric_state_automation.CONF_VALUE_TEMPLATE + ] = "{{ state.attributes.current_temperature }}" + else: + numeric_state_config[ + numeric_state_automation.CONF_VALUE_TEMPLATE + ] = "{{ state.attributes.current_humidity }}" + + if CONF_ABOVE in config: + numeric_state_config[CONF_ABOVE] = config[CONF_ABOVE] + if CONF_BELOW in config: + numeric_state_config[CONF_BELOW] = config[CONF_BELOW] + if CONF_FOR in config: + numeric_state_config[CONF_FOR] = config[CONF_FOR] + + numeric_state_config = numeric_state_automation.TRIGGER_SCHEMA(numeric_state_config) + return await numeric_state_automation.async_attach_trigger( + hass, numeric_state_config, action, automation_info, platform_type="device" + ) + + +async def async_get_trigger_capabilities(hass: HomeAssistant, config): + """List trigger capabilities.""" + trigger_type = config[CONF_TYPE] + + if trigger_type == "hvac_action_changed": + return None + + if trigger_type == "hvac_mode_changed": + return { + "extra_fields": vol.Schema( + {vol.Optional(CONF_FOR): cv.positive_time_period_dict} + ) + } + + if trigger_type == "current_temperature_changed": + unit_of_measurement = hass.config.units.temperature_unit + else: + unit_of_measurement = "%" + + return { + "extra_fields": vol.Schema( + { + vol.Optional( + CONF_ABOVE, description={"suffix": unit_of_measurement} + ): vol.Coerce(float), + vol.Optional( + CONF_BELOW, description={"suffix": unit_of_measurement} + ): vol.Coerce(float), + vol.Optional(CONF_FOR): cv.positive_time_period_dict, + } + ) + } diff --git a/homeassistant/components/climate/strings.json b/homeassistant/components/climate/strings.json index 7e97c7701c2..84854c713cf 100644 --- a/homeassistant/components/climate/strings.json +++ b/homeassistant/components/climate/strings.json @@ -1,5 +1,10 @@ { "device_automation": { + "trigger_type": { + "current_temperature_changed": "{entity_name} measured temperature changed", + "current_humidity_changed": "{entity_name} measured humidity changed", + "hvac_mode_changed": "{entity_name} HVAC mode changed" + }, "action_type": { "set_hvac_mode": "Change HVAC mode on {entity_name}", "set_preset_mode": "Change preset on {entity_name}" diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index 63eb688a0c1..9adc3cc0600 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -5,7 +5,7 @@ from pyhap.const import CATEGORY_THERMOSTAT from homeassistant.components.climate.const import ( ATTR_CURRENT_TEMPERATURE, - ATTR_HVAC_ACTIONS, + ATTR_HVAC_ACTION, ATTR_HVAC_MODE, ATTR_MAX_TEMP, ATTR_MIN_TEMP, @@ -293,7 +293,7 @@ class Thermostat(HomeAccessory): self._flag_heat_cool = False # Set current operation mode for supported thermostats - hvac_action = new_state.attributes.get(ATTR_HVAC_ACTIONS) + hvac_action = new_state.attributes.get(ATTR_HVAC_ACTION) if hvac_action: self.char_current_heat_cool.set_value( HC_HASS_TO_HOMEKIT_ACTION[hvac_action] diff --git a/tests/components/climate/test_device_trigger.py b/tests/components/climate/test_device_trigger.py new file mode 100644 index 00000000000..3b497912c52 --- /dev/null +++ b/tests/components/climate/test_device_trigger.py @@ -0,0 +1,243 @@ +"""The tests for Climate device triggers.""" +import voluptuous_serialize +import pytest + +from homeassistant.components.climate import DOMAIN, const, device_trigger +from homeassistant.setup import async_setup_component +import homeassistant.components.automation as automation +from homeassistant.helpers import device_registry, config_validation as cv + +from tests.common import ( + MockConfigEntry, + assert_lists_same, + async_mock_service, + mock_device_registry, + mock_registry, + async_get_device_automations, +) + + +@pytest.fixture +def device_reg(hass): + """Return an empty, loaded, registry.""" + return mock_device_registry(hass) + + +@pytest.fixture +def entity_reg(hass): + """Return an empty, loaded, registry.""" + return mock_registry(hass) + + +@pytest.fixture +def calls(hass): + """Track calls to a mock serivce.""" + return async_mock_service(hass, "test", "automation") + + +async def test_get_triggers(hass, device_reg, entity_reg): + """Test we get the expected triggers from a climate device.""" + config_entry = MockConfigEntry(domain="test", data={}) + config_entry.add_to_hass(hass) + device_entry = device_reg.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, + ) + entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id) + entity_id = f"{DOMAIN}.test_5678" + hass.states.async_set( + entity_id, + const.HVAC_MODE_COOL, + { + const.ATTR_HVAC_ACTION: const.CURRENT_HVAC_IDLE, + const.ATTR_CURRENT_HUMIDITY: 23, + const.ATTR_CURRENT_TEMPERATURE: 18, + }, + ) + expected_triggers = [ + { + "platform": "device", + "domain": DOMAIN, + "type": "hvac_mode_changed", + "device_id": device_entry.id, + "entity_id": entity_id, + }, + { + "platform": "device", + "domain": DOMAIN, + "type": "current_temperature_changed", + "device_id": device_entry.id, + "entity_id": entity_id, + }, + { + "platform": "device", + "domain": DOMAIN, + "type": "current_humidity_changed", + "device_id": device_entry.id, + "entity_id": entity_id, + }, + ] + triggers = await async_get_device_automations(hass, "trigger", device_entry.id) + assert_lists_same(triggers, expected_triggers) + + +async def test_if_fires_on_state_change(hass, calls): + """Test for turn_on and turn_off triggers firing.""" + hass.states.async_set( + "climate.entity", + const.HVAC_MODE_COOL, + { + const.ATTR_HVAC_ACTION: const.CURRENT_HVAC_IDLE, + const.ATTR_CURRENT_HUMIDITY: 23, + const.ATTR_CURRENT_TEMPERATURE: 18, + }, + ) + + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: [ + { + "trigger": { + "platform": "device", + "domain": DOMAIN, + "device_id": "", + "entity_id": "climate.entity", + "type": "hvac_mode_changed", + "to": const.HVAC_MODE_AUTO, + }, + "action": { + "service": "test.automation", + "data_template": {"some": "hvac_mode_changed"}, + }, + }, + { + "trigger": { + "platform": "device", + "domain": DOMAIN, + "device_id": "", + "entity_id": "climate.entity", + "type": "current_temperature_changed", + "above": 20, + }, + "action": { + "service": "test.automation", + "data_template": {"some": "current_temperature_changed"}, + }, + }, + { + "trigger": { + "platform": "device", + "domain": DOMAIN, + "device_id": "", + "entity_id": "climate.entity", + "type": "current_humidity_changed", + "below": 10, + }, + "action": { + "service": "test.automation", + "data_template": {"some": "current_humidity_changed"}, + }, + }, + ] + }, + ) + + # Fake that the HVAC mode is changing + hass.states.async_set( + "climate.entity", + const.HVAC_MODE_AUTO, + { + const.ATTR_HVAC_ACTION: const.CURRENT_HVAC_COOL, + const.ATTR_CURRENT_HUMIDITY: 23, + const.ATTR_CURRENT_TEMPERATURE: 18, + }, + ) + await hass.async_block_till_done() + assert len(calls) == 1 + assert calls[0].data["some"] == "hvac_mode_changed" + + # Fake that the temperature is changing + hass.states.async_set( + "climate.entity", + const.HVAC_MODE_AUTO, + { + const.ATTR_HVAC_ACTION: const.CURRENT_HVAC_COOL, + const.ATTR_CURRENT_HUMIDITY: 23, + const.ATTR_CURRENT_TEMPERATURE: 23, + }, + ) + await hass.async_block_till_done() + assert len(calls) == 2 + assert calls[1].data["some"] == "current_temperature_changed" + + # Fake that the humidity is changing + hass.states.async_set( + "climate.entity", + const.HVAC_MODE_AUTO, + { + const.ATTR_HVAC_ACTION: const.CURRENT_HVAC_COOL, + const.ATTR_CURRENT_HUMIDITY: 7, + const.ATTR_CURRENT_TEMPERATURE: 23, + }, + ) + await hass.async_block_till_done() + assert len(calls) == 3 + assert calls[2].data["some"] == "current_humidity_changed" + + +async def test_get_trigger_capabilities_hvac_mode(hass): + """Test we get the expected capabilities from a climate trigger.""" + capabilities = await device_trigger.async_get_trigger_capabilities( + hass, + { + "platform": "device", + "domain": "climate", + "type": "hvac_mode_changed", + "entity_id": "climate.upstairs", + "to": "heat", + }, + ) + assert capabilities and "extra_fields" in capabilities + + assert voluptuous_serialize.convert( + capabilities["extra_fields"], custom_serializer=cv.custom_serializer + ) == [{"name": "for", "optional": True, "type": "positive_time_period_dict"}] + + +@pytest.mark.parametrize( + "type", ["current_temperature_changed", "current_humidity_changed"] +) +async def test_get_trigger_capabilities_temp_humid(hass, type): + """Test we get the expected capabilities from a climate trigger.""" + capabilities = await device_trigger.async_get_trigger_capabilities( + hass, + { + "platform": "device", + "domain": "climate", + "type": "current_temperature_changed", + "entity_id": "climate.upstairs", + "above": "23", + }, + ) + + assert capabilities and "extra_fields" in capabilities + + assert voluptuous_serialize.convert( + capabilities["extra_fields"], custom_serializer=cv.custom_serializer + ) == [ + { + "description": {"suffix": "°C"}, + "name": "above", + "optional": True, + "type": "float", + }, + { + "description": {"suffix": "°C"}, + "name": "below", + "optional": True, + "type": "float", + }, + {"name": "for", "optional": True, "type": "positive_time_period_dict"}, + ] diff --git a/tests/components/demo/test_climate.py b/tests/components/demo/test_climate.py index eef03b2370a..2d1b7a85ff8 100644 --- a/tests/components/demo/test_climate.py +++ b/tests/components/demo/test_climate.py @@ -9,7 +9,7 @@ from homeassistant.components.climate.const import ( ATTR_CURRENT_TEMPERATURE, ATTR_FAN_MODE, ATTR_HUMIDITY, - ATTR_HVAC_ACTIONS, + ATTR_HVAC_ACTION, ATTR_HVAC_MODES, ATTR_MAX_HUMIDITY, ATTR_MAX_TEMP, @@ -233,7 +233,7 @@ async def test_set_hvac_bad_attr_and_state(hass): Also check the state. """ state = hass.states.get(ENTITY_CLIMATE) - assert state.attributes.get(ATTR_HVAC_ACTIONS) == CURRENT_HVAC_COOL + assert state.attributes.get(ATTR_HVAC_ACTION) == CURRENT_HVAC_COOL assert state.state == HVAC_MODE_COOL with pytest.raises(vol.Invalid): @@ -241,7 +241,7 @@ async def test_set_hvac_bad_attr_and_state(hass): await hass.async_block_till_done() state = hass.states.get(ENTITY_CLIMATE) - assert state.attributes.get(ATTR_HVAC_ACTIONS) == CURRENT_HVAC_COOL + assert state.attributes.get(ATTR_HVAC_ACTION) == CURRENT_HVAC_COOL assert state.state == HVAC_MODE_COOL diff --git a/tests/components/homekit/test_type_thermostats.py b/tests/components/homekit/test_type_thermostats.py index 8ad46e489d6..c896ad211e8 100644 --- a/tests/components/homekit/test_type_thermostats.py +++ b/tests/components/homekit/test_type_thermostats.py @@ -6,7 +6,7 @@ import pytest from homeassistant.components.climate.const import ( ATTR_CURRENT_TEMPERATURE, - ATTR_HVAC_ACTIONS, + ATTR_HVAC_ACTION, ATTR_HVAC_MODE, ATTR_HVAC_MODES, ATTR_MAX_TEMP, @@ -92,7 +92,7 @@ async def test_thermostat(hass, hk_driver, cls, events): { ATTR_TEMPERATURE: 22.2, ATTR_CURRENT_TEMPERATURE: 17.8, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_HEAT, + ATTR_HVAC_ACTION: CURRENT_HVAC_HEAT, }, ) await hass.async_block_till_done() @@ -108,7 +108,7 @@ async def test_thermostat(hass, hk_driver, cls, events): { ATTR_TEMPERATURE: 22.0, ATTR_CURRENT_TEMPERATURE: 23.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_IDLE, + ATTR_HVAC_ACTION: CURRENT_HVAC_IDLE, }, ) await hass.async_block_till_done() @@ -124,7 +124,7 @@ async def test_thermostat(hass, hk_driver, cls, events): { ATTR_TEMPERATURE: 20.0, ATTR_CURRENT_TEMPERATURE: 25.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_COOL, + ATTR_HVAC_ACTION: CURRENT_HVAC_COOL, }, ) await hass.async_block_till_done() @@ -140,7 +140,7 @@ async def test_thermostat(hass, hk_driver, cls, events): { ATTR_TEMPERATURE: 20.0, ATTR_CURRENT_TEMPERATURE: 19.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_IDLE, + ATTR_HVAC_ACTION: CURRENT_HVAC_IDLE, }, ) await hass.async_block_till_done() @@ -169,7 +169,7 @@ async def test_thermostat(hass, hk_driver, cls, events): ATTR_HVAC_MODES: [HVAC_MODE_HEAT, HVAC_MODE_COOL], ATTR_TEMPERATURE: 22.0, ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_HEAT, + ATTR_HVAC_ACTION: CURRENT_HVAC_HEAT, }, ) await hass.async_block_till_done() @@ -186,7 +186,7 @@ async def test_thermostat(hass, hk_driver, cls, events): ATTR_HVAC_MODES: [HVAC_MODE_HEAT, HVAC_MODE_COOL], ATTR_TEMPERATURE: 22.0, ATTR_CURRENT_TEMPERATURE: 25.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_COOL, + ATTR_HVAC_ACTION: CURRENT_HVAC_COOL, }, ) await hass.async_block_till_done() @@ -203,7 +203,7 @@ async def test_thermostat(hass, hk_driver, cls, events): ATTR_HVAC_MODES: [HVAC_MODE_HEAT, HVAC_MODE_COOL], ATTR_TEMPERATURE: 22.0, ATTR_CURRENT_TEMPERATURE: 22.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_IDLE, + ATTR_HVAC_ACTION: CURRENT_HVAC_IDLE, }, ) await hass.async_block_till_done() @@ -265,7 +265,7 @@ async def test_thermostat_auto(hass, hk_driver, cls, events): ATTR_TARGET_TEMP_HIGH: 22.0, ATTR_TARGET_TEMP_LOW: 20.0, ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_HEAT, + ATTR_HVAC_ACTION: CURRENT_HVAC_HEAT, }, ) await hass.async_block_till_done() @@ -284,7 +284,7 @@ async def test_thermostat_auto(hass, hk_driver, cls, events): ATTR_TARGET_TEMP_HIGH: 23.0, ATTR_TARGET_TEMP_LOW: 19.0, ATTR_CURRENT_TEMPERATURE: 24.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_COOL, + ATTR_HVAC_ACTION: CURRENT_HVAC_COOL, }, ) await hass.async_block_till_done() @@ -303,7 +303,7 @@ async def test_thermostat_auto(hass, hk_driver, cls, events): ATTR_TARGET_TEMP_HIGH: 23.0, ATTR_TARGET_TEMP_LOW: 19.0, ATTR_CURRENT_TEMPERATURE: 21.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_IDLE, + ATTR_HVAC_ACTION: CURRENT_HVAC_IDLE, }, ) await hass.async_block_till_done() @@ -349,7 +349,7 @@ async def test_thermostat_power_state(hass, hk_driver, cls, events): ATTR_HVAC_MODE: HVAC_MODE_HEAT, ATTR_TEMPERATURE: 23.0, ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_HEAT, + ATTR_HVAC_ACTION: CURRENT_HVAC_HEAT, }, ) await hass.async_block_till_done() @@ -367,7 +367,7 @@ async def test_thermostat_power_state(hass, hk_driver, cls, events): ATTR_HVAC_MODE: HVAC_MODE_HEAT, ATTR_TEMPERATURE: 23.0, ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_IDLE, + ATTR_HVAC_ACTION: CURRENT_HVAC_IDLE, }, ) await hass.async_block_till_done() @@ -381,7 +381,7 @@ async def test_thermostat_power_state(hass, hk_driver, cls, events): ATTR_HVAC_MODE: HVAC_MODE_OFF, ATTR_TEMPERATURE: 23.0, ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_HVAC_ACTIONS: CURRENT_HVAC_IDLE, + ATTR_HVAC_ACTION: CURRENT_HVAC_IDLE, }, ) await hass.async_block_till_done() diff --git a/tests/components/smartthings/test_climate.py b/tests/components/smartthings/test_climate.py index c366761ea1f..630174a0661 100644 --- a/tests/components/smartthings/test_climate.py +++ b/tests/components/smartthings/test_climate.py @@ -13,7 +13,7 @@ from homeassistant.components.climate.const import ( ATTR_CURRENT_TEMPERATURE, ATTR_FAN_MODE, ATTR_FAN_MODES, - ATTR_HVAC_ACTIONS, + ATTR_HVAC_ACTION, ATTR_HVAC_MODE, ATTR_HVAC_MODES, ATTR_TARGET_TEMP_HIGH, @@ -214,7 +214,7 @@ async def test_legacy_thermostat_entity_state(hass, legacy_thermostat): | SUPPORT_TARGET_TEMPERATURE_RANGE | SUPPORT_TARGET_TEMPERATURE ) - assert state.attributes[ATTR_HVAC_ACTIONS] == CURRENT_HVAC_IDLE + assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE assert sorted(state.attributes[ATTR_HVAC_MODES]) == [ HVAC_MODE_AUTO, HVAC_MODE_COOL, @@ -238,7 +238,7 @@ async def test_basic_thermostat_entity_state(hass, basic_thermostat): state.attributes[ATTR_SUPPORTED_FEATURES] == SUPPORT_TARGET_TEMPERATURE_RANGE | SUPPORT_TARGET_TEMPERATURE ) - assert ATTR_HVAC_ACTIONS not in state.attributes + assert ATTR_HVAC_ACTION not in state.attributes assert sorted(state.attributes[ATTR_HVAC_MODES]) == [ HVAC_MODE_COOL, HVAC_MODE_HEAT, @@ -259,7 +259,7 @@ async def test_thermostat_entity_state(hass, thermostat): | SUPPORT_TARGET_TEMPERATURE_RANGE | SUPPORT_TARGET_TEMPERATURE ) - assert state.attributes[ATTR_HVAC_ACTIONS] == CURRENT_HVAC_IDLE + assert state.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE assert sorted(state.attributes[ATTR_HVAC_MODES]) == [ HVAC_MODE_AUTO, HVAC_MODE_COOL,