Ejemplo n.º 1
0
    def mock_turn_on(service):
        """ Will fake the component has been turned on. """
        if service.data and ATTR_ENTITY_ID in service.data:
            entity_ids = extract_entity_ids(hass, service)
        else:
            entity_ids = hass.states.entity_ids(service.domain)

        for entity_id in entity_ids:
            domain, _ = split_entity_id(entity_id)

            if domain == "light":
                rgb_color = service.data.get(ATTR_RGB_COLOR)

                if rgb_color:
                    color = color_RGB_to_xy(rgb_color[0], rgb_color[1],
                                            rgb_color[2])

                else:
                    cur_state = hass.states.get(entity_id)

                    # Use current color if available
                    if cur_state and cur_state.attributes.get(ATTR_XY_COLOR):
                        color = cur_state.attributes.get(ATTR_XY_COLOR)
                    else:
                        color = random.choice(light_colors)

                data = {
                    ATTR_BRIGHTNESS: service.data.get(ATTR_BRIGHTNESS, 200),
                    ATTR_XY_COLOR: color
                }
            else:
                data = None

            hass.states.set(entity_id, STATE_ON, data)
Ejemplo n.º 2
0
 def entity_ids(self, domain_filter=None):
     """ List of entity ids that are being tracked. """
     if domain_filter is not None:
         return [entity_id for entity_id in self._states.keys()
                 if util.split_entity_id(entity_id)[0] == domain_filter]
     else:
         return list(self._states.keys())
Ejemplo n.º 3
0
def call_from_config(hass, config, blocking=False):
    """Call a service based on a config hash."""
    if not isinstance(config, dict) or CONF_SERVICE not in config:
        _LOGGER.error('Missing key %s: %s', CONF_SERVICE, config)
        return

    try:
        domain, service = split_entity_id(config[CONF_SERVICE])
    except ValueError:
        _LOGGER.error('Invalid service specified: %s', config[CONF_SERVICE])
        return

    service_data = config.get(CONF_SERVICE_DATA)

    if service_data is None:
        service_data = {}
    elif isinstance(service_data, dict):
        service_data = dict(service_data)
    else:
        _LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
        service_data = {}

    entity_id = config.get(CONF_SERVICE_ENTITY_ID)
    if isinstance(entity_id, str):
        service_data[ATTR_ENTITY_ID] = [ent.strip() for ent in
                                        entity_id.split(",")]
    elif entity_id is not None:
        service_data[ATTR_ENTITY_ID] = entity_id

    hass.services.call(domain, service, service_data, blocking)
Ejemplo n.º 4
0
    def mock_turn_on(service):
        """ Will fake the component has been turned on. """
        if service.data and ATTR_ENTITY_ID in service.data:
            entity_ids = extract_entity_ids(hass, service)
        else:
            entity_ids = hass.states.entity_ids(service.domain)

        for entity_id in entity_ids:
            domain, _ = split_entity_id(entity_id)

            if domain == "light":
                rgb_color = service.data.get(ATTR_RGB_COLOR)

                if rgb_color:
                    color = color_RGB_to_xy(
                        rgb_color[0], rgb_color[1], rgb_color[2])

                else:
                    cur_state = hass.states.get(entity_id)

                    # Use current color if available
                    if cur_state and cur_state.attributes.get(ATTR_XY_COLOR):
                        color = cur_state.attributes.get(ATTR_XY_COLOR)
                    else:
                        color = random.choice(light_colors)

                data = {
                    ATTR_BRIGHTNESS: service.data.get(ATTR_BRIGHTNESS, 200),
                    ATTR_XY_COLOR: color
                }
            else:
                data = None

            hass.states.set(entity_id, STATE_ON, data)
Ejemplo n.º 5
0
    def handle_turn_service(service):
        """ Method to handle calls to homeassistant.turn_on/off. """
        entity_ids = extract_entity_ids(hass, service)

        # Generic turn on/off method requires entity id
        if not entity_ids:
            _LOGGER.error(
                "homeassistant/%s cannot be called without entity_id",
                service.service)
            return

        # Group entity_ids by domain. groupby requires sorted data.
        by_domain = it.groupby(sorted(entity_ids),
                               lambda item: util.split_entity_id(item)[0])

        for domain, ent_ids in by_domain:
            # We want to block for all calls and only return when all calls
            # have been processed. If a service does not exist it causes a 10
            # second delay while we're blocking waiting for a response.
            # But services can be registered on other HA instances that are
            # listening to the bus too. So as a in between solution, we'll
            # block only if the service is defined in the current HA instance.
            blocking = hass.services.has_service(domain, service.service)

            # Create a new dict for this call
            data = dict(service.data)

            # ent_ids is a generator, convert it to a list.
            data[ATTR_ENTITY_ID] = list(ent_ids)

            hass.services.call(domain, service.service, data, blocking)
Ejemplo n.º 6
0
def call_from_config(hass, config, blocking=False):
    """Call a service based on a config hash."""
    if not isinstance(config, dict) or CONF_SERVICE not in config:
        _LOGGER.error('Missing key %s: %s', CONF_SERVICE, config)
        return

    try:
        domain, service = split_entity_id(config[CONF_SERVICE])
    except ValueError:
        _LOGGER.error('Invalid service specified: %s', config[CONF_SERVICE])
        return

    service_data = config.get(CONF_SERVICE_DATA)

    if service_data is None:
        service_data = {}
    elif isinstance(service_data, dict):
        service_data = dict(service_data)
    else:
        _LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
        service_data = {}

    entity_id = config.get(CONF_SERVICE_ENTITY_ID)
    if isinstance(entity_id, str):
        service_data[ATTR_ENTITY_ID] = [
            ent.strip() for ent in entity_id.split(",")
        ]
    elif entity_id is not None:
        service_data[ATTR_ENTITY_ID] = entity_id

    hass.services.call(domain, service, service_data, blocking)
Ejemplo n.º 7
0
def expand_entity_ids(hass, entity_ids):
    """ Returns the given list of entity ids and expands group ids into
        the entity ids it represents if found. """
    found_ids = []

    for entity_id in entity_ids:
        if not isinstance(entity_id, str):
            continue

        entity_id = entity_id.lower()

        try:
            # If entity_id points at a group, expand it
            domain, _ = util.split_entity_id(entity_id)

            if domain == DOMAIN:
                found_ids.extend(ent_id
                                 for ent_id in get_entity_ids(hass, entity_id)
                                 if ent_id not in found_ids)

            else:
                if entity_id not in found_ids:
                    found_ids.append(entity_id)

        except AttributeError:
            # Raised by util.split_entity_id if entity_id is not a string
            pass

    return found_ids
Ejemplo n.º 8
0
def is_on(hass, entity_id=None):
    """ Loads up the module to call the is_on method.
    If there is no entity id given we will check all. """
    if entity_id:
        group = get_component('group')

        entity_ids = group.expand_entity_ids([entity_id])
    else:
        entity_ids = hass.states.entity_ids

    for entity_id in entity_ids:
        domain = util.split_entity_id(entity_id)[0]

        module = get_component(domain)

        try:
            if module.is_on(hass, entity_id):
                return True

        except AttributeError:
            # module is None or method is_on does not exist
            _LOGGER.exception("Failed to call %s.is_on for %s",
                              module, entity_id)

    return False
Ejemplo n.º 9
0
def expand_entity_ids(hass, entity_ids):
    """ Returns the given list of entity ids and expands group ids into
        the entity ids it represents if found. """
    found_ids = []

    for entity_id in entity_ids:
        if not isinstance(entity_id, str):
            continue

        entity_id = entity_id.lower()

        try:
            # If entity_id points at a group, expand it
            domain, _ = util.split_entity_id(entity_id)

            if domain == DOMAIN:
                found_ids.extend(
                    ent_id for ent_id
                    in get_entity_ids(hass, entity_id)
                    if ent_id not in found_ids)

            else:
                if entity_id not in found_ids:
                    found_ids.append(entity_id)

        except AttributeError:
            # Raised by util.split_entity_id if entity_id is not a string
            pass

    return found_ids
Ejemplo n.º 10
0
def is_on(hass, entity_id=None):
    """ Loads up the module to call the is_on method.
    If there is no entity id given we will check all. """
    if entity_id:
        group = get_component('group')

        entity_ids = group.expand_entity_ids(hass, [entity_id])
    else:
        entity_ids = hass.states.entity_ids

    for entity_id in entity_ids:
        domain = util.split_entity_id(entity_id)[0]

        module = get_component(domain)

        try:
            if module.is_on(hass, entity_id):
                return True

        except AttributeError:
            # module is None or method is_on does not exist
            _LOGGER.exception("Failed to call %s.is_on for %s", module,
                              entity_id)

    return False
Ejemplo n.º 11
0
    def handle_turn_service(service):
        """ Method to handle calls to homeassistant.turn_on/off. """
        entity_ids = extract_entity_ids(hass, service)

        # Generic turn on/off method requires entity id
        if not entity_ids:
            _LOGGER.error(
                "homeassistant/%s cannot be called without entity_id",
                service.service)
            return

        # Group entity_ids by domain. groupby requires sorted data.
        by_domain = it.groupby(sorted(entity_ids),
                               lambda item: util.split_entity_id(item)[0])

        for domain, ent_ids in by_domain:
            # We want to block for all calls and only return when all calls
            # have been processed. If a service does not exist it causes a 10
            # second delay while we're blocking waiting for a response.
            # But services can be registered on other HA instances that are
            # listening to the bus too. So as a in between solution, we'll
            # block only if the service is defined in the current HA instance.
            blocking = hass.services.has_service(domain, service.service)

            # Create a new dict for this call
            data = dict(service.data)

            # ent_ids is a generator, convert it to a list.
            data[ATTR_ENTITY_ID] = list(ent_ids)

            hass.services.call(domain, service.service, data, blocking)
Ejemplo n.º 12
0
def is_on(hass, entity_id=None):
    """ Loads up the module to call the is_on method.
    If there is no entity id given we will check all. """
    logger = logging.getLogger(__name__)

    if entity_id:
        group = get_component('group', logger)

        entity_ids = group.expand_entity_ids([entity_id])
    else:
        entity_ids = hass.states.entity_ids

    for entity_id in entity_ids:
        domain = util.split_entity_id(entity_id)[0]

        module = get_component(domain, logger)

        try:
            if module.is_on(hass, entity_id):
                return True

        except AttributeError:
            # module is None or method is_on does not exist
            pass

    return False
Ejemplo n.º 13
0
 def _call_service(self, action):
     """ Calls the service specified in the action. """
     self.last_action = action.get(CONF_ALIAS, action[CONF_SERVICE])
     _LOGGER.info("Executing script %s step %s", self.alias,
                  self.last_action)
     domain, service = split_entity_id(action[CONF_SERVICE])
     data = action.get(CONF_SERVICE_DATA, {})
     self.hass.services.call(domain, service, data)
Ejemplo n.º 14
0
 def _call_service(self, action):
     """ Calls the service specified in the action. """
     self.last_action = action.get(CONF_ALIAS, action[CONF_SERVICE])
     _LOGGER.info("Executing script %s step %s", self.alias,
                  self.last_action)
     domain, service = split_entity_id(action[CONF_SERVICE])
     data = action.get(CONF_SERVICE_DATA, {})
     self.hass.services.call(domain, service, data)
Ejemplo n.º 15
0
    def entity_ids(self, domain_filter=None):
        """ List of entity ids that are being tracked. """
        if domain_filter is None:
            return list(self._states.keys())

        domain_filter = domain_filter.lower()

        return [state.entity_id for key, state in self._states.items() if util.split_entity_id(key)[0] == domain_filter]
Ejemplo n.º 16
0
 def _call_service(self, action):
     """ Calls the service specified in the action. """
     conf_service = action.get(CONF_SERVICE, action.get(CONF_SERVICE_OLD))
     self._last_action = action.get(CONF_ALIAS, conf_service)
     _LOGGER.info("Executing script %s step %s", self._name,
                  self._last_action)
     domain, service = split_entity_id(conf_service)
     data = action.get(CONF_SERVICE_DATA, {})
     self.hass.services.call(domain, service, data)
Ejemplo n.º 17
0
 def entity_ids(self, domain_filter=None):
     """ List of entity ids that are being tracked. """
     if domain_filter is not None:
         return [
             entity_id for entity_id in self._states.keys()
             if util.split_entity_id(entity_id)[0] == domain_filter
         ]
     else:
         return list(self._states.keys())
Ejemplo n.º 18
0
 def _call_service(self, action):
     """ Calls the service specified in the action. """
     conf_service = action.get(CONF_SERVICE, action.get(CONF_SERVICE_OLD))
     self._last_action = action.get(CONF_ALIAS, conf_service)
     _LOGGER.info("Executing script %s step %s", self._name,
                  self._last_action)
     domain, service = split_entity_id(conf_service)
     data = action.get(CONF_SERVICE_DATA, {})
     self.hass.services.call(domain, service, data)
Ejemplo n.º 19
0
    def entity_ids(self, domain_filter=None):
        """ List of entity ids that are being tracked. """
        if domain_filter is not None:
            domain_filter = domain_filter.lower()

            return [state.entity_id for key, state
                    in self._states.items()
                    if util.split_entity_id(key)[0] == domain_filter]
        else:
            return list(self._states.keys())
Ejemplo n.º 20
0
    def mock_turn_on(service):
        """ Will fake the component has been turned on. """
        for entity_id in extract_entity_ids(hass, service):
            domain, _ = split_entity_id(entity_id)

            if domain == "light":
                data = {ATTR_BRIGHTNESS: 200,
                        ATTR_XY_COLOR: random.choice(light_colors)}
            else:
                data = None

            hass.states.set(entity_id, STATE_ON, data)
Ejemplo n.º 21
0
    def mock_turn_on(service):
        """ Will fake the component has been turned on. """
        for entity_id in extract_entity_ids(hass, service):
            domain, _ = split_entity_id(entity_id)

            if domain == "light":
                data = {
                    ATTR_BRIGHTNESS: 200,
                    ATTR_XY_COLOR: random.choice(light_colors)
                }
            else:
                data = None

            hass.states.set(entity_id, STATE_ON, data)
Ejemplo n.º 22
0
    def action():
        """ Action to be executed. """
        _LOGGER.info("Executing rule %s", config.get(CONF_ALIAS, ""))

        if CONF_SERVICE in config:
            domain, service = split_entity_id(config[CONF_SERVICE])

            service_data = config.get(CONF_SERVICE_DATA, {})

            if not isinstance(service_data, dict):
                _LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
                service_data = {}

            if CONF_SERVICE_ENTITY_ID in config:
                service_data[ATTR_ENTITY_ID] = \
                    config[CONF_SERVICE_ENTITY_ID].split(",")

            hass.services.call(domain, service, service_data)
Ejemplo n.º 23
0
    def action():
        """ Action to be executed. """
        _LOGGER.info("Executing rule %s", config.get(CONF_ALIAS, ""))

        if CONF_SERVICE in config:
            domain, service = split_entity_id(config[CONF_SERVICE])

            service_data = config.get(CONF_SERVICE_DATA, {})

            if not isinstance(service_data, dict):
                _LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
                service_data = {}

            if CONF_SERVICE_ENTITY_ID in config:
                service_data[ATTR_ENTITY_ID] = \
                    config[CONF_SERVICE_ENTITY_ID].split(",")

            hass.services.call(domain, service, service_data)
Ejemplo n.º 24
0
    def fire(self, event_type, event_data=None, origin=EventOrigin.local):
        """ Fire an event. """
        with self._lock:
            # Copy the list of the current listeners because some listeners
            # remove themselves as a listener while being executed which
            # causes the iterator to be confused.
            get = self._listeners.get
            listeners = get(MATCH_ALL, []) + get(event_type, [])

            event = Event(event_type, event_data, origin)
            _LOGGER.info("Bus:Handling %s", event)

            quietStartComplete = None
            quietEndComplete = None

            if (len(self.quiet_time_start) > 0) and (len(self.quiet_time_end) > 0):
                currDateTime = dt.datetime.now()
                currDateOnly = dt.date(currDateTime.year, currDateTime.month, currDateTime.day)

                quietStartTimeOnly = dt.time(int(self.quiet_time_start[0]), int(self.quiet_time_start[1]), 0)
                quietStartComplete = dt.datetime.combine(currDateOnly, quietStartTimeOnly)

                quietEndTimeOnly = dt.time(int(self.quiet_time_end[0]), int(self.quiet_time_end[1]), 0)
                quietEndComplete = dt.datetime.combine(currDateOnly, quietEndTimeOnly)

            if (quietStartComplete is not None) and (quietEndComplete is not None) and (event.event_type == EVENT_STATE_CHANGED) and (len(self.api_keys) > 0) and (len(self.notify_entity_ids) > 0):
                if not(quietStartComplete < dt.datetime.now() < quietEndComplete):
                    for notify_entity_id in self.notify_entity_ids:
                        if ("old_state" in event_data):
                            if (notify_entity_id == event_data["entity_id"]):
                                new_state = event_data["new_state"]
                                for api_key in self.api_keys:
                                    splittedEntity = util.split_entity_id(event_data["entity_id"])
                                    push_obj = pushbullet.PushBullet(api_key)
                                    push_obj.pushNote("", "Home Assistant" , splittedEntity[0].replace("_", " ").title() + ": " + splittedEntity[1].replace("_", " ").title() + " is " + new_state.state.replace("_", " ").title())
                                break
            if not listeners:
                return

            for func in listeners:
                self._pool.add_job(JobPriority.from_event_type(event_type),
                                   (func, event))
Ejemplo n.º 25
0
    def handle_turn_service(service):
        """ Method to handle calls to homeassistant.turn_on/off. """

        entity_ids = extract_entity_ids(hass, service)

        # Generic turn on/off method requires entity id
        if not entity_ids:
            return

        # Group entity_ids by domain. groupby requires sorted data.
        by_domain = it.groupby(sorted(entity_ids),
                               lambda item: util.split_entity_id(item)[0])

        for domain, ent_ids in by_domain:
            # Create a new dict for this call
            data = dict(service.data)

            # ent_ids is a generator, convert it to a list.
            data[ATTR_ENTITY_ID] = list(ent_ids)

            hass.call_service(domain, service.service, data)
Ejemplo n.º 26
0
    def action():
        """ Action to be executed. """
        _LOGGER.info('Executing %s', name)
        logbook.log_entry(hass, name, 'has been triggered', DOMAIN)

        domain, service = split_entity_id(config[CONF_SERVICE])
        service_data = config.get(CONF_SERVICE_DATA, {})

        if not isinstance(service_data, dict):
            _LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
            service_data = {}

        if CONF_SERVICE_ENTITY_ID in config:
            try:
                service_data[ATTR_ENTITY_ID] = \
                    config[CONF_SERVICE_ENTITY_ID].split(",")
            except AttributeError:
                service_data[ATTR_ENTITY_ID] = \
                    config[CONF_SERVICE_ENTITY_ID]

        hass.services.call(domain, service, service_data)
Ejemplo n.º 27
0
    def action():
        """ Action to be executed. """
        _LOGGER.info('Executing %s', name)
        logbook.log_entry(hass, name, 'has been triggered', DOMAIN)

        domain, service = split_entity_id(config[CONF_SERVICE])
        service_data = config.get(CONF_SERVICE_DATA, {})

        if not isinstance(service_data, dict):
            _LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
            service_data = {}

        if CONF_SERVICE_ENTITY_ID in config:
            try:
                service_data[ATTR_ENTITY_ID] = \
                    config[CONF_SERVICE_ENTITY_ID].split(",")
            except AttributeError:
                service_data[ATTR_ENTITY_ID] = \
                    config[CONF_SERVICE_ENTITY_ID]

        hass.services.call(domain, service, service_data)
Ejemplo n.º 28
0
def setup(hass, config):
    """ Load the scripts from the configuration. """

    component = EntityComponent(_LOGGER, DOMAIN, hass)

    def service_handler(service):
        """ Execute a service call to script.<script name>. """
        entity_id = ENTITY_ID_FORMAT.format(service.service)
        script = component.entities.get(entity_id)
        if script:
            script.turn_on()

    for name, cfg in config[DOMAIN].items():
        if not cfg.get(CONF_SEQUENCE):
            _LOGGER.warn("Missing key 'sequence' for script %s", name)
            continue
        alias = cfg.get(CONF_ALIAS, name)
        script = Script(hass, alias, cfg[CONF_SEQUENCE])
        component.add_entities((script,))
        _, object_id = split_entity_id(script.entity_id)
        hass.services.register(DOMAIN, object_id, service_handler)

    def turn_on_service(service):
        """ Calls a service to turn script on. """
        # We could turn on script directly here, but we only want to offer
        # one way to do it. Otherwise no easy way to call invocations.
        for script in component.extract_from_service(service):
            turn_on(hass, script.entity_id)

    def turn_off_service(service):
        """ Cancels a script. """
        for script in component.extract_from_service(service):
            script.turn_off()

    hass.services.register(DOMAIN, SERVICE_TURN_ON, turn_on_service)
    hass.services.register(DOMAIN, SERVICE_TURN_OFF, turn_off_service)

    return True
Ejemplo n.º 29
0
    def handle_turn_service(service):
        """ Method to handle calls to homeassistant.turn_on/off. """
        entity_ids = extract_entity_ids(hass, service)

        # Generic turn on/off method requires entity id
        if not entity_ids:
            _LOGGER.error(
                "homeassistant/%s cannot be called without entity_id",
                service.service)
            return

        # Group entity_ids by domain. groupby requires sorted data.
        by_domain = it.groupby(sorted(entity_ids),
                               lambda item: util.split_entity_id(item)[0])

        for domain, ent_ids in by_domain:
            # Create a new dict for this call
            data = dict(service.data)

            # ent_ids is a generator, convert it to a list.
            data[ATTR_ENTITY_ID] = list(ent_ids)

            hass.call_service(domain, service.service, data)
Ejemplo n.º 30
0
 def domain(self):
     """ Returns domain of this state. """
     return util.split_entity_id(self.entity_id)[0]
Ejemplo n.º 31
0
 def test_split_entity_id(self):
     """ Test split_entity_id. """
     self.assertEqual(['domain', 'object_id'],
                      util.split_entity_id('domain.object_id'))
Ejemplo n.º 32
0
def turn_on(hass, entity_id):
    """ Turn script on. """
    _, object_id = split_entity_id(entity_id)

    hass.services.call(DOMAIN, object_id)
Ejemplo n.º 33
0
 def test_split_entity_id(self):
     """ Test split_entity_id. """
     self.assertEqual(["domain", "object_id"], util.split_entity_id("domain.object_id"))
Ejemplo n.º 34
0
 def turn_on(service):
     """ Calls a script. """
     for entity_id in _get_entities(service):
         domain, service = split_entity_id(entity_id)
         hass.services.call(domain, service, {})
Ejemplo n.º 35
0
 def turn_on(service):
     """ Calls a script. """
     for entity_id in service.data['entity_id']:
         domain, service = split_entity_id(entity_id)
         hass.services.call(domain, service, {})
Ejemplo n.º 36
0
 def object_id(self):
     """ Returns object_id of this state. """
     return util.split_entity_id(self.entity_id)[1]
Ejemplo n.º 37
0
 def domain(self):
     """ Returns domain of this state. """
     return util.split_entity_id(self.entity_id)[0]
Ejemplo n.º 38
0
def humanify(events):
    """
    Generator that converts a list of events into Entry objects.

    Will try to group events if possible:
     - if 2+ sensor updates in GROUP_BY_MINUTES, show last
     - if home assistant stop and start happen in same minute call it restarted
    """
    # pylint: disable=too-many-branches

    # Group events in batches of GROUP_BY_MINUTES
    for _, g_events in groupby(
            events,
            lambda event: event.time_fired.minute // GROUP_BY_MINUTES):

        events_batch = list(g_events)

        # Keep track of last sensor states
        last_sensor_event = {}

        # group HA start/stop events
        # Maps minute of event to 1: stop, 2: stop + start
        start_stop_events = {}

        # Process events
        for event in events_batch:
            if event.event_type == EVENT_STATE_CHANGED:
                entity_id = event.data.get('entity_id')

                if entity_id is None:
                    continue

                if entity_id.startswith('sensor.'):
                    last_sensor_event[entity_id] = event

            elif event.event_type == EVENT_HOMEASSISTANT_STOP:
                if event.time_fired.minute in start_stop_events:
                    continue

                start_stop_events[event.time_fired.minute] = 1

            elif event.event_type == EVENT_HOMEASSISTANT_START:
                if event.time_fired.minute not in start_stop_events:
                    continue

                start_stop_events[event.time_fired.minute] = 2

        # Yield entries
        for event in events_batch:
            if event.event_type == EVENT_STATE_CHANGED:

                # Do not report on new entities
                if 'old_state' not in event.data:
                    continue

                to_state = State.from_dict(event.data.get('new_state'))

                # if last_changed != last_updated only attributes have changed
                # we do not report on that yet. Also filter auto groups.
                if not to_state or \
                   to_state.last_changed != to_state.last_updated or \
                   to_state.domain == 'group' and \
                   to_state.attributes.get('auto', False):
                    continue

                domain = to_state.domain

                # Skip all but the last sensor state
                if domain == 'sensor' and \
                   event != last_sensor_event[to_state.entity_id]:
                    continue

                yield Entry(
                    event.time_fired,
                    name=to_state.name,
                    message=_entry_message_from_state(domain, to_state),
                    domain=domain,
                    entity_id=to_state.entity_id)

            elif event.event_type == EVENT_HOMEASSISTANT_START:
                if start_stop_events.get(event.time_fired.minute) == 2:
                    continue

                yield Entry(
                    event.time_fired, "Home Assistant", "started",
                    domain=HA_DOMAIN)

            elif event.event_type == EVENT_HOMEASSISTANT_STOP:
                if start_stop_events.get(event.time_fired.minute) == 2:
                    action = "restarted"
                else:
                    action = "stopped"

                yield Entry(
                    event.time_fired, "Home Assistant", action,
                    domain=HA_DOMAIN)

            elif event.event_type == EVENT_LOGBOOK_ENTRY:
                domain = event.data.get(ATTR_DOMAIN)
                entity_id = event.data.get(ATTR_ENTITY_ID)
                if domain is None and entity_id is not None:
                    try:
                        domain = util.split_entity_id(str(entity_id))[0]
                    except IndexError:
                        pass

                yield Entry(
                    event.time_fired, event.data.get(ATTR_NAME),
                    event.data.get(ATTR_MESSAGE), domain,
                    entity_id)
Ejemplo n.º 39
0
 def turn_on(service):
     """ Calls a script. """
     for entity_id in service.data['entity_id']:
         domain, service = split_entity_id(entity_id)
         hass.services.call(domain, service, {})
Ejemplo n.º 40
0
def humanify(events):
    """
    Generator that converts a list of events into Entry objects.

    Will try to group events if possible:
     - if 2+ sensor updates in GROUP_BY_MINUTES, show last
     - if home assistant stop and start happen in same minute call it restarted
    """
    # pylint: disable=too-many-branches

    # Group events in batches of GROUP_BY_MINUTES
    for _, g_events in groupby(
            events,
            lambda event: event.time_fired.minute // GROUP_BY_MINUTES):

        events_batch = list(g_events)

        # Keep track of last sensor states
        last_sensor_event = {}

        # group HA start/stop events
        # Maps minute of event to 1: stop, 2: stop + start
        start_stop_events = {}

        # Process events
        for event in events_batch:
            if event.event_type == EVENT_STATE_CHANGED:
                entity_id = event.data.get('entity_id')

                if entity_id is None:
                    continue

                if entity_id.startswith('sensor.'):
                    last_sensor_event[entity_id] = event

            elif event.event_type == EVENT_HOMEASSISTANT_STOP:
                if event.time_fired.minute in start_stop_events:
                    continue

                start_stop_events[event.time_fired.minute] = 1

            elif event.event_type == EVENT_HOMEASSISTANT_START:
                if event.time_fired.minute not in start_stop_events:
                    continue

                start_stop_events[event.time_fired.minute] = 2

        # Yield entries
        for event in events_batch:
            if event.event_type == EVENT_STATE_CHANGED:

                # Do not report on new entities
                if 'old_state' not in event.data:
                    continue

                to_state = State.from_dict(event.data.get('new_state'))

                # if last_changed == last_updated only attributes have changed
                # we do not report on that yet.
                if not to_state or \
                   to_state.last_changed != to_state.last_updated:
                    continue

                domain = to_state.domain

                # Skip all but the last sensor state
                if domain == 'sensor' and \
                   event != last_sensor_event[to_state.entity_id]:
                    continue

                yield Entry(
                    event.time_fired,
                    name=to_state.name,
                    message=_entry_message_from_state(domain, to_state),
                    domain=domain,
                    entity_id=to_state.entity_id)

            elif event.event_type == EVENT_HOMEASSISTANT_START:
                if start_stop_events.get(event.time_fired.minute) == 2:
                    continue

                yield Entry(
                    event.time_fired, "Home Assistant", "started",
                    domain=HA_DOMAIN)

            elif event.event_type == EVENT_HOMEASSISTANT_STOP:
                if start_stop_events.get(event.time_fired.minute) == 2:
                    action = "restarted"
                else:
                    action = "stopped"

                yield Entry(
                    event.time_fired, "Home Assistant", action,
                    domain=HA_DOMAIN)

            elif event.event_type == EVENT_LOGBOOK_ENTRY:
                domain = event.data.get(ATTR_DOMAIN)
                entity_id = event.data.get(ATTR_ENTITY_ID)
                if domain is None and entity_id is not None:
                    try:
                        domain = util.split_entity_id(str(entity_id))[0]
                    except IndexError:
                        pass

                yield Entry(
                    event.time_fired, event.data.get(ATTR_NAME),
                    event.data.get(ATTR_MESSAGE), domain,
                    entity_id)
Ejemplo n.º 41
0
 def test_split_entity_id(self):
     """ Test split_entity_id. """
     self.assertEqual(['domain', 'object_id'],
                      util.split_entity_id('domain.object_id'))
Ejemplo n.º 42
0
def turn_on(hass, entity_id):
    """ Turn script on. """
    _, object_id = split_entity_id(entity_id)

    hass.services.call(DOMAIN, object_id)
Ejemplo n.º 43
0
 def object_id(self):
     """ Returns object_id of this state. """
     return util.split_entity_id(self.entity_id)[1]