Ignore attribute changes in automation trigger from/to (#7651)
* Ignore attribute changes in automation trigger from/to * Quote names in deprecation warnings This makes it somewhat easier to read if the suggestion happens to be named "to". * Add test with same state, new attribute value
This commit is contained in:
parent
adde9e6231
commit
81f0826550
3 changed files with 30 additions and 8 deletions
|
@ -12,6 +12,7 @@ import homeassistant.util.dt as dt_util
|
||||||
from homeassistant.const import MATCH_ALL, CONF_PLATFORM
|
from homeassistant.const import MATCH_ALL, CONF_PLATFORM
|
||||||
from homeassistant.helpers.event import (
|
from homeassistant.helpers.event import (
|
||||||
async_track_state_change, async_track_point_in_utc_time)
|
async_track_state_change, async_track_point_in_utc_time)
|
||||||
|
from homeassistant.helpers.deprecation import get_deprecated
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
CONF_ENTITY_ID = 'entity_id'
|
CONF_ENTITY_ID = 'entity_id'
|
||||||
|
@ -40,7 +41,7 @@ def async_trigger(hass, config, action):
|
||||||
"""Listen for state changes based on configuration."""
|
"""Listen for state changes based on configuration."""
|
||||||
entity_id = config.get(CONF_ENTITY_ID)
|
entity_id = config.get(CONF_ENTITY_ID)
|
||||||
from_state = config.get(CONF_FROM, MATCH_ALL)
|
from_state = config.get(CONF_FROM, MATCH_ALL)
|
||||||
to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL
|
to_state = get_deprecated(config, CONF_TO, CONF_STATE, MATCH_ALL)
|
||||||
time_delta = config.get(CONF_FOR)
|
time_delta = config.get(CONF_FOR)
|
||||||
async_remove_state_for_cancel = None
|
async_remove_state_for_cancel = None
|
||||||
async_remove_state_for_listener = None
|
async_remove_state_for_listener = None
|
||||||
|
@ -75,12 +76,13 @@ def async_trigger(hass, config, action):
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if time_delta is None:
|
# Ignore changes to state attributes if from/to is in use
|
||||||
call_action()
|
match_all = (from_state == MATCH_ALL and to_state == MATCH_ALL)
|
||||||
|
if not match_all and from_s.last_changed == to_s.last_changed:
|
||||||
return
|
return
|
||||||
|
|
||||||
# If only state attributes changed, ignore this event
|
if time_delta is None:
|
||||||
if from_s.last_changed == to_s.last_changed:
|
call_action()
|
||||||
return
|
return
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
|
|
@ -23,8 +23,8 @@ def deprecated_substitute(substitute_name):
|
||||||
if not warnings.get(module_name):
|
if not warnings.get(module_name):
|
||||||
logger = logging.getLogger(module_name)
|
logger = logging.getLogger(module_name)
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"%s is deprecated. Please rename %s to "
|
"'%s' is deprecated. Please rename '%s' to "
|
||||||
"%s in '%s' to ensure future support.",
|
"'%s' in '%s' to ensure future support.",
|
||||||
substitute_name, substitute_name, func.__name__,
|
substitute_name, substitute_name, func.__name__,
|
||||||
inspect.getfile(self.__class__))
|
inspect.getfile(self.__class__))
|
||||||
warnings[module_name] = True
|
warnings[module_name] = True
|
||||||
|
@ -49,7 +49,7 @@ def get_deprecated(config, new_name, old_name, default=None):
|
||||||
module_name = inspect.getmodule(inspect.stack()[1][0]).__name__
|
module_name = inspect.getmodule(inspect.stack()[1][0]).__name__
|
||||||
logger = logging.getLogger(module_name)
|
logger = logging.getLogger(module_name)
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"%s is deprecated. Please rename %s to %s in your "
|
"'%s' is deprecated. Please rename '%s' to '%s' in your "
|
||||||
"configuration file.", old_name, old_name, new_name)
|
"configuration file.", old_name, old_name, new_name)
|
||||||
return config.get(old_name)
|
return config.get(old_name)
|
||||||
return config.get(new_name, default)
|
return config.get(new_name, default)
|
||||||
|
|
|
@ -110,6 +110,26 @@ class TestAutomationState(unittest.TestCase):
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
self.assertEqual(1, len(self.calls))
|
self.assertEqual(1, len(self.calls))
|
||||||
|
|
||||||
|
def test_if_fires_on_attribute_change_with_to_filter(self):
|
||||||
|
"""Test for not firing on attribute change."""
|
||||||
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
|
automation.DOMAIN: {
|
||||||
|
'trigger': {
|
||||||
|
'platform': 'state',
|
||||||
|
'entity_id': 'test.entity',
|
||||||
|
'to': 'world'
|
||||||
|
},
|
||||||
|
'action': {
|
||||||
|
'service': 'test.automation'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
self.hass.states.set('test.entity', 'world', {'test_attribute': 11})
|
||||||
|
self.hass.states.set('test.entity', 'world', {'test_attribute': 12})
|
||||||
|
self.hass.block_till_done()
|
||||||
|
self.assertEqual(1, len(self.calls))
|
||||||
|
|
||||||
def test_if_fires_on_entity_change_with_state_filter(self):
|
def test_if_fires_on_entity_change_with_state_filter(self):
|
||||||
"""Test for firing on entity change with state filter."""
|
"""Test for firing on entity change with state filter."""
|
||||||
assert setup_component(self.hass, automation.DOMAIN, {
|
assert setup_component(self.hass, automation.DOMAIN, {
|
||||||
|
|
Loading…
Add table
Reference in a new issue