Support this variable in template fan actions (#71795)

This commit is contained in:
Erik Montnemery 2022-05-13 18:33:44 +02:00 committed by GitHub
parent 8b412acc98
commit a17fa6d6d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 152 additions and 57 deletions

View file

@ -251,8 +251,9 @@ class TemplateFan(TemplateEntity, FanEntity):
**kwargs, **kwargs,
) -> None: ) -> None:
"""Turn on the fan.""" """Turn on the fan."""
await self._on_script.async_run( await self.async_run_script(
{ self._on_script,
run_variables={
ATTR_PERCENTAGE: percentage, ATTR_PERCENTAGE: percentage,
ATTR_PRESET_MODE: preset_mode, ATTR_PRESET_MODE: preset_mode,
}, },
@ -267,7 +268,7 @@ class TemplateFan(TemplateEntity, FanEntity):
async def async_turn_off(self, **kwargs: Any) -> None: async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the fan.""" """Turn off the fan."""
await self._off_script.async_run(context=self._context) await self.async_run_script(self._off_script, context=self._context)
self._state = STATE_OFF self._state = STATE_OFF
async def async_set_percentage(self, percentage: int) -> None: async def async_set_percentage(self, percentage: int) -> None:
@ -277,8 +278,10 @@ class TemplateFan(TemplateEntity, FanEntity):
self._preset_mode = None self._preset_mode = None
if self._set_percentage_script: if self._set_percentage_script:
await self._set_percentage_script.async_run( await self.async_run_script(
{ATTR_PERCENTAGE: self._percentage}, context=self._context self._set_percentage_script,
run_variables={ATTR_PERCENTAGE: self._percentage},
context=self._context,
) )
async def async_set_preset_mode(self, preset_mode: str) -> None: async def async_set_preset_mode(self, preset_mode: str) -> None:
@ -297,8 +300,10 @@ class TemplateFan(TemplateEntity, FanEntity):
self._percentage = None self._percentage = None
if self._set_preset_mode_script: if self._set_preset_mode_script:
await self._set_preset_mode_script.async_run( await self.async_run_script(
{ATTR_PRESET_MODE: self._preset_mode}, context=self._context self._set_preset_mode_script,
run_variables={ATTR_PRESET_MODE: self._preset_mode},
context=self._context,
) )
async def async_oscillate(self, oscillating: bool) -> None: async def async_oscillate(self, oscillating: bool) -> None:
@ -307,8 +312,10 @@ class TemplateFan(TemplateEntity, FanEntity):
return return
self._oscillating = oscillating self._oscillating = oscillating
await self._set_oscillating_script.async_run( await self.async_run_script(
{ATTR_OSCILLATING: oscillating}, context=self._context self._set_oscillating_script,
run_variables={ATTR_OSCILLATING: self.oscillating},
context=self._context,
) )
async def async_set_direction(self, direction: str) -> None: async def async_set_direction(self, direction: str) -> None:
@ -318,8 +325,10 @@ class TemplateFan(TemplateEntity, FanEntity):
if direction in _VALID_DIRECTIONS: if direction in _VALID_DIRECTIONS:
self._direction = direction self._direction = direction
await self._set_direction_script.async_run( await self.async_run_script(
{ATTR_DIRECTION: direction}, context=self._context self._set_direction_script,
run_variables={ATTR_DIRECTION: direction},
context=self._context,
) )
else: else:
_LOGGER.error( _LOGGER.error(

View file

@ -383,20 +383,25 @@ async def test_invalid_availability_template_keeps_component_available(
assert "x" in caplog_setup_text assert "x" in caplog_setup_text
async def test_on_off(hass): async def test_on_off(hass, calls):
"""Test turn on and turn off.""" """Test turn on and turn off."""
await _register_components(hass) await _register_components(hass)
expected_calls = 0
for func, state in [ for func, state, action in [
(common.async_turn_on, STATE_ON), (common.async_turn_on, STATE_ON, "turn_on"),
(common.async_turn_off, STATE_OFF), (common.async_turn_off, STATE_OFF, "turn_off"),
]: ]:
await func(hass, _TEST_FAN) await func(hass, _TEST_FAN)
assert hass.states.get(_STATE_INPUT_BOOLEAN).state == state assert hass.states.get(_STATE_INPUT_BOOLEAN).state == state
_verify(hass, state, 0, None, None, None) _verify(hass, state, 0, None, None, None)
expected_calls += 1
assert len(calls) == expected_calls
assert calls[-1].data["action"] == action
assert calls[-1].data["caller"] == _TEST_FAN
async def test_set_invalid_direction_from_initial_stage(hass): async def test_set_invalid_direction_from_initial_stage(hass, calls):
"""Test set invalid direction when fan is in initial state.""" """Test set invalid direction when fan is in initial state."""
await _register_components(hass) await _register_components(hass)
@ -407,29 +412,43 @@ async def test_set_invalid_direction_from_initial_stage(hass):
_verify(hass, STATE_ON, 0, None, None, None) _verify(hass, STATE_ON, 0, None, None, None)
async def test_set_osc(hass): async def test_set_osc(hass, calls):
"""Test set oscillating.""" """Test set oscillating."""
await _register_components(hass) await _register_components(hass)
expected_calls = 0
await common.async_turn_on(hass, _TEST_FAN) await common.async_turn_on(hass, _TEST_FAN)
expected_calls += 1
for state in [True, False]: for state in [True, False]:
await common.async_oscillate(hass, _TEST_FAN, state) await common.async_oscillate(hass, _TEST_FAN, state)
assert hass.states.get(_OSC_INPUT).state == str(state) assert hass.states.get(_OSC_INPUT).state == str(state)
_verify(hass, STATE_ON, 0, state, None, None) _verify(hass, STATE_ON, 0, state, None, None)
expected_calls += 1
assert len(calls) == expected_calls
assert calls[-1].data["action"] == "set_oscillating"
assert calls[-1].data["caller"] == _TEST_FAN
assert calls[-1].data["option"] == state
async def test_set_direction(hass): async def test_set_direction(hass, calls):
"""Test set valid direction.""" """Test set valid direction."""
await _register_components(hass) await _register_components(hass)
expected_calls = 0
await common.async_turn_on(hass, _TEST_FAN) await common.async_turn_on(hass, _TEST_FAN)
expected_calls += 1
for cmd in [DIRECTION_FORWARD, DIRECTION_REVERSE]: for cmd in [DIRECTION_FORWARD, DIRECTION_REVERSE]:
await common.async_set_direction(hass, _TEST_FAN, cmd) await common.async_set_direction(hass, _TEST_FAN, cmd)
assert hass.states.get(_DIRECTION_INPUT_SELECT).state == cmd assert hass.states.get(_DIRECTION_INPUT_SELECT).state == cmd
_verify(hass, STATE_ON, 0, None, cmd, None) _verify(hass, STATE_ON, 0, None, cmd, None)
expected_calls += 1
assert len(calls) == expected_calls
assert calls[-1].data["action"] == "set_direction"
assert calls[-1].data["caller"] == _TEST_FAN
assert calls[-1].data["option"] == cmd
async def test_set_invalid_direction(hass): async def test_set_invalid_direction(hass, calls):
"""Test set invalid direction when fan has valid direction.""" """Test set invalid direction when fan has valid direction."""
await _register_components(hass) await _register_components(hass)
@ -440,30 +459,36 @@ async def test_set_invalid_direction(hass):
_verify(hass, STATE_ON, 0, None, DIRECTION_FORWARD, None) _verify(hass, STATE_ON, 0, None, DIRECTION_FORWARD, None)
async def test_preset_modes(hass): async def test_preset_modes(hass, calls):
"""Test preset_modes.""" """Test preset_modes."""
await _register_components( await _register_components(
hass, ["off", "low", "medium", "high", "auto", "smart"], ["auto", "smart"] hass, ["off", "low", "medium", "high", "auto", "smart"], ["auto", "smart"]
) )
await common.async_turn_on(hass, _TEST_FAN) await common.async_turn_on(hass, _TEST_FAN)
for extra, state in [ for extra, state, expected_calls in [
("auto", "auto"), ("auto", "auto", 2),
("smart", "smart"), ("smart", "smart", 3),
("invalid", "smart"), ("invalid", "smart", 3),
]: ]:
await common.async_set_preset_mode(hass, _TEST_FAN, extra) await common.async_set_preset_mode(hass, _TEST_FAN, extra)
assert hass.states.get(_PRESET_MODE_INPUT_SELECT).state == state assert hass.states.get(_PRESET_MODE_INPUT_SELECT).state == state
assert len(calls) == expected_calls
assert calls[-1].data["action"] == "set_preset_mode"
assert calls[-1].data["caller"] == _TEST_FAN
assert calls[-1].data["option"] == state
await common.async_turn_on(hass, _TEST_FAN, preset_mode="auto") await common.async_turn_on(hass, _TEST_FAN, preset_mode="auto")
assert hass.states.get(_PRESET_MODE_INPUT_SELECT).state == "auto" assert hass.states.get(_PRESET_MODE_INPUT_SELECT).state == "auto"
async def test_set_percentage(hass): async def test_set_percentage(hass, calls):
"""Test set valid speed percentage.""" """Test set valid speed percentage."""
await _register_components(hass) await _register_components(hass)
expected_calls = 0
await common.async_turn_on(hass, _TEST_FAN) await common.async_turn_on(hass, _TEST_FAN)
expected_calls += 1
for state, value in [ for state, value in [
(STATE_ON, 100), (STATE_ON, 100),
(STATE_ON, 66), (STATE_ON, 66),
@ -472,13 +497,18 @@ async def test_set_percentage(hass):
await common.async_set_percentage(hass, _TEST_FAN, value) await common.async_set_percentage(hass, _TEST_FAN, value)
assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == value assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == value
_verify(hass, state, value, None, None, None) _verify(hass, state, value, None, None, None)
expected_calls += 1
assert len(calls) == expected_calls
assert calls[-1].data["action"] == "set_value"
assert calls[-1].data["caller"] == _TEST_FAN
assert calls[-1].data["value"] == value
await common.async_turn_on(hass, _TEST_FAN, percentage=50) await common.async_turn_on(hass, _TEST_FAN, percentage=50)
assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == 50 assert int(float(hass.states.get(_PERCENTAGE_INPUT_NUMBER).state)) == 50
_verify(hass, STATE_ON, 50, None, None, None) _verify(hass, STATE_ON, 50, None, None, None)
async def test_increase_decrease_speed(hass): async def test_increase_decrease_speed(hass, calls):
"""Test set valid increase and decrease speed.""" """Test set valid increase and decrease speed."""
await _register_components(hass, speed_count=3) await _register_components(hass, speed_count=3)
@ -495,7 +525,7 @@ async def test_increase_decrease_speed(hass):
_verify(hass, state, value, None, None, None) _verify(hass, state, value, None, None, None)
async def test_increase_decrease_speed_default_speed_count(hass): async def test_increase_decrease_speed_default_speed_count(hass, calls):
"""Test set valid increase and decrease speed.""" """Test set valid increase and decrease speed."""
await _register_components(hass) await _register_components(hass)
@ -512,7 +542,7 @@ async def test_increase_decrease_speed_default_speed_count(hass):
_verify(hass, state, value, None, None, None) _verify(hass, state, value, None, None, None)
async def test_set_invalid_osc_from_initial_state(hass): async def test_set_invalid_osc_from_initial_state(hass, calls):
"""Test set invalid oscillating when fan is in initial state.""" """Test set invalid oscillating when fan is in initial state."""
await _register_components(hass) await _register_components(hass)
@ -523,7 +553,7 @@ async def test_set_invalid_osc_from_initial_state(hass):
_verify(hass, STATE_ON, 0, None, None, None) _verify(hass, STATE_ON, 0, None, None, None)
async def test_set_invalid_osc(hass): async def test_set_invalid_osc(hass, calls):
"""Test set invalid oscillating when fan has valid osc.""" """Test set invalid oscillating when fan has valid osc."""
await _register_components(hass) await _register_components(hass)
@ -616,10 +646,19 @@ async def _register_components(
"percentage_template": "{{ states('input_number.percentage') }}", "percentage_template": "{{ states('input_number.percentage') }}",
"oscillating_template": "{{ states('input_select.osc') }}", "oscillating_template": "{{ states('input_select.osc') }}",
"direction_template": "{{ states('input_select.direction') }}", "direction_template": "{{ states('input_select.direction') }}",
"turn_on": { "turn_on": [
"service": "input_boolean.turn_on", {
"entity_id": _STATE_INPUT_BOOLEAN, "service": "input_boolean.turn_on",
}, "entity_id": _STATE_INPUT_BOOLEAN,
},
{
"service": "test.automation",
"data_template": {
"action": "turn_on",
"caller": "{{ this.entity_id }}",
},
},
],
"turn_off": [ "turn_off": [
{ {
"service": "input_boolean.turn_off", "service": "input_boolean.turn_off",
@ -632,35 +671,82 @@ async def _register_components(
"value": 0, "value": 0,
}, },
}, },
{
"service": "test.automation",
"data_template": {
"action": "turn_off",
"caller": "{{ this.entity_id }}",
},
},
], ],
"set_preset_mode": { "set_preset_mode": [
"service": "input_select.select_option", {
"data_template": { "service": "input_select.select_option",
"entity_id": _PRESET_MODE_INPUT_SELECT, "data_template": {
"option": "{{ preset_mode }}", "entity_id": _PRESET_MODE_INPUT_SELECT,
"option": "{{ preset_mode }}",
},
}, },
}, {
"set_percentage": { "service": "test.automation",
"service": "input_number.set_value", "data_template": {
"data_template": { "action": "set_preset_mode",
"entity_id": _PERCENTAGE_INPUT_NUMBER, "caller": "{{ this.entity_id }}",
"value": "{{ percentage }}", "option": "{{ preset_mode }}",
},
}, },
}, ],
"set_oscillating": { "set_percentage": [
"service": "input_select.select_option", {
"data_template": { "service": "input_number.set_value",
"entity_id": _OSC_INPUT, "data_template": {
"option": "{{ oscillating }}", "entity_id": _PERCENTAGE_INPUT_NUMBER,
"value": "{{ percentage }}",
},
}, },
}, {
"set_direction": { "service": "test.automation",
"service": "input_select.select_option", "data_template": {
"data_template": { "action": "set_value",
"entity_id": _DIRECTION_INPUT_SELECT, "caller": "{{ this.entity_id }}",
"option": "{{ direction }}", "value": "{{ percentage }}",
},
}, },
}, ],
"set_oscillating": [
{
"service": "input_select.select_option",
"data_template": {
"entity_id": _OSC_INPUT,
"option": "{{ oscillating }}",
},
},
{
"service": "test.automation",
"data_template": {
"action": "set_oscillating",
"caller": "{{ this.entity_id }}",
"option": "{{ oscillating }}",
},
},
],
"set_direction": [
{
"service": "input_select.select_option",
"data_template": {
"entity_id": _DIRECTION_INPUT_SELECT,
"option": "{{ direction }}",
},
},
{
"service": "test.automation",
"data_template": {
"action": "set_direction",
"caller": "{{ this.entity_id }}",
"option": "{{ direction }}",
},
},
],
} }
if preset_modes: if preset_modes: