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)
示例#3
0
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
示例#4
0
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
示例#5
0
    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'))
示例#6
0
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])
示例#7
0
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
示例#8
0
    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)
示例#9
0
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
示例#10
0
    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)
示例#11
0
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
示例#12
0
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
示例#13
0
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"))
示例#14
0
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
示例#15
0
    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'))
示例#16
0
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
示例#17
0
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
示例#18
0
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
示例#19
0
    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))
示例#20
0
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
示例#21
0
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))
示例#23
0
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
示例#24
0
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
示例#25
0
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
示例#26
0
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
示例#27
0
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
示例#28
0
    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)
示例#29
0
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
示例#30
0
    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)
示例#31
0
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
示例#32
0
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
示例#33
0
    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)
示例#34
0
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
示例#35
0
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
示例#36
0
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)
示例#38
0
    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)
示例#39
0
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)
示例#41
0
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
示例#42
0
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
示例#43
0
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
示例#44
0
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
示例#45
0
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
示例#46
0
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
示例#47
0
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
示例#48
0
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
示例#49
0
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
示例#50
0
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
示例#51
0
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
示例#52
0
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
示例#53
0
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
示例#54
0
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
示例#55
0
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
示例#56
0
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
示例#57
0
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