def setup(self, config): """Set up a full entity component. Loads the platforms from the config and will listen for supported discovered platforms. """ self.config = config # Look in config for Domain, Domain 2, Domain 3 etc and load them for p_type, p_config in config_per_platform(config, self.domain): self._setup_platform(p_type, p_config) if self.discovery_platforms: # Discovery listener for all items in discovery_platforms array # passed from a component's setup method (e.g. light/__init__.py) discovery.listen( self.hass, self.discovery_platforms.keys(), lambda service, info: self._setup_platform(self.discovery_platforms[service], {}, info), ) # Generic discovery listener for loading platform dynamically # Refer to: homeassistant.components.discovery.load_platform() def load_platform_callback(service, info): """Callback to load a platform.""" platform = info.pop(discovery.LOAD_PLATFORM) self._setup_platform(platform, {}, info if info else None) discovery.listen(self.hass, discovery.LOAD_PLATFORM + "." + self.domain, load_platform_callback)
def async_setup(self, config): """Set up a full entity component. Loads the platforms from the config and will listen for supported discovered platforms. This method must be run in the event loop. """ self.config = config # Look in config for Domain, Domain 2, Domain 3 etc and load them tasks = [] for p_type, p_config in config_per_platform(config, self.domain): tasks.append(self._async_setup_platform(p_type, p_config)) if tasks: yield from asyncio.wait(tasks, loop=self.hass.loop) # Generic discovery listener for loading platform dynamically # Refer to: homeassistant.components.discovery.load_platform() @callback def component_platform_discovered(platform, info): """Handle the loading of a platform.""" self.hass.async_add_job( self._async_setup_platform(platform, {}, info)) discovery.async_listen_platform( self.hass, self.domain, component_platform_discovered)
def prepare_setup_component(hass: core.HomeAssistant, config: dict, domain: str): """Prepare setup of a component and return processed config.""" # pylint: disable=too-many-return-statements component = loader.get_component(domain) missing_deps = [dep for dep in getattr(component, "DEPENDENCIES", []) if dep not in hass.config.components] if missing_deps: _LOGGER.error("Not initializing %s because not all dependencies loaded: %s", domain, ", ".join(missing_deps)) return None if hasattr(component, "CONFIG_SCHEMA"): try: config = component.CONFIG_SCHEMA(config) except vol.Invalid as ex: log_exception(ex, domain, config, hass) return None elif hasattr(component, "PLATFORM_SCHEMA"): platforms = [] for p_name, p_config in config_per_platform(config, domain): # Validate component specific platform schema try: p_validated = component.PLATFORM_SCHEMA(p_config) except vol.Invalid as ex: log_exception(ex, domain, config, hass) continue # Not all platform components follow same pattern for platforms # So if p_name is None we are not going to validate platform # (the automation component is one of them) if p_name is None: platforms.append(p_validated) continue platform = prepare_setup_platform(hass, config, domain, p_name) if platform is None: continue # Validate platform specific schema if hasattr(platform, "PLATFORM_SCHEMA"): try: p_validated = platform.PLATFORM_SCHEMA(p_validated) except vol.Invalid as ex: log_exception(ex, "{}.{}".format(domain, p_name), p_validated, hass) continue platforms.append(p_validated) # Create a copy of the configuration with all config for current # component removed and add validated config back in. filter_keys = extract_domain_configs(config, domain) config = {key: value for key, value in config.items() if key not in filter_keys} config[domain] = platforms if not _handle_requirements(hass, component, domain): return None return config
def async_process_component_config(hass, config, domain): """Check component configuration and return processed configuration. Returns None on error. This method must be run in the event loop. """ component = get_component(hass, domain) if hasattr(component, 'CONFIG_SCHEMA'): try: config = component.CONFIG_SCHEMA(config) except vol.Invalid as ex: async_log_exception(ex, domain, config, hass) return None elif hasattr(component, 'PLATFORM_SCHEMA'): platforms = [] for p_name, p_config in config_per_platform(config, domain): # Validate component specific platform schema try: p_validated = component.PLATFORM_SCHEMA(p_config) except vol.Invalid as ex: async_log_exception(ex, domain, config, hass) continue # Not all platform components follow same pattern for platforms # So if p_name is None we are not going to validate platform # (the automation component is one of them) if p_name is None: platforms.append(p_validated) continue platform = get_platform(hass, domain, p_name) if platform is None: continue # Validate platform specific schema if hasattr(platform, 'PLATFORM_SCHEMA'): # pylint: disable=no-member try: p_validated = platform.PLATFORM_SCHEMA(p_validated) except vol.Invalid as ex: async_log_exception(ex, '{}.{}'.format(domain, p_name), p_validated, hass) continue platforms.append(p_validated) # Create a copy of the configuration with all config for current # component removed and add validated config back in. filter_keys = extract_domain_configs(config, domain) config = {key: value for key, value in config.items() if key not in filter_keys} config[domain] = platforms return config
def test_config_per_platform(self): """Test config per platform method.""" config = OrderedDict([ ('zone', {'platform': 'hello'}), ('zoner', None), ('zone Hallo', [1, {'platform': 'hello 2'}]), ('zone 100', None), ]) assert [ ('hello', config['zone']), (None, 1), ('hello 2', config['zone Hallo'][1]), ] == list(helpers.config_per_platform(config, 'zone'))
async def _resetup_platform( hass: HomeAssistant, integration_name: str, integration_platform: str, unprocessed_conf: ConfigType, ) -> None: """Resetup a platform.""" integration = await async_get_integration(hass, integration_platform) conf = await conf_util.async_process_component_config( hass, unprocessed_conf, integration) if not conf: return root_config: dict[str, Any] = {integration_platform: []} # Extract only the config for template, ignore the rest. for p_type, p_config in config_per_platform(conf, integration_platform): if p_type != integration_name: continue root_config[integration_platform].append(p_config) component = integration.get_component() if hasattr(component, "async_reset_platform"): # If the integration has its own way to reset # use this method. await component.async_reset_platform(hass, integration_name) # type: ignore await component.async_setup(hass, root_config) # type: ignore return # If it's an entity platform, we use the entity_platform # async_reset method platform = async_get_platform_without_config_entry(hass, integration_name, integration_platform) if platform: await _async_reconfig_platform(platform, root_config[integration_platform]) return if not root_config[integration_platform]: # No config for this platform # and it's not loaded. Nothing to do. return await _async_setup_platform(hass, integration_name, integration_platform, root_config[integration_platform])
def async_setup(hass, config): """Set up the telegram bot component.""" @asyncio.coroutine def async_setup_platform(p_type, p_config=None, discovery_info=None): """Set up a telegram bot platform.""" platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: _LOGGER.error("Unknown notification service specified") return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) try: if hasattr(platform, 'async_setup_platform'): notify_service = yield from \ platform.async_setup_platform(hass, p_config, discovery_info) elif hasattr(platform, 'setup_platform'): notify_service = yield from hass.loop.run_in_executor( None, platform.setup_platform, hass, p_config, discovery_info) else: raise HomeAssistantError("Invalid Telegram bot platform") if notify_service is None: _LOGGER.error( "Failed to initialize Telegram bot %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) return setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) @asyncio.coroutine def async_platform_discovered(platform, info): """Handle the loading of a platform.""" yield from async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) return True
def setup(self, config): """ Sets up a full entity component: - Loads the platforms from the config - Will listen for supported discovered platforms """ # Look in config for Domain, Domain 2, Domain 3 etc and load them for p_type, p_config in \ config_per_platform(config, self.domain, self.logger): self._setup_platform(p_type, p_config) if self.discovery_platforms: discovery.listen(self.hass, self.discovery_platforms.keys(), self._entity_discovered)
async def async_validate_config(hass, config): """Validate config.""" scripts = {} for _, p_config in config_per_platform(config, DOMAIN): for object_id, cfg in p_config.items(): cfg = await _try_async_validate_config_item(hass, object_id, cfg, config) if cfg is not None: scripts[object_id] = cfg # Create a copy of the configuration with all config for current # component removed and add validated config back in. config = config_without_domain(config, DOMAIN) config[DOMAIN] = scripts return config
def setup(hass, config): """Setup the notify services.""" success = False descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) for platform, p_config in config_per_platform(config, DOMAIN): notify_implementation = bootstrap.prepare_setup_platform( hass, config, DOMAIN, platform) if notify_implementation is None: _LOGGER.error("Unknown notification service specified.") continue notify_service = notify_implementation.get_service(hass, p_config) if notify_service is None: _LOGGER.error("Failed to initialize notification service %s", platform) continue def notify_message(notify_service, call): """Handle sending notification message service calls.""" message = call.data.get(ATTR_MESSAGE) if message is None: _LOGGER.error( 'Received call to %s without attribute %s', call.service, ATTR_MESSAGE) return title = template.render( hass, call.data.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)) target = call.data.get(ATTR_TARGET) message = template.render(hass, message) data = call.data.get(ATTR_DATA) notify_service.send_message(message, title=title, target=target, data=data) service_call_handler = partial(notify_message, notify_service) service_notify = p_config.get(CONF_NAME, SERVICE_NOTIFY) hass.services.register(DOMAIN, service_notify, service_call_handler, descriptions.get(SERVICE_NOTIFY)) success = True return success
async def async_setup(hass, config): """Set up configured zones as well as home assistant zone if necessary.""" hass.data[DOMAIN] = {} entities = set() zone_entries = configured_zones(hass) for _, entry in config_per_platform(config, DOMAIN): if slugify(entry[CONF_NAME]) not in zone_entries: zone = Zone( hass, entry[CONF_NAME], entry[CONF_LATITUDE], entry[CONF_LONGITUDE], entry.get(CONF_RADIUS), entry.get(CONF_ICON), entry.get(CONF_PASSIVE), ) zone.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, entry[CONF_NAME], entities) hass.async_create_task(zone.async_update_ha_state()) entities.add(zone.entity_id) if ENTITY_ID_HOME in entities or HOME_ZONE in zone_entries: return True zone = Zone( hass, hass.config.location_name, hass.config.latitude, hass.config.longitude, DEFAULT_RADIUS, ICON_HOME, False, ) zone.entity_id = ENTITY_ID_HOME hass.async_create_task(zone.async_update_ha_state()) @callback def core_config_updated(_): """Handle core config updated.""" zone.name = hass.config.location_name zone.latitude = hass.config.latitude zone.longitude = hass.config.longitude zone.async_write_ha_state() hass.bus.async_listen(EVENT_CORE_CONFIG_UPDATE, core_config_updated) return True
def test_config_per_platform(): """Test config per platform method.""" config = OrderedDict( [ ("zone", {"platform": "hello"}), ("zoner", None), ("zone Hallo", [1, {"platform": "hello 2"}]), ("zone 100", None), ] ) assert [ ("hello", config["zone"]), (None, 1), ("hello 2", config["zone Hallo"][1]), ] == list(helpers.config_per_platform(config, "zone"))
async def async_validate_config(hass, config): """Validate config.""" automations = [] validated_automations = await asyncio.gather( *(_try_async_validate_config_item(hass, p_config, config) for _, p_config in config_per_platform(config, DOMAIN))) for validated_automation in validated_automations: if validated_automation is not None: automations.append(validated_automation) # Create a copy of the configuration with all config for current # component removed and add validated config back in. config = config_without_domain(config, DOMAIN) config[DOMAIN] = automations return config
def test_config_per_platform(self): """Test config per platform method.""" config = OrderedDict([ ('zone', { 'platform': 'hello' }), ('zoner', None), ('zone Hallo', [1, { 'platform': 'hello 2' }]), ('zone 100', None), ]) assert [('hello', config['zone']), (None, 1), ('hello 2', config['zone Hallo'][1]), (None, None) ] == list(helpers.config_per_platform(config, 'zone'))
async def async_validate_config(hass, config): """Validate config.""" automations = list( filter( lambda x: x is not None, await asyncio.gather( *(_try_async_validate_config_item(hass, p_config, config) for _, p_config in config_per_platform(config, DOMAIN))), )) # Create a copy of the configuration with all config for current # component removed and add validated config back in. config = config_without_domain(config, DOMAIN) config[DOMAIN] = automations return config
def setup(hass, config): """Setup the notify services.""" success = False descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) for platform, p_config in config_per_platform(config, DOMAIN): notify_implementation = bootstrap.prepare_setup_platform( hass, config, DOMAIN, platform) if notify_implementation is None: _LOGGER.error("Unknown notification service specified.") continue notify_service = notify_implementation.get_service(hass, p_config) if notify_service is None: _LOGGER.error("Failed to initialize notification service %s", platform) continue def notify_message(notify_service, call): """Handle sending notification message service calls.""" message = call.data[ATTR_MESSAGE] title = template.render( hass, call.data.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)) target = call.data.get(ATTR_TARGET) message = template.render(hass, message) data = call.data.get(ATTR_DATA) notify_service.send_message(message, title=title, target=target, data=data) service_call_handler = partial(notify_message, notify_service) service_notify = p_config.get(CONF_NAME, SERVICE_NOTIFY) hass.services.register(DOMAIN, service_notify, service_call_handler, descriptions.get(SERVICE_NOTIFY), schema=NOTIFY_SERVICE_SCHEMA) success = True return success
async def async_extract_config(hass, config): """Extract device tracker config and split between legacy and modern.""" legacy = [] for platform in await asyncio.gather( *(async_create_platform_type(hass, config, p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN))): if platform is None: continue if platform.type == PLATFORM_TYPE_LEGACY: legacy.append(platform) else: raise ValueError("Unable to determine type for {}: {}".format( platform.name, platform.type)) return legacy
def setup(self, config): """Set up a full entity component. Loads the platforms from the config and will listen for supported discovered platforms. """ self.config = config # Look in config for Domain, Domain 2, Domain 3 etc and load them for p_type, p_config in config_per_platform(config, self.domain): self._setup_platform(p_type, p_config) if self.discovery_platforms: discovery.listen( self.hass, self.discovery_platforms.keys(), lambda service, info: self._setup_platform( self.discovery_platforms[service], {}, info))
async def async_setup(hass: HomeAssistant, config): """Set up STT.""" providers = {} async def async_setup_platform(p_type, p_config=None, discovery_info=None): """Set up a TTS platform.""" if p_config is None: p_config = {} platform = await async_prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: return try: provider = await platform.async_get_engine(hass, p_config, discovery_info) if provider is None: _LOGGER.error("Error setting up platform %s", p_type) return provider.name = p_type provider.hass = hass providers[provider.name] = provider except Exception: # pylint: disable=broad-except _LOGGER.exception("Error setting up platform: %s", p_type) return setup_tasks = [ asyncio.create_task(async_setup_platform(p_type, p_config)) for p_type, p_config in config_per_platform(config, DOMAIN) ] if setup_tasks: await asyncio.wait(setup_tasks) # Add discovery support async def async_platform_discovered(platform, info): """Handle for discovered platform.""" await async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) hass.http.register_view(SpeechToTextView(providers)) return True
def setup(hass, config): """ Sets up notify services. """ success = False descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) for platform, p_config in config_per_platform(config, DOMAIN, _LOGGER): # get platform notify_implementation = get_component( 'notify.{}'.format(platform)) if notify_implementation is None: _LOGGER.error("Unknown notification service specified.") continue # create platform service notify_service = notify_implementation.get_service( hass, {DOMAIN: p_config}) if notify_service is None: _LOGGER.error("Failed to initialize notification service %s", platform) continue # create service handler def notify_message(notify_service, call): """ Handle sending notification message service calls. """ message = call.data.get(ATTR_MESSAGE) if message is None: return title = call.data.get(ATTR_TITLE, ATTR_TITLE_DEFAULT) notify_service.send_message(message, title=title) # register service service_call_handler = partial(notify_message, notify_service) service_notify = p_config.get(CONF_NAME, SERVICE_NOTIFY) hass.services.register(DOMAIN, service_notify, service_call_handler, descriptions.get(service_notify)) success = True return success
def setup(self, config): """Set up a full entity component. Loads the platforms from the config and will listen for supported discovered platforms. """ self.config = config # Look in config for Domain, Domain 2, Domain 3 etc and load them for p_type, p_config in config_per_platform(config, self.domain): self._setup_platform(p_type, p_config) if self.discovery_platforms: discovery.listen( self.hass, self.discovery_platforms.keys(), lambda service, info: self._setup_platform(self.discovery_platforms[service], {}, info))
def setup(hass, config): """ Sets up automation. """ for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER): platform = get_component('automation.{}'.format(p_type)) if platform is None: _LOGGER.error("Unknown automation platform specified: %s", p_type) continue if platform.register(hass, p_config, _get_action(hass, p_config)): _LOGGER.info("Initialized %s rule %s", p_type, p_config.get(CONF_ALIAS, "")) else: _LOGGER.error("Error setting up rule %s", p_config.get(CONF_ALIAS, "")) return True
def setup(hass, config): """ Sets up automation. """ for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER): platform = get_component('automation.{}'.format(p_type)) if platform is None: _LOGGER.error("Unknown automation platform specified: %s", p_type) continue if platform.register(hass, p_config, _get_action(hass, p_config)): _LOGGER.info( "Initialized %s rule %s", p_type, p_config.get(CONF_ALIAS, "")) else: _LOGGER.error( "Error setting up rule %s", p_config.get(CONF_ALIAS, "")) return True
def setup(hass, config): """Setup zone.""" entities = set() for _, entry in config_per_platform(config, DOMAIN): name = entry.get(CONF_NAME) zone = Zone(hass, name, entry[CONF_LATITUDE], entry[CONF_LONGITUDE], entry.get(CONF_RADIUS), entry.get(CONF_ICON), entry.get(CONF_PASSIVE)) zone.entity_id = generate_entity_id(ENTITY_ID_FORMAT, name, entities) zone.update_ha_state() entities.add(zone.entity_id) if ENTITY_ID_HOME not in entities: zone = Zone(hass, hass.config.location_name, hass.config.latitude, hass.config.longitude, DEFAULT_RADIUS, ICON_HOME, False) zone.entity_id = ENTITY_ID_HOME zone.update_ha_state() return True
def setup(hass, config): """ Sets up automation. """ success = False for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER): platform = prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: _LOGGER.error("Unknown automation platform specified: %s", p_type) continue if platform.register(hass, p_config, _get_action(hass, p_config)): _LOGGER.info("Initialized %s rule %s", p_type, p_config.get(CONF_ALIAS, "")) success = True else: _LOGGER.error("Error setting up rule %s", p_config.get(CONF_ALIAS, "")) return success
def setup(self, config): """Set up a full entity component. Loads the platforms from the config and will listen for supported discovered platforms. """ self.config = config # Look in config for Domain, Domain 2, Domain 3 etc and load them for p_type, p_config in config_per_platform(config, self.domain): self._setup_platform(p_type, p_config) # Generic discovery listener for loading platform dynamically # Refer to: homeassistant.components.discovery.load_platform() def component_platform_discovered(platform, info): """Callback to load a platform.""" self._setup_platform(platform, {}, info) discovery.listen_platform(self.hass, self.domain, component_platform_discovered)
def setup(hass, config): """ Sets up automation. """ success = False for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER): platform = prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: _LOGGER.error("Unknown automation platform specified: %s", p_type) continue if platform.register(hass, p_config, _get_action(hass, p_config)): _LOGGER.info( "Initialized %s rule %s", p_type, p_config.get(CONF_ALIAS, "")) success = True else: _LOGGER.error( "Error setting up rule %s", p_config.get(CONF_ALIAS, "")) return success
async def async_extract_config( hass: HomeAssistant, config: ConfigType) -> list[DeviceTrackerPlatform]: """Extract device tracker config and split between legacy and modern.""" legacy: list[DeviceTrackerPlatform] = [] for platform in await asyncio.gather( *(async_create_platform_type(hass, config, p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN))): if platform is None: continue if platform.type == PLATFORM_TYPE_LEGACY: legacy.append(platform) else: raise ValueError( f"Unable to determine type for {platform.name}: {platform.type}" ) return legacy
def async_setup(hass, config): """Setup zone.""" entities = set() tasks = [] for _, entry in config_per_platform(config, DOMAIN): name = entry.get(CONF_NAME) zone = Zone(hass, name, entry[CONF_LATITUDE], entry[CONF_LONGITUDE], entry.get(CONF_RADIUS), entry.get(CONF_ICON), entry.get(CONF_PASSIVE)) zone.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, name, entities) tasks.append(zone.async_update_ha_state()) entities.add(zone.entity_id) if ENTITY_ID_HOME not in entities: zone = Zone(hass, hass.config.location_name, hass.config.latitude, hass.config.longitude, DEFAULT_RADIUS, ICON_HOME, False) zone.entity_id = ENTITY_ID_HOME tasks.append(zone.async_update_ha_state()) yield from asyncio.wait(tasks, loop=hass.loop) return True
async def reload_config(call): """Reload the scene config.""" try: conf = await conf_util.async_hass_config_yaml(hass) except HomeAssistantError as err: _LOGGER.error(err) return integration = await async_get_integration(hass, SCENE_DOMAIN) conf = await conf_util.async_process_component_config(hass, conf, integration) if not conf or not platform: return await platform.async_reset() # Extract only the config for the Home Assistant platform, ignore the rest. for p_type, p_config in config_per_platform(conf, SCENE_DOMAIN): if p_type != HA_DOMAIN: continue _process_scenes_config(hass, async_add_entities, p_config)
async def async_setup(hass, config): """Setup configured zones as well as home assistant zone if necessary.""" hass.data[DOMAIN] = {} entities = set() zone_entries = configured_zones(hass) for _, entry in config_per_platform(config, DOMAIN): if slugify(entry[CONF_NAME]) not in zone_entries: zone = Zone(hass, entry[CONF_NAME], entry[CONF_LATITUDE], entry[CONF_LONGITUDE], entry.get(CONF_RADIUS), entry.get(CONF_ICON), entry.get(CONF_PASSIVE)) zone.entity_id = async_generate_entity_id( ENTITY_ID_FORMAT, entry[CONF_NAME], entities) hass.async_add_job(zone.async_update_ha_state()) entities.add(zone.entity_id) if ENTITY_ID_HOME not in entities and HOME_ZONE not in zone_entries: zone = Zone(hass, hass.config.location_name, hass.config.latitude, hass.config.longitude, DEFAULT_RADIUS, ICON_HOME, False) zone.entity_id = ENTITY_ID_HOME hass.async_add_job(zone.async_update_ha_state()) return True
async def async_setup(hass, config): """Setup configured zones as well as home assistant zone if necessary.""" hass.data[DOMAIN] = {} entities = set() zone_entries = configured_zones(hass) for _, entry in config_per_platform(config, DOMAIN): if slugify(entry[CONF_NAME]) not in zone_entries: zone = Zone(hass, entry[CONF_NAME], entry[CONF_LATITUDE], entry[CONF_LONGITUDE], entry.get(CONF_RADIUS), entry.get(CONF_ICON), entry.get(CONF_PASSIVE)) zone.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, entry[CONF_NAME], entities) hass.async_add_job(zone.async_update_ha_state()) entities.add(zone.entity_id) if ENTITY_ID_HOME not in entities and HOME_ZONE not in zone_entries: zone = Zone(hass, hass.config.location_name, hass.config.latitude, hass.config.longitude, DEFAULT_RADIUS, ICON_HOME, False) zone.entity_id = ENTITY_ID_HOME hass.async_add_job(zone.async_update_ha_state()) return True
def async_setup(hass, config): """Set up the zone.""" entities = set() tasks = [] for _, entry in config_per_platform(config, DOMAIN): name = entry.get(CONF_NAME) zone = Zone(hass, name, entry[CONF_LATITUDE], entry[CONF_LONGITUDE], entry.get(CONF_RADIUS), entry.get(CONF_ICON), entry.get(CONF_PASSIVE)) zone.entity_id = async_generate_entity_id( ENTITY_ID_FORMAT, name, entities) tasks.append(zone.async_update_ha_state()) entities.add(zone.entity_id) if ENTITY_ID_HOME not in entities: zone = Zone(hass, hass.config.location_name, hass.config.latitude, hass.config.longitude, DEFAULT_RADIUS, ICON_HOME, False) zone.entity_id = ENTITY_ID_HOME tasks.append(zone.async_update_ha_state()) yield from asyncio.wait(tasks, loop=hass.loop) return True
def setup(self, config): """ Sets up a full device component: - Loads the platforms from the config - Will update devices on an interval - Will listen for supported discovered platforms """ # only setup group if name is given if self.group_name is None: self.group = None else: self.group = group.Group(self.hass, self.group_name, user_defined=False) # Look in config for Domain, Domain 2, Domain 3 etc and load them for p_type, p_config in \ config_per_platform(config, self.domain, self.logger): self._setup_platform(p_type, p_config) if self.discovery_platforms: discovery.listen(self.hass, self.discovery_platforms.keys(), self._device_discovered)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the ONVIF component.""" # Import from yaml configs = {} for p_type, p_config in config_per_platform(config, "camera"): if p_type != DOMAIN: continue config = p_config.copy() if config[CONF_HOST] not in configs: configs[config[CONF_HOST]] = { CONF_HOST: config[CONF_HOST], CONF_NAME: config.get(CONF_NAME, DEFAULT_NAME), CONF_PASSWORD: config.get(CONF_PASSWORD, DEFAULT_PASSWORD), CONF_PORT: config.get(CONF_PORT, DEFAULT_PORT), CONF_USERNAME: config.get(CONF_USERNAME, DEFAULT_USERNAME), } for conf in configs.values(): hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_IMPORT}, data=conf)) return True
async def async_setup(self, config: ConfigType) -> None: """Set up a full entity component. Loads the platforms from the config and will listen for supported discovered platforms. This method must be run in the event loop. """ self.config = config # Look in config for Domain, Domain 2, Domain 3 etc and load them for p_type, p_config in config_per_platform(config, self.domain): self.hass.async_create_task( self.async_setup_platform(p_type, p_config)) # Generic discovery listener for loading platform dynamically # Refer to: homeassistant.helpers.discovery.async_load_platform() async def component_platform_discovered( platform: str, info: Optional[Dict[str, Any]]) -> None: """Handle the loading of a platform.""" await self.async_setup_platform(platform, {}, info) discovery.async_listen_platform(self.hass, self.domain, component_platform_discovered)
def setup(hass: HomeAssistantType, config: ConfigType): """Setup device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) try: conf = _CONFIG_SCHEMA(config).get(DOMAIN, []) except vol.Invalid as ex: log_exception(ex, DOMAIN, config) return False else: conf = conf[0] if len(conf) > 0 else {} consider_home = conf.get(CONF_CONSIDER_HOME, timedelta(seconds=DEFAULT_CONSIDER_HOME)) track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) devices = load_config(yaml_path, hass, consider_home) tracker = DeviceTracker(hass, consider_home, track_new, devices) def setup_platform(p_type, p_config, disc_info=None): """Setup a device tracker platform.""" platform = prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'get_scanner'): scanner = platform.get_scanner(hass, {DOMAIN: p_config}) if scanner is None: _LOGGER.error('Error setting up platform %s', p_type) return setup_scanner_platform(hass, p_config, scanner, tracker.see) return if not platform.setup_scanner(hass, p_config, tracker.see): _LOGGER.error('Error setting up platform %s', p_type) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) for p_type, p_config in config_per_platform(config, DOMAIN): setup_platform(p_type, p_config) def device_tracker_discovered(service, info): """Called when a device tracker platform is discovered.""" setup_platform(DISCOVERY_PLATFORMS[service], {}, info) discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), device_tracker_discovered) def update_stale(now): """Clean up stale devices.""" tracker.update_stale(now) track_utc_time_change(hass, update_stale, second=range(0, 60, 5)) tracker.setup_group() def see_service(call): """Service to see a device.""" args = { key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY, ATTR_ATTRIBUTES) } tracker.see(**args) descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) hass.services.register(DOMAIN, SERVICE_SEE, see_service, descriptions.get(SERVICE_SEE)) return True
def setup(hass, config): """ Exposes light control via statemachine and services. """ # Load built-in profiles and custom profiles profile_paths = [os.path.join(os.path.dirname(__file__), LIGHT_PROFILES_FILE), hass.get_config_path(LIGHT_PROFILES_FILE)] profiles = {} for profile_path in profile_paths: if os.path.isfile(profile_path): with open(profile_path) as inp: reader = csv.reader(inp) # Skip the header next(reader, None) try: for profile_id, color_x, color_y, brightness in reader: profiles[profile_id] = (float(color_x), float(color_y), int(brightness)) except ValueError: # ValueError if not 4 values per row # ValueError if convert to float/int failed _LOGGER.error( "Error parsing light profiles from %s", profile_path) return False # Dict to track entity_id -> lights lights = {} # Track all lights in a group light_group = group.Group(hass, GROUP_NAME_ALL_LIGHTS, user_defined=False) def add_lights(new_lights): """ Add lights to the component to track. """ for light in new_lights: if light is not None and light not in lights.values(): light.entity_id = generate_entity_id( ENTITY_ID_FORMAT, light.name, lights.keys()) lights[light.entity_id] = light light.update_ha_state(hass) light_group.update_tracked_entity_ids(lights.keys()) for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER): platform = get_component(ENTITY_ID_FORMAT.format(p_type)) if platform is None: _LOGGER.error("Unknown type specified: %s", p_type) platform.setup_platform(hass, p_config, add_lights) def update_lights_state(now): """ Update the states of all the lights. """ if lights: _LOGGER.info("Updating light states") for light in lights.values(): light.update_ha_state(hass, True) update_lights_state(None) def light_discovered(service, info): """ Called when a light is discovered. """ platform = get_component( ENTITY_ID_FORMAT.format(DISCOVERY_PLATFORMS[service])) platform.setup_platform(hass, {}, add_lights, info) discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), light_discovered) 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(hass, True) # Update light state every 30 seconds hass.track_time_change(update_lights_state, second=[0, 30]) # Listen for light on and light off service calls hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_light_service) hass.services.register(DOMAIN, SERVICE_TURN_OFF, handle_light_service) return True
async def async_setup(hass, config): """Set up the notify services.""" hass.data.setdefault(NOTIFY_SERVICES, {}) async def persistent_notification(service: ServiceCall) -> None: """Send notification via the built-in persistsent_notify integration.""" payload = {} message = service.data[ATTR_MESSAGE] message.hass = hass payload[ATTR_MESSAGE] = message.async_render(parse_result=False) title = service.data.get(ATTR_TITLE) if title: title.hass = hass payload[ATTR_TITLE] = title.async_render(parse_result=False) await hass.services.async_call(pn.DOMAIN, pn.SERVICE_CREATE, payload, blocking=True) async def async_setup_platform(integration_name, p_config=None, discovery_info=None): """Set up a notify platform.""" if p_config is None: p_config = {} platform = await async_prepare_setup_platform(hass, config, DOMAIN, integration_name) if platform is None: _LOGGER.error("Unknown notification service specified") return _LOGGER.info("Setting up %s.%s", DOMAIN, integration_name) notify_service = None try: if hasattr(platform, "async_get_service"): notify_service = await platform.async_get_service( hass, p_config, discovery_info) elif hasattr(platform, "get_service"): notify_service = await hass.async_add_executor_job( platform.get_service, hass, p_config, discovery_info) else: raise HomeAssistantError("Invalid notify platform.") if notify_service is None: # Platforms can decide not to create a service based # on discovery data. if discovery_info is None: _LOGGER.error( "Failed to initialize notification service %s", integration_name) return except Exception: # pylint: disable=broad-except _LOGGER.exception("Error setting up platform %s", integration_name) return if discovery_info is None: discovery_info = {} conf_name = p_config.get(CONF_NAME) or discovery_info.get(CONF_NAME) target_service_name_prefix = conf_name or integration_name service_name = slugify(conf_name or SERVICE_NOTIFY) await notify_service.async_setup(hass, service_name, target_service_name_prefix) await notify_service.async_register_services() hass.data[NOTIFY_SERVICES].setdefault(integration_name, []).append(notify_service) hass.config.components.add(f"{DOMAIN}.{integration_name}") return True hass.services.async_register( DOMAIN, SERVICE_PERSISTENT_NOTIFICATION, persistent_notification, schema=PERSISTENT_NOTIFICATION_SERVICE_SCHEMA, ) setup_tasks = [ asyncio.create_task(async_setup_platform(integration_name, p_config)) for integration_name, p_config in config_per_platform(config, DOMAIN) ] if setup_tasks: await asyncio.wait(setup_tasks) async def async_platform_discovered(platform, info): """Handle for discovered platform.""" await async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) return True
def async_setup(hass: HomeAssistantType, config: ConfigType): """Setup device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) try: conf = config.get(DOMAIN, []) except vol.Invalid as ex: async_log_exception(ex, DOMAIN, config, hass) return False else: conf = conf[0] if len(conf) > 0 else {} consider_home = conf.get(CONF_CONSIDER_HOME, timedelta(seconds=DEFAULT_CONSIDER_HOME)) track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) devices = yield from async_load_config(yaml_path, hass, consider_home) tracker = DeviceTracker(hass, consider_home, track_new, devices) # update tracked devices update_tasks = [device.async_update_ha_state() for device in devices if device.track] if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) @asyncio.coroutine def async_setup_platform(p_type, p_config, disc_info=None): """Setup a device tracker platform.""" platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'get_scanner'): scanner = yield from hass.loop.run_in_executor( None, platform.get_scanner, hass, {DOMAIN: p_config}) if scanner is None: _LOGGER.error('Error setting up platform %s', p_type) return yield from async_setup_scanner_platform( hass, p_config, scanner, tracker.async_see) return ret = yield from hass.loop.run_in_executor( None, platform.setup_scanner, hass, p_config, tracker.see) if not ret: _LOGGER.error('Error setting up platform %s', p_type) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) yield from tracker.async_setup_group() @callback def async_device_tracker_discovered(service, info): """Called when a device tracker platform is discovered.""" hass.async_add_job( async_setup_platform(DISCOVERY_PLATFORMS[service], {}, info)) discovery.async_listen( hass, DISCOVERY_PLATFORMS.keys(), async_device_tracker_discovered) # Clean up stale devices async_track_utc_time_change( hass, tracker.async_update_stale, second=range(0, 60, 5)) @asyncio.coroutine def async_see_service(call): """Service to see a device.""" args = {key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY, ATTR_ATTRIBUTES)} yield from tracker.async_see(**args) descriptions = yield from hass.loop.run_in_executor( None, load_yaml_config_file, os.path.join(os.path.dirname(__file__), 'services.yaml') ) hass.services.async_register( DOMAIN, SERVICE_SEE, async_see_service, descriptions.get(SERVICE_SEE)) return True
def async_setup(hass, config): """Track states and offer events for mailboxes.""" mailboxes = [] yield from hass.components.frontend.async_register_built_in_panel( 'mailbox', 'mailbox', 'mdi:mailbox') hass.http.register_view(MailboxPlatformsView(mailboxes)) hass.http.register_view(MailboxMessageView(mailboxes)) hass.http.register_view(MailboxMediaView(mailboxes)) hass.http.register_view(MailboxDeleteView(mailboxes)) @asyncio.coroutine def async_setup_platform(p_type, p_config=None, discovery_info=None): """Set up a mailbox platform.""" if p_config is None: p_config = {} if discovery_info is None: discovery_info = {} platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: _LOGGER.error("Unknown mailbox platform specified") return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) mailbox = None try: if hasattr(platform, 'async_get_handler'): mailbox = yield from \ platform.async_get_handler(hass, p_config, discovery_info) elif hasattr(platform, 'get_handler'): mailbox = yield from hass.async_add_job( platform.get_handler, hass, p_config, discovery_info) else: raise HomeAssistantError("Invalid mailbox platform.") if mailbox is None: _LOGGER.error( "Failed to initialize mailbox platform %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) return mailboxes.append(mailbox) mailbox_entity = MailboxEntity(hass, mailbox) component = EntityComponent( logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL) yield from component.async_add_entities([mailbox_entity]) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) @asyncio.coroutine def async_platform_discovered(platform, info): """Handle for discovered platform.""" yield from async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) return True
async def async_setup(hass, config): """Track states and offer events for mailboxes.""" mailboxes = [] await hass.components.frontend.async_register_built_in_panel( 'mailbox', 'mailbox', 'mdi:mailbox') hass.http.register_view(MailboxPlatformsView(mailboxes)) hass.http.register_view(MailboxMessageView(mailboxes)) hass.http.register_view(MailboxMediaView(mailboxes)) hass.http.register_view(MailboxDeleteView(mailboxes)) async def async_setup_platform(p_type, p_config=None, discovery_info=None): """Set up a mailbox platform.""" if p_config is None: p_config = {} if discovery_info is None: discovery_info = {} platform = await async_prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: _LOGGER.error("Unknown mailbox platform specified") return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) mailbox = None try: if hasattr(platform, 'async_get_handler'): mailbox = await \ platform.async_get_handler(hass, p_config, discovery_info) elif hasattr(platform, 'get_handler'): mailbox = await hass.async_add_executor_job( platform.get_handler, hass, p_config, discovery_info) else: raise HomeAssistantError("Invalid mailbox platform.") if mailbox is None: _LOGGER.error("Failed to initialize mailbox platform %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) return mailboxes.append(mailbox) mailbox_entity = MailboxEntity(mailbox) component = EntityComponent(logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL) await component.async_add_entities([mailbox_entity]) setup_tasks = [ async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN) ] if setup_tasks: await asyncio.wait(setup_tasks, loop=hass.loop) async def async_platform_discovered(platform, info): """Handle for discovered platform.""" await async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) return True
def async_setup(hass, config): """Setup TTS.""" tts = SpeechManager(hass) try: conf = config[DOMAIN][0] if len(config.get(DOMAIN, [])) > 0 else {} use_cache = conf.get(CONF_CACHE, DEFAULT_CACHE) cache_dir = conf.get(CONF_CACHE_DIR, DEFAULT_CACHE_DIR) time_memory = conf.get(CONF_TIME_MEMORY, DEFAULT_TIME_MEMORY) yield from tts.async_init_cache(use_cache, cache_dir, time_memory) except (HomeAssistantError, KeyError) as err: _LOGGER.error("Error on cache init %s", err) return False hass.http.register_view(TextToSpeechView(tts)) descriptions = yield from hass.loop.run_in_executor( None, load_yaml_config_file, os.path.join(os.path.dirname(__file__), 'services.yaml')) @asyncio.coroutine def async_setup_platform(p_type, p_config, disc_info=None): """Setup a tts platform.""" platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'async_get_engine'): provider = yield from platform.async_get_engine( hass, p_config) else: provider = yield from hass.loop.run_in_executor( None, platform.get_engine, hass, p_config) if provider is None: _LOGGER.error('Error setting up platform %s', p_type) return tts.async_register_engine(p_type, provider, p_config) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) return @asyncio.coroutine def async_say_handle(service): """Service handle for say.""" entity_ids = service.data.get(ATTR_ENTITY_ID) message = service.data.get(ATTR_MESSAGE) cache = service.data.get(ATTR_CACHE) language = service.data.get(ATTR_LANGUAGE) try: url = yield from tts.async_get_url( p_type, message, cache=cache, language=language) except HomeAssistantError as err: _LOGGER.error("Error on init tts: %s", err) return data = { ATTR_MEDIA_CONTENT_ID: url, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, } if entity_ids: data[ATTR_ENTITY_ID] = entity_ids yield from hass.services.async_call( DOMAIN_MP, SERVICE_PLAY_MEDIA, data, blocking=True) hass.services.async_register( DOMAIN, "{}_{}".format(p_type, SERVICE_SAY), async_say_handle, descriptions.get(SERVICE_SAY), schema=SCHEMA_SERVICE_SAY) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) @asyncio.coroutine def async_clear_cache_handle(service): """Handle clear cache service call.""" yield from tts.async_clear_cache() hass.services.async_register( DOMAIN, SERVICE_CLEAR_CACHE, async_clear_cache_handle, descriptions.get(SERVICE_CLEAR_CACHE), schema=SCHEMA_SERVICE_CLEAR_CACHE) return True
def _setup_component(hass, domain, config): """Setup a component for Home Assistant.""" # pylint: disable=too-many-return-statements,too-many-branches if domain in hass.config.components: return True with _SETUP_LOCK: # It might have been loaded while waiting for lock if domain in hass.config.components: return True if domain in _CURRENT_SETUP: _LOGGER.error('Attempt made to setup %s during setup of %s', domain, domain) return False component = loader.get_component(domain) missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', []) if dep not in hass.config.components] if missing_deps: _LOGGER.error( 'Not initializing %s because not all dependencies loaded: %s', domain, ", ".join(missing_deps)) return False if hasattr(component, 'CONFIG_SCHEMA'): try: config = component.CONFIG_SCHEMA(config) except vol.MultipleInvalid as ex: _LOGGER.error('Invalid config for [%s]: %s', domain, ex) return False elif hasattr(component, 'PLATFORM_SCHEMA'): platforms = [] for p_name, p_config in config_per_platform(config, domain): # Validate component specific platform schema try: p_validated = component.PLATFORM_SCHEMA(p_config) except vol.MultipleInvalid as ex: _LOGGER.error('Invalid platform config for [%s]: %s. %s', domain, ex, p_config) return False # Not all platform components follow same pattern for platforms # Sof if p_name is None we are not going to validate platform # (the automation component is one of them) if p_name is None: platforms.append(p_validated) continue platform = prepare_setup_platform(hass, config, domain, p_name) if platform is None: return False # Validate platform specific schema if hasattr(platform, 'PLATFORM_SCHEMA'): try: p_validated = platform.PLATFORM_SCHEMA(p_validated) except vol.MultipleInvalid as ex: _LOGGER.error( 'Invalid platform config for [%s.%s]: %s. %s', domain, p_name, ex, p_config) return False platforms.append(p_validated) # Create a copy of the configuration with all config for current # component removed and add validated config back in. filter_keys = extract_domain_configs(config, domain) config = {key: value for key, value in config.items() if key not in filter_keys} config[domain] = platforms if not _handle_requirements(hass, component, domain): return False _CURRENT_SETUP.append(domain) try: if not component.setup(hass, config): _LOGGER.error('component %s failed to initialize', domain) return False except Exception: # pylint: disable=broad-except _LOGGER.exception('Error during setup of component %s', domain) return False finally: _CURRENT_SETUP.remove(domain) hass.config.components.append(component.DOMAIN) # Assumption: if a component does not depend on groups # it communicates with devices if group.DOMAIN not in getattr(component, 'DEPENDENCIES', []): hass.pool.add_worker() hass.bus.fire( EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN}) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) conf = config.get(DOMAIN, []) conf = conf[0] if conf else {} consider_home = conf.get(CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME) defaults = conf.get(CONF_NEW_DEVICE_DEFAULTS, {}) track_new = conf.get(CONF_TRACK_NEW) if track_new is None: track_new = defaults.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) devices = await async_load_config(yaml_path, hass, consider_home) tracker = DeviceTracker( hass, consider_home, track_new, defaults, devices) async def async_setup_platform(p_type, p_config, disc_info=None): """Set up a device tracker platform.""" platform = await async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) try: scanner = None setup = None if hasattr(platform, 'async_get_scanner'): scanner = await platform.async_get_scanner( hass, {DOMAIN: p_config}) elif hasattr(platform, 'get_scanner'): scanner = await hass.async_add_job( platform.get_scanner, hass, {DOMAIN: p_config}) elif hasattr(platform, 'async_setup_scanner'): setup = await platform.async_setup_scanner( hass, p_config, tracker.async_see, disc_info) elif hasattr(platform, 'setup_scanner'): setup = await hass.async_add_job( platform.setup_scanner, hass, p_config, tracker.see, disc_info) elif hasattr(platform, 'async_setup_entry'): setup = await platform.async_setup_entry( hass, p_config, tracker.async_see) else: raise HomeAssistantError("Invalid device_tracker platform.") if scanner: async_setup_scanner_platform( hass, p_config, scanner, tracker.async_see, p_type) return if not setup: _LOGGER.error("Error setting up platform %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception("Error setting up platform %s", p_type) hass.data[DOMAIN] = async_setup_platform setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: await asyncio.wait(setup_tasks, loop=hass.loop) tracker.async_setup_group() async def async_platform_discovered(platform, info): """Load a platform.""" await async_setup_platform(platform, {}, disc_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) # Clean up stale devices async_track_utc_time_change( hass, tracker.async_update_stale, second=range(0, 60, 5)) async def async_see_service(call): """Service to see a device.""" # Temp workaround for iOS, introduced in 0.65 data = dict(call.data) data.pop('hostname', None) data.pop('battery_status', None) await tracker.async_see(**data) hass.services.async_register( DOMAIN, SERVICE_SEE, async_see_service, SERVICE_SEE_PAYLOAD_SCHEMA) # restore await tracker.async_setup_tracked_device() return True
def async_process_component_config(hass: HomeAssistant, config: Dict, domain: str) -> Optional[Dict]: """Check component configuration and return processed configuration. Returns None on error. This method must be run in the event loop. """ component = get_component(hass, domain) if hasattr(component, 'CONFIG_SCHEMA'): try: config = component.CONFIG_SCHEMA(config) # type: ignore except vol.Invalid as ex: async_log_exception(ex, domain, config, hass) return None elif hasattr(component, 'PLATFORM_SCHEMA'): platforms = [] for p_name, p_config in config_per_platform(config, domain): # Validate component specific platform schema try: p_validated = component.PLATFORM_SCHEMA( # type: ignore p_config) except vol.Invalid as ex: async_log_exception(ex, domain, config, hass) continue # Not all platform components follow same pattern for platforms # So if p_name is None we are not going to validate platform # (the automation component is one of them) if p_name is None: platforms.append(p_validated) continue platform = get_platform(hass, domain, p_name) if platform is None: continue # Validate platform specific schema if hasattr(platform, 'PLATFORM_SCHEMA'): # pylint: disable=no-member try: p_validated = platform.PLATFORM_SCHEMA( # type: ignore p_validated) except vol.Invalid as ex: async_log_exception(ex, '{}.{}'.format(domain, p_name), p_validated, hass) continue platforms.append(p_validated) # Create a copy of the configuration with all config for current # component removed and add validated config back in. filter_keys = extract_domain_configs(config, domain) config = { key: value for key, value in config.items() if key not in filter_keys } config[domain] = platforms return config
def setup(hass, config): """ Setup device tracker """ yaml_path = hass.config.path(YAML_DEVICES) csv_path = hass.config.path(CSV_DEVICES) if os.path.isfile(csv_path) and not os.path.isfile(yaml_path) and \ convert_csv_config(csv_path, yaml_path): os.remove(csv_path) conf = config.get(DOMAIN, {}) consider_home = util.convert(conf.get(CONF_CONSIDER_HOME), int, DEFAULT_CONF_CONSIDER_HOME) track_new = util.convert(conf.get(CONF_TRACK_NEW), bool, DEFAULT_CONF_TRACK_NEW) devices = load_config(yaml_path, hass, timedelta(seconds=consider_home)) tracker = DeviceTracker(hass, consider_home, track_new, devices) def setup_platform(p_type, p_config, disc_info=None): """ Setup a device tracker platform. """ platform = prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'get_scanner'): scanner = platform.get_scanner(hass, {DOMAIN: p_config}) if scanner is None: _LOGGER.error('Error setting up platform %s', p_type) return setup_scanner_platform(hass, p_config, scanner, tracker.see) return if not platform.setup_scanner(hass, p_config, tracker.see): _LOGGER.error('Error setting up platform %s', p_type) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) for p_type, p_config in \ config_per_platform(config, DOMAIN, _LOGGER): setup_platform(p_type, p_config) def device_tracker_discovered(service, info): """ Called when a device tracker platform is discovered. """ setup_platform(DISCOVERY_PLATFORMS[service], {}, info) discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), device_tracker_discovered) def update_stale(now): """ Clean up stale devices. """ tracker.update_stale(now) track_utc_time_change(hass, update_stale, second=range(0, 60, 5)) tracker.setup_group() def see_service(call): """ Service to see a device. """ args = {key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS)} tracker.see(**args) hass.services.register(DOMAIN, SERVICE_SEE, see_service) return True
def setup(hass, config): """Setup device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) conf = config.get(DOMAIN, {}) # Config can be an empty list. In that case, substitute a dict if isinstance(conf, list): conf = conf[0] if len(conf) > 0 else {} consider_home = timedelta( seconds=util.convert(conf.get(CONF_CONSIDER_HOME), int, DEFAULT_CONSIDER_HOME)) track_new = util.convert(conf.get(CONF_TRACK_NEW), bool, DEFAULT_CONF_TRACK_NEW) home_range = util.convert(conf.get(CONF_HOME_RANGE), int, DEFAULT_HOME_RANGE) devices = load_config(yaml_path, hass, consider_home, home_range) tracker = DeviceTracker(hass, consider_home, track_new, home_range, devices) def setup_platform(p_type, p_config, disc_info=None): """Setup a device tracker platform.""" platform = prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'get_scanner'): scanner = platform.get_scanner(hass, {DOMAIN: p_config}) if scanner is None: _LOGGER.error('Error setting up platform %s', p_type) return setup_scanner_platform(hass, p_config, scanner, tracker.see) return if not platform.setup_scanner(hass, p_config, tracker.see): _LOGGER.error('Error setting up platform %s', p_type) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) for p_type, p_config in config_per_platform(config, DOMAIN): setup_platform(p_type, p_config) def device_tracker_discovered(service, info): """Called when a device tracker platform is discovered.""" setup_platform(DISCOVERY_PLATFORMS[service], {}, info) discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), device_tracker_discovered) def update_stale(now): """Clean up stale devices.""" tracker.update_stale(now) track_utc_time_change(hass, update_stale, second=range(0, 60, 5)) tracker.setup_group() def see_service(call): """Service to see a device.""" args = {key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY)} tracker.see(**args) descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) hass.services.register(DOMAIN, SERVICE_SEE, see_service, descriptions.get(SERVICE_SEE)) return True
async def async_setup(hass, config): """Set up TTS.""" tts = SpeechManager(hass) try: conf = config[DOMAIN][0] if config.get(DOMAIN, []) else {} use_cache = conf.get(CONF_CACHE, DEFAULT_CACHE) cache_dir = conf.get(CONF_CACHE_DIR, DEFAULT_CACHE_DIR) time_memory = conf.get(CONF_TIME_MEMORY, DEFAULT_TIME_MEMORY) base_url = conf.get(CONF_BASE_URL) or hass.config.api.base_url await tts.async_init_cache(use_cache, cache_dir, time_memory, base_url) except (HomeAssistantError, KeyError) as err: _LOGGER.error("Error on cache init %s", err) return False hass.http.register_view(TextToSpeechView(tts)) hass.http.register_view(TextToSpeechUrlView(tts)) async def async_setup_platform(p_type, p_config, disc_info=None): """Set up a TTS platform.""" platform = await async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'async_get_engine'): provider = await platform.async_get_engine( hass, p_config) else: provider = await hass.async_add_job( platform.get_engine, hass, p_config) if provider is None: _LOGGER.error("Error setting up platform %s", p_type) return tts.async_register_engine(p_type, provider, p_config) except Exception: # pylint: disable=broad-except _LOGGER.exception("Error setting up platform: %s", p_type) return async def async_say_handle(service): """Service handle for say.""" entity_ids = service.data.get(ATTR_ENTITY_ID) message = service.data.get(ATTR_MESSAGE) cache = service.data.get(ATTR_CACHE) language = service.data.get(ATTR_LANGUAGE) options = service.data.get(ATTR_OPTIONS) try: url = await tts.async_get_url( p_type, message, cache=cache, language=language, options=options ) except HomeAssistantError as err: _LOGGER.error("Error on init TTS: %s", err) return data = { ATTR_MEDIA_CONTENT_ID: url, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, } if entity_ids: data[ATTR_ENTITY_ID] = entity_ids await hass.services.async_call( DOMAIN_MP, SERVICE_PLAY_MEDIA, data, blocking=True) hass.services.async_register( DOMAIN, "{}_{}".format(p_type, SERVICE_SAY), async_say_handle, schema=SCHEMA_SERVICE_SAY) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: await asyncio.wait(setup_tasks, loop=hass.loop) async def async_clear_cache_handle(service): """Handle clear cache service call.""" await tts.async_clear_cache() hass.services.async_register( DOMAIN, SERVICE_CLEAR_CACHE, async_clear_cache_handle, schema=SCHEMA_SERVICE_CLEAR_CACHE) return True
def async_setup(hass, config): """Set up the notify services.""" targets = {} @asyncio.coroutine def async_setup_platform(p_type, p_config=None, discovery_info=None): """Set up a notify platform.""" if p_config is None: p_config = {} platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: _LOGGER.error("Unknown notification service specified") return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) notify_service = None try: if hasattr(platform, 'async_get_service'): notify_service = yield from \ platform.async_get_service(hass, p_config, discovery_info) elif hasattr(platform, 'get_service'): notify_service = yield from hass.async_add_job( platform.get_service, hass, p_config, discovery_info) else: raise HomeAssistantError("Invalid notify platform.") if notify_service is None: # Platforms can decide not to create a service based # on discovery data. if discovery_info is None: _LOGGER.error( "Failed to initialize notification service %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) return notify_service.hass = hass if discovery_info is None: discovery_info = {} @asyncio.coroutine def async_notify_message(service): """Handle sending notification message service calls.""" kwargs = {} message = service.data[ATTR_MESSAGE] title = service.data.get(ATTR_TITLE) if title: title.hass = hass kwargs[ATTR_TITLE] = title.async_render() if targets.get(service.service) is not None: kwargs[ATTR_TARGET] = [targets[service.service]] elif service.data.get(ATTR_TARGET) is not None: kwargs[ATTR_TARGET] = service.data.get(ATTR_TARGET) message.hass = hass kwargs[ATTR_MESSAGE] = message.async_render() kwargs[ATTR_DATA] = service.data.get(ATTR_DATA) yield from notify_service.async_send_message(**kwargs) if hasattr(notify_service, 'targets'): platform_name = ( p_config.get(CONF_NAME) or discovery_info.get(CONF_NAME) or p_type) for name, target in notify_service.targets.items(): target_name = slugify('{}_{}'.format(platform_name, name)) targets[target_name] = target hass.services.async_register( DOMAIN, target_name, async_notify_message, schema=NOTIFY_SERVICE_SCHEMA) platform_name = ( p_config.get(CONF_NAME) or discovery_info.get(CONF_NAME) or SERVICE_NOTIFY) platform_name_slug = slugify(platform_name) hass.services.async_register( DOMAIN, platform_name_slug, async_notify_message, schema=NOTIFY_SERVICE_SCHEMA) hass.config.components.add('{}.{}'.format(DOMAIN, p_type)) return True setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) @asyncio.coroutine def async_platform_discovered(platform, info): """Handle for discovered platform.""" yield from async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) return True
def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) conf = config.get(DOMAIN, []) conf = conf[0] if conf else {} consider_home = conf.get(CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME) track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) devices = yield from async_load_config(yaml_path, hass, consider_home) tracker = DeviceTracker(hass, consider_home, track_new, devices) @asyncio.coroutine def async_setup_platform(p_type, p_config, disc_info=None): """Set up a device tracker platform.""" platform = yield from async_prepare_setup_platform( hass, config, DOMAIN, p_type) if platform is None: return _LOGGER.info("Setting up %s.%s", DOMAIN, p_type) try: scanner = None setup = None if hasattr(platform, 'async_get_scanner'): scanner = yield from platform.async_get_scanner( hass, {DOMAIN: p_config}) elif hasattr(platform, 'get_scanner'): scanner = yield from hass.async_add_job( platform.get_scanner, hass, {DOMAIN: p_config}) elif hasattr(platform, 'async_setup_scanner'): setup = yield from platform.async_setup_scanner( hass, p_config, tracker.async_see, disc_info) elif hasattr(platform, 'setup_scanner'): setup = yield from hass.async_add_job( platform.setup_scanner, hass, p_config, tracker.see, disc_info) else: raise HomeAssistantError("Invalid device_tracker platform.") if scanner: async_setup_scanner_platform( hass, p_config, scanner, tracker.async_see, p_type) return if not setup: _LOGGER.error("Error setting up platform %s", p_type) return except Exception: # pylint: disable=broad-except _LOGGER.exception("Error setting up platform %s", p_type) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config in config_per_platform(config, DOMAIN)] if setup_tasks: yield from asyncio.wait(setup_tasks, loop=hass.loop) tracker.async_setup_group() @callback def async_device_tracker_discovered(service, info): """Handle the discovery of device tracker platforms.""" hass.async_add_job( async_setup_platform(DISCOVERY_PLATFORMS[service], {}, info)) discovery.async_listen( hass, DISCOVERY_PLATFORMS.keys(), async_device_tracker_discovered) @asyncio.coroutine def async_platform_discovered(platform, info): """Load a platform.""" yield from async_setup_platform(platform, {}, disc_info=info) discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered) # Clean up stale devices async_track_utc_time_change( hass, tracker.async_update_stale, second=range(0, 60, 5)) @asyncio.coroutine def async_see_service(call): """Service to see a device.""" args = {key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY, ATTR_ATTRIBUTES)} yield from tracker.async_see(**args) descriptions = yield from hass.async_add_job( load_yaml_config_file, os.path.join(os.path.dirname(__file__), 'services.yaml') ) hass.services.async_register( DOMAIN, SERVICE_SEE, async_see_service, descriptions.get(SERVICE_SEE)) # restore yield from tracker.async_setup_tracked_device() return True
async def async_process_component_config( hass: HomeAssistant, config: Dict, integration: Integration) \ -> Optional[Dict]: """Check component configuration and return processed configuration. Returns None on error. This method must be run in the event loop. """ domain = integration.domain try: component = integration.get_component() except ImportError as ex: _LOGGER.error("Unable to import %s: %s", domain, ex) return None if hasattr(component, 'CONFIG_SCHEMA'): try: return component.CONFIG_SCHEMA(config) # type: ignore except vol.Invalid as ex: async_log_exception(ex, domain, config, hass) return None component_platform_schema = getattr( component, 'PLATFORM_SCHEMA_BASE', getattr(component, 'PLATFORM_SCHEMA', None)) if component_platform_schema is None: return config platforms = [] for p_name, p_config in config_per_platform(config, domain): # Validate component specific platform schema try: p_validated = component_platform_schema(p_config) except vol.Invalid as ex: async_log_exception(ex, domain, p_config, hass) continue # Not all platform components follow same pattern for platforms # So if p_name is None we are not going to validate platform # (the automation component is one of them) if p_name is None: platforms.append(p_validated) continue try: p_integration = await async_get_integration(hass, p_name) except IntegrationNotFound: continue if (not hass.config.skip_pip and p_integration.requirements and not await async_process_requirements( hass, p_integration.domain, p_integration.requirements)): continue try: platform = p_integration.get_platform(domain) except ImportError: continue # Validate platform specific schema if hasattr(platform, 'PLATFORM_SCHEMA'): # pylint: disable=no-member try: p_validated = platform.PLATFORM_SCHEMA( # type: ignore p_config) except vol.Invalid as ex: async_log_exception(ex, '{}.{}'.format(domain, p_name), p_config, hass) continue platforms.append(p_validated) # Create a copy of the configuration with all config for current # component removed and add validated config back in. config = config_without_domain(config, domain) config[domain] = platforms return config
def setup(hass, config): """Setup the notify services.""" success = False descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) targets = {} for platform, p_config in config_per_platform(config, DOMAIN): notify_implementation = bootstrap.prepare_setup_platform( hass, config, DOMAIN, platform) if notify_implementation is None: _LOGGER.error("Unknown notification service specified") continue notify_service = notify_implementation.get_service(hass, p_config) if notify_service is None: _LOGGER.error("Failed to initialize notification service %s", platform) continue def notify_message(notify_service, call): """Handle sending notification message service calls.""" kwargs = {} message = call.data[ATTR_MESSAGE] title = call.data.get(ATTR_TITLE) if title: title.hass = hass kwargs[ATTR_TITLE] = title.render() if targets.get(call.service) is not None: kwargs[ATTR_TARGET] = [targets[call.service]] elif call.data.get(ATTR_TARGET) is not None: kwargs[ATTR_TARGET] = call.data.get(ATTR_TARGET) message.hass = hass kwargs[ATTR_MESSAGE] = message.render() kwargs[ATTR_DATA] = call.data.get(ATTR_DATA) notify_service.send_message(**kwargs) service_call_handler = partial(notify_message, notify_service) if hasattr(notify_service, 'targets'): platform_name = (p_config.get(CONF_NAME) or platform) for name, target in notify_service.targets.items(): target_name = slugify('{}_{}'.format(platform_name, name)) targets[target_name] = target hass.services.register(DOMAIN, target_name, service_call_handler, descriptions.get(SERVICE_NOTIFY), schema=NOTIFY_SERVICE_SCHEMA) platform_name = (p_config.get(CONF_NAME) or SERVICE_NOTIFY) platform_name_slug = slugify(platform_name) hass.services.register( DOMAIN, platform_name_slug, service_call_handler, descriptions.get(SERVICE_NOTIFY), schema=NOTIFY_SERVICE_SCHEMA) success = True return success