def test_setting_up_group(self): """Setup the setting of a group.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass, group_name='everyone') # No group after setup assert 0 == len(self.hass.states.entity_ids()) component.add_entities([EntityTest(name='hello')]) # group exists assert 2 == len(self.hass.states.entity_ids()) assert ['group.everyone'] == self.hass.states.entity_ids('group') group = self.hass.states.get('group.everyone') assert ('test_domain.hello',) == group.attributes.get('entity_id') # group extended component.add_entities([EntityTest(name='hello2')]) assert 3 == len(self.hass.states.entity_ids()) group = self.hass.states.get('group.everyone') assert ['test_domain.hello', 'test_domain.hello2'] == \ sorted(group.attributes.get('entity_id'))
def test_setting_up_group(self): """Setup the setting of a group.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass, group_name='everyone') # No group after setup assert 0 == len(self.hass.states.entity_ids()) component.add_entities([EntityTest(name='hello')]) # group exists assert 2 == len(self.hass.states.entity_ids()) assert ['group.everyone'] == self.hass.states.entity_ids('group') group = self.hass.states.get('group.everyone') assert ('test_domain.hello', ) == group.attributes.get('entity_id') # group extended component.add_entities([EntityTest(name='hello2')]) assert 3 == len(self.hass.states.entity_ids()) group = self.hass.states.get('group.everyone') assert ['test_domain.hello', 'test_domain.hello2'] == \ sorted(group.attributes.get('entity_id'))
def test_not_assigning_entity_id_if_prescribes_one(self): """Test for not assigning an entity ID.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass) assert 'hello.world' not in self.hass.states.entity_ids() component.add_entities([EntityTest(entity_id='hello.world')]) assert 'hello.world' in self.hass.states.entity_ids()
def setup(hass, config): """Setup input select.""" if not isinstance(config.get(DOMAIN), dict): _LOGGER.error('Expected %s config to be a dictionary', DOMAIN) return False component = EntityComponent(_LOGGER, DOMAIN, hass) entities = [] for object_id, cfg in config[DOMAIN].items(): if object_id != slugify(object_id): _LOGGER.warning( "Found invalid key for boolean input: %s. " "Use %s instead", object_id, slugify(object_id)) continue if not cfg: _LOGGER.warning("No configuration specified for %s", object_id) continue name = cfg.get(CONF_NAME) options = cfg.get(CONF_OPTIONS) if not isinstance(options, list) or len(options) == 0: _LOGGER.warning('Key %s should be a list of options', CONF_OPTIONS) continue options = [str(val) for val in options] state = cfg.get(CONF_INITIAL) if state not in options: state = options[0] icon = cfg.get(CONF_ICON) entities.append(InputSelect(object_id, name, state, options, icon)) if not entities: return False def select_option_service(call): """Handle a calls to the input select services.""" target_inputs = component.extract_from_service(call) for input_select in target_inputs: input_select.select_option(call.data[ATTR_OPTION]) hass.services.register(DOMAIN, SERVICE_SELECT_OPTION, select_option_service, schema=SERVICE_SELECT_OPTION_SCHEMA) component.add_entities(entities) return True
def setup(hass, config): """Set up input slider.""" if not isinstance(config.get(DOMAIN), dict): _LOGGER.error('Expected %s config to be a dictionary', DOMAIN) return False component = EntityComponent(_LOGGER, DOMAIN, hass) entities = [] for object_id, cfg in config[DOMAIN].items(): if object_id != slugify(object_id): _LOGGER.warning( "Found invalid key for boolean input: %s. " "Use %s instead", object_id, slugify(object_id)) continue if not cfg: _LOGGER.warning("No configuration specified for %s", object_id) continue name = cfg.get(CONF_NAME) minimum = cfg.get(CONF_MIN) maximum = cfg.get(CONF_MAX) state = cfg.get(CONF_INITIAL, minimum) step = cfg.get(CONF_STEP, 1) icon = cfg.get(CONF_ICON) unit = cfg.get(ATTR_UNIT_OF_MEASUREMENT) if state < minimum: state = minimum if state > maximum: state = maximum entities.append( InputSlider(object_id, name, state, minimum, maximum, step, icon, unit)) if not entities: return False def select_value_service(call): """Handle a calls to the input slider services.""" target_inputs = component.extract_from_service(call) for input_slider in target_inputs: input_slider.select_value(call.data[ATTR_VALUE]) hass.services.register(DOMAIN, SERVICE_SELECT_VALUE, select_value_service, schema=SERVICE_SELECT_VALUE_SCHEMA) component.add_entities(entities) return True
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.is_on: _LOGGER.warning("Script %s already running.", entity_id) return script.turn_on(variables=service.data) for object_id, cfg in config[DOMAIN].items(): alias = cfg.get(CONF_ALIAS, object_id) script = ScriptEntity(hass, object_id, alias, cfg[CONF_SEQUENCE]) component.add_entities((script, )) hass.services.register(DOMAIN, object_id, service_handler, schema=SCRIPT_SERVICE_SCHEMA) def turn_on_service(service): """Call 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 detect invocations. for script in component.extract_from_service(service): turn_on(hass, script.entity_id, service.data.get(ATTR_VARIABLES)) def turn_off_service(service): """Cancel a script.""" for script in component.extract_from_service(service): script.turn_off() def toggle_service(service): """Toggle a script.""" for script in component.extract_from_service(service): script.toggle() hass.services.register(DOMAIN, SERVICE_TURN_ON, turn_on_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) hass.services.register(DOMAIN, SERVICE_TURN_OFF, turn_off_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) hass.services.register(DOMAIN, SERVICE_TOGGLE, toggle_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) return True
def test_not_adding_duplicate_entities(self): """Test for not adding duplicate entities.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass) assert 0 == len(self.hass.states.entity_ids()) component.add_entities([None, EntityTest(unique_id='not_very_unique')]) assert 1 == len(self.hass.states.entity_ids()) component.add_entities([EntityTest(unique_id='not_very_unique')]) assert 1 == len(self.hass.states.entity_ids())
def test_extract_from_service_returns_all_if_no_entity_id(self): """Test the extraction of everything from service.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass) component.add_entities([ EntityTest(name='test_1'), EntityTest(name='test_2'), ]) call = ha.ServiceCall('test', 'service') assert ['test_domain.test_1', 'test_domain.test_2'] == \ sorted(ent.entity_id for ent in component.extract_from_service(call))
def test_extract_from_service_filter_out_non_existing_entities(self): """Test the extraction of non existing entities from service.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass) component.add_entities([ EntityTest(name='test_1'), EntityTest(name='test_2'), ]) call = ha.ServiceCall('test', 'service', { 'entity_id': ['test_domain.test_2', 'test_domain.non_exist'] }) assert ['test_domain.test_2'] == \ [ent.entity_id for ent in component.extract_from_service(call)]
def setup(hass, config): """Set up input boolean.""" if not isinstance(config.get(DOMAIN), dict): _LOGGER.error('Expected %s config to be a dictionary', DOMAIN) return False component = EntityComponent(_LOGGER, DOMAIN, hass) entities = [] for object_id, cfg in config[DOMAIN].items(): if object_id != slugify(object_id): _LOGGER.warning( "Found invalid key for boolean input: %s. " "Use %s instead", object_id, slugify(object_id)) continue if not cfg: cfg = {} name = cfg.get(CONF_NAME) state = cfg.get(CONF_INITIAL, False) icon = cfg.get(CONF_ICON) entities.append(InputBoolean(object_id, name, state, icon)) if not entities: return False def toggle_service(service): """Handle a calls to the input boolean services.""" target_inputs = component.extract_from_service(service) for input_b in target_inputs: if service.service == SERVICE_TURN_ON: input_b.turn_on() else: input_b.turn_off() hass.services.register(DOMAIN, SERVICE_TURN_OFF, toggle_service, schema=TOGGLE_SERVICE_SCHEMA) hass.services.register(DOMAIN, SERVICE_TURN_ON, toggle_service, schema=TOGGLE_SERVICE_SCHEMA) component.add_entities(entities) return True
def test_extract_from_service_filter_out_non_existing_entities(self): """Test the extraction of non existing entities from service.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass) component.add_entities([ EntityTest(name='test_1'), EntityTest(name='test_2'), ]) call = ha.ServiceCall( 'test', 'service', {'entity_id': ['test_domain.test_2', 'test_domain.non_exist']}) assert ['test_domain.test_2'] == \ [ent.entity_id for ent in component.extract_from_service(call)]
def test_update_state_adds_entities(self): """Test if updating poll entities cause an entity to be added works.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass) ent1 = EntityTest() ent2 = EntityTest(should_poll=True) component.add_entities([ent2]) assert 1 == len(self.hass.states.entity_ids()) ent2.update_ha_state = lambda *_: component.add_entities([ent1]) fire_time_changed(self.hass, dt_util.utcnow().replace(second=0)) self.hass.pool.block_till_done() assert 2 == len(self.hass.states.entity_ids())
def setup(hass, config): """Set up input boolean.""" if not isinstance(config.get(DOMAIN), dict): _LOGGER.error('Expected %s config to be a dictionary', DOMAIN) return False component = EntityComponent(_LOGGER, DOMAIN, hass) entities = [] for object_id, cfg in config[DOMAIN].items(): if object_id != slugify(object_id): _LOGGER.warning("Found invalid key for boolean input: %s. " "Use %s instead", object_id, slugify(object_id)) continue if not cfg: cfg = {} name = cfg.get(CONF_NAME) state = cfg.get(CONF_INITIAL, False) icon = cfg.get(CONF_ICON) entities.append(InputBoolean(object_id, name, state, icon)) if not entities: return False def toggle_service(service): """Handle a calls to the input boolean services.""" target_inputs = component.extract_from_service(service) for input_b in target_inputs: if service.service == SERVICE_TURN_ON: input_b.turn_on() else: input_b.turn_off() hass.services.register(DOMAIN, SERVICE_TURN_OFF, toggle_service, schema=TOGGLE_SERVICE_SCHEMA) hass.services.register(DOMAIN, SERVICE_TURN_ON, toggle_service, schema=TOGGLE_SERVICE_SCHEMA) component.add_entities(entities) return True
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.is_on: _LOGGER.warning("Script %s already running.", entity_id) return script.turn_on(variables=service.data) for object_id, cfg in config[DOMAIN].items(): alias = cfg.get(CONF_ALIAS, object_id) script = ScriptEntity(hass, object_id, alias, cfg[CONF_SEQUENCE]) component.add_entities((script,)) hass.services.register(DOMAIN, object_id, service_handler, schema=SCRIPT_SERVICE_SCHEMA) def turn_on_service(service): """Call 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 detect invocations. for script in component.extract_from_service(service): turn_on(hass, script.entity_id, service.data.get(ATTR_VARIABLES)) def turn_off_service(service): """Cancel a script.""" for script in component.extract_from_service(service): script.turn_off() def toggle_service(service): """Toggle a script.""" for script in component.extract_from_service(service): script.toggle() hass.services.register(DOMAIN, SERVICE_TURN_ON, turn_on_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) hass.services.register(DOMAIN, SERVICE_TURN_OFF, turn_off_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) hass.services.register(DOMAIN, SERVICE_TOGGLE, toggle_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) return True
def test_polling_only_updates_entities_it_should_poll(self): """Test the polling of only updated entities.""" component = EntityComponent(_LOGGER, DOMAIN, self.hass, 20) no_poll_ent = EntityTest(should_poll=False) no_poll_ent.update_ha_state = Mock() poll_ent = EntityTest(should_poll=True) poll_ent.update_ha_state = Mock() component.add_entities([no_poll_ent, poll_ent]) no_poll_ent.update_ha_state.reset_mock() poll_ent.update_ha_state.reset_mock() fire_time_changed(self.hass, dt_util.utcnow().replace(second=0)) self.hass.pool.block_till_done() assert not no_poll_ent.update_ha_state.called assert poll_ent.update_ha_state.called