Example #1
0
def async_load_config(path: str, hass: HomeAssistantType,
                      consider_home: timedelta):
    """Load devices from YAML configuration file.

    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required('name'):
        cv.string,
        vol.Optional('track', default=False):
        cv.boolean,
        vol.Optional('mac', default=None):
        vol.Any(None, vol.All(cv.string, vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE):
        cv.boolean,
        vol.Optional('gravatar', default=None):
        vol.Any(None, cv.string),
        vol.Optional('picture', default=None):
        vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home):
        vol.All(cv.time_period, cv.positive_timedelta),
        vol.Optional('vendor', default=None):
        vol.Any(None, cv.string),
    })
    try:
        result = []
        try:
            devices = yield from hass.loop.run_in_executor(
                None, load_yaml_config_file, path)
        except HomeAssistantError as err:
            _LOGGER.error('Unable to load %s: %s', path, str(err))
            return []

        for dev_id, device in devices.items():
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                async_log_exception(exp, dev_id, devices, hass)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
def async_load_config(path: str, hass: HomeAssistantType,
                      consider_home: timedelta):
    """Load devices from YAML configuration file.

    This method is a coroutine.
    """
    dev_schema = vol.Schema({
        vol.Required('name'): cv.string,
        vol.Optional('track', default=False): cv.boolean,
        vol.Optional('mac', default=None): vol.Any(None, vol.All(cv.string,
                                                                 vol.Upper)),
        vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean,
        vol.Optional('gravatar', default=None): vol.Any(None, cv.string),
        vol.Optional('picture', default=None): vol.Any(None, cv.string),
        vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All(
            cv.time_period, cv.positive_timedelta),
        vol.Optional('vendor', default=None): vol.Any(None, cv.string),
    })
    try:
        result = []
        try:
            devices = yield from hass.loop.run_in_executor(
                None, load_yaml_config_file, path)
        except HomeAssistantError as err:
            _LOGGER.error('Unable to load %s: %s', path, str(err))
            return []

        for dev_id, device in devices.items():
            try:
                device = dev_schema(device)
                device['dev_id'] = cv.slugify(dev_id)
            except vol.Invalid as exp:
                async_log_exception(exp, dev_id, devices, hass)
            else:
                result.append(Device(hass, **device))
        return result
    except (HomeAssistantError, FileNotFoundError):
        # When YAML file could not be loaded/did not contain a dict
        return []
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, 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

        _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.loop.run_in_executor(
                    None, 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.loop.run_in_executor(
                    None, platform.setup_scanner, hass, p_config, tracker.see,
                    disc_info)
            else:
                raise HomeAssistantError("Invalid device_tracker platform.")

            if scanner:
                yield from async_setup_scanner_platform(
                    hass, p_config, scanner, tracker.async_see)
                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)

    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)

    @asyncio.coroutine
    def async_platform_discovered(platform, info):
        """Callback to 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.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
Example #4
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, 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

        _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.loop.run_in_executor(
                    None, platform.get_scanner, hass, {DOMAIN: p_config})
            elif hasattr(platform, 'async_setup_scanner'):
                setup = yield from platform.async_setup_scanner(
                    hass, p_config, tracker.see)
            elif hasattr(platform, 'setup_scanner'):
                setup = yield from hass.loop.run_in_executor(
                    None, platform.setup_scanner, hass, p_config, tracker.see)
            else:
                raise HomeAssistantError("Invalid device_tracker platform.")

            if scanner:
                yield from async_setup_scanner_platform(
                    hass, p_config, scanner, tracker.async_see)
                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)

    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