async def async_setup(opp: OpenPeerPower, config: dict): """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(): opp.async_create_task( opp.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_IMPORT}, data=conf ) ) return True
async def async_validate_config(opp, 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(opp, 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
async def async_validate_config(opp, config): """Validate config.""" automations = [] validated_automations = await asyncio.gather( *(_try_async_validate_config_item(opp, 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
async def async_extract_config(opp, config): """Extract device tracker config and split between legacy and modern.""" legacy = [] for platform in await asyncio.gather( *(async_create_platform_type(opp, 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
async def async_setup(opp: OpenPeerPower, 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(opp, config, DOMAIN, p_type) if platform is None: return try: provider = await platform.async_get_engine(opp, p_config, discovery_info) if provider is None: _LOGGER.error("Error setting up platform %s", p_type) return provider.name = p_type provider.opp = opp 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(opp, DOMAIN, async_platform_discovered) opp.http.register_view(SpeechToTextView(providers)) 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_extract_config( opp: OpenPeerPower, 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(opp, 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
async def reload_config(call): """Reload the scene config.""" try: conf = await conf_util.async_opp_config_yaml(opp) except OpenPeerPowerError as err: _LOGGER.error(err) return integration = await async_get_integration(opp, SCENE_DOMAIN) conf = await conf_util.async_process_component_config( opp, conf, integration) if not conf or not platform: return await platform.async_reset() # Extract only the config for the Open Peer Power 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(opp, async_add_entities, p_config)
async def async_setup(opp, config): """Set up the notify services.""" opp.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.opp = opp payload[ATTR_MESSAGE] = message.async_render(parse_result=False) title = service.data.get(ATTR_TITLE) if title: title.opp = opp payload[ATTR_TITLE] = title.async_render(parse_result=False) await opp.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( opp, config, DOMAIN, integration_name ) if platform is None: _LOGGER.error("Unknown notification service specified") return full_name = f"{DOMAIN}.{integration_name}" _LOGGER.info("Setting up %s", full_name) with async_start_setup(opp, [full_name]): notify_service = None try: if hasattr(platform, "async_get_service"): notify_service = await platform.async_get_service( opp, p_config, discovery_info ) elif hasattr(platform, "get_service"): notify_service = await opp.async_add_executor_job( platform.get_service, opp, p_config, discovery_info ) else: raise OpenPeerPowerError("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( opp, service_name, target_service_name_prefix ) await notify_service.async_register_services() opp.data[NOTIFY_SERVICES].setdefault(integration_name, []).append( notify_service ) opp.config.components.add(f"{DOMAIN}.{integration_name}") return True opp.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(opp, DOMAIN, async_platform_discovered) return True
async def async_process_component_config( # noqa: C901 opp: OpenPeerPower, config: ConfigType, integration: Integration) -> ConfigType | None: """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 LOAD_EXCEPTIONS as ex: _LOGGER.error("Unable to import %s: %s", domain, ex) return None # Check if the integration has a custom config validator config_validator = None try: config_validator = integration.get_platform("config") except ImportError as err: # Filter out import error of the config platform. # If the config platform contains bad imports, make sure # that still fails. if err.name != f"{integration.pkg_path}.config": _LOGGER.error("Error importing config platform %s: %s", domain, err) return None if config_validator is not None and hasattr(config_validator, "async_validate_config"): try: return await config_validator.async_validate_config( # type: ignore opp, config) except (vol.Invalid, OpenPeerPowerError) as ex: async_log_exception(ex, domain, config, opp, integration.documentation) return None except Exception: # pylint: disable=broad-except _LOGGER.exception("Unknown error calling %s config validator", domain) return None # No custom config validator, proceed with schema validation if hasattr(component, "CONFIG_SCHEMA"): try: return component.CONFIG_SCHEMA(config) # type: ignore except vol.Invalid as ex: async_log_exception(ex, domain, config, opp, integration.documentation) return None except Exception: # pylint: disable=broad-except _LOGGER.exception("Unknown error calling %s CONFIG_SCHEMA", domain) 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, opp, integration.documentation) continue except Exception: # pylint: disable=broad-except _LOGGER.exception( "Unknown error validating %s platform config with %s component platform schema", p_name, domain, ) 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_with_requirements( opp, p_name) except (RequirementsNotFound, IntegrationNotFound) as ex: _LOGGER.error("Platform error: %s - %s", domain, ex) continue try: platform = p_integration.get_platform(domain) except LOAD_EXCEPTIONS: _LOGGER.exception("Platform error: %s", domain) continue # Validate platform specific schema if hasattr(platform, "PLATFORM_SCHEMA"): try: p_validated = platform.PLATFORM_SCHEMA( p_config) # type: ignore except vol.Invalid as ex: async_log_exception( ex, f"{domain}.{p_name}", p_config, opp, p_integration.documentation, ) continue except Exception: # pylint: disable=broad-except _LOGGER.exception( "Unknown error validating config for %s platform for %s component with PLATFORM_SCHEMA", p_name, domain, ) 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
async def async_setup(opp, config): """Set up the notify services.""" targets = {} async 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 = await async_prepare_setup_platform(opp, 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 = await platform.async_get_service( opp, p_config, discovery_info) elif hasattr(platform, "get_service"): notify_service = await opp.async_add_job( platform.get_service, opp, p_config, discovery_info) else: raise OpenPeerPowerError("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.opp = opp if discovery_info is None: discovery_info = {} async 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.opp = opp 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.opp = opp kwargs[ATTR_MESSAGE] = message.async_render() kwargs[ATTR_DATA] = service.data.get(ATTR_DATA) await 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(f"{platform_name}_{name}") targets[target_name] = target opp.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) opp.services.async_register( DOMAIN, platform_name_slug, async_notify_message, schema=NOTIFY_SERVICE_SCHEMA, ) opp.config.components.add(f"{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: 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(opp, DOMAIN, async_platform_discovered) return True
async def async_setup(opp, config): """Track states and offer events for mailboxes.""" mailboxes = [] opp.components.frontend.async_register_built_in_panel( "mailbox", "mailbox", "mdi:mailbox") opp.http.register_view(MailboxPlatformsView(mailboxes)) opp.http.register_view(MailboxMessageView(mailboxes)) opp.http.register_view(MailboxMediaView(mailboxes)) opp.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(opp, 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( opp, p_config, discovery_info) elif hasattr(platform, "get_handler"): mailbox = await opp.async_add_executor_job( platform.get_handler, opp, p_config, discovery_info) else: raise OpenPeerPowerError("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, opp, SCAN_INTERVAL) await component.async_add_entities([mailbox_entity]) 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) async def async_platform_discovered(platform, info): """Handle for discovered platform.""" await async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(opp, DOMAIN, async_platform_discovered) return True
async def async_setup(opp, config): """Set up TTS.""" tts = SpeechManager(opp) 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) opp.data[BASE_URL_KEY] = base_url await tts.async_init_cache(use_cache, cache_dir, time_memory, base_url) except (OpenPeerPowerError, KeyError): _LOGGER.exception("Error on cache init") return False opp.http.register_view(TextToSpeechView(tts)) opp.http.register_view(TextToSpeechUrlView(tts)) # Load service descriptions from tts/services.yaml integration = await async_get_integration(opp, DOMAIN) services_yaml = integration.file_path / "services.yaml" services_dict = cast( dict, await opp.async_add_executor_job(load_yaml, str(services_yaml))) 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(opp, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, "async_get_engine"): provider = await platform.async_get_engine( opp, p_config, discovery_info) else: provider = await opp.async_add_executor_job( platform.get_engine, opp, p_config, discovery_info) 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[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_path(p_type, message, cache=cache, language=language, options=options) except OpenPeerPowerError as err: _LOGGER.error("Error on init TTS: %s", err) return base = tts.base_url or get_url(opp) url = base + url data = { ATTR_MEDIA_CONTENT_ID: url, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, ATTR_ENTITY_ID: entity_ids, } await opp.services.async_call( DOMAIN_MP, SERVICE_PLAY_MEDIA, data, blocking=True, context=service.context, ) service_name = p_config.get(CONF_SERVICE_NAME, f"{p_type}_{SERVICE_SAY}") opp.services.async_register(DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY) # Register the service description service_desc = { CONF_NAME: f"Say an TTS message with {p_type}", CONF_DESCRIPTION: f"Say something using text-to-speech on a media player with {p_type}.", CONF_FIELDS: services_dict[SERVICE_SAY][CONF_FIELDS], } async_set_service_schema(opp, DOMAIN, service_name, service_desc) 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) async def async_platform_discovered(platform, info): """Handle for discovered platform.""" await async_setup_platform(platform, discovery_info=info) discovery.async_listen_platform(opp, DOMAIN, async_platform_discovered) async def async_clear_cache_handle(service): """Handle clear cache service call.""" await tts.async_clear_cache() opp.services.async_register( DOMAIN, SERVICE_CLEAR_CACHE, async_clear_cache_handle, schema=SCHEMA_SERVICE_CLEAR_CACHE, ) return True