Fire event when we remove a state
This commit is contained in:
parent
e170484f16
commit
ada2fb4ec0
4 changed files with 67 additions and 23 deletions
|
@ -438,7 +438,20 @@ class StateMachine(object):
|
|||
entity_id = entity_id.lower()
|
||||
|
||||
with self._lock:
|
||||
return self._states.pop(entity_id, None) is not None
|
||||
old_state = self._states.pop(entity_id, None)
|
||||
|
||||
if old_state is None:
|
||||
return False
|
||||
|
||||
event_data = {
|
||||
'entity_id': entity_id,
|
||||
'old_state': old_state,
|
||||
'new_state': None,
|
||||
}
|
||||
|
||||
self._bus.fire(EVENT_STATE_CHANGED, event_data)
|
||||
|
||||
return True
|
||||
|
||||
def set(self, entity_id, new_state, attributes=None):
|
||||
"""Set the state of an entity, add entity if it does not exist.
|
||||
|
@ -468,10 +481,11 @@ class StateMachine(object):
|
|||
state = State(entity_id, new_state, attributes, last_changed)
|
||||
self._states[entity_id] = state
|
||||
|
||||
event_data = {'entity_id': entity_id, 'new_state': state}
|
||||
|
||||
if old_state:
|
||||
event_data['old_state'] = old_state
|
||||
event_data = {
|
||||
'entity_id': entity_id,
|
||||
'old_state': old_state,
|
||||
'new_state': state,
|
||||
}
|
||||
|
||||
self._bus.fire(EVENT_STATE_CHANGED, event_data)
|
||||
|
||||
|
|
|
@ -34,16 +34,19 @@ def track_state_change(hass, entity_ids, action, from_state=None,
|
|||
if event.data['entity_id'] not in entity_ids:
|
||||
return
|
||||
|
||||
if 'old_state' in event.data:
|
||||
old_state = event.data['old_state'].state
|
||||
else:
|
||||
if event.data['old_state'] is None:
|
||||
old_state = None
|
||||
else:
|
||||
old_state = event.data['old_state'].state
|
||||
|
||||
if _matcher(old_state, from_state) and \
|
||||
_matcher(event.data['new_state'].state, to_state):
|
||||
if event.data['new_state'] is None:
|
||||
new_state = None
|
||||
else:
|
||||
new_state = event.data['new_state'].state
|
||||
|
||||
if _matcher(old_state, from_state) and _matcher(new_state, to_state):
|
||||
action(event.data['entity_id'],
|
||||
event.data.get('old_state'),
|
||||
event.data['old_state'],
|
||||
event.data['new_state'])
|
||||
|
||||
hass.bus.listen(EVENT_STATE_CHANGED, state_change_listener)
|
||||
|
|
|
@ -24,8 +24,6 @@ class TestEventHelpers(unittest.TestCase):
|
|||
def setUp(self): # pylint: disable=invalid-name
|
||||
""" things to be run when tests are started. """
|
||||
self.hass = ha.HomeAssistant()
|
||||
self.hass.states.set("light.Bowl", "on")
|
||||
self.hass.states.set("switch.AC", "off")
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""" Stop down stuff we started. """
|
||||
|
@ -87,7 +85,7 @@ class TestEventHelpers(unittest.TestCase):
|
|||
self.assertEqual(3, len(wildcard_runs))
|
||||
|
||||
def test_track_state_change(self):
|
||||
""" Test track_state_change. """
|
||||
"""Test track_state_change."""
|
||||
# 2 lists to track how often our callbacks get called
|
||||
specific_runs = []
|
||||
wildcard_runs = []
|
||||
|
@ -97,32 +95,48 @@ class TestEventHelpers(unittest.TestCase):
|
|||
'on', 'off')
|
||||
|
||||
track_state_change(
|
||||
self.hass, 'light.Bowl', lambda a, b, c: wildcard_runs.append(1),
|
||||
self.hass, 'light.Bowl',
|
||||
lambda _, old_s, new_s: wildcard_runs.append((old_s, new_s)),
|
||||
ha.MATCH_ALL, ha.MATCH_ALL)
|
||||
|
||||
# Adding state to state machine
|
||||
self.hass.states.set("light.Bowl", "on")
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual(0, len(specific_runs))
|
||||
self.assertEqual(1, len(wildcard_runs))
|
||||
self.assertIsNone(wildcard_runs[-1][0])
|
||||
self.assertIsNotNone(wildcard_runs[-1][1])
|
||||
|
||||
# Set same state should not trigger a state change/listener
|
||||
self.hass.states.set('light.Bowl', 'on')
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual(0, len(specific_runs))
|
||||
self.assertEqual(0, len(wildcard_runs))
|
||||
self.assertEqual(1, len(wildcard_runs))
|
||||
|
||||
# State change off -> on
|
||||
self.hass.states.set('light.Bowl', 'off')
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual(1, len(specific_runs))
|
||||
self.assertEqual(1, len(wildcard_runs))
|
||||
self.assertEqual(2, len(wildcard_runs))
|
||||
|
||||
# State change off -> off
|
||||
self.hass.states.set('light.Bowl', 'off', {"some_attr": 1})
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual(1, len(specific_runs))
|
||||
self.assertEqual(2, len(wildcard_runs))
|
||||
self.assertEqual(3, len(wildcard_runs))
|
||||
|
||||
# State change off -> on
|
||||
self.hass.states.set('light.Bowl', 'on')
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual(1, len(specific_runs))
|
||||
self.assertEqual(3, len(wildcard_runs))
|
||||
self.assertEqual(4, len(wildcard_runs))
|
||||
|
||||
self.hass.states.remove('light.bowl')
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual(1, len(specific_runs))
|
||||
self.assertEqual(5, len(wildcard_runs))
|
||||
self.assertIsNotNone(wildcard_runs[-1][0])
|
||||
self.assertIsNone(wildcard_runs[-1][1])
|
||||
|
||||
def test_track_sunrise(self):
|
||||
""" Test track sunrise """
|
||||
|
|
|
@ -20,7 +20,6 @@ import homeassistant.core as ha
|
|||
from homeassistant.exceptions import (
|
||||
HomeAssistantError, InvalidEntityFormatError)
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.helpers.event import track_state_change
|
||||
from homeassistant.const import (
|
||||
__version__, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
||||
EVENT_STATE_CHANGED, ATTR_FRIENDLY_NAME, TEMP_CELCIUS,
|
||||
|
@ -150,7 +149,7 @@ class TestEventBus(unittest.TestCase):
|
|||
self.bus._pool.add_worker()
|
||||
old_count = len(self.bus.listeners)
|
||||
|
||||
listener = lambda x: len
|
||||
def listener(_): pass
|
||||
|
||||
self.bus.listen('test', listener)
|
||||
|
||||
|
@ -280,12 +279,26 @@ class TestStateMachine(unittest.TestCase):
|
|||
|
||||
def test_remove(self):
|
||||
""" Test remove method. """
|
||||
self.assertTrue('light.bowl' in self.states.entity_ids())
|
||||
self.pool.add_worker()
|
||||
events = []
|
||||
self.bus.listen(EVENT_STATE_CHANGED,
|
||||
lambda event: events.append(event))
|
||||
|
||||
self.assertIn('light.bowl', self.states.entity_ids())
|
||||
self.assertTrue(self.states.remove('light.bowl'))
|
||||
self.assertFalse('light.bowl' in self.states.entity_ids())
|
||||
self.pool.block_till_done()
|
||||
|
||||
self.assertNotIn('light.bowl', self.states.entity_ids())
|
||||
self.assertEqual(1, len(events))
|
||||
self.assertEqual('light.bowl', events[0].data.get('entity_id'))
|
||||
self.assertIsNotNone(events[0].data.get('old_state'))
|
||||
self.assertEqual('light.bowl', events[0].data['old_state'].entity_id)
|
||||
self.assertIsNone(events[0].data.get('new_state'))
|
||||
|
||||
# If it does not exist, we should get False
|
||||
self.assertFalse(self.states.remove('light.Bowl'))
|
||||
self.pool.block_till_done()
|
||||
self.assertEqual(1, len(events))
|
||||
|
||||
def test_case_insensitivty(self):
|
||||
self.pool.add_worker()
|
||||
|
|
Loading…
Add table
Reference in a new issue