Esempio n. 1
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable):
    """Helper method to connect scanner-based platform to device tracker.

    This method is a coroutine.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    scanner.hass = hass

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    @asyncio.coroutine
    def async_device_tracker_scan(now: dt_util.dt.datetime):
        """Called when interval matches."""
        found_devices = yield from scanner.async_scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = yield from scanner.async_get_device_name(mac)
                seen.add(mac)
            hass.async_add_job(async_see_device(mac=mac, host_name=host_name))

    async_track_time_interval(hass, async_device_tracker_scan, interval)
    hass.async_add_job(async_device_tracker_scan, None)
Esempio n. 2
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable,
                                 platform: str):
    """Set up the connect scanner-based platform to device tracker.

    This method must be run in the event loop.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    update_lock = asyncio.Lock(loop=hass.loop)
    scanner.hass = hass

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    async def async_device_tracker_scan(now: dt_util.dt.datetime):
        """Handle interval matches."""
        if update_lock.locked():
            _LOGGER.warning(
                "Updating device list from %s took longer than the scheduled "
                "scan interval %s", platform, interval)
            return

        async with update_lock:
            found_devices = await scanner.async_scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = await scanner.async_get_device_name(mac)
                seen.add(mac)

            try:
                extra_attributes = (await
                                    scanner.async_get_extra_attributes(mac))
            except NotImplementedError:
                extra_attributes = dict()

            kwargs = {
                'mac': mac,
                'host_name': host_name,
                'source_type': SOURCE_TYPE_ROUTER,
                'attributes': {
                    'scanner': scanner.__class__.__name__,
                    **extra_attributes
                }
            }

            zone_home = hass.states.get(zone.ENTITY_ID_HOME)
            if zone_home:
                kwargs['gps'] = [
                    zone_home.attributes[ATTR_LATITUDE],
                    zone_home.attributes[ATTR_LONGITUDE]
                ]
                kwargs['gps_accuracy'] = 0

            hass.async_add_job(async_see_device(**kwargs))

    async_track_time_interval(hass, async_device_tracker_scan, interval)
    hass.async_add_job(async_device_tracker_scan(None))
Esempio n. 3
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable):
    """Helper method to connect scanner-based platform to device tracker.

    This method is a coroutine.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    def device_tracker_scan(now: dt_util.dt.datetime):
        """Called when interval matches."""
        found_devices = scanner.scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = scanner.get_device_name(mac)
                seen.add(mac)
            hass.add_job(async_see_device(mac=mac, host_name=host_name))

    async_track_utc_time_change(
        hass, device_tracker_scan, second=range(0, 60, interval))

    hass.async_add_job(device_tracker_scan, None)
Esempio n. 4
0
async def async_setup_entry(hass: HomeAssistantType,
                            entry: ConfigEntry) -> bool:
    """Setup a VEN from a config flow entry"""

    config = hass.data[const.DOMAIN][const.DATA_CONFIG]

    from pyoadr_ven import OpenADRVenAgent

    ven_config = config.get(const.DOMAIN)
    oadr_agent = OpenADRVenAgent(
        ven_id=balena.get_device_uuid(),
        vtn_id=ven_config.get(const.VTN_ID),
        vtn_address=ven_config.get(const.VTN_ADDRESS),
        poll_interval_secs=ven_config.get(const.POLL_INTERVAL_SECS),
        log_xml=ven_config.get(const.LOG_XML),
        opt_timeout_secs=ven_config.get(const.OPT_TIMEOUT_SECS),
        opt_default_decision=ven_config.get(const.OPT_DEFAULT_DECISION),
        report_parameters=ven_config.get(const.REPORT_PARAMETERS),
        client_pem_bundle=ven_config.get(const.CLIENT_PEM_BUNDLE_FILEPATH),
        vtn_ca_cert=ven_config.get(const.CA_CERT_FILEPATH),
        db_filepath=ven_config.get(const.DB_FILEPATH),
    )

    hass.data[const.DOMAIN][const.OADR_AGENT] = oadr_agent

    # Register services defined in services.py
    await services.async_setup_services(hass)

    hass.async_add_job(
        hass.config_entries.async_forward_entry_setup(entry, "binary_sensor"))

    # Return boolean to indicate that initialization was successful.
    _LOGGER.info("PowerShaper entry setup complete")
    return True
Esempio n. 5
0
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
                               async_add_devices, discovery_info=None):
    """Set up the cast platform."""
    import pychromecast

    # Import CEC IGNORE attributes
    pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
    hass.data.setdefault(ADDED_CAST_DEVICES_KEY, {})
    hass.data.setdefault(KNOWN_CHROMECASTS_KEY, {})

    # None -> use discovery; (host, port) -> manually specify chromecast.
    want_host = None
    if discovery_info:
        want_host = (discovery_info.get('host'), discovery_info.get('port'))
    elif CONF_HOST in config:
        want_host = (config.get(CONF_HOST), DEFAULT_PORT)

    enable_discovery = False
    if want_host is None:
        # We were explicitly told to enable pychromecast discovery.
        enable_discovery = True
    elif want_host[1] != DEFAULT_PORT:
        # We're trying to add a group, so we have to use pychromecast's
        # discovery to get the correct friendly name.
        enable_discovery = True

    if enable_discovery:
        @callback
        def async_cast_discovered(chromecast):
            """Callback for when a new chromecast is discovered."""
            if want_host is not None and \
                    (chromecast.host, chromecast.port) != want_host:
                return  # for groups, only add requested device
            cast_device = _async_create_cast_device(hass, chromecast)

            if cast_device is not None:
                async_add_devices([cast_device])

        async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED,
                                 async_cast_discovered)
        # Re-play the callback for all past chromecasts, store the objects in
        # a list to avoid concurrent modification resulting in exception.
        for chromecast in list(hass.data[KNOWN_CHROMECASTS_KEY].values()):
            async_cast_discovered(chromecast)

        hass.async_add_job(_setup_internal_discovery, hass)
    else:
        # Manually add a "normal" Chromecast, we can do that without discovery.
        try:
            chromecast = await hass.async_add_job(
                pychromecast.Chromecast, *want_host)
        except pychromecast.ChromecastConnectionError as err:
            _LOGGER.warning("Can't set up chromecast on %s: %s",
                            want_host[0], err)
            raise PlatformNotReady
        key = (chromecast.host, chromecast.port, chromecast.uuid)
        cast_device = _async_create_cast_device(hass, chromecast)
        if cast_device is not None:
            hass.data[KNOWN_CHROMECASTS_KEY][key] = chromecast
            async_add_devices([cast_device])
Esempio n. 6
0
async def _handle_entity_call(
    hass: HomeAssistantType,
    entity: "Entity",
    func: Union[str, Callable[..., Any]],
    data: Union[Dict, ha.ServiceCall],
    context: ha.Context,
) -> None:
    """Handle calling service method."""
    entity.async_set_context(context)

    if isinstance(func, str):
        result = hass.async_add_job(partial(getattr(entity, func),
                                            **data))  # type: ignore
    else:
        result = hass.async_add_job(func, entity, data)

    # Guard because callback functions do not return a task when passed to async_add_job.
    if result is not None:
        await result

    if asyncio.iscoroutine(result):
        _LOGGER.error(
            "Service %s for %s incorrectly returns a coroutine object. Await result instead in service handler. Report bug to integration author",
            func,
            entity.entity_id,
        )
        await result  # type: ignore
Esempio n. 7
0
def async_see(
    hass: HomeAssistantType,
    mac: str = None,
    dev_id: str = None,
    host_name: str = None,
    location_name: str = None,
    gps: GPSType = None,
    gps_accuracy=None,
    battery: int = None,
    attributes: dict = None,
):
    """Call service to notify you see device."""
    data = {
        key: value
        for key, value in (
            (ATTR_MAC, mac),
            (ATTR_DEV_ID, dev_id),
            (ATTR_HOST_NAME, host_name),
            (ATTR_LOCATION_NAME, location_name),
            (ATTR_GPS, gps),
            (ATTR_GPS_ACCURACY, gps_accuracy),
            (ATTR_BATTERY, battery),
        ) if value is not None
    }
    if attributes:
        data[ATTR_ATTRIBUTES] = attributes
    hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_SEE, data))
Esempio n. 8
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable,
                                 platform: str):
    """Set up the connect scanner-based platform to device tracker.

    This method must be run in the event loop.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    update_lock = asyncio.Lock(loop=hass.loop)
    scanner.hass = hass

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    @asyncio.coroutine
    def async_device_tracker_scan(now: dt_util.dt.datetime):
        """Handle interval matches."""
        if update_lock.locked():
            _LOGGER.warning(
                "Updating device list from %s took longer than the scheduled "
                "scan interval %s", platform, interval)
            return

        with (yield from update_lock):
            found_devices = yield from scanner.async_scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = yield from scanner.async_get_device_name(mac)
                seen.add(mac)

            try:
                extra_attributes = (yield from
                                    scanner.async_get_extra_attributes(mac))
            except NotImplementedError:
                extra_attributes = dict()

            kwargs = {
                'mac': mac,
                'host_name': host_name,
                'source_type': SOURCE_TYPE_ROUTER,
                'attributes': {
                    'scanner': scanner.__class__.__name__,
                    **extra_attributes
                }
            }

            zone_home = hass.states.get(zone.ENTITY_ID_HOME)
            if zone_home:
                kwargs['gps'] = [zone_home.attributes[ATTR_LATITUDE],
                                 zone_home.attributes[ATTR_LONGITUDE]]
                kwargs['gps_accuracy'] = 0

            hass.async_add_job(async_see_device(**kwargs))

    async_track_time_interval(hass, async_device_tracker_scan, interval)
    hass.async_add_job(async_device_tracker_scan(None))
Esempio n. 9
0
def async_publish(hass: HomeAssistantType,
                  topic: Any,
                  payload,
                  qos=None,
                  retain=None) -> None:
    """Publish message to an MQTT topic."""
    data = _build_publish_data(topic, qos, retain)
    data[ATTR_PAYLOAD] = payload
    hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_PUBLISH, data))
Esempio n. 10
0
async def async_setup_entry(hass: HomeAssistantType,
                            entry: ConfigEntry) -> bool:
    """Setup UK carbon intensity integration from a config flow entry"""

    hass.async_add_job(
        hass.config_entries.async_forward_entry_setup(entry, "binary_sensor"))

    # Return boolean to indicate that initialization was successful.
    _LOGGER.debug("UK carbon intensity integration entry setup complete")
    return True
Esempio n. 11
0
async def async_setup(hass: HomeAssistantType, config: ConfigType):
    """Register the iZone component config."""
    conf = config.get(DOMAIN)
    if not conf:
        return True

    hass.data[DATA_CONFIG] = conf

    # Explicitly added in the config file, create a config entry.
    hass.async_add_job(hass.config_entries.flow.async_init(
        DOMAIN, context={'source': config_entries.SOURCE_IMPORT}))

    return True
Esempio n. 12
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable,
                                 platform: str):
    """Helper method to connect scanner-based platform to device tracker.

    This method must be run in the event loop.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    update_lock = asyncio.Lock(loop=hass.loop)
    scanner.hass = hass

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    @asyncio.coroutine
    def async_device_tracker_scan(now: dt_util.dt.datetime):
        """Called when interval matches."""
        if update_lock.locked():
            _LOGGER.warning(
                "Updating device list from %s took longer than the scheduled "
                "scan interval %s", platform, interval)
            return

        with (yield from update_lock):
            found_devices = yield from scanner.async_scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = yield from scanner.async_get_device_name(mac)
                seen.add(mac)

            kwargs = {
                'mac': mac,
                'host_name': host_name,
                'source_type': SOURCE_TYPE_ROUTER
            }

            zone_home = hass.states.get(zone.ENTITY_ID_HOME)
            if zone_home:
                kwargs['gps'] = [
                    zone_home.attributes[ATTR_LATITUDE],
                    zone_home.attributes[ATTR_LONGITUDE]
                ]
                kwargs['gps_accuracy'] = 0

            hass.async_add_job(async_see_device(**kwargs))

    async_track_time_interval(hass, async_device_tracker_scan, interval)
    hass.async_add_job(async_device_tracker_scan(None))
Esempio n. 13
0
async def async_setup(hass: HomeAssistantType, config: Dict) -> bool:
    """Set up the switcher component."""
    from aioswitcher.bridge import SwitcherV2Bridge

    phone_id = config[DOMAIN][CONF_PHONE_ID]
    device_id = config[DOMAIN][CONF_DEVICE_ID]
    device_password = config[DOMAIN][CONF_DEVICE_PASSWORD]

    v2bridge = SwitcherV2Bridge(hass.loop, phone_id, device_id,
                                device_password)

    await v2bridge.start()

    async def async_stop_bridge(event: EventType) -> None:
        """On homeassistant stop, gracefully stop the bridge if running."""
        await v2bridge.stop()

    hass.async_add_job(
        hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP,
                                   async_stop_bridge))

    try:
        device_data = await wait_for(v2bridge.queue.get(),
                                     timeout=5.0,
                                     loop=hass.loop)
    except (Asyncio_TimeoutError, RuntimeError):
        _LOGGER.exception("failed to get response from device")
        await v2bridge.stop()
        return False

    hass.data[DOMAIN] = {DATA_DEVICE: device_data}

    hass.async_create_task(
        async_load_platform(hass, SWITCH_DOMAIN, DOMAIN, None, config))

    @callback
    def device_updates(timestamp: Optional[datetime]) -> None:
        """Use for updating the device data from the queue."""
        if v2bridge.running:
            try:
                device_new_data = v2bridge.queue.get_nowait()
                if device_new_data:
                    async_dispatcher_send(hass, SIGNAL_SWITCHER_DEVICE_UPDATE,
                                          device_new_data)
            except QueueEmpty:
                pass

    async_track_time_interval(hass, device_updates, timedelta(seconds=4))

    return True
Esempio n. 14
0
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
                                async_add_entities, discovery_info):
    """Set up the cast platform."""
    import pychromecast

    # Import CEC IGNORE attributes
    pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
    hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set())
    hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set())

    info = None
    if discovery_info is not None:
        info = ChromecastInfo(host=discovery_info['host'],
                              port=discovery_info['port'])
    elif CONF_HOST in config:
        info = ChromecastInfo(host=config[CONF_HOST], port=DEFAULT_PORT)

    @callback
    def async_cast_discovered(discover: ChromecastInfo) -> None:
        """Handle discovery of a new chromecast."""
        if info is not None and info.host_port != discover.host_port:
            # Not our requested cast device.
            return

        cast_device = _async_create_cast_device(hass, discover)
        if cast_device is not None:
            async_add_entities([cast_device])

    remove_handler = async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED,
                                              async_cast_discovered)
    # Re-play the callback for all past chromecasts, store the objects in
    # a list to avoid concurrent modification resulting in exception.
    for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]):
        async_cast_discovered(chromecast)

    if info is None or info.is_audio_group:
        # If we were a) explicitly told to enable discovery or
        # b) have an audio group cast device, we need internal discovery.
        hass.async_add_job(_setup_internal_discovery, hass)
    else:
        info = await hass.async_add_job(_fill_out_missing_chromecast_info,
                                        info)
        if info.friendly_name is None:
            _LOGGER.debug(
                "Cannot retrieve detail information for chromecast"
                " %s, the device may not be online", info)
            remove_handler()
            raise PlatformNotReady

        hass.async_add_job(_discover_chromecast, hass, info)
Esempio n. 15
0
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
                                async_add_entities, discovery_info):
    """Set up the cast platform."""
    import pychromecast

    # Import CEC IGNORE attributes
    pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
    hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set())
    hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set())

    info = None
    if discovery_info is not None:
        info = ChromecastInfo(host=discovery_info['host'],
                              port=discovery_info['port'])
    elif CONF_HOST in config:
        info = ChromecastInfo(host=config[CONF_HOST],
                              port=DEFAULT_PORT)

    @callback
    def async_cast_discovered(discover: ChromecastInfo) -> None:
        """Handle discovery of a new chromecast."""
        if info is not None and info.host_port != discover.host_port:
            # Not our requested cast device.
            return

        cast_device = _async_create_cast_device(hass, discover)
        if cast_device is not None:
            async_add_entities([cast_device])

    remove_handler = async_dispatcher_connect(
        hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered)
    # Re-play the callback for all past chromecasts, store the objects in
    # a list to avoid concurrent modification resulting in exception.
    for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]):
        async_cast_discovered(chromecast)

    if info is None or info.is_audio_group:
        # If we were a) explicitly told to enable discovery or
        # b) have an audio group cast device, we need internal discovery.
        hass.async_add_job(_setup_internal_discovery, hass)
    else:
        info = await hass.async_add_job(_fill_out_missing_chromecast_info,
                                        info)
        if info.friendly_name is None:
            _LOGGER.debug("Cannot retrieve detail information for chromecast"
                          " %s, the device may not be online", info)
            remove_handler()
            raise PlatformNotReady

        hass.async_add_job(_discover_chromecast, hass, info)
Esempio n. 16
0
def async_see(hass: HomeAssistantType, mac: str = None, dev_id: str = None,
              host_name: str = None, location_name: str = None,
              gps: GPSType = None, gps_accuracy=None,
              battery: int = None, attributes: dict = None):
    """Call service to notify you see device."""
    data = {key: value for key, value in
            ((ATTR_MAC, mac),
             (ATTR_DEV_ID, dev_id),
             (ATTR_HOST_NAME, host_name),
             (ATTR_LOCATION_NAME, location_name),
             (ATTR_GPS, gps),
             (ATTR_GPS_ACCURACY, gps_accuracy),
             (ATTR_BATTERY, battery)) if value is not None}
    if attributes:
        data[ATTR_ATTRIBUTES] = attributes
    hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_SEE, data))
Esempio n. 17
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up the Azure Event Grid platform."""
    try:
        LOGGER.debug("async_setup")

        topics = config.get(DOMAIN)
        all_event_grids = {}
        LOGGER.debug("adding sensors")
        hass.async_add_job(
            discovery.async_load_platform(hass, 'sensor', DOMAIN, {}, config))

        @asyncio.coroutine
        def async_handle_event_grid_service(service_call):
            """Handle calls to event grid services."""
            topic_name = service_call.data[CONF_NAME]
            eventGrid = all_event_grids[topic_name]

            if service_call.service == SERVICE_AZURE_EVENT_GRID__PUBLISH_MESSAGE:
                eventGrid.event_grid_publish_message(service_call)

        for i in topics.items():
            LOGGER.debug(i)
            name = i[0]
            host = i[1][CONF_HOST]
            key = i[1][CONF_TOPIC_KEY]
            LOGGER.debug(f"setting up topic: {name}")
            if host and key:
                LOGGER.debug(f'with host: {host}')
                eventGrid = AzureEventGrid(hass, host, name, key)
                all_event_grids[name] = eventGrid
            elif host or key:
                LOGGER.error(
                    f'Incorrect config, please supply either both Host and Topic Key or Monitored Variables. Supplied {i[1]}'
                )
        hass.services.async_register(DOMAIN,
                                     SERVICE_AZURE_EVENT_GRID__PUBLISH_MESSAGE,
                                     async_handle_event_grid_service,
                                     schema=MQTT_PUBLISH_SCHEMA)
    except Exception as err:
        LOGGER.error("Error async_setup: %s", err)

    return True
Esempio n. 18
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable):
    """Helper method to connect scanner-based platform to device tracker.

    This method is a coroutine.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    scanner.hass = hass

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    @asyncio.coroutine
    def async_device_tracker_scan(now: dt_util.dt.datetime):
        """Called when interval matches."""
        found_devices = yield from scanner.async_scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = yield from scanner.async_get_device_name(mac)
                seen.add(mac)

            kwargs = {
                'mac': mac,
                'host_name': host_name,
                'source_type': SOURCE_TYPE_ROUTER
            }

            zone_home = hass.states.get(zone.ENTITY_ID_HOME)
            if zone_home:
                kwargs['gps'] = [
                    zone_home.attributes[ATTR_LATITUDE],
                    zone_home.attributes[ATTR_LONGITUDE]
                ]
                kwargs['gps_accuracy'] = 0

            hass.async_add_job(async_see_device(**kwargs))

    async_track_time_interval(hass, async_device_tracker_scan, interval)
    hass.async_add_job(async_device_tracker_scan, None)
Esempio n. 19
0
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
    try:
        api = await AirthingsAPI.login(
            entry.data[CONF_API_KEY],
            LoginDetails(entry.data[CONF_EMAIL], entry.data[CONF_PASSWORD]),
        )
    except Exception:
        logger.exception("login failed")
        return False

    hass.data[DOMAIN][KEY_API] = api

    for platform in PLATFORMS:
        hass.async_add_job(
            hass.config_entries.async_forward_entry_setup, entry, platform
        )

    logger.info("starting auto update")
    api.start_auto_update(timedelta(minutes=10))

    return True
Esempio n. 20
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable):
    """Helper method to connect scanner-based platform to device tracker.

    This method is a coroutine.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    scanner.hass = hass

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    @asyncio.coroutine
    def async_device_tracker_scan(now: dt_util.dt.datetime):
        """Called when interval matches."""
        found_devices = yield from scanner.async_scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = yield from scanner.async_get_device_name(mac)
                seen.add(mac)

            kwargs = {
                'mac': mac,
                'host_name': host_name,
                'source_type': SOURCE_TYPE_ROUTER
            }

            zone_home = hass.states.get(zone.ENTITY_ID_HOME)
            if zone_home:
                kwargs['gps'] = [zone_home.attributes[ATTR_LATITUDE],
                                 zone_home.attributes[ATTR_LONGITUDE]]
                kwargs['gps_accuracy'] = 0

            hass.async_add_job(async_see_device(**kwargs))

    async_track_time_interval(hass, async_device_tracker_scan, interval)
    hass.async_add_job(async_device_tracker_scan, None)
Esempio n. 21
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up the HomematicIP Cloud component."""
    hass.data[DOMAIN] = {}

    accesspoints = config.get(DOMAIN, [])

    for conf in accesspoints:
        if conf[CONF_ACCESSPOINT] not in set(
                entry.data[HMIPC_HAPID]
                for entry in hass.config_entries.async_entries(DOMAIN)):
            hass.async_add_job(
                hass.config_entries.flow.async_init(
                    DOMAIN,
                    context={"source": config_entries.SOURCE_IMPORT},
                    data={
                        HMIPC_HAPID: conf[CONF_ACCESSPOINT],
                        HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN],
                        HMIPC_NAME: conf[CONF_NAME],
                    },
                ))

    return True
Esempio n. 22
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(CONF_NAME):
        cv.string,
        vol.Optional(CONF_ICON, default=None):
        vol.Any(None, cv.icon),
        vol.Optional('track', default=False):
        cv.boolean,
        vol.Optional(CONF_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),
    })
    try:
        result = []
        try:
            devices = yield from hass.async_add_job(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():
            # Deprecated option. We just ignore it to avoid breaking change
            device.pop('vendor', None)
            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 []
Esempio n. 23
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(CONF_NAME): cv.string,
        vol.Optional(CONF_ICON, default=None): vol.Any(None, cv.icon),
        vol.Optional('track', default=False): cv.boolean,
        vol.Optional(CONF_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),
    })
    try:
        result = []
        try:
            devices = yield from hass.async_add_job(
                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():
            # Deprecated option. We just ignore it to avoid breaking change
            device.pop('vendor', None)
            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 []
Esempio n. 24
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up the HomematicIP Cloud component."""
    hass.data[DOMAIN] = {}

    accesspoints = config.get(DOMAIN, [])

    for conf in accesspoints:
        if conf[CONF_ACCESSPOINT] not in set(
                entry.data[HMIPC_HAPID]
                for entry in hass.config_entries.async_entries(DOMAIN)):
            hass.async_add_job(
                hass.config_entries.flow.async_init(
                    DOMAIN,
                    context={"source": config_entries.SOURCE_IMPORT},
                    data={
                        HMIPC_HAPID: conf[CONF_ACCESSPOINT],
                        HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN],
                        HMIPC_NAME: conf[CONF_NAME],
                    },
                ))

    async def _async_activate_eco_mode_with_duration(service) -> None:
        """Service to activate eco mode with duration."""
        duration = service.data[ATTR_DURATION]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_duration(duration)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_absence_with_duration(duration)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION,
        _async_activate_eco_mode_with_duration,
        schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_DURATION,
    )

    async def _async_activate_eco_mode_with_period(service) -> None:
        """Service to activate eco mode with period."""
        endtime = service.data[ATTR_ENDTIME]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_period(endtime)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_absence_with_period(endtime)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD,
        _async_activate_eco_mode_with_period,
        schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_PERIOD,
    )

    async def _async_activate_vacation(service) -> None:
        """Service to activate vacation."""
        endtime = service.data[ATTR_ENDTIME]
        temperature = service.data[ATTR_TEMPERATURE]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_vacation(endtime, temperature)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_vacation(endtime, temperature)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_VACATION,
        _async_activate_vacation,
        schema=SCHEMA_ACTIVATE_VACATION,
    )

    async def _async_deactivate_eco_mode(service) -> None:
        """Service to deactivate eco mode."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_absence()
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.deactivate_absence()

    hass.services.async_register(
        DOMAIN,
        SERVICE_DEACTIVATE_ECO_MODE,
        _async_deactivate_eco_mode,
        schema=SCHEMA_DEACTIVATE_ECO_MODE,
    )

    async def _async_deactivate_vacation(service) -> None:
        """Service to deactivate vacation."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_vacation()
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.deactivate_vacation()

    hass.services.async_register(
        DOMAIN,
        SERVICE_DEACTIVATE_VACATION,
        _async_deactivate_vacation,
        schema=SCHEMA_DEACTIVATE_VACATION,
    )

    async def _set_active_climate_profile(service) -> None:
        """Service to set the active climate profile."""
        entity_id_list = service.data[ATTR_ENTITY_ID]
        climate_profile_index = service.data[ATTR_CLIMATE_PROFILE_INDEX] - 1

        for hap in hass.data[DOMAIN].values():
            if entity_id_list != "all":
                for entity_id in entity_id_list:
                    group = hap.hmip_device_by_entity_id.get(entity_id)
                    if group and isinstance(group, AsyncHeatingGroup):
                        await group.set_active_profile(climate_profile_index)
            else:
                for group in hap.home.groups:
                    if isinstance(group, AsyncHeatingGroup):
                        await group.set_active_profile(climate_profile_index)

    hass.services.async_register(
        DOMAIN,
        SERVICE_SET_ACTIVE_CLIMATE_PROFILE,
        _set_active_climate_profile,
        schema=SCHEMA_SET_ACTIVE_CLIMATE_PROFILE,
    )

    async def _async_dump_hap_config(service) -> None:
        """Service to dump the configuration of a Homematic IP Access Point."""
        config_path = (service.data.get(ATTR_CONFIG_OUTPUT_PATH)
                       or hass.config.config_dir)
        config_file_prefix = service.data[ATTR_CONFIG_OUTPUT_FILE_PREFIX]
        anonymize = service.data[ATTR_ANONYMIZE]

        for hap in hass.data[DOMAIN].values():
            hap_sgtin = hap.config_entry.unique_id

            if anonymize:
                hap_sgtin = hap_sgtin[-4:]

            file_name = f"{config_file_prefix}_{hap_sgtin}.json"
            path = Path(config_path)
            config_file = path / file_name

            json_state = await hap.home.download_configuration()
            json_state = handle_config(json_state, anonymize)

            config_file.write_text(json_state, encoding="utf8")

    hass.services.async_register(
        DOMAIN,
        SERVICE_DUMP_HAP_CONFIG,
        _async_dump_hap_config,
        schema=SCHEMA_DUMP_HAP_CONFIG,
    )

    async def _async_reset_energy_counter(service):
        """Service to reset the energy counter."""
        entity_id_list = service.data[ATTR_ENTITY_ID]

        for hap in hass.data[DOMAIN].values():
            if entity_id_list != "all":
                for entity_id in entity_id_list:
                    device = hap.hmip_device_by_entity_id.get(entity_id)
                    if device and isinstance(device, AsyncSwitchMeasuring):
                        await device.reset_energy_counter()
            else:
                for device in hap.home.devices:
                    if isinstance(device, AsyncSwitchMeasuring):
                        await device.reset_energy_counter()

    hass.helpers.service.async_register_admin_service(
        DOMAIN,
        SERVICE_RESET_ENERGY_COUNTER,
        _async_reset_energy_counter,
        schema=SCHEMA_RESET_ENERGY_COUNTER,
    )

    def _get_home(hapid: str) -> Optional[AsyncHome]:
        """Return a HmIP home."""
        hap = hass.data[DOMAIN].get(hapid)
        if hap:
            return hap.home

        _LOGGER.info("No matching access point found for access point id %s",
                     hapid)
        return None

    return True
Esempio n. 25
0
def async_publish(hass: HomeAssistantType, topic: Any, payload, qos=None,
                  retain=None) -> None:
    """Publish message to an MQTT topic."""
    data = _build_publish_data(topic, qos, retain)
    data[ATTR_PAYLOAD] = payload
    hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_PUBLISH, data))
Esempio n. 26
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up the HomematicIP Cloud component."""
    hass.data[DOMAIN] = {}

    accesspoints = config.get(DOMAIN, [])

    for conf in accesspoints:
        if conf[CONF_ACCESSPOINT] not in configured_haps(hass):
            hass.async_add_job(
                hass.config_entries.flow.async_init(
                    DOMAIN,
                    context={"source": config_entries.SOURCE_IMPORT},
                    data={
                        HMIPC_HAPID: conf[CONF_ACCESSPOINT],
                        HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN],
                        HMIPC_NAME: conf[CONF_NAME],
                    },
                )
            )

    async def _async_activate_eco_mode_with_duration(service):
        """Service to activate eco mode with duration."""
        duration = service.data[ATTR_DURATION]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_duration(duration)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_absence_with_duration(duration)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION,
        _async_activate_eco_mode_with_duration,
        schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_DURATION,
    )

    async def _async_activate_eco_mode_with_period(service):
        """Service to activate eco mode with period."""
        endtime = service.data[ATTR_ENDTIME]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_period(endtime)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_absence_with_period(endtime)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD,
        _async_activate_eco_mode_with_period,
        schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_PERIOD,
    )

    async def _async_activate_vacation(service):
        """Service to activate vacation."""
        endtime = service.data[ATTR_ENDTIME]
        temperature = service.data[ATTR_TEMPERATURE]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_vacation(endtime, temperature)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_vacation(endtime, temperature)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_VACATION,
        _async_activate_vacation,
        schema=SCHEMA_ACTIVATE_VACATION,
    )

    async def _async_deactivate_eco_mode(service):
        """Service to deactivate eco mode."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_absence()
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.deactivate_absence()

    hass.services.async_register(
        DOMAIN,
        SERVICE_DEACTIVATE_ECO_MODE,
        _async_deactivate_eco_mode,
        schema=SCHEMA_DEACTIVATE_ECO_MODE,
    )

    async def _async_deactivate_vacation(service):
        """Service to deactivate vacation."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_vacation()
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.deactivate_vacation()

    hass.services.async_register(
        DOMAIN,
        SERVICE_DEACTIVATE_VACATION,
        _async_deactivate_vacation,
        schema=SCHEMA_DEACTIVATE_VACATION,
    )

    async def _set_active_climate_profile(service):
        """Service to set the active climate profile."""
        entity_id_list = service.data[ATTR_ENTITY_ID]
        climate_profile_index = service.data[ATTR_CLIMATE_PROFILE_INDEX] - 1

        for hap in hass.data[DOMAIN].values():
            if entity_id_list != "all":
                for entity_id in entity_id_list:
                    group = hap.hmip_device_by_entity_id.get(entity_id)
                    if group:
                        await group.set_active_profile(climate_profile_index)
            else:
                for group in hap.home.groups:
                    if isinstance(group, AsyncHeatingGroup):
                        await group.set_active_profile(climate_profile_index)

    hass.services.async_register(
        DOMAIN,
        SERVICE_SET_ACTIVE_CLIMATE_PROFILE,
        _set_active_climate_profile,
        schema=SCHEMA_SET_ACTIVE_CLIMATE_PROFILE,
    )

    def _get_home(hapid: str):
        """Return a HmIP home."""
        hap = hass.data[DOMAIN].get(hapid)
        if hap:
            return hap.home

        _LOGGER.info("No matching access point found for access point id %s", hapid)
        return None

    return True
Esempio n. 27
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
Esempio n. 28
0
async def async_setup_platform(hass: HomeAssistantType,
                               config: ConfigType,
                               async_add_devices,
                               discovery_info=None):
    """Set up the cast platform."""
    import pychromecast

    # Import CEC IGNORE attributes
    pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
    hass.data.setdefault(ADDED_CAST_DEVICES_KEY, {})
    hass.data.setdefault(KNOWN_CHROMECASTS_KEY, {})

    # None -> use discovery; (host, port) -> manually specify chromecast.
    want_host = None
    if discovery_info:
        want_host = (discovery_info.get('host'), discovery_info.get('port'))
    elif CONF_HOST in config:
        want_host = (config.get(CONF_HOST), DEFAULT_PORT)

    enable_discovery = False
    if want_host is None:
        # We were explicitly told to enable pychromecast discovery.
        enable_discovery = True
    elif want_host[1] != DEFAULT_PORT:
        # We're trying to add a group, so we have to use pychromecast's
        # discovery to get the correct friendly name.
        enable_discovery = True

    if enable_discovery:

        @callback
        def async_cast_discovered(chromecast):
            """Callback for when a new chromecast is discovered."""
            if want_host is not None and \
                    (chromecast.host, chromecast.port) != want_host:
                return  # for groups, only add requested device
            cast_device = _async_create_cast_device(hass, chromecast)

            if cast_device is not None:
                async_add_devices([cast_device])

        async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED,
                                 async_cast_discovered)
        # Re-play the callback for all past chromecasts, store the objects in
        # a list to avoid concurrent modification resulting in exception.
        for chromecast in list(hass.data[KNOWN_CHROMECASTS_KEY].values()):
            async_cast_discovered(chromecast)

        hass.async_add_job(_setup_internal_discovery, hass)
    else:
        # Manually add a "normal" Chromecast, we can do that without discovery.
        try:
            chromecast = await hass.async_add_job(pychromecast.Chromecast,
                                                  *want_host)
        except pychromecast.ChromecastConnectionError as err:
            _LOGGER.warning("Can't set up chromecast on %s: %s", want_host[0],
                            err)
            raise PlatformNotReady
        key = (chromecast.host, chromecast.port, chromecast.uuid)
        cast_device = _async_create_cast_device(hass, chromecast)
        if cast_device is not None:
            hass.data[KNOWN_CHROMECASTS_KEY][key] = chromecast
            async_add_devices([cast_device])
Esempio n. 29
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)
    defaults = conf.get(CONF_NEW_DEVICE_DEFAULTS, {})

    devices = yield from async_load_config(yaml_path, hass, consider_home)
    tracker = DeviceTracker(
        hass, consider_home, track_new, defaults, 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()

    @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