Esempio n. 1
0
    def test_extract_entity_ids(self):
        """ Test extract_entity_ids method. """
        call = ha.ServiceCall('light', 'turn_on',
                              {ATTR_ENTITY_ID: 'light.Bowl'})

        self.assertEqual(['light.bowl'], extract_entity_ids(self.hass, call))

        call = ha.ServiceCall('light', 'turn_on',
                              {ATTR_ENTITY_ID: 'group.test'})

        self.assertEqual(['light.ceiling', 'light.kitchen'],
                         extract_entity_ids(self.hass, call))
Esempio n. 2
0
    def test_extract_entity_ids(self):
        """ Test extract_entity_ids method. """
        call = ha.ServiceCall('light', 'turn_on',
                              {ATTR_ENTITY_ID: 'light.Bowl'})

        self.assertEqual(['light.bowl'],
                         extract_entity_ids(self.hass, call))

        call = ha.ServiceCall('light', 'turn_on',
                              {ATTR_ENTITY_ID: 'group.test'})

        self.assertEqual(['light.ceiling', 'light.kitchen'],
                         extract_entity_ids(self.hass, call))
Esempio n. 3
0
    def thermostat_service(service):
        """ Handles calls to the services. """
        # Convert the entity ids to valid light ids
        target_thermostats = [
            thermostats[entity_id]
            for entity_id in extract_entity_ids(hass, service)
            if entity_id in thermostats
        ]

        if not target_thermostats:
            target_thermostats = thermostats.values()

        if service.service == SERVICE_TURN_AWAY_MODE_ON:
            for thermostat in target_thermostats:
                thermostat.turn_away_mode_on()

        elif service.service == SERVICE_TURN_AWAY_MODE_OFF:
            for thermostat in target_thermostats:
                thermostat.turn_away_mode_off()

        elif service.service == SERVICE_SET_TEMPERATURE:
            temperature = util.convert(service.data.get(ATTR_TEMPERATURE),
                                       float)

            if temperature is None:
                return

            for thermostat in target_thermostats:
                thermostat.nest.set_temperature(temperature)

        for thermostat in target_thermostats:
            thermostat.update_ha_state(hass, True)
Esempio n. 4
0
    def thermostat_service(service):
        """ Handles calls to the services. """
        # Convert the entity ids to valid light ids
        target_thermostats = [thermostats[entity_id] for entity_id
                              in extract_entity_ids(hass, service)
                              if entity_id in thermostats]

        if not target_thermostats:
            target_thermostats = thermostats.values()

        if service.service == SERVICE_TURN_AWAY_MODE_ON:
            for thermostat in target_thermostats:
                thermostat.turn_away_mode_on()

        elif service.service == SERVICE_TURN_AWAY_MODE_OFF:
            for thermostat in target_thermostats:
                thermostat.turn_away_mode_off()

        elif service.service == SERVICE_SET_TEMPERATURE:
            temperature = util.convert(
                service.data.get(ATTR_TEMPERATURE), float)

            if temperature is None:
                return

            for thermostat in target_thermostats:
                thermostat.nest.set_temperature(temperature)

        for thermostat in target_thermostats:
            thermostat.update_ha_state(hass, True)
Esempio 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)
Esempio n. 6
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)
Esempio n. 7
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)
Esempio n. 8
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)
Esempio n. 9
0
    def mock_turn_off(service):
        """ Will fake the component has been turned off. """
        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:
            hass.states.set(entity_id, STATE_OFF)
Esempio n. 10
0
    def mock_turn_off(service):
        """ Will fake the component has been turned off. """
        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:
            hass.states.set(entity_id, STATE_OFF)
Esempio n. 11
0
 def extract_from_service(self, service):
     """
     Takes a service and extracts all known entities.
     Will return all if no entity IDs given in service.
     """
     if ATTR_ENTITY_ID not in service.data:
         return self.entities.values()
     else:
         return [self.entities[entity_id] for entity_id
                 in extract_entity_ids(self.hass, service)
                 if entity_id in self.entities]
Esempio n. 12
0
    def _service_to_entities(service):
        """ Helper method to get entities from service. """
        entity_ids = extract_entity_ids(hass, service)

        if entity_ids:
            for entity_id in entity_ids:
                cast = casts.get(entity_id)

                if cast:
                    yield entity_id, cast

        else:
            yield from casts.items()
Esempio n. 13
0
    def _service_to_entities(service):
        """ Helper method to get entities from service. """
        entity_ids = extract_entity_ids(hass, service)

        if entity_ids:
            for entity_id in entity_ids:
                cast = casts.get(entity_id)

                if cast:
                    yield entity_id, cast

        else:
            yield from casts.items()
Esempio n. 14
0
    def handle_switch_service(service):
        """ Handles calls to the switch services. """
        target_switches = [switches[entity_id] for entity_id
                           in extract_entity_ids(hass, service)
                           if entity_id in switches]

        if not target_switches:
            target_switches = switches.values()

        for switch in target_switches:
            if service.service == SERVICE_TURN_ON:
                switch.turn_on()
            else:
                switch.turn_off()

            switch.update_ha_state(hass)
Esempio n. 15
0
    def handle_switch_service(service):
        """ Handles calls to the switch services. """
        devices = [ent_to_switch[entity_id] for entity_id
                   in extract_entity_ids(hass, service)
                   if entity_id in ent_to_switch]

        if not devices:
            devices = switches

        for switch in devices:
            if service.service == SERVICE_TURN_ON:
                switch.turn_on()
            else:
                switch.turn_off()

            switch.update_ha_state(hass)
Esempio n. 16
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":
                data = {ATTR_BRIGHTNESS: 200,
                        ATTR_XY_COLOR: random.choice(light_colors)}
            else:
                data = None

            hass.states.set(entity_id, STATE_ON, data)
Esempio n. 17
0
    def handle_switch_service(service):
        """ Handles calls to the switch services. """
        devices = [
            ent_to_switch[entity_id]
            for entity_id in extract_entity_ids(hass, service)
            if entity_id in ent_to_switch
        ]

        if not devices:
            devices = switches

        for switch in devices:
            if service.service == SERVICE_TURN_ON:
                switch.turn_on()
            else:
                switch.turn_off()

            switch.update_ha_state(hass)
Esempio n. 18
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":
                data = {
                    ATTR_BRIGHTNESS: 200,
                    ATTR_XY_COLOR: random.choice(light_colors)
                }
            else:
                data = None

            hass.states.set(entity_id, STATE_ON, data)
Esempio n. 19
0
    def thermostat_service(service):
        """ Handles calls to the services. """

        # Convert the entity ids to valid light ids
        target_thermostats = [thermostats[entity_id] for entity_id
                              in extract_entity_ids(hass, service)
                              if entity_id in thermostats]

        if not target_thermostats:
            target_thermostats = thermostats.values()

        if service.service == SERVICE_SET_AWAY_MODE:
            away_mode = service.data.get(ATTR_AWAY_MODE)

            if away_mode is None:
                _LOGGER.error(
                    "Received call to %s without attribute %s",
                    SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE)

            elif away_mode:
                for thermostat in target_thermostats:
                    thermostat.turn_away_mode_on()
            else:
                for thermostat in target_thermostats:
                    thermostat.turn_away_mode_off()

        elif service.service == SERVICE_SET_TEMPERATURE:
            temperature = util.convert(
                service.data.get(ATTR_TEMPERATURE), float)

            if temperature is None:
                return

            for thermostat in target_thermostats:
                thermostat.set_temperature(temperature)

        for thermostat in target_thermostats:
            thermostat.update_ha_state(True)
Esempio n. 20
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.services.call(domain, service.service, data, True)
Esempio n. 21
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.services.call(domain, service.service, data)
Esempio n. 22
0
    def handle_light_service(service):
        """ Hande a turn light on or off service call. """
        # Get and validate data
        dat = service.data

        # Convert the entity ids to valid light ids
        lights = [ent_to_light[entity_id] for entity_id
                  in extract_entity_ids(hass, service)
                  if entity_id in ent_to_light]

        if not lights:
            lights = list(ent_to_light.values())

        params = {}

        transition = util.convert(dat.get(ATTR_TRANSITION), int)

        if transition is not None:
            params[ATTR_TRANSITION] = transition

        if service.service == SERVICE_TURN_OFF:
            for light in lights:
                # pylint: disable=star-args
                light.turn_off(**params)

        else:
            # Processing extra data for turn light on request

            # We process the profile first so that we get the desired
            # behavior that extra service data attributes overwrite
            # profile values
            profile = profiles.get(dat.get(ATTR_PROFILE))

            if profile:
                *params[ATTR_XY_COLOR], params[ATTR_BRIGHTNESS] = profile

            if ATTR_BRIGHTNESS in dat:
                # We pass in the old value as the default parameter if parsing
                # of the new one goes wrong.
                params[ATTR_BRIGHTNESS] = util.convert(
                    dat.get(ATTR_BRIGHTNESS), int, params.get(ATTR_BRIGHTNESS))

            if ATTR_XY_COLOR in dat:
                try:
                    # xy_color should be a list containing 2 floats
                    xycolor = dat.get(ATTR_XY_COLOR)

                    # Without this check, a xycolor with value '99' would work
                    if not isinstance(xycolor, str):
                        params[ATTR_XY_COLOR] = [float(val) for val in xycolor]

                except (TypeError, ValueError):
                    # TypeError if xy_color is not iterable
                    # ValueError if value could not be converted to float
                    pass

            if ATTR_RGB_COLOR in dat:
                try:
                    # rgb_color should be a list containing 3 ints
                    rgb_color = dat.get(ATTR_RGB_COLOR)

                    if len(rgb_color) == 3:
                        params[ATTR_XY_COLOR] = \
                            util.color_RGB_to_xy(int(rgb_color[0]),
                                                 int(rgb_color[1]),
                                                 int(rgb_color[2]))

                except (TypeError, ValueError):
                    # TypeError if rgb_color is not iterable
                    # ValueError if not all values can be converted to int
                    pass

            for light in lights:
                # pylint: disable=star-args
                light.turn_on(**params)

        for light in lights:
            light.update_ha_state(hass, True)
Esempio n. 23
0
    def handle_light_service(service):
        """ Hande a turn light on or off service call. """
        # Get and validate data
        dat = service.data

        # Convert the entity ids to valid light ids
        target_lights = [
            lights[entity_id]
            for entity_id in extract_entity_ids(hass, service)
            if entity_id in lights
        ]

        if not target_lights:
            target_lights = lights.values()

        params = {}

        transition = util.convert(dat.get(ATTR_TRANSITION), int)

        if transition is not None:
            params[ATTR_TRANSITION] = transition

        if service.service == SERVICE_TURN_OFF:
            for light in target_lights:
                # pylint: disable=star-args
                light.turn_off(**params)

        else:
            # Processing extra data for turn light on request

            # We process the profile first so that we get the desired
            # behavior that extra service data attributes overwrite
            # profile values
            profile = profiles.get(dat.get(ATTR_PROFILE))

            if profile:
                *params[ATTR_XY_COLOR], params[ATTR_BRIGHTNESS] = profile

            if ATTR_BRIGHTNESS in dat:
                # We pass in the old value as the default parameter if parsing
                # of the new one goes wrong.
                params[ATTR_BRIGHTNESS] = util.convert(
                    dat.get(ATTR_BRIGHTNESS), int, params.get(ATTR_BRIGHTNESS))

            if ATTR_XY_COLOR in dat:
                try:
                    # xy_color should be a list containing 2 floats
                    xycolor = dat.get(ATTR_XY_COLOR)

                    # Without this check, a xycolor with value '99' would work
                    if not isinstance(xycolor, str):
                        params[ATTR_XY_COLOR] = [float(val) for val in xycolor]

                except (TypeError, ValueError):
                    # TypeError if xy_color is not iterable
                    # ValueError if value could not be converted to float
                    pass

            if ATTR_RGB_COLOR in dat:
                try:
                    # rgb_color should be a list containing 3 ints
                    rgb_color = dat.get(ATTR_RGB_COLOR)

                    if len(rgb_color) == 3:
                        params[ATTR_XY_COLOR] = \
                            util.color_RGB_to_xy(int(rgb_color[0]),
                                                 int(rgb_color[1]),
                                                 int(rgb_color[2]))

                except (TypeError, ValueError):
                    # TypeError if rgb_color is not iterable
                    # ValueError if not all values can be converted to int
                    pass

            if ATTR_FLASH in dat:
                if dat[ATTR_FLASH] == FLASH_SHORT:
                    params[ATTR_FLASH] = FLASH_SHORT

                elif dat[ATTR_FLASH] == FLASH_LONG:
                    params[ATTR_FLASH] = FLASH_LONG

            for light in target_lights:
                # pylint: disable=star-args
                light.turn_on(**params)

        for light in target_lights:
            light.update_ha_state(True)