diff --git a/homeassistant/components/climate/icons.json b/homeassistant/components/climate/icons.json index 9f016f80597..636df375d66 100644 --- a/homeassistant/components/climate/icons.json +++ b/homeassistant/components/climate/icons.json @@ -98,6 +98,18 @@ } }, "triggers": { + "current_humidity_changed": { + "trigger": "mdi:water-percent" + }, + "current_humidity_crossed_threshold": { + "trigger": "mdi:water-percent" + }, + "current_temperature_changed": { + "trigger": "mdi:thermometer" + }, + "current_temperature_crossed_threshold": { + "trigger": "mdi:thermometer" + }, "hvac_mode_changed": { "trigger": "mdi:thermostat" }, @@ -110,6 +122,12 @@ "started_heating": { "trigger": "mdi:fire" }, + "target_humidity_changed": { + "trigger": "mdi:water-percent" + }, + "target_humidity_crossed_threshold": { + "trigger": "mdi:water-percent" + }, "target_temperature_changed": { "trigger": "mdi:thermometer" }, diff --git a/homeassistant/components/climate/strings.json b/homeassistant/components/climate/strings.json index 005d397ed63..819d2591765 100644 --- a/homeassistant/components/climate/strings.json +++ b/homeassistant/components/climate/strings.json @@ -312,6 +312,78 @@ }, "title": "Climate", "triggers": { + "current_humidity_changed": { + "description": "Triggers after the humidity measured by one or more climate-control devices changes.", + "fields": { + "above": { + "description": "Trigger when the humidity is above this value.", + "name": "Above" + }, + "below": { + "description": "Trigger when the humidity is below this value.", + "name": "Below" + } + }, + "name": "Climate-control device current humidity changed" + }, + "current_humidity_crossed_threshold": { + "description": "Triggers after the humidity measured by one or more climate-control devices crosses a threshold.", + "fields": { + "behavior": { + "description": "[%key:component::climate::common::trigger_behavior_description%]", + "name": "[%key:component::climate::common::trigger_behavior_name%]" + }, + "lower_limit": { + "description": "Lower threshold limit.", + "name": "Lower threshold" + }, + "threshold_type": { + "description": "Type of threshold crossing to trigger on.", + "name": "Threshold type" + }, + "upper_limit": { + "description": "Upper threshold limit.", + "name": "Upper threshold" + } + }, + "name": "Climate-control device current humidity crossed threshold" + }, + "current_temperature_changed": { + "description": "Triggers after the temperature measured by one or more climate-control devices changes.", + "fields": { + "above": { + "description": "Trigger when the temperature is above this value.", + "name": "Above" + }, + "below": { + "description": "Trigger when the temperature is below this value.", + "name": "Below" + } + }, + "name": "Climate-control device current temperature changed" + }, + "current_temperature_crossed_threshold": { + "description": "Triggers after the temperature measured by one or more climate-control devices crosses a threshold.", + "fields": { + "behavior": { + "description": "[%key:component::climate::common::trigger_behavior_description%]", + "name": "[%key:component::climate::common::trigger_behavior_name%]" + }, + "lower_limit": { + "description": "Lower threshold limit.", + "name": "Lower threshold" + }, + "threshold_type": { + "description": "Type of threshold crossing to trigger on.", + "name": "Threshold type" + }, + "upper_limit": { + "description": "Upper threshold limit.", + "name": "Upper threshold" + } + }, + "name": "Climate-control device current temperature crossed threshold" + }, "hvac_mode_changed": { "description": "Triggers after the mode of one or more climate-control devices changes.", "fields": { @@ -356,6 +428,42 @@ }, "name": "Climate-control device started heating" }, + "target_humidity_changed": { + "description": "Triggers after the humidity setpoint of one or more climate-control devices changes.", + "fields": { + "above": { + "description": "Trigger when the target humidity is above this value.", + "name": "Above" + }, + "below": { + "description": "Trigger when the target humidity is below this value.", + "name": "Below" + } + }, + "name": "Climate-control device target humidity changed" + }, + "target_humidity_crossed_threshold": { + "description": "Triggers after the humidity setpoint of one or more climate-control devices crosses a threshold.", + "fields": { + "behavior": { + "description": "[%key:component::climate::common::trigger_behavior_description%]", + "name": "[%key:component::climate::common::trigger_behavior_name%]" + }, + "lower_limit": { + "description": "Lower threshold limit.", + "name": "Lower threshold" + }, + "threshold_type": { + "description": "Type of threshold crossing to trigger on.", + "name": "Threshold type" + }, + "upper_limit": { + "description": "Upper threshold limit.", + "name": "Upper threshold" + } + }, + "name": "Climate-control device target humidity crossed threshold" + }, "target_temperature_changed": { "description": "Triggers after the temperature setpoint of one or more climate-control devices changes.", "fields": { diff --git a/homeassistant/components/climate/trigger.py b/homeassistant/components/climate/trigger.py index 0ac8a0addbd..fa02031b2ea 100644 --- a/homeassistant/components/climate/trigger.py +++ b/homeassistant/components/climate/trigger.py @@ -17,7 +17,15 @@ from homeassistant.helpers.trigger import ( make_entity_transition_trigger, ) -from .const import ATTR_HVAC_ACTION, DOMAIN, HVACAction, HVACMode +from .const import ( + ATTR_CURRENT_HUMIDITY, + ATTR_CURRENT_TEMPERATURE, + ATTR_HUMIDITY, + ATTR_HVAC_ACTION, + DOMAIN, + HVACAction, + HVACMode, +) CONF_HVAC_MODE = "hvac_mode" @@ -45,6 +53,18 @@ class HVACModeChangedTrigger(EntityTargetStateTriggerBase): TRIGGERS: dict[str, type[Trigger]] = { + "current_humidity_changed": make_entity_numerical_state_attribute_changed_trigger( + DOMAIN, ATTR_CURRENT_HUMIDITY + ), + "current_humidity_crossed_threshold": make_entity_numerical_state_attribute_crossed_threshold_trigger( + DOMAIN, ATTR_CURRENT_HUMIDITY + ), + "current_temperature_changed": make_entity_numerical_state_attribute_changed_trigger( + DOMAIN, ATTR_CURRENT_TEMPERATURE + ), + "current_temperature_crossed_threshold": make_entity_numerical_state_attribute_crossed_threshold_trigger( + DOMAIN, ATTR_CURRENT_TEMPERATURE + ), "hvac_mode_changed": HVACModeChangedTrigger, "started_cooling": make_entity_target_state_attribute_trigger( DOMAIN, ATTR_HVAC_ACTION, HVACAction.COOLING @@ -52,6 +72,12 @@ TRIGGERS: dict[str, type[Trigger]] = { "started_drying": make_entity_target_state_attribute_trigger( DOMAIN, ATTR_HVAC_ACTION, HVACAction.DRYING ), + "target_humidity_changed": make_entity_numerical_state_attribute_changed_trigger( + DOMAIN, ATTR_HUMIDITY + ), + "target_humidity_crossed_threshold": make_entity_numerical_state_attribute_crossed_threshold_trigger( + DOMAIN, ATTR_HUMIDITY + ), "target_temperature_changed": make_entity_numerical_state_attribute_changed_trigger( DOMAIN, ATTR_TEMPERATURE ), diff --git a/homeassistant/components/climate/triggers.yaml b/homeassistant/components/climate/triggers.yaml index 9b4469eed67..0614e0ccd36 100644 --- a/homeassistant/components/climate/triggers.yaml +++ b/homeassistant/components/climate/triggers.yaml @@ -65,6 +65,48 @@ hvac_mode_changed: - unknown multiple: true +current_humidity_changed: + target: *trigger_climate_target + fields: + above: *number_or_entity + below: *number_or_entity + +current_humidity_crossed_threshold: + target: *trigger_climate_target + fields: + behavior: *trigger_behavior + threshold_type: *trigger_threshold_type + lower_limit: *number_or_entity + upper_limit: *number_or_entity + +target_humidity_changed: + target: *trigger_climate_target + fields: + above: *number_or_entity + below: *number_or_entity + +target_humidity_crossed_threshold: + target: *trigger_climate_target + fields: + behavior: *trigger_behavior + threshold_type: *trigger_threshold_type + lower_limit: *number_or_entity + upper_limit: *number_or_entity + +current_temperature_changed: + target: *trigger_climate_target + fields: + above: *number_or_entity + below: *number_or_entity + +current_temperature_crossed_threshold: + target: *trigger_climate_target + fields: + behavior: *trigger_behavior + threshold_type: *trigger_threshold_type + lower_limit: *number_or_entity + upper_limit: *number_or_entity + target_temperature_changed: target: *trigger_climate_target fields: diff --git a/tests/components/climate/test_trigger.py b/tests/components/climate/test_trigger.py index 6993427e6c4..6af1c638d30 100644 --- a/tests/components/climate/test_trigger.py +++ b/tests/components/climate/test_trigger.py @@ -9,6 +9,9 @@ import pytest import voluptuous as vol from homeassistant.components.climate.const import ( + ATTR_CURRENT_HUMIDITY, + ATTR_CURRENT_TEMPERATURE, + ATTR_HUMIDITY, ATTR_HVAC_ACTION, HVACAction, HVACMode, @@ -67,7 +70,13 @@ async def target_climates(hass: HomeAssistant) -> list[str]: @pytest.mark.parametrize( "trigger_key", [ + "climate.current_humidity_changed", + "climate.current_humidity_crossed_threshold", + "climate.current_temperature_changed", + "climate.current_temperature_crossed_threshold", "climate.hvac_mode_changed", + "climate.target_humidity_changed", + "climate.target_humidity_crossed_threshold", "climate.target_temperature_changed", "climate.target_temperature_crossed_threshold", "climate.turned_off", @@ -367,9 +376,27 @@ async def test_climate_state_trigger_behavior_any( @pytest.mark.parametrize( ("trigger", "trigger_options", "states"), [ + *parametrize_xxx_changed_trigger_states( + "climate.current_humidity_changed", ATTR_CURRENT_HUMIDITY + ), + *parametrize_xxx_changed_trigger_states( + "climate.current_temperature_changed", ATTR_CURRENT_TEMPERATURE + ), + *parametrize_xxx_changed_trigger_states( + "climate.target_humidity_changed", ATTR_HUMIDITY + ), *parametrize_xxx_changed_trigger_states( "climate.target_temperature_changed", ATTR_TEMPERATURE ), + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.current_humidity_crossed_threshold", ATTR_CURRENT_HUMIDITY + ), + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.current_temperature_crossed_threshold", ATTR_CURRENT_TEMPERATURE + ), + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.target_humidity_crossed_threshold", ATTR_HUMIDITY + ), *parametrize_xxx_crossed_threshold_trigger_states( "climate.target_temperature_crossed_threshold", ATTR_TEMPERATURE ), @@ -510,6 +537,15 @@ async def test_climate_state_trigger_behavior_first( @pytest.mark.parametrize( ("trigger", "trigger_options", "states"), [ + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.current_humidity_crossed_threshold", ATTR_CURRENT_HUMIDITY + ), + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.current_temperature_crossed_threshold", ATTR_CURRENT_TEMPERATURE + ), + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.target_humidity_crossed_threshold", ATTR_HUMIDITY + ), *parametrize_xxx_crossed_threshold_trigger_states( "climate.target_temperature_crossed_threshold", ATTR_TEMPERATURE ), @@ -650,6 +686,15 @@ async def test_climate_state_trigger_behavior_last( @pytest.mark.parametrize( ("trigger", "trigger_options", "states"), [ + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.current_humidity_crossed_threshold", ATTR_CURRENT_HUMIDITY + ), + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.current_temperature_crossed_threshold", ATTR_CURRENT_TEMPERATURE + ), + *parametrize_xxx_crossed_threshold_trigger_states( + "climate.target_humidity_crossed_threshold", ATTR_HUMIDITY + ), *parametrize_xxx_crossed_threshold_trigger_states( "climate.target_temperature_crossed_threshold", ATTR_TEMPERATURE ),