示例#1
0
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    value_template = config.get(CONF_VALUE_TEMPLATE)

    # Local variable to keep track of if the action has already been triggered
    already_triggered = False

    def state_changed_listener(entity_id, from_s, to_s):
        """Listen for state changes and calls action."""
        nonlocal already_triggered
        template_result = condition.template(hass, value_template)

        # Check to see if template returns true
        if template_result and not already_triggered:
            already_triggered = True
            action({
                'trigger': {
                    'platform': 'template',
                    'entity_id': entity_id,
                    'from_state': from_s,
                    'to_state': to_s,
                },
            })
        elif not template_result:
            already_triggered = False

    track_state_change(hass, MATCH_ALL, state_changed_listener)
    return True
示例#2
0
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    value_template = config.get(CONF_VALUE_TEMPLATE)

    # Local variable to keep track of if the action has already been triggered
    already_triggered = False

    def state_changed_listener(entity_id, from_s, to_s):
        """Listen for state changes and calls action."""
        nonlocal already_triggered
        template_result = condition.template(hass, value_template)

        # Check to see if template returns true
        if template_result and not already_triggered:
            already_triggered = True
            action({
                'trigger': {
                    'platform': 'template',
                    'entity_id': entity_id,
                    'from_state': from_s,
                    'to_state': to_s,
                },
            })
        elif not template_result:
            already_triggered = False

    track_state_change(hass, MATCH_ALL, state_changed_listener)
    return True
示例#3
0
文件: state.py 项目: lumavp/blumate
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    entity_id = config.get(CONF_ENTITY_ID)
    from_state = config.get(CONF_FROM, MATCH_ALL)
    to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL
    time_delta = config.get(CONF_FOR)

    def state_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        def call_action():
            """Call action with right context."""
            action({
                'trigger': {
                    'platform': 'state',
                    'entity_id': entity,
                    'from_state': from_s,
                    'to_state': to_s,
                    'for': time_delta,
                }
            })

        if time_delta is None:
            call_action()
            return

        def state_for_listener(now):
            """Fire on state changes after a delay and calls action."""
            hass.bus.remove_listener(EVENT_STATE_CHANGED,
                                     attached_state_for_cancel)
            call_action()

        def state_for_cancel_listener(entity, inner_from_s, inner_to_s):
            """Fire on changes and cancel for listener if changed."""
            if inner_to_s.state == to_s.state:
                return
            hass.bus.remove_listener(EVENT_TIME_CHANGED,
                                     attached_state_for_listener)
            hass.bus.remove_listener(EVENT_STATE_CHANGED,
                                     attached_state_for_cancel)

        attached_state_for_listener = track_point_in_time(
            hass, state_for_listener,
            dt_util.utcnow() + time_delta)

        attached_state_for_cancel = track_state_change(
            hass, entity, state_for_cancel_listener)

    track_state_change(hass, entity_id, state_automation_listener, from_state,
                       to_state)

    return True
示例#4
0
文件: state.py 项目: bdfoster/blumate
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    entity_id = config.get(CONF_ENTITY_ID)
    from_state = config.get(CONF_FROM, MATCH_ALL)
    to_state = config.get(CONF_TO) or config.get(CONF_STATE) or MATCH_ALL
    time_delta = config.get(CONF_FOR)

    def state_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        def call_action():
            """Call action with right context."""
            action({
                'trigger': {
                    'platform': 'state',
                    'entity_id': entity,
                    'from_state': from_s,
                    'to_state': to_s,
                    'for': time_delta,
                }
            })

        if time_delta is None:
            call_action()
            return

        def state_for_listener(now):
            """Fire on state changes after a delay and calls action."""
            hass.bus.remove_listener(
                EVENT_STATE_CHANGED, attached_state_for_cancel)
            call_action()

        def state_for_cancel_listener(entity, inner_from_s, inner_to_s):
            """Fire on changes and cancel for listener if changed."""
            if inner_to_s.state == to_s.state:
                return
            hass.bus.remove_listener(EVENT_TIME_CHANGED,
                                     attached_state_for_listener)
            hass.bus.remove_listener(EVENT_STATE_CHANGED,
                                     attached_state_for_cancel)

        attached_state_for_listener = track_point_in_time(
            hass, state_for_listener, dt_util.utcnow() + time_delta)

        attached_state_for_cancel = track_state_change(
            hass, entity, state_for_cancel_listener)

    track_state_change(
        hass, entity_id, state_automation_listener, from_state, to_state)

    return True
示例#5
0
def setup(hass, config):  # pylint: disable=too-many-locals,too-many-statements
    """Get the zones and offsets from configuration.yaml."""
    ignored_zones = []
    if 'ignored_zones' in config[DOMAIN]:
        for variable in config[DOMAIN]['ignored_zones']:
            ignored_zones.append(variable)

    # Get the devices from configuration.yaml.
    if 'devices' not in config[DOMAIN]:
        _LOGGER.error('devices not found in config')
        return False

    proximity_devices = []
    for variable in config[DOMAIN]['devices']:
        proximity_devices.append(variable)

    # Get the direction of travel tolerance from configuration.yaml.
    tolerance = config[DOMAIN].get('tolerance', DEFAULT_TOLERANCE)

    # Get the zone to monitor proximity to from configuration.yaml.
    proximity_zone = config[DOMAIN].get('zone', DEFAULT_PROXIMITY_ZONE)

    entity_id = DOMAIN + '.' + proximity_zone
    proximity_zone = 'zone.' + proximity_zone

    state = hass.states.get(proximity_zone)
    zone_friendly_name = (state.name).lower()

    # Set the default values.
    dist_to_zone = 'not set'
    dir_of_travel = 'not set'
    nearest = 'not set'

    proximity = Proximity(hass, zone_friendly_name, dist_to_zone,
                          dir_of_travel, nearest, ignored_zones,
                          proximity_devices, tolerance, proximity_zone)
    proximity.entity_id = entity_id

    proximity.update_ha_state()

    # Main command to monitor proximity of devices.
    track_state_change(hass, proximity_devices,
                       proximity.check_proximity_state_change)

    return True
示例#6
0
def setup(hass, config):  # pylint: disable=too-many-locals,too-many-statements
    """Get the zones and offsets from configuration.yaml."""
    ignored_zones = []
    if 'ignored_zones' in config[DOMAIN]:
        for variable in config[DOMAIN]['ignored_zones']:
            ignored_zones.append(variable)

    # Get the devices from configuration.yaml.
    if 'devices' not in config[DOMAIN]:
        _LOGGER.error('devices not found in config')
        return False

    proximity_devices = []
    for variable in config[DOMAIN]['devices']:
        proximity_devices.append(variable)

    # Get the direction of travel tolerance from configuration.yaml.
    tolerance = config[DOMAIN].get('tolerance', DEFAULT_TOLERANCE)

    # Get the zone to monitor proximity to from configuration.yaml.
    proximity_zone = config[DOMAIN].get('zone', DEFAULT_PROXIMITY_ZONE)

    entity_id = DOMAIN + '.' + proximity_zone
    proximity_zone = 'zone.' + proximity_zone

    state = hass.states.get(proximity_zone)
    zone_friendly_name = (state.name).lower()

    # Set the default values.
    dist_to_zone = 'not set'
    dir_of_travel = 'not set'
    nearest = 'not set'

    proximity = Proximity(hass, zone_friendly_name, dist_to_zone,
                          dir_of_travel, nearest, ignored_zones,
                          proximity_devices, tolerance, proximity_zone)
    proximity.entity_id = entity_id

    proximity.update_ha_state()

    # Main command to monitor proximity of devices.
    track_state_change(hass, proximity_devices,
                       proximity.check_proximity_state_change)

    return True
示例#7
0
    def __init__(self, hass, device, friendly_name, sensor_class,
                 value_template, entity_ids):
        """Initialize the Template binary sensor."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT,
                                            device,
                                            hass=hass)
        self._name = friendly_name
        self._sensor_class = sensor_class
        self._template = value_template
        self._state = None

        self.update()

        def template_bsensor_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids, template_bsensor_state_listener)
示例#8
0
    def __init__(self, hass, name, children, commands, attributes):
        """Initialize the Universal media device."""
        # pylint: disable=too-many-arguments
        self.hass = hass
        self._name = name
        self._children = children
        self._cmds = commands
        self._attrs = attributes
        self._child_state = None

        def on_dependency_update(*_):
            """Update bm state when dependencies update."""
            self.update_ha_state(True)

        depend = copy(children)
        for entity in attributes.values():
            depend.append(entity[0])

        track_state_change(hass, depend, on_dependency_update)
示例#9
0
    def __init__(self, hass, name, heater_entity_id, sensor_entity_id,
                 min_temp, max_temp, target_temp):
        """Initialize the thermostat."""
        self.hass = hass
        self._name = name
        self.heater_entity_id = heater_entity_id

        self._active = False
        self._cur_temp = None
        self._min_temp = min_temp
        self._max_temp = max_temp
        self._target_temp = target_temp
        self._unit = None

        track_state_change(hass, sensor_entity_id, self._sensor_changed)

        sensor_state = hass.states.get(sensor_entity_id)
        if sensor_state:
            self._update_temp(sensor_state)
示例#10
0
    def __init__(self, hass, device_id, friendly_name, unit_of_measurement,
                 state_template, entity_ids):
        """Initialize the sensor."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                            hass=hass)
        self._name = friendly_name
        self._unit_of_measurement = unit_of_measurement
        self._template = state_template
        self._state = None

        self.update()

        def template_sensor_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids,
                           template_sensor_state_listener)
示例#11
0
    def __init__(self, hass, name, children, commands, attributes):
        """Initialize the Universal media device."""
        # pylint: disable=too-many-arguments
        self.hass = hass
        self._name = name
        self._children = children
        self._cmds = commands
        self._attrs = attributes
        self._child_state = None

        def on_dependency_update(*_):
            """Update bm state when dependencies update."""
            self.update_ha_state(True)

        depend = copy(children)
        for entity in attributes.values():
            depend.append(entity[0])

        track_state_change(hass, depend, on_dependency_update)
示例#12
0
    def __init__(self, hass, device, friendly_name, sensor_class,
                 value_template, entity_ids):
        """Initialize the Template binary sensor."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device,
                                            hass=hass)
        self._name = friendly_name
        self._sensor_class = sensor_class
        self._template = value_template
        self._state = None

        self.update()

        def template_bsensor_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids,
                           template_bsensor_state_listener)
示例#13
0
    def __init__(self, hass, device_id, friendly_name, unit_of_measurement,
                 state_template, entity_ids):
        """Initialize the sensor."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT,
                                            device_id,
                                            hass=hass)
        self._name = friendly_name
        self._unit_of_measurement = unit_of_measurement
        self._template = state_template
        self._state = None

        self.update()

        def template_sensor_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids, template_sensor_state_listener)
示例#14
0
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    entity_id = config.get(CONF_ENTITY_ID)
    below = config.get(CONF_BELOW)
    above = config.get(CONF_ABOVE)
    value_template = config.get(CONF_VALUE_TEMPLATE)

    # pylint: disable=unused-argument
    def state_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        if to_s is None:
            return

        variables = {
            'trigger': {
                'platform': 'numeric_state',
                'entity_id': entity,
                'below': below,
                'above': above,
            }
        }

        # If new one doesn't match, nothing to do
        if not condition.numeric_state(
                hass, to_s, below, above, value_template, variables):
            return

        # Only match if old didn't exist or existed but didn't match
        # Written as: skip if old one did exist and matched
        if from_s is not None and condition.numeric_state(
                hass, from_s, below, above, value_template, variables):
            return

        variables['trigger']['from_state'] = from_s
        variables['trigger']['to_state'] = to_s

        action(variables)

    track_state_change(
        hass, entity_id, state_automation_listener)

    return True
示例#15
0
    def __init__(self, hass, device_id, friendly_name, state_template,
                 on_action, off_action, entity_ids):
        """Initialize the Template switch."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                            hass=hass)
        self._name = friendly_name
        self._template = state_template
        self._on_script = Script(hass, on_action)
        self._off_script = Script(hass, off_action)
        self._state = False

        self.update()

        def template_switch_state_listener(entity, old_state, new_state):
            """Called when the target device changes state."""
            self.update_ha_state(True)

        track_state_change(hass, entity_ids,
                           template_switch_state_listener)
示例#16
0
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    entity_id = config.get(CONF_ENTITY_ID)
    below = config.get(CONF_BELOW)
    above = config.get(CONF_ABOVE)
    value_template = config.get(CONF_VALUE_TEMPLATE)

    # pylint: disable=unused-argument
    def state_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        if to_s is None:
            return

        variables = {
            'trigger': {
                'platform': 'numeric_state',
                'entity_id': entity,
                'below': below,
                'above': above,
            }
        }

        # If new one doesn't match, nothing to do
        if not condition.numeric_state(hass, to_s, below, above,
                                       value_template, variables):
            return

        # Only match if old didn't exist or existed but didn't match
        # Written as: skip if old one did exist and matched
        if from_s is not None and condition.numeric_state(
                hass, from_s, below, above, value_template, variables):
            return

        variables['trigger']['from_state'] = from_s
        variables['trigger']['to_state'] = to_s

        action(variables)

    track_state_change(hass, entity_id, state_automation_listener)

    return True
示例#17
0
文件: zone.py 项目: bdfoster/blumate
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    entity_id = config.get(CONF_ENTITY_ID)
    zone_entity_id = config.get(CONF_ZONE)
    event = config.get(CONF_EVENT)

    def zone_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        if from_s and not location.has_location(from_s) or \
           not location.has_location(to_s):
            return

        zone_state = hass.states.get(zone_entity_id)
        if from_s:
            from_match = condition.zone(hass, zone_state, from_s)
        else:
            from_match = False
        to_match = condition.zone(hass, zone_state, to_s)

        # pylint: disable=too-many-boolean-expressions
        if event == EVENT_ENTER and not from_match and to_match or \
           event == EVENT_LEAVE and from_match and not to_match:
            action({
                'trigger': {
                    'platform': 'zone',
                    'entity_id': entity,
                    'from_state': from_s,
                    'to_state': to_s,
                    'zone': zone_state,
                    'event': event,
                },
            })

    track_state_change(
        hass, entity_id, zone_automation_listener, MATCH_ALL, MATCH_ALL)

    return True
示例#18
0
def trigger(hass, config, action):
    """Listen for state changes based on configuration."""
    entity_id = config.get(CONF_ENTITY_ID)
    zone_entity_id = config.get(CONF_ZONE)
    event = config.get(CONF_EVENT)

    def zone_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        if from_s and not location.has_location(from_s) or \
           not location.has_location(to_s):
            return

        zone_state = hass.states.get(zone_entity_id)
        if from_s:
            from_match = condition.zone(hass, zone_state, from_s)
        else:
            from_match = False
        to_match = condition.zone(hass, zone_state, to_s)

        # pylint: disable=too-many-boolean-expressions
        if event == EVENT_ENTER and not from_match and to_match or \
           event == EVENT_LEAVE and from_match and not to_match:
            action({
                'trigger': {
                    'platform': 'zone',
                    'entity_id': entity,
                    'from_state': from_s,
                    'to_state': to_s,
                    'zone': zone_state,
                    'event': event,
                },
            })

    track_state_change(hass, entity_id, zone_automation_listener, MATCH_ALL,
                       MATCH_ALL)

    return True
示例#19
0
文件: state.py 项目: lumavp/blumate
    def state_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        def call_action():
            """Call action with right context."""
            action({
                'trigger': {
                    'platform': 'state',
                    'entity_id': entity,
                    'from_state': from_s,
                    'to_state': to_s,
                    'for': time_delta,
                }
            })

        if time_delta is None:
            call_action()
            return

        def state_for_listener(now):
            """Fire on state changes after a delay and calls action."""
            hass.bus.remove_listener(EVENT_STATE_CHANGED,
                                     attached_state_for_cancel)
            call_action()

        def state_for_cancel_listener(entity, inner_from_s, inner_to_s):
            """Fire on changes and cancel for listener if changed."""
            if inner_to_s.state == to_s.state:
                return
            hass.bus.remove_listener(EVENT_TIME_CHANGED,
                                     attached_state_for_listener)
            hass.bus.remove_listener(EVENT_STATE_CHANGED,
                                     attached_state_for_cancel)

        attached_state_for_listener = track_point_in_time(
            hass, state_for_listener,
            dt_util.utcnow() + time_delta)

        attached_state_for_cancel = track_state_change(
            hass, entity, state_for_cancel_listener)
示例#20
0
文件: state.py 项目: bdfoster/blumate
    def state_automation_listener(entity, from_s, to_s):
        """Listen for state changes and calls action."""
        def call_action():
            """Call action with right context."""
            action({
                'trigger': {
                    'platform': 'state',
                    'entity_id': entity,
                    'from_state': from_s,
                    'to_state': to_s,
                    'for': time_delta,
                }
            })

        if time_delta is None:
            call_action()
            return

        def state_for_listener(now):
            """Fire on state changes after a delay and calls action."""
            hass.bus.remove_listener(
                EVENT_STATE_CHANGED, attached_state_for_cancel)
            call_action()

        def state_for_cancel_listener(entity, inner_from_s, inner_to_s):
            """Fire on changes and cancel for listener if changed."""
            if inner_to_s.state == to_s.state:
                return
            hass.bus.remove_listener(EVENT_TIME_CHANGED,
                                     attached_state_for_listener)
            hass.bus.remove_listener(EVENT_STATE_CHANGED,
                                     attached_state_for_cancel)

        attached_state_for_listener = track_point_in_time(
            hass, state_for_listener, dt_util.utcnow() + time_delta)

        attached_state_for_cancel = track_state_change(
            hass, entity, state_for_cancel_listener)
示例#21
0
    def __init__(self, hass, name, indoor_temp_sensor, outdoor_temp_sensor,
                 indoor_humidity_sensor, calib_factor):
        """Initialize the sensor."""
        self._state = None
        self._name = name
        self._indoor_temp_sensor = indoor_temp_sensor
        self._indoor_humidity_sensor = indoor_humidity_sensor
        self._outdoor_temp_sensor = outdoor_temp_sensor
        self._calib_factor = calib_factor
        self._is_metric = (hass.config.temperature_unit == TEMP_CELSIUS)

        self._dewpoint = None
        self._indoor_temp = None
        self._outdoor_temp = None
        self._indoor_hum = None
        self._crit_temp = None

        track_state_change(hass, indoor_temp_sensor, self._sensor_changed)
        track_state_change(hass, outdoor_temp_sensor, self._sensor_changed)
        track_state_change(hass, indoor_humidity_sensor, self._sensor_changed)

        # Read initial state
        indoor_temp = hass.states.get(indoor_temp_sensor)
        outdoor_temp = hass.states.get(outdoor_temp_sensor)
        indoor_hum = hass.states.get(indoor_humidity_sensor)

        if indoor_temp:
            self._indoor_temp = \
                MoldIndicator._update_temp_sensor(indoor_temp)

        if outdoor_temp:
            self._outdoor_temp = \
                MoldIndicator._update_temp_sensor(outdoor_temp)

        if indoor_hum:
            self._indoor_hum = \
                MoldIndicator._update_hum_sensor(indoor_hum)

        self.update()
示例#22
0
    def __init__(self, hass, name, indoor_temp_sensor, outdoor_temp_sensor,
                 indoor_humidity_sensor, calib_factor):
        """Initialize the sensor."""
        self._state = None
        self._name = name
        self._indoor_temp_sensor = indoor_temp_sensor
        self._indoor_humidity_sensor = indoor_humidity_sensor
        self._outdoor_temp_sensor = outdoor_temp_sensor
        self._calib_factor = calib_factor
        self._is_metric = (hass.config.temperature_unit == TEMP_CELSIUS)

        self._dewpoint = None
        self._indoor_temp = None
        self._outdoor_temp = None
        self._indoor_hum = None
        self._crit_temp = None

        track_state_change(hass, indoor_temp_sensor, self._sensor_changed)
        track_state_change(hass, outdoor_temp_sensor, self._sensor_changed)
        track_state_change(hass, indoor_humidity_sensor, self._sensor_changed)

        # Read initial state
        indoor_temp = hass.states.get(indoor_temp_sensor)
        outdoor_temp = hass.states.get(outdoor_temp_sensor)
        indoor_hum = hass.states.get(indoor_humidity_sensor)

        if indoor_temp:
            self._indoor_temp = \
                MoldIndicator._update_temp_sensor(indoor_temp)

        if outdoor_temp:
            self._outdoor_temp = \
                MoldIndicator._update_temp_sensor(outdoor_temp)

        if indoor_hum:
            self._indoor_hum = \
                MoldIndicator._update_hum_sensor(indoor_hum)

        self.update()
示例#23
0
    def test_track_state_change(self):
        """Test track_state_change."""
        # 2 lists to track how often our callbacks get called
        specific_runs = []
        wildcard_runs = []
        wildercard_runs = []

        track_state_change(
            self.hass, 'light.Bowl', lambda a, b, c: specific_runs.append(1),
            'on', 'off')

        track_state_change(
            self.hass, 'light.Bowl',
            lambda _, old_s, new_s: wildcard_runs.append((old_s, new_s)))

        track_state_change(
            self.hass, MATCH_ALL,
            lambda _, old_s, new_s: wildercard_runs.append((old_s, new_s)))

        # 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.assertEqual(1, len(wildercard_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(1, len(wildcard_runs))
        self.assertEqual(1, len(wildercard_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(2, len(wildcard_runs))
        self.assertEqual(2, len(wildercard_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(3, len(wildcard_runs))
        self.assertEqual(3, len(wildercard_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(4, len(wildcard_runs))
        self.assertEqual(4, len(wildercard_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.assertEqual(5, len(wildercard_runs))
        self.assertIsNotNone(wildcard_runs[-1][0])
        self.assertIsNone(wildcard_runs[-1][1])
        self.assertIsNotNone(wildercard_runs[-1][0])
        self.assertIsNone(wildercard_runs[-1][1])

        # Set state for different entity id
        self.hass.states.set('switch.kitchen', 'on')
        self.hass.pool.block_till_done()
        self.assertEqual(1, len(specific_runs))
        self.assertEqual(5, len(wildcard_runs))
        self.assertEqual(6, len(wildercard_runs))
示例#24
0
 def track_state_change_decorator(action):
     """Decorator to track state changes."""
     event.track_state_change(HASS, entity_ids,
                              functools.partial(action, HASS), from_state,
                              to_state)
     return action
示例#25
0
    def test_track_state_change(self):
        """Test track_state_change."""
        # 2 lists to track how often our callbacks get called
        specific_runs = []
        wildcard_runs = []
        wildercard_runs = []

        track_state_change(self.hass, 'light.Bowl',
                           lambda a, b, c: specific_runs.append(1), 'on',
                           'off')

        track_state_change(
            self.hass, 'light.Bowl',
            lambda _, old_s, new_s: wildcard_runs.append((old_s, new_s)))

        track_state_change(
            self.hass, MATCH_ALL,
            lambda _, old_s, new_s: wildercard_runs.append((old_s, new_s)))

        # 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.assertEqual(1, len(wildercard_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(1, len(wildcard_runs))
        self.assertEqual(1, len(wildercard_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(2, len(wildcard_runs))
        self.assertEqual(2, len(wildercard_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(3, len(wildcard_runs))
        self.assertEqual(3, len(wildercard_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(4, len(wildcard_runs))
        self.assertEqual(4, len(wildercard_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.assertEqual(5, len(wildercard_runs))
        self.assertIsNotNone(wildcard_runs[-1][0])
        self.assertIsNone(wildcard_runs[-1][1])
        self.assertIsNotNone(wildercard_runs[-1][0])
        self.assertIsNone(wildercard_runs[-1][1])

        # Set state for different entity id
        self.hass.states.set('switch.kitchen', 'on')
        self.hass.pool.block_till_done()
        self.assertEqual(1, len(specific_runs))
        self.assertEqual(5, len(wildcard_runs))
        self.assertEqual(6, len(wildercard_runs))
示例#26
0
 def start(self):
     """Start tracking members."""
     track_state_change(
         self.hass, self.tracking, self._state_changed_listener)
示例#27
0
 def track_state_change_decorator(action):
     """Decorator to track state changes."""
     event.track_state_change(HASS, entity_ids,
                              functools.partial(action, HASS),
                              from_state, to_state)
     return action