mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 14:17:45 +00:00
Add availability_template to Template Vacuum platform (#26514)
* Added availability_template to Template Vacuum platform * Added to test for invalid values in availability_template * Updated AVAILABILITY_TEMPLATE Rendering error * Moved const to package Const.py * Removed 'Magic' string * Cleaned up const and compare lowercase result to 'true' * reverted _available back to boolean * Fixed tests (async, magic values and state checks)
This commit is contained in:
parent
ed82ec5d8e
commit
11c9bab078
@ -44,6 +44,8 @@ from homeassistant.exceptions import TemplateError
|
|||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_VACUUMS = "vacuums"
|
CONF_VACUUMS = "vacuums"
|
||||||
@ -67,6 +69,7 @@ VACUUM_SCHEMA = vol.Schema(
|
|||||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_BATTERY_LEVEL_TEMPLATE): cv.template,
|
vol.Optional(CONF_BATTERY_LEVEL_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_FAN_SPEED_TEMPLATE): cv.template,
|
vol.Optional(CONF_FAN_SPEED_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_AVAILABILITY_TEMPLATE): cv.template,
|
||||||
vol.Required(SERVICE_START): cv.SCRIPT_SCHEMA,
|
vol.Required(SERVICE_START): cv.SCRIPT_SCHEMA,
|
||||||
vol.Optional(SERVICE_PAUSE): cv.SCRIPT_SCHEMA,
|
vol.Optional(SERVICE_PAUSE): cv.SCRIPT_SCHEMA,
|
||||||
vol.Optional(SERVICE_STOP): cv.SCRIPT_SCHEMA,
|
vol.Optional(SERVICE_STOP): cv.SCRIPT_SCHEMA,
|
||||||
@ -94,6 +97,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||||||
state_template = device_config.get(CONF_VALUE_TEMPLATE)
|
state_template = device_config.get(CONF_VALUE_TEMPLATE)
|
||||||
battery_level_template = device_config.get(CONF_BATTERY_LEVEL_TEMPLATE)
|
battery_level_template = device_config.get(CONF_BATTERY_LEVEL_TEMPLATE)
|
||||||
fan_speed_template = device_config.get(CONF_FAN_SPEED_TEMPLATE)
|
fan_speed_template = device_config.get(CONF_FAN_SPEED_TEMPLATE)
|
||||||
|
availability_template = device_config.get(CONF_AVAILABILITY_TEMPLATE)
|
||||||
|
|
||||||
start_action = device_config[SERVICE_START]
|
start_action = device_config[SERVICE_START]
|
||||||
pause_action = device_config.get(SERVICE_PAUSE)
|
pause_action = device_config.get(SERVICE_PAUSE)
|
||||||
@ -113,6 +117,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||||||
(CONF_VALUE_TEMPLATE, state_template),
|
(CONF_VALUE_TEMPLATE, state_template),
|
||||||
(CONF_BATTERY_LEVEL_TEMPLATE, battery_level_template),
|
(CONF_BATTERY_LEVEL_TEMPLATE, battery_level_template),
|
||||||
(CONF_FAN_SPEED_TEMPLATE, fan_speed_template),
|
(CONF_FAN_SPEED_TEMPLATE, fan_speed_template),
|
||||||
|
(CONF_AVAILABILITY_TEMPLATE, availability_template),
|
||||||
):
|
):
|
||||||
if template is None:
|
if template is None:
|
||||||
continue
|
continue
|
||||||
@ -152,6 +157,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||||||
state_template,
|
state_template,
|
||||||
battery_level_template,
|
battery_level_template,
|
||||||
fan_speed_template,
|
fan_speed_template,
|
||||||
|
availability_template,
|
||||||
start_action,
|
start_action,
|
||||||
pause_action,
|
pause_action,
|
||||||
stop_action,
|
stop_action,
|
||||||
@ -178,6 +184,7 @@ class TemplateVacuum(StateVacuumDevice):
|
|||||||
state_template,
|
state_template,
|
||||||
battery_level_template,
|
battery_level_template,
|
||||||
fan_speed_template,
|
fan_speed_template,
|
||||||
|
availability_template,
|
||||||
start_action,
|
start_action,
|
||||||
pause_action,
|
pause_action,
|
||||||
stop_action,
|
stop_action,
|
||||||
@ -198,6 +205,7 @@ class TemplateVacuum(StateVacuumDevice):
|
|||||||
self._template = state_template
|
self._template = state_template
|
||||||
self._battery_level_template = battery_level_template
|
self._battery_level_template = battery_level_template
|
||||||
self._fan_speed_template = fan_speed_template
|
self._fan_speed_template = fan_speed_template
|
||||||
|
self._availability_template = availability_template
|
||||||
self._supported_features = SUPPORT_START
|
self._supported_features = SUPPORT_START
|
||||||
|
|
||||||
self._start_script = Script(hass, start_action)
|
self._start_script = Script(hass, start_action)
|
||||||
@ -235,6 +243,7 @@ class TemplateVacuum(StateVacuumDevice):
|
|||||||
self._state = None
|
self._state = None
|
||||||
self._battery_level = None
|
self._battery_level = None
|
||||||
self._fan_speed = None
|
self._fan_speed = None
|
||||||
|
self._available = True
|
||||||
|
|
||||||
if self._template:
|
if self._template:
|
||||||
self._supported_features |= SUPPORT_STATE
|
self._supported_features |= SUPPORT_STATE
|
||||||
@ -280,6 +289,11 @@ class TemplateVacuum(StateVacuumDevice):
|
|||||||
"""Return the polling state."""
|
"""Return the polling state."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return if the device is available."""
|
||||||
|
return self._available
|
||||||
|
|
||||||
async def async_start(self):
|
async def async_start(self):
|
||||||
"""Start or resume the cleaning task."""
|
"""Start or resume the cleaning task."""
|
||||||
await self._start_script.async_run(context=self._context)
|
await self._start_script.async_run(context=self._context)
|
||||||
@ -421,3 +435,16 @@ class TemplateVacuum(StateVacuumDevice):
|
|||||||
self._fan_speed_list,
|
self._fan_speed_list,
|
||||||
)
|
)
|
||||||
self._fan_speed = None
|
self._fan_speed = None
|
||||||
|
# Update availability if availability template is defined
|
||||||
|
if self._availability_template is not None:
|
||||||
|
try:
|
||||||
|
self._available = (
|
||||||
|
self._availability_template.async_render().lower() == "true"
|
||||||
|
)
|
||||||
|
except (TemplateError, ValueError) as ex:
|
||||||
|
_LOGGER.error(
|
||||||
|
"Could not render %s template %s: %s",
|
||||||
|
CONF_AVAILABILITY_TEMPLATE,
|
||||||
|
self._name,
|
||||||
|
ex,
|
||||||
|
)
|
||||||
|
@ -3,7 +3,7 @@ import logging
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import setup
|
from homeassistant import setup
|
||||||
from homeassistant.const import STATE_ON, STATE_UNKNOWN
|
from homeassistant.const import STATE_ON, STATE_OFF, STATE_UNKNOWN, STATE_UNAVAILABLE
|
||||||
from homeassistant.components.vacuum import (
|
from homeassistant.components.vacuum import (
|
||||||
ATTR_BATTERY_LEVEL,
|
ATTR_BATTERY_LEVEL,
|
||||||
STATE_CLEANING,
|
STATE_CLEANING,
|
||||||
@ -210,6 +210,68 @@ async def test_invalid_templates(hass, calls):
|
|||||||
_verify(hass, STATE_UNKNOWN, None)
|
_verify(hass, STATE_UNKNOWN, None)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_available_template_with_entities(hass, calls):
|
||||||
|
"""Test availability templates with values from other entities."""
|
||||||
|
|
||||||
|
assert await setup.async_setup_component(
|
||||||
|
hass,
|
||||||
|
"vacuum",
|
||||||
|
{
|
||||||
|
"vacuum": {
|
||||||
|
"platform": "template",
|
||||||
|
"vacuums": {
|
||||||
|
"test_template_vacuum": {
|
||||||
|
"availability_template": "{{ is_state('availability_state.state', 'on') }}",
|
||||||
|
"start": {"service": "script.vacuum_start"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_start()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# When template returns true..
|
||||||
|
hass.states.async_set("availability_state.state", STATE_ON)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Device State should not be unavailable
|
||||||
|
assert hass.states.get("vacuum.test_template_vacuum").state != STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
# When Availability template returns false
|
||||||
|
hass.states.async_set("availability_state.state", STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# device state should be unavailable
|
||||||
|
assert hass.states.get("vacuum.test_template_vacuum").state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
||||||
|
async def test_invalid_availability_template_keeps_component_available(hass, caplog):
|
||||||
|
"""Test that an invalid availability keeps the device available."""
|
||||||
|
assert await setup.async_setup_component(
|
||||||
|
hass,
|
||||||
|
"vacuum",
|
||||||
|
{
|
||||||
|
"vacuum": {
|
||||||
|
"platform": "template",
|
||||||
|
"vacuums": {
|
||||||
|
"test_template_vacuum": {
|
||||||
|
"availability_template": "{{ x - 12 }}",
|
||||||
|
"start": {"service": "script.vacuum_start"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_start()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert hass.states.get("vacuum.test_template_vacuum") != STATE_UNAVAILABLE
|
||||||
|
assert ("UndefinedError: 'x' is undefined") in caplog.text
|
||||||
|
|
||||||
|
|
||||||
# End of template tests #
|
# End of template tests #
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user