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))
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)
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)
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)
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)
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)
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)
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]
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()
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)