cover_template:i open/close/stop actions no longer required. Improve tests (#8344)

pull/8343/head^2
PhracturedBlue 2017-07-06 22:35:59 -07:00 committed by Paulus Schoutsen
parent a7d5a8d93e
commit b67c5df525
2 changed files with 122 additions and 102 deletions

View File

@ -40,14 +40,15 @@ STOP_ACTION = 'stop_cover'
POSITION_ACTION = 'set_cover_position'
TILT_ACTION = 'set_cover_tilt_position'
CONF_VALUE_OR_POSITION_TEMPLATE = 'value_or_position'
CONF_OPEN_OR_CLOSE = 'open_or_close'
TILT_FEATURES = (SUPPORT_OPEN_TILT | SUPPORT_CLOSE_TILT | SUPPORT_STOP_TILT |
SUPPORT_SET_TILT_POSITION)
COVER_SCHEMA = vol.Schema({
vol.Required(OPEN_ACTION): cv.SCRIPT_SCHEMA,
vol.Required(CLOSE_ACTION): cv.SCRIPT_SCHEMA,
vol.Required(STOP_ACTION): cv.SCRIPT_SCHEMA,
vol.Inclusive(OPEN_ACTION, CONF_OPEN_OR_CLOSE): cv.SCRIPT_SCHEMA,
vol.Inclusive(CLOSE_ACTION, CONF_OPEN_OR_CLOSE): cv.SCRIPT_SCHEMA,
vol.Optional(STOP_ACTION): cv.SCRIPT_SCHEMA,
vol.Exclusive(CONF_POSITION_TEMPLATE,
CONF_VALUE_OR_POSITION_TEMPLATE): cv.template,
vol.Exclusive(CONF_VALUE_TEMPLATE,
@ -77,9 +78,9 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
position_template = device_config.get(CONF_POSITION_TEMPLATE)
tilt_template = device_config.get(CONF_TILT_TEMPLATE)
icon_template = device_config.get(CONF_ICON_TEMPLATE)
open_action = device_config[OPEN_ACTION]
close_action = device_config[CLOSE_ACTION]
stop_action = device_config[STOP_ACTION]
open_action = device_config.get(OPEN_ACTION)
close_action = device_config.get(CLOSE_ACTION)
stop_action = device_config.get(STOP_ACTION)
position_action = device_config.get(POSITION_ACTION)
tilt_action = device_config.get(TILT_ACTION)
@ -88,6 +89,10 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
CONF_VALUE_TEMPLATE, CONF_VALUE_TEMPLATE)
continue
if position_action is None and open_action is None:
_LOGGER.error('Must specify at least one of %s' or '%s',
OPEN_ACTION, POSITION_ACTION)
continue
template_entity_ids = set()
if state_template is not None:
temp_ids = state_template.extract_entities()
@ -147,9 +152,15 @@ class CoverTemplate(CoverDevice):
self._position_template = position_template
self._tilt_template = tilt_template
self._icon_template = icon_template
self._open_script = Script(hass, open_action)
self._close_script = Script(hass, close_action)
self._stop_script = Script(hass, stop_action)
self._open_script = None
if open_action is not None:
self._open_script = Script(hass, open_action)
self._close_script = None
if close_action is not None:
self._close_script = Script(hass, close_action)
self._stop_script = None
if stop_action is not None:
self._stop_script = Script(hass, stop_action)
self._position_script = None
if position_action is not None:
self._position_script = Script(hass, position_action)
@ -227,9 +238,12 @@ class CoverTemplate(CoverDevice):
@property
def supported_features(self):
"""Flag supported features."""
supported_features = SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP
supported_features = SUPPORT_OPEN | SUPPORT_CLOSE
if self.current_cover_position is not None:
if self._stop_script is not None:
supported_features |= SUPPORT_STOP
if self._position_script is not None:
supported_features |= SUPPORT_SET_POSITION
if self.current_cover_tilt_position is not None:
@ -245,23 +259,30 @@ class CoverTemplate(CoverDevice):
@asyncio.coroutine
def async_open_cover(self, **kwargs):
"""Move the cover up."""
self.hass.async_add_job(self._open_script.async_run())
if self._open_script:
self.hass.async_add_job(self._open_script.async_run())
elif self._position_script:
self.hass.async_add_job(self._position_script.async_run(
{"position": 100}))
@asyncio.coroutine
def async_close_cover(self, **kwargs):
"""Move the cover down."""
self.hass.async_add_job(self._close_script.async_run())
if self._close_script:
self.hass.async_add_job(self._close_script.async_run())
elif self._position_script:
self.hass.async_add_job(self._position_script.async_run(
{"position": 0}))
@asyncio.coroutine
def async_stop_cover(self, **kwargs):
"""Fire the stop action."""
self.hass.async_add_job(self._stop_script.async_run())
if self._stop_script:
self.hass.async_add_job(self._stop_script.async_run())
@asyncio.coroutine
def async_set_cover_position(self, **kwargs):
"""Set cover position."""
if ATTR_POSITION not in kwargs:
return
self._position = kwargs[ATTR_POSITION]
self.hass.async_add_job(self._position_script.async_run(
{"position": self._position}))
@ -283,8 +304,6 @@ class CoverTemplate(CoverDevice):
@asyncio.coroutine
def async_set_cover_tilt_position(self, **kwargs):
"""Move the cover tilt to a specific position."""
if ATTR_TILT_POSITION not in kwargs:
return
self._tilt_value = kwargs[ATTR_TILT_POSITION]
self.hass.async_add_job(self._tilt_script.async_run(
{"tilt": self._tilt_value}))

View File

@ -54,10 +54,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
}
}
}
@ -79,7 +75,7 @@ class TestTemplateCover(unittest.TestCase):
assert state.state == STATE_CLOSED
def test_template_state_boolean(self):
"""Test the state text of a template."""
"""Test the value_template attribute."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -96,10 +92,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
}
}
}
@ -112,7 +104,7 @@ class TestTemplateCover(unittest.TestCase):
assert state.state == STATE_OPEN
def test_template_position(self):
"""Test the state text of a template."""
"""Test the position_template attribute."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -129,10 +121,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test'
},
}
}
}
@ -170,7 +158,7 @@ class TestTemplateCover(unittest.TestCase):
assert state.state == STATE_CLOSED
def test_template_tilt(self):
"""Test the state text of a template."""
"""Test the tilt_template attribute."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -189,10 +177,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
}
}
}
@ -205,7 +189,7 @@ class TestTemplateCover(unittest.TestCase):
assert state.attributes.get('current_tilt_position') == 42.0
def test_template_out_of_bounds(self):
"""Test the state text of a template."""
"""Test template out-of-bounds condition."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -224,10 +208,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
}
}
}
@ -260,10 +240,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'icon_template':
"{% if states.cover.test_state.state %}"
"mdi:check"
@ -294,14 +270,26 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'icon_template':
"{% if states.cover.test_state.state %}"
"mdi:check"
"{% endif %}"
},
}
}
})
self.hass.start()
self.hass.block_till_done()
assert self.hass.states.all() == []
def test_template_open_or_position(self):
"""Test that at least one of open_cover or set_position is used."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
'platform': 'template',
'covers': {
'test_template_cover': {
'value_template':
"{{ 1 == 1 }}",
}
}
}
@ -312,8 +300,32 @@ class TestTemplateCover(unittest.TestCase):
assert self.hass.states.all() == []
def test_template_open_and_close(self):
"""Test that if open_cover is specified, cose_cover is too."""
with assert_setup_component(0, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
'platform': 'template',
'covers': {
'test_template_cover': {
'value_template':
"{{ 1 == 1 }}",
'open_cover': {
'service': 'cover.open_cover',
'entity_id': 'cover.test_state'
},
},
}
}
})
self.hass.start()
self.hass.block_till_done()
assert self.hass.states.all() == []
def test_template_non_numeric(self):
"""Test the state text of a template."""
"""Test that tilt_template values are numeric."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -336,10 +348,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
}
}
}
@ -353,7 +361,7 @@ class TestTemplateCover(unittest.TestCase):
assert state.attributes.get('current_position') is None
def test_open_action(self):
"""Test the state text of a template."""
"""Test the open_cover command."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -369,10 +377,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
}
}
}
@ -390,7 +394,7 @@ class TestTemplateCover(unittest.TestCase):
assert len(self.calls) == 1
def test_close_stop_action(self):
"""Test the state text of a template."""
"""Test the close-cover and stop_cover commands."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -429,29 +433,30 @@ class TestTemplateCover(unittest.TestCase):
assert len(self.calls) == 2
def test_set_position(self):
"""Test the state text of a template."""
"""Test the set_position command."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'input_slider', {
'input_slider': {
'test': {
'min': '0',
'max': '100',
'initial': '42',
}
}
})
assert setup.setup_component(self.hass, 'cover', {
'cover': {
'platform': 'template',
'covers': {
'test_template_cover': {
'position_template':
"{{ 100 }}",
'open_cover': {
'service': 'cover.open_cover',
'entity_id': 'cover.test_state'
},
'close_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.stop_cover',
'entity_id': 'cover.test_state'
},
"{{ states.input_slider.test.state | int }}",
'set_cover_position': {
'service': 'test.automation',
'service': 'input_slider.select_value',
'entity_id': 'input_slider.test',
'data_template': {
'value': '{{ position }}'
},
},
}
}
@ -461,17 +466,29 @@ class TestTemplateCover(unittest.TestCase):
self.hass.start()
self.hass.block_till_done()
state = self.hass.states.set('input_slider.test', 42)
self.hass.block_till_done()
state = self.hass.states.get('cover.test_template_cover')
assert state.state == STATE_OPEN
cover.set_cover_position(self.hass, 42,
cover.open_cover(self.hass, 'cover.test_template_cover')
self.hass.block_till_done()
state = self.hass.states.get('cover.test_template_cover')
assert state.attributes.get('current_position') == 100.0
cover.close_cover(self.hass, 'cover.test_template_cover')
self.hass.block_till_done()
state = self.hass.states.get('cover.test_template_cover')
assert state.attributes.get('current_position') == 0.0
cover.set_cover_position(self.hass, 25,
'cover.test_template_cover')
self.hass.block_till_done()
assert len(self.calls) == 1
state = self.hass.states.get('cover.test_template_cover')
assert state.attributes.get('current_position') == 25.0
def test_set_tilt_position(self):
"""Test the state text of a template."""
"""Test the set_tilt_position command."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -488,10 +505,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.stop_cover',
'entity_id': 'cover.test_state'
},
'set_cover_tilt_position': {
'service': 'test.automation',
},
@ -510,7 +523,7 @@ class TestTemplateCover(unittest.TestCase):
assert len(self.calls) == 1
def test_open_tilt_action(self):
"""Test the state text of a template."""
"""Test the open_cover_tilt command."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -527,10 +540,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.stop_cover',
'entity_id': 'cover.test_state'
},
'set_cover_tilt_position': {
'service': 'test.automation',
},
@ -548,7 +557,7 @@ class TestTemplateCover(unittest.TestCase):
assert len(self.calls) == 1
def test_close_tilt_action(self):
"""Test the state text of a template."""
"""Test the close_cover_tilt command."""
with assert_setup_component(1, 'cover'):
assert setup.setup_component(self.hass, 'cover', {
'cover': {
@ -565,10 +574,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.stop_cover',
'entity_id': 'cover.test_state'
},
'set_cover_tilt_position': {
'service': 'test.automation',
},
@ -603,10 +608,6 @@ class TestTemplateCover(unittest.TestCase):
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'stop_cover': {
'service': 'cover.close_cover',
'entity_id': 'cover.test_state'
},
'icon_template':
"{% if states.cover.test_state.state %}"
"mdi:check"